From 107854bde3681e72fb99075585b30a120444c5a3 Mon Sep 17 00:00:00 2001 From: mostafa7171 Date: Sun, 18 Jan 2026 11:59:48 +0330 Subject: [PATCH] first push --- .env.local | 24 + .env.prod | 22 + .gitignore | 136 + Dockerfile | 12 + GateWay.py | 75 + KuChicken/__init__.py | 0 KuChicken/asgi.py | 16 + KuChicken/celery.py | 5 + KuChicken/settings.py | 229 + KuChicken/urls.py | 28 + KuChicken/wsgi.py | 16 + LiveStock/Contractor/__init__.py | 0 LiveStock/Contractor/excel_processing.py | 0 LiveStock/Contractor/filterset.py | 20 + LiveStock/Contractor/helpers.py | 0 LiveStock/Contractor/serializers.py | 14 + LiveStock/Contractor/urls.py | 14 + LiveStock/Contractor/views.py | 60 + LiveStock/Cooperative/__init__.py | 0 LiveStock/Cooperative/excel_processing.py | 0 LiveStock/Cooperative/filterset.py | 17 + LiveStock/Cooperative/helpers.py | 0 LiveStock/Cooperative/serializers.py | 66 + LiveStock/Cooperative/urls.py | 21 + LiveStock/Cooperative/views.py | 196 + LiveStock/Jahad/__init__.py | 0 LiveStock/Jahad/excel_processing.py | 1906 + LiveStock/Jahad/filterset.py | 35 + LiveStock/Jahad/helpers.py | 45 + LiveStock/Jahad/serializers.py | 54 + LiveStock/Jahad/urls.py | 59 + LiveStock/Jahad/views.py | 690 + LiveStock/LiveStoksAndPoultry/__init__.py | 0 .../LiveStoksAndPoultry/excel_processing.py | 174 + LiveStock/LiveStoksAndPoultry/filterset.py | 22 + LiveStock/LiveStoksAndPoultry/helpers.py | 30 + LiveStock/LiveStoksAndPoultry/serializers.py | 36 + LiveStock/LiveStoksAndPoultry/urls.py | 28 + LiveStock/LiveStoksAndPoultry/views.py | 459 + LiveStock/Rancher/__init__.py | 0 LiveStock/Rancher/excel_processing.py | 592 + LiveStock/Rancher/filterset.py | 25 + LiveStock/Rancher/helpers.py | 111 + LiveStock/Rancher/serializers.py | 40 + LiveStock/Rancher/urls.py | 38 + LiveStock/Rancher/views.py | 352 + LiveStock/Union/__init__.py | 0 LiveStock/Union/excel_processing.py | 0 LiveStock/Union/filterset.py | 17 + LiveStock/Union/helpers.py | 0 LiveStock/Union/serializers.py | 15 + LiveStock/Union/urls.py | 14 + LiveStock/Union/views.py | 181 + LiveStock/__init__.py | 0 LiveStock/admin.py | 3 + LiveStock/apps.py | 6 + LiveStock/helpers.py | 21 + LiveStock/migrations/0001_initial.py | 39 + .../0002_livestockprovincejahad_name.py | 18 + .../migrations/0003_auto_20250302_1254.py | 33 + .../migrations/0004_cooperative_union.py | 67 + ...ckproduct_livestockrolseproduct_rancher.py | 109 + .../migrations/0006_auto_20250302_1627.py | 35 + .../migrations/0007_auto_20250303_0931.py | 37 + .../migrations/0008_auto_20250303_0933.py | 24 + .../migrations/0009_auto_20250303_1021.py | 70 + .../0010_livestockallocations_rancher.py | 19 + ...011_remove_livestockallocations_rancher.py | 17 + ...12_remove_livestockrolseproduct_rancher.py | 17 + LiveStock/migrations/0013_livestock.py | 43 + .../migrations/0014_auto_20250305_1331.py | 23 + .../migrations/0015_rancher_allow_buy.py | 18 + .../migrations/0016_auto_20250305_1701.py | 23 + .../migrations/0017_auto_20250306_0033.py | 48 + .../migrations/0018_auto_20250306_1106.py | 45 + .../migrations/0019_auto_20250306_1921.py | 23 + .../migrations/0020_auto_20250307_1118.py | 60 + .../migrations/0021_auto_20250307_1312.py | 34 + .../migrations/0022_rancher_has_script.py | 18 + .../migrations/0023_rancher_cooperative.py | 19 + .../migrations/0024_auto_20250307_2117.py | 33 + .../migrations/0025_auto_20250307_2128.py | 21 + .../migrations/0026_auto_20250308_1507.py | 28 + ...estockrolseproduct_total_receipt_weight.py | 18 + .../migrations/0028_auto_20250309_1036.py | 23 + ...9_livestockrolseproduct_total_allocated.py | 18 + ...e_livestockrolseproduct_total_allocated.py | 17 + .../0031_cooperativeproductsshare.py | 38 + .../migrations/0032_auto_20250310_1639.py | 23 + .../migrations/0033_auto_20250310_1747.py | 23 + .../migrations/0034_auto_20250311_1002.py | 23 + LiveStock/migrations/0035_posseller.py | 37 + LiveStock/migrations/0036_rancher_type.py | 18 + .../migrations/0037_auto_20250312_1146.py | 33 + .../migrations/0038_auto_20250312_1422.py | 23 + .../0039_alter_rancher_dhi_amount.py | 18 + .../migrations/0040_auto_20250409_1829.py | 23 + .../migrations/0041_livestock_archive_date.py | 18 + .../migrations/0042_auto_20250414_1544.py | 23 + .../0043_livestock_age_of_archive.py | 18 + ..._cooperativeproductsshare_company_price.py | 18 + .../migrations/0045_auto_20250810_1102.py | 33 + LiveStock/migrations/__init__.py | 0 LiveStock/models.py | 372 + LiveStock/sms_management.py | 29 + LiveStock/tests.py | 3 + LiveStock/urls.py | 10 + LiveStock/views.py | 3 + README.md | 2 + RasadyaarBale/__init__.py | 0 RasadyaarBale/admin.py | 3 + RasadyaarBale/apps.py | 6 + RasadyaarBale/helper.py | 1 + RasadyaarBale/migrations/0001_initial.py | 38 + .../migrations/0002_user_bale_super_admin.py | 18 + .../0003_user_bale_rasadyar_user.py | 20 + RasadyaarBale/migrations/__init__.py | 0 RasadyaarBale/models.py | 19 + RasadyaarBale/tests.py | 3 + RasadyaarBale/urls.py | 15 + RasadyaarBale/views.py | 230 + assets/img/img-min.png | Bin 0 -> 796204 bytes authentication/__init__.py | 0 authentication/admin.py | 3 + authentication/apps.py | 6 + authentication/arvan_image/arvan_storage.py | 169 + authentication/filterset.py | 29 + authentication/healthcheck.py | 5 + authentication/helper/__init__.py | 0 authentication/helper/helper.py | 78 + authentication/helper/image_services.py | 21 + .../helper/make_user_gate_way_id.py | 12 + authentication/helper/refresh.py | 12 + authentication/log.py | 82 + authentication/message/__init__.py | 0 authentication/message/serializers.py | 28 + authentication/message/views.py | 195 + authentication/migrations/0001_initial.py | 431 + .../migrations/0002_auto_20231005_0439.py | 39 + .../migrations/0003_auto_20231112_1026.py | 73 + .../migrations/0004_auto_20231112_1223.py | 44 + .../migrations/0005_auto_20231112_1544.py | 39 + .../migrations/0006_auto_20231114_0931.py | 39 + .../migrations/0007_auto_20231120_1913.py | 44 + .../migrations/0008_auto_20231120_2009.py | 61 + .../migrations/0009_auto_20231120_2134.py | 43 + .../migrations/0010_auto_20231202_1108.py | 39 + .../migrations/0011_auto_20231205_1256.py | 39 + .../migrations/0012_auto_20231211_1102.py | 39 + .../migrations/0013_auto_20231214_1418.py | 39 + .../migrations/0014_auto_20240107_1133.py | 39 + .../migrations/0015_auto_20240107_2228.py | 39 + .../migrations/0016_auto_20240110_0238.py | 39 + .../migrations/0017_auto_20240131_1351.py | 44 + .../migrations/0018_auto_20240131_1405.py | 45 + .../migrations/0019_auto_20240131_1429.py | 43 + .../migrations/0020_auto_20240220_1341.py | 39 + .../migrations/0021_auto_20240326_1330.py | 305 + .../migrations/0022_auto_20240326_1425.py | 219 + .../migrations/0023_auto_20240408_1626.py | 87 + .../migrations/0024_auto_20240408_1632.py | 44 + .../migrations/0025_auto_20240416_1440.py | 39 + .../migrations/0026_auto_20240417_1103.py | 44 + .../migrations/0027_auto_20240420_0033.py | 39 + .../migrations/0028_auto_20240427_1357.py | 44 + .../migrations/0029_auto_20240511_1129.py | 39 + .../migrations/0030_auto_20240511_1312.py | 39 + .../migrations/0031_auto_20240516_1321.py | 45 + .../migrations/0032_auto_20240517_1337.py | 69 + .../migrations/0033_auto_20240517_1351.py | 44 + .../migrations/0034_auto_20240527_1506.py | 44 + .../migrations/0035_auto_20240612_0954.py | 39 + .../migrations/0036_auto_20240612_1137.py | 39 + .../migrations/0037_auto_20240612_1936.py | 39 + .../migrations/0038_auto_20240613_1101.py | 39 + .../migrations/0039_auto_20240616_0956.py | 39 + .../migrations/0040_auto_20240618_1451.py | 39 + .../migrations/0041_auto_20240713_0951.py | 39 + .../migrations/0042_auto_20240713_1024.py | 39 + .../migrations/0043_auto_20240803_1121.py | 39 + .../migrations/0044_auto_20240820_1038.py | 39 + .../migrations/0045_auto_20240830_1034.py | 39 + .../migrations/0046_auto_20240912_0926.py | 39 + .../migrations/0047_auto_20240912_1105.py | 39 + .../migrations/0048_auto_20240912_1118.py | 39 + .../migrations/0049_auto_20241005_1324.py | 44 + .../migrations/0050_auto_20241029_1116.py | 39 + .../migrations/0051_auto_20241130_1837.py | 49 + .../migrations/0052_auto_20241208_1147.py | 39 + .../migrations/0053_auto_20241215_1031.py | 39 + .../migrations/0054_auto_20241228_0926.py | 39 + .../migrations/0055_auto_20250112_1550.py | 39 + .../migrations/0056_auto_20250118_1418.py | 39 + .../migrations/0057_auto_20250121_0857.py | 79 + .../migrations/0058_auto_20250126_2046.py | 39 + .../migrations/0059_auto_20250126_2122.py | 39 + .../migrations/0060_auto_20250302_1203.py | 39 + .../migrations/0061_auto_20250302_1351.py | 39 + .../migrations/0062_auto_20250302_1458.py | 39 + .../migrations/0063_auto_20250303_1205.py | 39 + .../migrations/0064_auto_20250303_1315.py | 39 + .../migrations/0065_auto_20250303_1500.py | 39 + .../migrations/0066_auto_20250306_1106.py | 39 + .../migrations/0067_auto_20250525_1503.py | 39 + .../migrations/0068_auto_20250525_1504.py | 39 + .../migrations/0069_auto_20250525_1505.py | 39 + .../migrations/0070_auto_20250527_1154.py | 39 + .../migrations/0071_auto_20250601_1023.py | 39 + .../migrations/0072_auto_20250901_1207.py | 39 + .../migrations/0073_auto_20250920_1257.py | 39 + .../migrations/0074_auto_20251028_0856.py | 39 + .../migrations/0075_auto_20251029_1055.py | 39 + .../migrations/0076_auto_20251104_1340.py | 54 + .../migrations/0077_auto_20251110_1100.py | 39 + .../migrations/0078_auto_20251208_1617.py | 39 + .../migrations/0079_auto_20251213_1632.py | 44 + .../migrations/0080_auto_20251214_1635.py | 39 + .../migrations/0081_auto_20251217_1648.py | 39 + authentication/migrations/__init__.py | 0 authentication/models.py | 548 + authentication/permission_views.py | 75 + authentication/permissions.py | 329 + authentication/register.py | 4427 ++ authentication/sahandsms/__init__.py | 0 authentication/sahandsms/sms.py | 590 + authentication/serializer/__init__.py | 0 authentication/serializer/serializer.py | 308 + authentication/serializers.py | 106 + authentication/sms_management.py | 3070 ++ authentication/tests.py | 3 + authentication/urls.py | 235 + authentication/views.py | 3163 ++ bot_eata.py | 1855 + cancel_bar_and_provice_request.py | 12 + cron_gid.py | 14 + cron_out_province_request.py | 15 + cron_report.py | 15 + cron_return_archive.py | 11 + cron_send_sms_from_notif.py | 11 + cron_seven_am.py | 19 + cron_sms.py | 16 + delete_kill_request_cron.py | 12 + deposit_id.py | 25 + deposit_percent.py | 13 + docker-compose.yml | 7 + every_12_hours.py | 16 + general_urls.py | 11 + helper_eata.py | 3 + main.py | 16 + manage.py | 22 + notification/__init__.py | 0 notification/admin.py | 3 + notification/apps.py | 6 + notification/consumers.py | 48 + notification/middleware.py | 56 + notification/migrations/0001_initial.py | 115 + .../migrations/0002_auto_20250121_0857.py | 39 + .../migrations/0003_dashboardnotification.py | 38 + .../0004_alter_dashboardnotification_role.py | 19 + notification/migrations/__init__.py | 0 notification/models.py | 151 + notification/najva/__init__.py | 0 notification/najva/get_segments_detail.py | 17 + notification/najva/send_notif_to_segments.py | 75 + notification/najva_views.py | 159 + notification/notify.py | 25 + notification/pushe/__init__.py | 0 notification/pushe/constants.py | 3 + .../pushe/send_custom_content_notification.py | 53 + .../pushe/send_filtered_notification.py | 54 + .../pushe/send_notification_with_action.py | 67 + .../pushe/send_simple_notification.py | 52 + .../pushe/send_transactional_notification.py | 57 + notification/routing.py | 7 + notification/serializers.py | 27 + notification/signals.py | 16 + notification/tests.py | 3 + notification/urls.py | 16 + notification/views.py | 103 + panel/CityOperator/__init__.py | 0 panel/CityOperator/helpers.py | 456 + panel/CityOperator/serializers.py | 138 + panel/CityOperator/views.py | 666 + panel/KillHouse/__init__.py | 0 panel/KillHouse/excel_processing.py | 19548 ++++++++ panel/KillHouse/helpers.py | 2034 + panel/KillHouse/serializers.py | 6036 +++ panel/KillHouse/views.py | 19742 ++++++++ panel/ProvinceOperator/__init__.py | 0 panel/ProvinceOperator/excel_processing.py | 25023 ++++++++++ panel/ProvinceOperator/helpers.py | 284 + panel/ProvinceOperator/serializers.py | 6380 +++ panel/ProvinceOperator/services/__init__.py | 0 .../services/pos_transfer_service.py | 71 + panel/ProvinceOperator/views.py | 27737 +++++++++++ panel/ReportingPanel/__init__.py | 0 panel/ReportingPanel/excel_output.py | 174 + panel/ReportingPanel/filterset.py | 61 + panel/ReportingPanel/helper.py | 173 + panel/ReportingPanel/models.py | 10 + panel/ReportingPanel/serializer.py | 1873 + panel/ReportingPanel/views.py | 8959 ++++ panel/VetFarm/__init__.py | 0 panel/VetFarm/excel_processing.py | 679 + panel/VetFarm/helpers.py | 260 + panel/VetFarm/serializers.py | 190 + panel/VetFarm/views.py | 452 + panel/__init__.py | 0 panel/admin.py | 4 + panel/apps.py | 6 + panel/convert_date.py | 80 + panel/excel_processing.py | 38244 ++++++++++++++++ panel/filterset.py | 646 + panel/helper.py | 255 + panel/helper_excel.py | 538 + panel/management/__init__.py | 0 panel/management/commands/__init__.py | 0 .../management/commands/function_executor.py | 215 + panel/management/timing_function.py | 26 + panel/merge_database.py | 402 + panel/migrations/0001_initial.py | 3101 ++ panel/migrations/0002_auto_20230918_2031.py | 99 + panel/migrations/0003_auto_20230918_2035.py | 63 + panel/migrations/0004_auto_20230918_2110.py | 114 + panel/migrations/0005_auto_20230919_0035.py | 64 + panel/migrations/0006_auto_20230923_1311.py | 75 + panel/migrations/0007_auto_20230926_0954.py | 64 + panel/migrations/0008_auto_20230926_1440.py | 64 + panel/migrations/0009_auto_20230927_1033.py | 64 + panel/migrations/0010_auto_20230927_1047.py | 64 + panel/migrations/0011_auto_20230927_1416.py | 64 + panel/migrations/0012_auto_20230927_1554.py | 96 + panel/migrations/0013_auto_20230928_1502.py | 69 + panel/migrations/0014_auto_20231002_1157.py | 69 + panel/migrations/0015_auto_20231002_1201.py | 69 + panel/migrations/0016_auto_20231004_1101.py | 96 + panel/migrations/0017_auto_20231004_1452.py | 69 + panel/migrations/0018_auto_20231004_1508.py | 64 + panel/migrations/0019_auto_20231004_1528.py | 82 + panel/migrations/0020_auto_20231004_1539.py | 59 + panel/migrations/0021_auto_20231004_1552.py | 64 + panel/migrations/0022_auto_20231005_0439.py | 84 + panel/migrations/0023_auto_20231007_1338.py | 64 + panel/migrations/0024_auto_20231009_1240.py | 65 + panel/migrations/0025_auto_20231010_1249.py | 79 + panel/migrations/0026_auto_20231011_1337.py | 96 + panel/migrations/0027_auto_20231015_1349.py | 69 + panel/migrations/0028_auto_20231016_1211.py | 69 + panel/migrations/0029_auto_20231017_1511.py | 64 + panel/migrations/0030_auto_20231028_1327.py | 82 + panel/migrations/0031_auto_20231031_1233.py | 74 + panel/migrations/0032_auto_20231031_1509.py | 64 + panel/migrations/0033_auto_20231101_1240.py | 69 + panel/migrations/0034_auto_20231103_1509.py | 64 + panel/migrations/0035_auto_20231104_1118.py | 69 + panel/migrations/0036_auto_20231105_1224.py | 64 + panel/migrations/0037_auto_20231106_1225.py | 90 + panel/migrations/0038_auto_20231106_1546.py | 65 + panel/migrations/0039_auto_20231108_1156.py | 70 + panel/migrations/0040_auto_20231111_1426.py | 69 + panel/migrations/0041_auto_20231112_2305.py | 64 + panel/migrations/0042_auto_20231114_0930.py | 59 + panel/migrations/0043_auto_20231122_1203.py | 69 + panel/migrations/0044_auto_20231126_1221.py | 104 + panel/migrations/0045_auto_20231126_2005.py | 67 + panel/migrations/0046_auto_20231126_2030.py | 74 + panel/migrations/0047_auto_20231127_1018.py | 64 + panel/migrations/0048_auto_20231127_1404.py | 64 + panel/migrations/0049_auto_20231127_1506.py | 69 + panel/migrations/0050_auto_20231129_1029.py | 70 + panel/migrations/0051_auto_20231129_1452.py | 74 + panel/migrations/0052_auto_20231129_1539.py | 69 + panel/migrations/0053_auto_20231201_1759.py | 69 + panel/migrations/0053_auto_20231202_1108.py | 84 + panel/migrations/0054_auto_20231201_2242.py | 74 + ...o_20231202_1108_0054_auto_20231201_2242.py | 14 + panel/migrations/0056_auto_20231202_2323.py | 69 + panel/migrations/0057_auto_20231205_1256.py | 84 + panel/migrations/0058_auto_20231210_1253.py | 64 + panel/migrations/0059_auto_20231210_1400.py | 64 + panel/migrations/0060_auto_20231211_0917.py | 79 + panel/migrations/0061_auto_20231211_1102.py | 108 + panel/migrations/0062_auto_20231211_1209.py | 64 + panel/migrations/0063_auto_20231212_1000.py | 84 + panel/migrations/0064_auto_20231212_1035.py | 65 + panel/migrations/0065_auto_20231214_1409.py | 83 + panel/migrations/0066_auto_20231214_1418.py | 66 + panel/migrations/0067_auto_20231216_1015.py | 80 + panel/migrations/0068_auto_20231216_1030.py | 74 + panel/migrations/0069_auto_20231216_1448.py | 69 + panel/migrations/0070_auto_20231216_2041.py | 64 + panel/migrations/0071_auto_20231225_1502.py | 64 + panel/migrations/0072_auto_20231226_1543.py | 64 + panel/migrations/0073_auto_20231227_1020.py | 132 + panel/migrations/0074_auto_20231227_1520.py | 64 + panel/migrations/0075_auto_20231228_1158.py | 64 + panel/migrations/0076_auto_20231230_0919.py | 59 + panel/migrations/0077_auto_20240102_0907.py | 84 + panel/migrations/0078_auto_20240102_1009.py | 65 + panel/migrations/0079_auto_20240102_1253.py | 79 + panel/migrations/0080_auto_20240103_1246.py | 97 + panel/migrations/0081_auto_20240103_1417.py | 64 + panel/migrations/0082_auto_20240103_1455.py | 68 + panel/migrations/0083_auto_20240107_1039.py | 79 + panel/migrations/0084_auto_20240107_1133.py | 94 + panel/migrations/0085_auto_20240107_1325.py | 63 + panel/migrations/0086_auto_20240107_2228.py | 81 + panel/migrations/0087_auto_20240107_2243.py | 75 + panel/migrations/0088_auto_20240108_0954.py | 64 + panel/migrations/0089_auto_20240108_1100.py | 79 + panel/migrations/0090_auto_20240108_1137.py | 64 + panel/migrations/0091_auto_20240108_2134.py | 64 + panel/migrations/0092_auto_20240108_2257.py | 64 + panel/migrations/0093_auto_20240108_2352.py | 81 + panel/migrations/0094_auto_20240109_1042.py | 99 + panel/migrations/0095_auto_20240110_0238.py | 109 + panel/migrations/0096_auto_20240111_1559.py | 64 + panel/migrations/0097_auto_20240114_1305.py | 64 + panel/migrations/0098_auto_20240114_1343.py | 69 + panel/migrations/0099_auto_20240115_1039.py | 64 + panel/migrations/0100_auto_20240118_1118.py | 64 + panel/migrations/0101_auto_20240121_1159.py | 69 + panel/migrations/0102_auto_20240123_1234.py | 108 + panel/migrations/0103_auto_20240127_0916.py | 69 + panel/migrations/0104_auto_20240130_1008.py | 95 + panel/migrations/0105_auto_20240205_1011.py | 64 + panel/migrations/0106_auto_20240206_1500.py | 70 + panel/migrations/0107_auto_20240206_1510.py | 64 + panel/migrations/0108_auto_20240207_1006.py | 73 + panel/migrations/0109_auto_20240214_0923.py | 79 + panel/migrations/0110_auto_20240214_1029.py | 64 + panel/migrations/0111_auto_20240220_0856.py | 84 + panel/migrations/0112_auto_20240220_1341.py | 85 + panel/migrations/0113_auto_20240221_1105.py | 82 + panel/migrations/0114_auto_20240221_1306.py | 85 + panel/migrations/0115_auto_20240221_1314.py | 64 + panel/migrations/0116_auto_20240221_1317.py | 69 + panel/migrations/0117_auto_20240221_1520.py | 69 + panel/migrations/0118_auto_20240222_1235.py | 64 + panel/migrations/0119_auto_20240222_1346.py | 64 + panel/migrations/0120_auto_20240222_1432.py | 64 + panel/migrations/0121_auto_20240226_1343.py | 64 + panel/migrations/0122_auto_20240226_1524.py | 99 + panel/migrations/0123_auto_20240227_1159.py | 69 + panel/migrations/0124_auto_20240303_1034.py | 64 + panel/migrations/0125_auto_20240303_1044.py | 64 + panel/migrations/0126_auto_20240303_1103.py | 64 + panel/migrations/0127_auto_20240309_1046.py | 89 + panel/migrations/0128_auto_20240311_1159.py | 64 + panel/migrations/0129_auto_20240311_1555.py | 83 + panel/migrations/0130_auto_20240312_1158.py | 64 + panel/migrations/0131_auto_20240315_2202.py | 80 + panel/migrations/0132_auto_20240318_1139.py | 64 + panel/migrations/0133_auto_20240409_1145.py | 770 + panel/migrations/0134_auto_20240409_1202.py | 70 + panel/migrations/0135_auto_20240409_1220.py | 68 + panel/migrations/0136_auto_20240413_1322.py | 88 + panel/migrations/0137_auto_20240414_1050.py | 64 + panel/migrations/0138_auto_20240414_1206.py | 99 + panel/migrations/0139_auto_20240416_1440.py | 104 + panel/migrations/0140_auto_20240417_1103.py | 83 + panel/migrations/0141_auto_20240417_1257.py | 64 + panel/migrations/0142_auto_20240418_1428.py | 64 + panel/migrations/0143_auto_20240418_1550.py | 64 + panel/migrations/0144_auto_20240420_0033.py | 84 + panel/migrations/0145_auto_20240420_1517.py | 81 + panel/migrations/0146_auto_20240427_1357.py | 64 + panel/migrations/0147_auto_20240428_1211.py | 64 + panel/migrations/0148_auto_20240429_1110.py | 79 + panel/migrations/0149_auto_20240429_1131.py | 65 + panel/migrations/0150_auto_20240430_1203.py | 83 + panel/migrations/0151_auto_20240430_1327.py | 69 + panel/migrations/0152_auto_20240506_1344.py | 99 + panel/migrations/0153_auto_20240506_1401.py | 69 + panel/migrations/0154_auto_20240506_1502.py | 79 + panel/migrations/0155_auto_20240507_1044.py | 64 + panel/migrations/0156_auto_20240507_1105.py | 63 + panel/migrations/0157_auto_20240507_1110.py | 64 + panel/migrations/0158_auto_20240507_2243.py | 64 + panel/migrations/0159_auto_20240507_2343.py | 64 + panel/migrations/0160_auto_20240508_1019.py | 69 + panel/migrations/0161_auto_20240508_1203.py | 69 + panel/migrations/0162_auto_20240511_1129.py | 106 + panel/migrations/0163_auto_20240511_1312.py | 76 + panel/migrations/0164_auto_20240512_1109.py | 69 + panel/migrations/0165_auto_20240513_1219.py | 82 + panel/migrations/0166_auto_20240513_1255.py | 69 + panel/migrations/0167_auto_20240513_1256.py | 64 + panel/migrations/0168_auto_20240515_1153.py | 79 + panel/migrations/0169_auto_20240515_1301.py | 64 + panel/migrations/0170_auto_20240515_1453.py | 85 + panel/migrations/0171_auto_20240515_1549.py | 62 + panel/migrations/0172_auto_20240515_2306.py | 74 + panel/migrations/0173_auto_20240515_2310.py | 139 + panel/migrations/0174_auto_20240515_2326.py | 64 + panel/migrations/0175_auto_20240516_0015.py | 154 + panel/migrations/0176_auto_20240516_1132.py | 82 + panel/migrations/0177_auto_20240516_1320.py | 83 + panel/migrations/0178_auto_20240517_1337.py | 119 + panel/migrations/0179_auto_20240517_1352.py | 109 + panel/migrations/0180_auto_20240517_2240.py | 99 + panel/migrations/0181_auto_20240521_1033.py | 69 + panel/migrations/0182_auto_20240521_1054.py | 64 + panel/migrations/0183_auto_20240523_1653.py | 64 + panel/migrations/0184_auto_20240525_1028.py | 69 + panel/migrations/0185_auto_20240528_1234.py | 69 + panel/migrations/0186_auto_20240604_1332.py | 110 + panel/migrations/0187_auto_20240605_1034.py | 134 + panel/migrations/0188_auto_20240605_1220.py | 64 + panel/migrations/0189_auto_20240605_1844.py | 64 + panel/migrations/0190_auto_20240606_1050.py | 64 + panel/migrations/0191_auto_20240606_1122.py | 64 + panel/migrations/0192_auto_20240608_1038.py | 75 + panel/migrations/0193_auto_20240608_2310.py | 64 + panel/migrations/0194_auto_20240608_2326.py | 82 + panel/migrations/0195_auto_20240611_0019.py | 65 + panel/migrations/0196_auto_20240612_0051.py | 84 + panel/migrations/0197_auto_20240612_1118.py | 91 + panel/migrations/0198_auto_20240612_1230.py | 69 + panel/migrations/0199_auto_20240612_1137.py | 94 + panel/migrations/0200_auto_20240613_1037.py | 64 + panel/migrations/0201_auto_20240613_1106.py | 70 + panel/migrations/0202_auto_20240613_1043.py | 64 + panel/migrations/0203_auto_20240613_1101.py | 70 + panel/migrations/0204_auto_20240616_0110.py | 65 + panel/migrations/0205_auto_20240616_0956.py | 84 + panel/migrations/0206_auto_20240617_1954.py | 64 + panel/migrations/0207_auto_20240618_1054.py | 64 + panel/migrations/0208_auto_20240618_1417.py | 74 + panel/migrations/0209_auto_20240618_1451.py | 66 + panel/migrations/0210_auto_20240619_1119.py | 89 + panel/migrations/0211_auto_20240619_1701.py | 64 + panel/migrations/0212_auto_20240620_1006.py | 64 + panel/migrations/0213_auto_20240622_1055.py | 74 + panel/migrations/0214_auto_20240622_1153.py | 69 + panel/migrations/0215_auto_20240622_1158.py | 63 + panel/migrations/0216_auto_20240622_1229.py | 91 + panel/migrations/0217_auto_20240622_1622.py | 64 + panel/migrations/0218_auto_20240624_1409.py | 64 + panel/migrations/0219_auto_20240629_1100.py | 64 + panel/migrations/0220_auto_20240629_1118.py | 80 + panel/migrations/0221_auto_20240629_1150.py | 70 + panel/migrations/0222_auto_20240630_1147.py | 117 + panel/migrations/0223_auto_20240630_1148.py | 64 + panel/migrations/0224_auto_20240630_1351.py | 80 + panel/migrations/0225_auto_20240630_1443.py | 64 + panel/migrations/0226_auto_20240701_1553.py | 64 + panel/migrations/0227_auto_20240702_1406.py | 79 + panel/migrations/0228_auto_20240702_1417.py | 69 + panel/migrations/0229_auto_20240702_1510.py | 64 + panel/migrations/0230_auto_20240703_0926.py | 64 + panel/migrations/0231_auto_20240703_1036.py | 71 + panel/migrations/0232_auto_20240703_1101.py | 64 + panel/migrations/0233_auto_20240703_1419.py | 64 + panel/migrations/0234_auto_20240703_1555.py | 69 + panel/migrations/0235_auto_20240706_1424.py | 80 + panel/migrations/0236_auto_20240706_1520.py | 64 + panel/migrations/0237_auto_20240706_1652.py | 117 + panel/migrations/0238_auto_20240707_1153.py | 64 + panel/migrations/0239_auto_20240708_1341.py | 80 + panel/migrations/0240_auto_20240709_1204.py | 159 + panel/migrations/0241_auto_20240710_1333.py | 69 + panel/migrations/0242_auto_20240713_0951.py | 84 + panel/migrations/0243_auto_20240713_1024.py | 84 + panel/migrations/0244_auto_20240713_1139.py | 80 + panel/migrations/0245_auto_20240713_1236.py | 87 + panel/migrations/0246_auto_20240713_1250.py | 89 + panel/migrations/0247_auto_20240713_1516.py | 90 + panel/migrations/0248_auto_20240717_1145.py | 69 + panel/migrations/0249_auto_20240717_1208.py | 94 + panel/migrations/0250_auto_20240717_1306.py | 69 + panel/migrations/0251_auto_20240717_1332.py | 81 + panel/migrations/0252_auto_20240717_1350.py | 64 + panel/migrations/0253_auto_20240718_1206.py | 64 + panel/migrations/0254_auto_20240718_1303.py | 79 + panel/migrations/0255_auto_20240720_1218.py | 64 + panel/migrations/0256_auto_20240724_1147.py | 64 + panel/migrations/0257_auto_20240725_1040.py | 74 + panel/migrations/0258_auto_20240725_1112.py | 69 + panel/migrations/0259_auto_20240727_1222.py | 64 + panel/migrations/0260_auto_20240731_2252.py | 69 + panel/migrations/0261_auto_20240802_1111.py | 70 + panel/migrations/0262_auto_20240803_1121.py | 88 + panel/migrations/0263_auto_20240803_1509.py | 74 + panel/migrations/0264_auto_20240803_1523.py | 64 + panel/migrations/0265_auto_20240803_1527.py | 65 + panel/migrations/0266_auto_20240804_1011.py | 64 + panel/migrations/0267_auto_20240804_1406.py | 70 + panel/migrations/0268_auto_20240804_2127.py | 74 + panel/migrations/0269_auto_20240804_2128.py | 74 + panel/migrations/0270_auto_20240806_2324.py | 64 + panel/migrations/0271_auto_20240808_1144.py | 70 + panel/migrations/0272_auto_20240808_1209.py | 95 + panel/migrations/0273_auto_20240808_1410.py | 80 + panel/migrations/0274_auto_20240809_1838.py | 228 + panel/migrations/0275_auto_20240809_1850.py | 64 + panel/migrations/0276_auto_20240810_0922.py | 191 + panel/migrations/0277_auto_20240810_0928.py | 224 + panel/migrations/0278_auto_20240810_1357.py | 95 + panel/migrations/0279_auto_20240811_1102.py | 79 + panel/migrations/0280_auto_20240812_1015.py | 63 + panel/migrations/0281_auto_20240812_1015.py | 64 + panel/migrations/0282_auto_20240812_1349.py | 64 + panel/migrations/0283_auto_20240813_0921.py | 79 + panel/migrations/0284_auto_20240814_1007.py | 69 + panel/migrations/0285_auto_20240814_1017.py | 64 + panel/migrations/0286_auto_20240815_1337.py | 69 + panel/migrations/0287_auto_20240817_1040.py | 69 + panel/migrations/0288_auto_20240817_1052.py | 80 + panel/migrations/0289_auto_20240819_1141.py | 64 + panel/migrations/0290_auto_20240819_1227.py | 63 + panel/migrations/0291_auto_20240819_1233.py | 64 + panel/migrations/0292_auto_20240819_1325.py | 79 + panel/migrations/0293_auto_20240820_1038.py | 83 + panel/migrations/0294_auto_20240821_0917.py | 64 + panel/migrations/0295_auto_20240821_1000.py | 64 + panel/migrations/0296_auto_20240826_1223.py | 79 + panel/migrations/0297_auto_20240828_1203.py | 82 + panel/migrations/0298_auto_20240828_1410.py | 67 + panel/migrations/0299_auto_20240828_1416.py | 75 + panel/migrations/0300_auto_20240829_0958.py | 64 + panel/migrations/0301_auto_20240829_1025.py | 69 + panel/migrations/0302_auto_20240830_1023.py | 59 + panel/migrations/0303_auto_20240830_1033.py | 59 + panel/migrations/0304_auto_20240830_1033.py | 59 + panel/migrations/0305_auto_20240831_1000.py | 69 + panel/migrations/0306_auto_20240907_1020.py | 59 + panel/migrations/0307_auto_20240911_1147.py | 81 + panel/migrations/0308_auto_20240912_0926.py | 87 + panel/migrations/0309_auto_20240912_1121.py | 103 + panel/migrations/0310_auto_20240912_1211.py | 69 + panel/migrations/0311_auto_20240914_1038.py | 79 + panel/migrations/0312_auto_20240915_1241.py | 75 + panel/migrations/0313_auto_20241005_1310.py | 79 + panel/migrations/0314_auto_20241012_1226.py | 129 + panel/migrations/0315_auto_20241015_1027.py | 63 + panel/migrations/0316_auto_20241015_1036.py | 64 + panel/migrations/0317_auto_20241017_1226.py | 64 + panel/migrations/0318_auto_20241022_1026.py | 79 + panel/migrations/0319_auto_20241022_1028.py | 64 + panel/migrations/0320_auto_20241023_1309.py | 84 + panel/migrations/0321_auto_20241023_1326.py | 64 + panel/migrations/0322_auto_20241024_0931.py | 64 + panel/migrations/0323_auto_20241024_2016.py | 78 + panel/migrations/0324_auto_20241024_2018.py | 79 + panel/migrations/0325_auto_20241024_2018.py | 59 + panel/migrations/0326_auto_20241026_0950.py | 69 + panel/migrations/0327_auto_20241026_1309.py | 64 + panel/migrations/0328_auto_20241029_1116.py | 93 + panel/migrations/0329_auto_20241103_0927.py | 64 + panel/migrations/0330_auto_20241103_0936.py | 63 + panel/migrations/0331_auto_20241103_0938.py | 64 + panel/migrations/0332_auto_20241103_0939.py | 64 + panel/migrations/0333_auto_20241103_0947.py | 63 + panel/migrations/0334_auto_20241104_1433.py | 324 + panel/migrations/0335_auto_20241104_2248.py | 89 + panel/migrations/0336_auto_20241105_0834.py | 69 + panel/migrations/0337_auto_20241105_2335.py | 83 + panel/migrations/0338_auto_20241106_1605.py | 65 + panel/migrations/0339_auto_20241107_1047.py | 63 + panel/migrations/0340_auto_20241107_1055.py | 65 + panel/migrations/0341_auto_20241107_1450.py | 63 + panel/migrations/0342_auto_20241107_1456.py | 65 + panel/migrations/0343_auto_20241108_1518.py | 63 + panel/migrations/0344_auto_20241108_1527.py | 65 + panel/migrations/0345_auto_20241108_1547.py | 63 + panel/migrations/0346_auto_20241108_1552.py | 65 + panel/migrations/0347_auto_20241109_1406.py | 73 + panel/migrations/0348_auto_20241109_1421.py | 64 + panel/migrations/0349_auto_20241109_1506.py | 66 + panel/migrations/0350_auto_20241109_1555.py | 64 + panel/migrations/0351_auto_20241109_2036.py | 69 + panel/migrations/0352_auto_20241110_1035.py | 64 + panel/migrations/0353_auto_20241110_1345.py | 69 + panel/migrations/0354_auto_20241110_1354.py | 77 + panel/migrations/0355_auto_20241110_2306.py | 64 + panel/migrations/0356_auto_20241112_1250.py | 82 + panel/migrations/0357_auto_20241112_1332.py | 64 + panel/migrations/0358_auto_20241112_1459.py | 64 + panel/migrations/0359_auto_20241112_1511.py | 63 + panel/migrations/0360_auto_20241113_1050.py | 59 + panel/migrations/0361_auto_20241113_1058.py | 63 + panel/migrations/0362_auto_20241113_1102.py | 64 + panel/migrations/0363_auto_20241114_1345.py | 64 + panel/migrations/0364_auto_20241115_1217.py | 69 + panel/migrations/0365_auto_20241116_0944.py | 69 + panel/migrations/0366_auto_20241116_1121.py | 74 + panel/migrations/0367_auto_20241116_1144.py | 67 + panel/migrations/0368_auto_20241116_1148.py | 64 + panel/migrations/0369_auto_20241117_1013.py | 85 + panel/migrations/0370_auto_20241117_1020.py | 64 + panel/migrations/0371_auto_20241117_1545.py | 89 + panel/migrations/0372_auto_20241117_2222.py | 99 + panel/migrations/0373_auto_20241118_0811.py | 64 + panel/migrations/0374_auto_20241118_0946.py | 82 + panel/migrations/0375_auto_20241118_1054.py | 69 + panel/migrations/0376_auto_20241118_2152.py | 379 + panel/migrations/0377_auto_20241118_2157.py | 69 + panel/migrations/0378_auto_20241118_2317.py | 134 + panel/migrations/0379_auto_20241120_0810.py | 64 + panel/migrations/0380_auto_20241126_1028.py | 82 + panel/migrations/0381_auto_20241126_1047.py | 64 + panel/migrations/0382_auto_20241126_1606.py | 64 + panel/migrations/0383_auto_20241127_0958.py | 79 + panel/migrations/0384_auto_20241130_1018.py | 119 + panel/migrations/0385_auto_20241130_1048.py | 114 + panel/migrations/0386_auto_20241130_1830.py | 69 + panel/migrations/0387_auto_20241130_1836.py | 59 + panel/migrations/0388_auto_20241130_1902.py | 69 + panel/migrations/0389_auto_20241130_2009.py | 64 + panel/migrations/0390_auto_20241203_0901.py | 64 + panel/migrations/0391_auto_20241203_0935.py | 63 + panel/migrations/0392_auto_20241203_0946.py | 64 + panel/migrations/0393_auto_20241204_1334.py | 93 + panel/migrations/0394_auto_20241204_1357.py | 69 + panel/migrations/0395_auto_20241207_1034.py | 79 + panel/migrations/0396_auto_20241208_1147.py | 104 + panel/migrations/0397_auto_20241209_1422.py | 69 + panel/migrations/0398_auto_20241211_0956.py | 80 + panel/migrations/0399_auto_20241211_1115.py | 64 + panel/migrations/0400_auto_20241214_1358.py | 79 + panel/migrations/0401_auto_20241215_1031.py | 90 + panel/migrations/0402_auto_20241215_1139.py | 64 + panel/migrations/0403_auto_20241215_1458.py | 66 + panel/migrations/0404_auto_20241216_1214.py | 65 + panel/migrations/0405_auto_20241216_1524.py | 69 + panel/migrations/0406_auto_20241216_1532.py | 64 + panel/migrations/0407_auto_20241216_1625.py | 74 + panel/migrations/0408_auto_20241218_1435.py | 64 + panel/migrations/0409_auto_20241221_1150.py | 116 + panel/migrations/0410_auto_20241221_1258.py | 74 + panel/migrations/0411_auto_20241221_1357.py | 75 + panel/migrations/0412_auto_20241221_1535.py | 74 + panel/migrations/0413_auto_20241222_1203.py | 74 + panel/migrations/0414_auto_20241223_1441.py | 95 + panel/migrations/0415_auto_20241223_1547.py | 91 + panel/migrations/0416_auto_20241225_1417.py | 79 + panel/migrations/0417_auto_20241231_1523.py | 79 + panel/migrations/0418_auto_20241231_2121.py | 92 + panel/migrations/0419_auto_20250106_1612.py | 75 + panel/migrations/0420_auto_20250107_1233.py | 75 + panel/migrations/0421_auto_20250107_1807.py | 79 + panel/migrations/0422_auto_20250112_1004.py | 94 + panel/migrations/0423_auto_20250112_1550.py | 94 + panel/migrations/0424_auto_20250113_1532.py | 75 + panel/migrations/0425_auto_20250119_1410.py | 80 + panel/migrations/0426_auto_20250120_0929.py | 73 + panel/migrations/0427_auto_20250120_0941.py | 74 + panel/migrations/0428_auto_20250120_1638.py | 149 + panel/migrations/0429_auto_20250121_0857.py | 133 + panel/migrations/0430_auto_20250125_1225.py | 95 + panel/migrations/0431_auto_20250127_1622.py | 111 + panel/migrations/0432_auto_20250201_1449.py | 74 + panel/migrations/0433_auto_20250205_1303.py | 75 + panel/migrations/0434_auto_20250209_0918.py | 74 + panel/migrations/0435_auto_20250209_1024.py | 95 + panel/migrations/0436_auto_20250210_1938.py | 109 + panel/migrations/0437_auto_20250211_1410.py | 74 + panel/migrations/0438_auto_20250212_0900.py | 89 + panel/migrations/0439_auto_20250212_0957.py | 85 + panel/migrations/0440_auto_20250212_1003.py | 89 + panel/migrations/0441_auto_20250212_1455.py | 108 + panel/migrations/0442_auto_20250216_1014.py | 104 + panel/migrations/0443_auto_20250217_1419.py | 84 + panel/migrations/0444_auto_20250217_1557.py | 98 + panel/migrations/0445_auto_20250217_1707.py | 74 + panel/migrations/0446_auto_20250218_0853.py | 84 + panel/migrations/0447_auto_20250218_1015.py | 74 + panel/migrations/0448_auto_20250222_1023.py | 94 + panel/migrations/0449_auto_20250222_1112.py | 74 + panel/migrations/0450_auto_20250222_1636.py | 74 + panel/migrations/0451_auto_20250223_0958.py | 79 + panel/migrations/0452_auto_20250223_1001.py | 77 + panel/migrations/0453_auto_20250223_1005.py | 74 + panel/migrations/0454_auto_20250223_1006.py | 79 + panel/migrations/0455_auto_20250223_1128.py | 74 + panel/migrations/0456_auto_20250224_1320.py | 72 + panel/migrations/0457_auto_20250224_1322.py | 76 + panel/migrations/0458_auto_20250225_1118.py | 98 + panel/migrations/0459_auto_20250225_1144.py | 74 + panel/migrations/0460_auto_20250226_0937.py | 74 + panel/migrations/0461_auto_20250302_1203.py | 69 + panel/migrations/0462_auto_20250302_1351.py | 69 + panel/migrations/0463_auto_20250302_1458.py | 69 + panel/migrations/0464_auto_20250302_1628.py | 81 + panel/migrations/0465_auto_20250303_1205.py | 76 + panel/migrations/0466_auto_20250303_1315.py | 84 + panel/migrations/0467_auto_20250303_1500.py | 69 + panel/migrations/0468_auto_20250304_1730.py | 74 + panel/migrations/0469_auto_20250305_1330.py | 69 + panel/migrations/0470_auto_20250307_1650.py | 74 + panel/migrations/0471_auto_20250316_2255.py | 89 + panel/migrations/0472_auto_20250413_1442.py | 89 + panel/migrations/0473_auto_20250413_1557.py | 79 + panel/migrations/0474_auto_20250414_1231.py | 74 + panel/migrations/0475_auto_20250414_1710.py | 74 + panel/migrations/0476_auto_20250420_1106.py | 74 + panel/migrations/0477_auto_20250420_1108.py | 74 + panel/migrations/0478_auto_20250428_1358.py | 74 + panel/migrations/0479_auto_20250503_1400.py | 96 + panel/migrations/0480_auto_20250504_1149.py | 90 + panel/migrations/0481_auto_20250504_1207.py | 74 + panel/migrations/0482_auto_20250505_1431.py | 79 + panel/migrations/0483_auto_20250506_1054.py | 74 + panel/migrations/0484_auto_20250510_1211.py | 84 + panel/migrations/0485_auto_20250511_1456.py | 74 + panel/migrations/0486_auto_20250517_0910.py | 74 + panel/migrations/0487_auto_20250517_1602.py | 79 + panel/migrations/0488_auto_20250517_1701.py | 79 + panel/migrations/0489_auto_20250518_1144.py | 74 + panel/migrations/0490_auto_20250520_1132.py | 74 + panel/migrations/0491_auto_20250525_1503.py | 69 + panel/migrations/0492_auto_20250525_1504.py | 69 + panel/migrations/0493_auto_20250525_1505.py | 69 + panel/migrations/0494_auto_20250526_0939.py | 103 + panel/migrations/0495_auto_20250526_1214.py | 84 + panel/migrations/0496_auto_20250526_1440.py | 94 + panel/migrations/0497_auto_20250527_0854.py | 74 + panel/migrations/0498_auto_20250527_1032.py | 74 + panel/migrations/0499_auto_20250528_1132.py | 93 + panel/migrations/0500_auto_20250528_1140.py | 84 + panel/migrations/0501_auto_20250528_1554.py | 84 + panel/migrations/0502_auto_20250531_1005.py | 74 + panel/migrations/0503_auto_20250531_1207.py | 84 + panel/migrations/0504_auto_20250531_1249.py | 74 + panel/migrations/0505_auto_20250531_1332.py | 74 + panel/migrations/0506_auto_20250531_1344.py | 73 + panel/migrations/0507_auto_20250531_1433.py | 74 + panel/migrations/0508_auto_20250601_1023.py | 93 + panel/migrations/0509_auto_20250602_1504.py | 74 + panel/migrations/0510_auto_20250603_1443.py | 80 + panel/migrations/0511_auto_20250607_0938.py | 91 + panel/migrations/0512_auto_20250607_1053.py | 73 + panel/migrations/0513_auto_20250607_1502.py | 75 + panel/migrations/0514_auto_20250607_1612.py | 74 + panel/migrations/0515_auto_20250607_1624.py | 74 + panel/migrations/0516_auto_20250609_1157.py | 74 + panel/migrations/0517_auto_20250609_1435.py | 75 + panel/migrations/0518_auto_20250610_1345.py | 119 + panel/migrations/0519_auto_20250610_1345.py | 69 + panel/migrations/0520_auto_20250628_1428.py | 74 + panel/migrations/0521_auto_20250628_1502.py | 74 + panel/migrations/0522_auto_20250707_0926.py | 91 + panel/migrations/0523_auto_20250707_0959.py | 74 + panel/migrations/0524_auto_20250708_0838.py | 79 + panel/migrations/0525_auto_20250708_1018.py | 74 + panel/migrations/0526_auto_20250708_1421.py | 109 + panel/migrations/0527_auto_20250709_1112.py | 74 + panel/migrations/0528_auto_20250713_1028.py | 74 + panel/migrations/0529_auto_20250714_1045.py | 89 + panel/migrations/0530_auto_20250714_1100.py | 74 + panel/migrations/0531_auto_20250719_0857.py | 74 + panel/migrations/0532_auto_20250719_0938.py | 74 + panel/migrations/0533_auto_20250720_1445.py | 90 + panel/migrations/0534_auto_20250720_1510.py | 75 + panel/migrations/0535_auto_20250722_1133.py | 74 + panel/migrations/0536_auto_20250722_1248.py | 108 + panel/migrations/0537_auto_20250723_0917.py | 79 + panel/migrations/0538_auto_20250723_1013.py | 79 + panel/migrations/0539_auto_20250727_0734.py | 75 + panel/migrations/0540_auto_20250727_1238.py | 91 + panel/migrations/0541_auto_20250727_1453.py | 117 + panel/migrations/0542_auto_20250803_0821.py | 79 + panel/migrations/0543_auto_20250803_1532.py | 139 + panel/migrations/0544_auto_20250805_0852.py | 75 + panel/migrations/0545_auto_20250806_1515.py | 94 + panel/migrations/0546_auto_20250806_1553.py | 79 + panel/migrations/0547_auto_20250809_0949.py | 89 + panel/migrations/0548_auto_20250809_1021.py | 74 + panel/migrations/0549_auto_20250809_1237.py | 74 + panel/migrations/0550_auto_20250809_1351.py | 84 + panel/migrations/0551_auto_20250809_1409.py | 74 + panel/migrations/0552_auto_20250809_1522.py | 74 + panel/migrations/0553_auto_20250809_1613.py | 74 + panel/migrations/0554_auto_20250810_1256.py | 99 + panel/migrations/0555_auto_20250810_1354.py | 105 + panel/migrations/0556_auto_20250810_1414.py | 114 + panel/migrations/0557_auto_20250811_0909.py | 91 + panel/migrations/0558_auto_20250817_0851.py | 74 + panel/migrations/0559_auto_20250817_1014.py | 74 + panel/migrations/0560_auto_20250817_1040.py | 74 + panel/migrations/0561_auto_20250817_1048.py | 79 + panel/migrations/0562_auto_20250817_1351.py | 74 + panel/migrations/0563_auto_20250818_0941.py | 83 + panel/migrations/0564_auto_20250820_1145.py | 74 + panel/migrations/0565_auto_20250820_1530.py | 74 + panel/migrations/0566_auto_20250825_1122.py | 79 + panel/migrations/0567_auto_20250825_1535.py | 74 + panel/migrations/0568_auto_20250825_1605.py | 74 + panel/migrations/0569_auto_20250826_0913.py | 91 + panel/migrations/0570_auto_20250826_0943.py | 74 + panel/migrations/0571_auto_20250827_1013.py | 74 + panel/migrations/0572_auto_20250827_1509.py | 92 + panel/migrations/0573_auto_20250829_0135.py | 84 + panel/migrations/0574_auto_20250830_0839.py | 74 + panel/migrations/0575_auto_20250831_0913.py | 84 + panel/migrations/0576_auto_20250901_0847.py | 91 + panel/migrations/0577_auto_20250901_1207.py | 91 + panel/migrations/0578_auto_20250902_1208.py | 89 + panel/migrations/0579_auto_20250902_1540.py | 94 + panel/migrations/0580_auto_20250903_0907.py | 89 + panel/migrations/0581_auto_20250914_1103.py | 94 + panel/migrations/0582_auto_20250914_1449.py | 79 + panel/migrations/0583_auto_20250914_1621.py | 93 + panel/migrations/0584_auto_20250914_1630.py | 72 + panel/migrations/0585_auto_20250915_0902.py | 74 + panel/migrations/0586_auto_20250915_1411.py | 79 + panel/migrations/0587_auto_20250915_1433.py | 74 + panel/migrations/0588_auto_20250915_1603.py | 75 + panel/migrations/0589_auto_20250916_0935.py | 94 + panel/migrations/0590_auto_20250916_1031.py | 74 + panel/migrations/0591_auto_20250916_1427.py | 94 + panel/migrations/0592_auto_20250920_0849.py | 74 + panel/migrations/0592_auto_20250920_0938.py | 79 + ...o_20250920_0849_0592_auto_20250920_0938.py | 14 + panel/migrations/0594_auto_20250920_1257.py | 82 + panel/migrations/0595_auto_20250920_1554.py | 113 + panel/migrations/0595_auto_20250920_1648.py | 99 + ...o_20250920_1554_0595_auto_20250920_1648.py | 14 + panel/migrations/0597_auto_20250920_1652.py | 74 + panel/migrations/0598_auto_20250921_0848.py | 79 + panel/migrations/0599_auto_20250922_0840.py | 134 + panel/migrations/0600_auto_20250922_1048.py | 74 + panel/migrations/0601_auto_20250922_1333.py | 114 + panel/migrations/0602_auto_20250922_1339.py | 74 + panel/migrations/0603_auto_20250924_1347.py | 84 + panel/migrations/0604_auto_20250924_1427.py | 99 + panel/migrations/0605_auto_20250925_1046.py | 74 + panel/migrations/0606_auto_20250925_1108.py | 79 + panel/migrations/0607_auto_20250925_1345.py | 129 + panel/migrations/0608_auto_20250925_1422.py | 84 + panel/migrations/0609_auto_20250925_1501.py | 79 + panel/migrations/0610_auto_20250927_2016.py | 74 + panel/migrations/0611_auto_20250927_2020.py | 89 + panel/migrations/0612_auto_20250927_2024.py | 79 + panel/migrations/0613_auto_20250927_2026.py | 74 + panel/migrations/0614_auto_20250927_2028.py | 74 + panel/migrations/0615_auto_20250927_2041.py | 74 + panel/migrations/0616_auto_20250929_1505.py | 74 + panel/migrations/0617_auto_20250929_1856.py | 106 + panel/migrations/0618_auto_20250929_1900.py | 74 + panel/migrations/0619_auto_20250930_1003.py | 74 + panel/migrations/0620_auto_20250930_1118.py | 74 + panel/migrations/0621_auto_20251001_1123.py | 74 + panel/migrations/0622_auto_20251004_1105.py | 80 + panel/migrations/0623_auto_20251005_1416.py | 390 + panel/migrations/0624_auto_20251006_0847.py | 79 + panel/migrations/0625_auto_20251006_0905.py | 79 + panel/migrations/0626_auto_20251006_1457.py | 74 + panel/migrations/0627_auto_20251006_1554.py | 101 + panel/migrations/0628_auto_20251007_1220.py | 74 + panel/migrations/0629_auto_20251007_1443.py | 74 + panel/migrations/0630_auto_20251007_1546.py | 74 + panel/migrations/0631_auto_20251008_1014.py | 79 + panel/migrations/0632_auto_20251012_1433.py | 79 + panel/migrations/0633_auto_20251018_2111.py | 96 + panel/migrations/0634_auto_20251021_1331.py | 90 + panel/migrations/0635_auto_20251021_1408.py | 79 + panel/migrations/0636_auto_20251021_1424.py | 89 + panel/migrations/0637_auto_20251021_1531.py | 129 + panel/migrations/0638_auto_20251021_1541.py | 107 + panel/migrations/0639_auto_20251022_1518.py | 79 + panel/migrations/0640_auto_20251025_1110.py | 94 + panel/migrations/0641_auto_20251025_1116.py | 84 + panel/migrations/0642_auto_20251026_1719.py | 74 + panel/migrations/0643_auto_20251026_2043.py | 74 + panel/migrations/0644_auto_20251026_2048.py | 69 + panel/migrations/0645_auto_20251027_0917.py | 99 + panel/migrations/0646_auto_20251027_1215.py | 74 + panel/migrations/0647_auto_20251028_0856.py | 74 + panel/migrations/0648_auto_20251028_0857.py | 69 + panel/migrations/0649_auto_20251028_0940.py | 69 + .../0650_rename_trafic_to_traffic_code.py | 18 + panel/migrations/0651_auto_20251028_1219.py | 74 + panel/migrations/0652_auto_20251029_0933.py | 90 + panel/migrations/0653_auto_20251029_0954.py | 83 + panel/migrations/0654_auto_20251029_0955.py | 79 + panel/migrations/0655_auto_20251029_1055.py | 79 + panel/migrations/0656_auto_20251029_1609.py | 79 + panel/migrations/0657_auto_20251102_1322.py | 74 + panel/migrations/0658_auto_20251102_1437.py | 99 + panel/migrations/0659_auto_20251102_1614.py | 74 + panel/migrations/0660_auto_20251102_2037.py | 91 + panel/migrations/0661_auto_20251102_2044.py | 74 + panel/migrations/0662_auto_20251103_1453.py | 94 + panel/migrations/0663_auto_20251103_1525.py | 104 + panel/migrations/0664_auto_20251104_1353.py | 114 + panel/migrations/0665_auto_20251105_1111.py | 84 + panel/migrations/0666_auto_20251109_1151.py | 80 + panel/migrations/0667_auto_20251109_1443.py | 74 + panel/migrations/0668_auto_20251109_1448.py | 74 + panel/migrations/0669_auto_20251110_1001.py | 123 + panel/migrations/0670_auto_20251110_1100.py | 94 + panel/migrations/0671_auto_20251110_1101.py | 69 + panel/migrations/0672_auto_20251110_2116.py | 93 + panel/migrations/0673_auto_20251111_1150.py | 74 + panel/migrations/0674_auto_20251115_1354.py | 137 + panel/migrations/0675_auto_20251115_1509.py | 74 + panel/migrations/0676_auto_20251115_1709.py | 329 + panel/migrations/0677_auto_20251116_1459.py | 69 + panel/migrations/0678_auto_20251125_0840.py | 79 + panel/migrations/0679_auto_20251125_0843.py | 75 + panel/migrations/0680_auto_20251130_1538.py | 74 + panel/migrations/0681_auto_20251202_1539.py | 93 + panel/migrations/0682_auto_20251203_1617.py | 100 + panel/migrations/0683_auto_20251208_1617.py | 91 + panel/migrations/0684_auto_20251213_1632.py | 197 + panel/migrations/0685_auto_20251214_1635.py | 80 + panel/migrations/0686_auto_20251215_1654.py | 117 + panel/migrations/0687_auto_20251216_1653.py | 147 + panel/migrations/0688_auto_20251217_1648.py | 436 + panel/migrations/__init__.py | 0 panel/models.py | 7444 +++ panel/pos_helper.py | 263 + panel/poultry/__init__.py | 0 panel/poultry/excel_processing.py | 10772 +++++ panel/poultry/helpers.py | 304 + panel/poultry/serializers.py | 3367 ++ panel/poultry/views.py | 10383 +++++ panel/scripts/__init__.py | 0 panel/scripts/database_merge.py | 6 + panel/temp_keys.py | 430 + panel/templatetags/__init__.py | 0 panel/templatetags/jalali_filters.py | 47 + panel/tests.py | 3 + panel/urls.py | 1393 + panel/validate_headers.py | 120 + panel/views.py | 77 + pdf/__init__.py | 0 pdf/views.py | 1391 + province_orderid.py | 5 + requirements.txt | 92 + samasat_cron.py | 10 + static/assets/fonts/BNaznnBd.ttf | Bin 0 -> 60716 bytes static/assets/fonts/btitrb.ttf | Bin 0 -> 62008 bytes static/assets/fonts/nazanin.ttf | Bin 0 -> 61560 bytes static/assets/fonts/tits.ttf | Bin 0 -> 62008 bytes static/assets/img/bazrasi.png | Bin 0 -> 231264 bytes static/assets/img/bg.png | Bin 0 -> 236983 bytes static/assets/img/blue_bg.png | Bin 0 -> 235678 bytes static/assets/img/killhouse.png | Bin 0 -> 17403 bytes static/assets/img/poultry.png | Bin 0 -> 19073 bytes static/assets/img/summary_report.png | Bin 0 -> 241154 bytes static/css/styles.css | 199 + static/css/styles_for_hatching_detail.css | 284 + temp_functions.py | 382 + temp_model.txt | 17 + ...ital_agreement_for_buying_and_selling.html | 259 + templates/base.html | 17 + .../management_all_poultry_and_warehouse.html | 500 + templates/poultry_datail.html | 1485 + templates/poultry_science_report.html | 440 + templates/summary_report.html | 91 + templatetags/__init__.py | 0 templatetags/jalali_filters.py | 47 + ticket/__init__.py | 0 ticket/admin.py | 3 + ticket/apps.py | 6 + ticket/bucket.py | 97 + ticket/customer_views.py | 127 + ticket/helper.py | 75 + ticket/migrations/0001_initial.py | 150 + ticket/migrations/0002_auto_20240612_0954.py | 66 + .../0003_alter_ticketsupport_ticket_id.py | 18 + ticket/migrations/0004_auto_20240612_1936.py | 31 + .../migrations/0005_messagesupport_sender.py | 18 + ticket/migrations/0006_auto_20240615_1418.py | 35 + .../migrations/0007_ticketsupport_to_user.py | 20 + .../0008_messagesupport_send_message.py | 18 + .../migrations/0009_ticketsupport_is_read.py | 18 + .../0010_remove_ticketsupport_is_read.py | 17 + .../0011_ticketsupport_last_message.py | 18 + ticket/migrations/0012_auto_20240907_1417.py | 21 + ticket/migrations/0013_ticketpermission.py | 23 + ticket/migrations/0014_auto_20240911_0853.py | 32 + ticket/migrations/0015_auto_20240912_1105.py | 34 + .../migrations/0016_ticketsupport_picture.py | 18 + ticket/migrations/0017_auto_20240912_1118.py | 30 + ticket/migrations/0018_auto_20240912_1258.py | 24 + .../0019_remove_ticketsupport_picture.py | 17 + ticket/migrations/0020_ticketsupport_role.py | 18 + .../0021_messagesupport_last_seen.py | 18 + ticket/migrations/0022_auto_20240917_0951.py | 22 + ticket/migrations/0023_auto_20241228_0919.py | 20 + ticket/migrations/0024_ticketsupport.py | 45 + .../migrations/0025_messagesupport_ticket.py | 19 + ticket/migrations/0026_messagesupport_file.py | 18 + .../0027_ticketsupport_unread_message.py | 18 + .../migrations/0028_messagesupport_read_by.py | 19 + ticket/migrations/0029_auto_20250126_2046.py | 30 + ticket/migrations/0030_auto_20250126_2122.py | 29 + .../0031_ticketsupport_referred_date.py | 18 + .../migrations/0032_ticketclosepermission.py | 21 + ticket/migrations/__init__.py | 0 ticket/models.py | 190 + ticket/operator_views.py | 117 + ticket/serializers.py | 163 + ticket/tests.py | 3 + ticket/urls.py | 22 + ticket/views.py | 512 + 1100 files changed, 291872 insertions(+) create mode 100644 .env.local create mode 100644 .env.prod create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 GateWay.py create mode 100644 KuChicken/__init__.py create mode 100644 KuChicken/asgi.py create mode 100644 KuChicken/celery.py create mode 100644 KuChicken/settings.py create mode 100644 KuChicken/urls.py create mode 100644 KuChicken/wsgi.py create mode 100644 LiveStock/Contractor/__init__.py create mode 100644 LiveStock/Contractor/excel_processing.py create mode 100644 LiveStock/Contractor/filterset.py create mode 100644 LiveStock/Contractor/helpers.py create mode 100644 LiveStock/Contractor/serializers.py create mode 100644 LiveStock/Contractor/urls.py create mode 100644 LiveStock/Contractor/views.py create mode 100644 LiveStock/Cooperative/__init__.py create mode 100644 LiveStock/Cooperative/excel_processing.py create mode 100644 LiveStock/Cooperative/filterset.py create mode 100644 LiveStock/Cooperative/helpers.py create mode 100644 LiveStock/Cooperative/serializers.py create mode 100644 LiveStock/Cooperative/urls.py create mode 100644 LiveStock/Cooperative/views.py create mode 100644 LiveStock/Jahad/__init__.py create mode 100644 LiveStock/Jahad/excel_processing.py create mode 100644 LiveStock/Jahad/filterset.py create mode 100644 LiveStock/Jahad/helpers.py create mode 100644 LiveStock/Jahad/serializers.py create mode 100644 LiveStock/Jahad/urls.py create mode 100644 LiveStock/Jahad/views.py create mode 100644 LiveStock/LiveStoksAndPoultry/__init__.py create mode 100644 LiveStock/LiveStoksAndPoultry/excel_processing.py create mode 100644 LiveStock/LiveStoksAndPoultry/filterset.py create mode 100644 LiveStock/LiveStoksAndPoultry/helpers.py create mode 100644 LiveStock/LiveStoksAndPoultry/serializers.py create mode 100644 LiveStock/LiveStoksAndPoultry/urls.py create mode 100644 LiveStock/LiveStoksAndPoultry/views.py create mode 100644 LiveStock/Rancher/__init__.py create mode 100644 LiveStock/Rancher/excel_processing.py create mode 100644 LiveStock/Rancher/filterset.py create mode 100644 LiveStock/Rancher/helpers.py create mode 100644 LiveStock/Rancher/serializers.py create mode 100644 LiveStock/Rancher/urls.py create mode 100644 LiveStock/Rancher/views.py create mode 100644 LiveStock/Union/__init__.py create mode 100644 LiveStock/Union/excel_processing.py create mode 100644 LiveStock/Union/filterset.py create mode 100644 LiveStock/Union/helpers.py create mode 100644 LiveStock/Union/serializers.py create mode 100644 LiveStock/Union/urls.py create mode 100644 LiveStock/Union/views.py create mode 100644 LiveStock/__init__.py create mode 100644 LiveStock/admin.py create mode 100644 LiveStock/apps.py create mode 100644 LiveStock/helpers.py create mode 100644 LiveStock/migrations/0001_initial.py create mode 100644 LiveStock/migrations/0002_livestockprovincejahad_name.py create mode 100644 LiveStock/migrations/0003_auto_20250302_1254.py create mode 100644 LiveStock/migrations/0004_cooperative_union.py create mode 100644 LiveStock/migrations/0005_livestockallocations_livestockproduct_livestockrolseproduct_rancher.py create mode 100644 LiveStock/migrations/0006_auto_20250302_1627.py create mode 100644 LiveStock/migrations/0007_auto_20250303_0931.py create mode 100644 LiveStock/migrations/0008_auto_20250303_0933.py create mode 100644 LiveStock/migrations/0009_auto_20250303_1021.py create mode 100644 LiveStock/migrations/0010_livestockallocations_rancher.py create mode 100644 LiveStock/migrations/0011_remove_livestockallocations_rancher.py create mode 100644 LiveStock/migrations/0012_remove_livestockrolseproduct_rancher.py create mode 100644 LiveStock/migrations/0013_livestock.py create mode 100644 LiveStock/migrations/0014_auto_20250305_1331.py create mode 100644 LiveStock/migrations/0015_rancher_allow_buy.py create mode 100644 LiveStock/migrations/0016_auto_20250305_1701.py create mode 100644 LiveStock/migrations/0017_auto_20250306_0033.py create mode 100644 LiveStock/migrations/0018_auto_20250306_1106.py create mode 100644 LiveStock/migrations/0019_auto_20250306_1921.py create mode 100644 LiveStock/migrations/0020_auto_20250307_1118.py create mode 100644 LiveStock/migrations/0021_auto_20250307_1312.py create mode 100644 LiveStock/migrations/0022_rancher_has_script.py create mode 100644 LiveStock/migrations/0023_rancher_cooperative.py create mode 100644 LiveStock/migrations/0024_auto_20250307_2117.py create mode 100644 LiveStock/migrations/0025_auto_20250307_2128.py create mode 100644 LiveStock/migrations/0026_auto_20250308_1507.py create mode 100644 LiveStock/migrations/0027_livestockrolseproduct_total_receipt_weight.py create mode 100644 LiveStock/migrations/0028_auto_20250309_1036.py create mode 100644 LiveStock/migrations/0029_livestockrolseproduct_total_allocated.py create mode 100644 LiveStock/migrations/0030_remove_livestockrolseproduct_total_allocated.py create mode 100644 LiveStock/migrations/0031_cooperativeproductsshare.py create mode 100644 LiveStock/migrations/0032_auto_20250310_1639.py create mode 100644 LiveStock/migrations/0033_auto_20250310_1747.py create mode 100644 LiveStock/migrations/0034_auto_20250311_1002.py create mode 100644 LiveStock/migrations/0035_posseller.py create mode 100644 LiveStock/migrations/0036_rancher_type.py create mode 100644 LiveStock/migrations/0037_auto_20250312_1146.py create mode 100644 LiveStock/migrations/0038_auto_20250312_1422.py create mode 100644 LiveStock/migrations/0039_alter_rancher_dhi_amount.py create mode 100644 LiveStock/migrations/0040_auto_20250409_1829.py create mode 100644 LiveStock/migrations/0041_livestock_archive_date.py create mode 100644 LiveStock/migrations/0042_auto_20250414_1544.py create mode 100644 LiveStock/migrations/0043_livestock_age_of_archive.py create mode 100644 LiveStock/migrations/0044_cooperativeproductsshare_company_price.py create mode 100644 LiveStock/migrations/0045_auto_20250810_1102.py create mode 100644 LiveStock/migrations/__init__.py create mode 100644 LiveStock/models.py create mode 100644 LiveStock/sms_management.py create mode 100644 LiveStock/tests.py create mode 100644 LiveStock/urls.py create mode 100644 LiveStock/views.py create mode 100644 README.md create mode 100644 RasadyaarBale/__init__.py create mode 100644 RasadyaarBale/admin.py create mode 100644 RasadyaarBale/apps.py create mode 100644 RasadyaarBale/helper.py create mode 100644 RasadyaarBale/migrations/0001_initial.py create mode 100644 RasadyaarBale/migrations/0002_user_bale_super_admin.py create mode 100644 RasadyaarBale/migrations/0003_user_bale_rasadyar_user.py create mode 100644 RasadyaarBale/migrations/__init__.py create mode 100644 RasadyaarBale/models.py create mode 100644 RasadyaarBale/tests.py create mode 100644 RasadyaarBale/urls.py create mode 100644 RasadyaarBale/views.py create mode 100644 assets/img/img-min.png create mode 100644 authentication/__init__.py create mode 100644 authentication/admin.py create mode 100644 authentication/apps.py create mode 100644 authentication/arvan_image/arvan_storage.py create mode 100644 authentication/filterset.py create mode 100644 authentication/healthcheck.py create mode 100644 authentication/helper/__init__.py create mode 100644 authentication/helper/helper.py create mode 100644 authentication/helper/image_services.py create mode 100644 authentication/helper/make_user_gate_way_id.py create mode 100644 authentication/helper/refresh.py create mode 100644 authentication/log.py create mode 100644 authentication/message/__init__.py create mode 100644 authentication/message/serializers.py create mode 100644 authentication/message/views.py create mode 100644 authentication/migrations/0001_initial.py create mode 100644 authentication/migrations/0002_auto_20231005_0439.py create mode 100644 authentication/migrations/0003_auto_20231112_1026.py create mode 100644 authentication/migrations/0004_auto_20231112_1223.py create mode 100644 authentication/migrations/0005_auto_20231112_1544.py create mode 100644 authentication/migrations/0006_auto_20231114_0931.py create mode 100644 authentication/migrations/0007_auto_20231120_1913.py create mode 100644 authentication/migrations/0008_auto_20231120_2009.py create mode 100644 authentication/migrations/0009_auto_20231120_2134.py create mode 100644 authentication/migrations/0010_auto_20231202_1108.py create mode 100644 authentication/migrations/0011_auto_20231205_1256.py create mode 100644 authentication/migrations/0012_auto_20231211_1102.py create mode 100644 authentication/migrations/0013_auto_20231214_1418.py create mode 100644 authentication/migrations/0014_auto_20240107_1133.py create mode 100644 authentication/migrations/0015_auto_20240107_2228.py create mode 100644 authentication/migrations/0016_auto_20240110_0238.py create mode 100644 authentication/migrations/0017_auto_20240131_1351.py create mode 100644 authentication/migrations/0018_auto_20240131_1405.py create mode 100644 authentication/migrations/0019_auto_20240131_1429.py create mode 100644 authentication/migrations/0020_auto_20240220_1341.py create mode 100644 authentication/migrations/0021_auto_20240326_1330.py create mode 100644 authentication/migrations/0022_auto_20240326_1425.py create mode 100644 authentication/migrations/0023_auto_20240408_1626.py create mode 100644 authentication/migrations/0024_auto_20240408_1632.py create mode 100644 authentication/migrations/0025_auto_20240416_1440.py create mode 100644 authentication/migrations/0026_auto_20240417_1103.py create mode 100644 authentication/migrations/0027_auto_20240420_0033.py create mode 100644 authentication/migrations/0028_auto_20240427_1357.py create mode 100644 authentication/migrations/0029_auto_20240511_1129.py create mode 100644 authentication/migrations/0030_auto_20240511_1312.py create mode 100644 authentication/migrations/0031_auto_20240516_1321.py create mode 100644 authentication/migrations/0032_auto_20240517_1337.py create mode 100644 authentication/migrations/0033_auto_20240517_1351.py create mode 100644 authentication/migrations/0034_auto_20240527_1506.py create mode 100644 authentication/migrations/0035_auto_20240612_0954.py create mode 100644 authentication/migrations/0036_auto_20240612_1137.py create mode 100644 authentication/migrations/0037_auto_20240612_1936.py create mode 100644 authentication/migrations/0038_auto_20240613_1101.py create mode 100644 authentication/migrations/0039_auto_20240616_0956.py create mode 100644 authentication/migrations/0040_auto_20240618_1451.py create mode 100644 authentication/migrations/0041_auto_20240713_0951.py create mode 100644 authentication/migrations/0042_auto_20240713_1024.py create mode 100644 authentication/migrations/0043_auto_20240803_1121.py create mode 100644 authentication/migrations/0044_auto_20240820_1038.py create mode 100644 authentication/migrations/0045_auto_20240830_1034.py create mode 100644 authentication/migrations/0046_auto_20240912_0926.py create mode 100644 authentication/migrations/0047_auto_20240912_1105.py create mode 100644 authentication/migrations/0048_auto_20240912_1118.py create mode 100644 authentication/migrations/0049_auto_20241005_1324.py create mode 100644 authentication/migrations/0050_auto_20241029_1116.py create mode 100644 authentication/migrations/0051_auto_20241130_1837.py create mode 100644 authentication/migrations/0052_auto_20241208_1147.py create mode 100644 authentication/migrations/0053_auto_20241215_1031.py create mode 100644 authentication/migrations/0054_auto_20241228_0926.py create mode 100644 authentication/migrations/0055_auto_20250112_1550.py create mode 100644 authentication/migrations/0056_auto_20250118_1418.py create mode 100644 authentication/migrations/0057_auto_20250121_0857.py create mode 100644 authentication/migrations/0058_auto_20250126_2046.py create mode 100644 authentication/migrations/0059_auto_20250126_2122.py create mode 100644 authentication/migrations/0060_auto_20250302_1203.py create mode 100644 authentication/migrations/0061_auto_20250302_1351.py create mode 100644 authentication/migrations/0062_auto_20250302_1458.py create mode 100644 authentication/migrations/0063_auto_20250303_1205.py create mode 100644 authentication/migrations/0064_auto_20250303_1315.py create mode 100644 authentication/migrations/0065_auto_20250303_1500.py create mode 100644 authentication/migrations/0066_auto_20250306_1106.py create mode 100644 authentication/migrations/0067_auto_20250525_1503.py create mode 100644 authentication/migrations/0068_auto_20250525_1504.py create mode 100644 authentication/migrations/0069_auto_20250525_1505.py create mode 100644 authentication/migrations/0070_auto_20250527_1154.py create mode 100644 authentication/migrations/0071_auto_20250601_1023.py create mode 100644 authentication/migrations/0072_auto_20250901_1207.py create mode 100644 authentication/migrations/0073_auto_20250920_1257.py create mode 100644 authentication/migrations/0074_auto_20251028_0856.py create mode 100644 authentication/migrations/0075_auto_20251029_1055.py create mode 100644 authentication/migrations/0076_auto_20251104_1340.py create mode 100644 authentication/migrations/0077_auto_20251110_1100.py create mode 100644 authentication/migrations/0078_auto_20251208_1617.py create mode 100644 authentication/migrations/0079_auto_20251213_1632.py create mode 100644 authentication/migrations/0080_auto_20251214_1635.py create mode 100644 authentication/migrations/0081_auto_20251217_1648.py create mode 100644 authentication/migrations/__init__.py create mode 100644 authentication/models.py create mode 100644 authentication/permission_views.py create mode 100644 authentication/permissions.py create mode 100644 authentication/register.py create mode 100644 authentication/sahandsms/__init__.py create mode 100644 authentication/sahandsms/sms.py create mode 100644 authentication/serializer/__init__.py create mode 100644 authentication/serializer/serializer.py create mode 100644 authentication/serializers.py create mode 100644 authentication/sms_management.py create mode 100644 authentication/tests.py create mode 100644 authentication/urls.py create mode 100644 authentication/views.py create mode 100644 bot_eata.py create mode 100644 cancel_bar_and_provice_request.py create mode 100644 cron_gid.py create mode 100644 cron_out_province_request.py create mode 100644 cron_report.py create mode 100644 cron_return_archive.py create mode 100644 cron_send_sms_from_notif.py create mode 100644 cron_seven_am.py create mode 100644 cron_sms.py create mode 100644 delete_kill_request_cron.py create mode 100644 deposit_id.py create mode 100644 deposit_percent.py create mode 100644 docker-compose.yml create mode 100644 every_12_hours.py create mode 100644 general_urls.py create mode 100644 helper_eata.py create mode 100644 main.py create mode 100644 manage.py create mode 100644 notification/__init__.py create mode 100644 notification/admin.py create mode 100644 notification/apps.py create mode 100644 notification/consumers.py create mode 100644 notification/middleware.py create mode 100644 notification/migrations/0001_initial.py create mode 100644 notification/migrations/0002_auto_20250121_0857.py create mode 100644 notification/migrations/0003_dashboardnotification.py create mode 100644 notification/migrations/0004_alter_dashboardnotification_role.py create mode 100644 notification/migrations/__init__.py create mode 100644 notification/models.py create mode 100644 notification/najva/__init__.py create mode 100644 notification/najva/get_segments_detail.py create mode 100644 notification/najva/send_notif_to_segments.py create mode 100644 notification/najva_views.py create mode 100644 notification/notify.py create mode 100644 notification/pushe/__init__.py create mode 100644 notification/pushe/constants.py create mode 100644 notification/pushe/send_custom_content_notification.py create mode 100644 notification/pushe/send_filtered_notification.py create mode 100644 notification/pushe/send_notification_with_action.py create mode 100644 notification/pushe/send_simple_notification.py create mode 100644 notification/pushe/send_transactional_notification.py create mode 100644 notification/routing.py create mode 100644 notification/serializers.py create mode 100644 notification/signals.py create mode 100644 notification/tests.py create mode 100644 notification/urls.py create mode 100644 notification/views.py create mode 100644 panel/CityOperator/__init__.py create mode 100644 panel/CityOperator/helpers.py create mode 100644 panel/CityOperator/serializers.py create mode 100644 panel/CityOperator/views.py create mode 100644 panel/KillHouse/__init__.py create mode 100644 panel/KillHouse/excel_processing.py create mode 100644 panel/KillHouse/helpers.py create mode 100644 panel/KillHouse/serializers.py create mode 100644 panel/KillHouse/views.py create mode 100644 panel/ProvinceOperator/__init__.py create mode 100644 panel/ProvinceOperator/excel_processing.py create mode 100644 panel/ProvinceOperator/helpers.py create mode 100644 panel/ProvinceOperator/serializers.py create mode 100644 panel/ProvinceOperator/services/__init__.py create mode 100644 panel/ProvinceOperator/services/pos_transfer_service.py create mode 100644 panel/ProvinceOperator/views.py create mode 100644 panel/ReportingPanel/__init__.py create mode 100644 panel/ReportingPanel/excel_output.py create mode 100644 panel/ReportingPanel/filterset.py create mode 100644 panel/ReportingPanel/helper.py create mode 100644 panel/ReportingPanel/models.py create mode 100644 panel/ReportingPanel/serializer.py create mode 100644 panel/ReportingPanel/views.py create mode 100644 panel/VetFarm/__init__.py create mode 100644 panel/VetFarm/excel_processing.py create mode 100644 panel/VetFarm/helpers.py create mode 100644 panel/VetFarm/serializers.py create mode 100644 panel/VetFarm/views.py create mode 100644 panel/__init__.py create mode 100644 panel/admin.py create mode 100644 panel/apps.py create mode 100644 panel/convert_date.py create mode 100644 panel/excel_processing.py create mode 100644 panel/filterset.py create mode 100644 panel/helper.py create mode 100644 panel/helper_excel.py create mode 100644 panel/management/__init__.py create mode 100644 panel/management/commands/__init__.py create mode 100644 panel/management/commands/function_executor.py create mode 100644 panel/management/timing_function.py create mode 100644 panel/merge_database.py create mode 100644 panel/migrations/0001_initial.py create mode 100644 panel/migrations/0002_auto_20230918_2031.py create mode 100644 panel/migrations/0003_auto_20230918_2035.py create mode 100644 panel/migrations/0004_auto_20230918_2110.py create mode 100644 panel/migrations/0005_auto_20230919_0035.py create mode 100644 panel/migrations/0006_auto_20230923_1311.py create mode 100644 panel/migrations/0007_auto_20230926_0954.py create mode 100644 panel/migrations/0008_auto_20230926_1440.py create mode 100644 panel/migrations/0009_auto_20230927_1033.py create mode 100644 panel/migrations/0010_auto_20230927_1047.py create mode 100644 panel/migrations/0011_auto_20230927_1416.py create mode 100644 panel/migrations/0012_auto_20230927_1554.py create mode 100644 panel/migrations/0013_auto_20230928_1502.py create mode 100644 panel/migrations/0014_auto_20231002_1157.py create mode 100644 panel/migrations/0015_auto_20231002_1201.py create mode 100644 panel/migrations/0016_auto_20231004_1101.py create mode 100644 panel/migrations/0017_auto_20231004_1452.py create mode 100644 panel/migrations/0018_auto_20231004_1508.py create mode 100644 panel/migrations/0019_auto_20231004_1528.py create mode 100644 panel/migrations/0020_auto_20231004_1539.py create mode 100644 panel/migrations/0021_auto_20231004_1552.py create mode 100644 panel/migrations/0022_auto_20231005_0439.py create mode 100644 panel/migrations/0023_auto_20231007_1338.py create mode 100644 panel/migrations/0024_auto_20231009_1240.py create mode 100644 panel/migrations/0025_auto_20231010_1249.py create mode 100644 panel/migrations/0026_auto_20231011_1337.py create mode 100644 panel/migrations/0027_auto_20231015_1349.py create mode 100644 panel/migrations/0028_auto_20231016_1211.py create mode 100644 panel/migrations/0029_auto_20231017_1511.py create mode 100644 panel/migrations/0030_auto_20231028_1327.py create mode 100644 panel/migrations/0031_auto_20231031_1233.py create mode 100644 panel/migrations/0032_auto_20231031_1509.py create mode 100644 panel/migrations/0033_auto_20231101_1240.py create mode 100644 panel/migrations/0034_auto_20231103_1509.py create mode 100644 panel/migrations/0035_auto_20231104_1118.py create mode 100644 panel/migrations/0036_auto_20231105_1224.py create mode 100644 panel/migrations/0037_auto_20231106_1225.py create mode 100644 panel/migrations/0038_auto_20231106_1546.py create mode 100644 panel/migrations/0039_auto_20231108_1156.py create mode 100644 panel/migrations/0040_auto_20231111_1426.py create mode 100644 panel/migrations/0041_auto_20231112_2305.py create mode 100644 panel/migrations/0042_auto_20231114_0930.py create mode 100644 panel/migrations/0043_auto_20231122_1203.py create mode 100644 panel/migrations/0044_auto_20231126_1221.py create mode 100644 panel/migrations/0045_auto_20231126_2005.py create mode 100644 panel/migrations/0046_auto_20231126_2030.py create mode 100644 panel/migrations/0047_auto_20231127_1018.py create mode 100644 panel/migrations/0048_auto_20231127_1404.py create mode 100644 panel/migrations/0049_auto_20231127_1506.py create mode 100644 panel/migrations/0050_auto_20231129_1029.py create mode 100644 panel/migrations/0051_auto_20231129_1452.py create mode 100644 panel/migrations/0052_auto_20231129_1539.py create mode 100644 panel/migrations/0053_auto_20231201_1759.py create mode 100644 panel/migrations/0053_auto_20231202_1108.py create mode 100644 panel/migrations/0054_auto_20231201_2242.py create mode 100644 panel/migrations/0055_merge_0053_auto_20231202_1108_0054_auto_20231201_2242.py create mode 100644 panel/migrations/0056_auto_20231202_2323.py create mode 100644 panel/migrations/0057_auto_20231205_1256.py create mode 100644 panel/migrations/0058_auto_20231210_1253.py create mode 100644 panel/migrations/0059_auto_20231210_1400.py create mode 100644 panel/migrations/0060_auto_20231211_0917.py create mode 100644 panel/migrations/0061_auto_20231211_1102.py create mode 100644 panel/migrations/0062_auto_20231211_1209.py create mode 100644 panel/migrations/0063_auto_20231212_1000.py create mode 100644 panel/migrations/0064_auto_20231212_1035.py create mode 100644 panel/migrations/0065_auto_20231214_1409.py create mode 100644 panel/migrations/0066_auto_20231214_1418.py create mode 100644 panel/migrations/0067_auto_20231216_1015.py create mode 100644 panel/migrations/0068_auto_20231216_1030.py create mode 100644 panel/migrations/0069_auto_20231216_1448.py create mode 100644 panel/migrations/0070_auto_20231216_2041.py create mode 100644 panel/migrations/0071_auto_20231225_1502.py create mode 100644 panel/migrations/0072_auto_20231226_1543.py create mode 100644 panel/migrations/0073_auto_20231227_1020.py create mode 100644 panel/migrations/0074_auto_20231227_1520.py create mode 100644 panel/migrations/0075_auto_20231228_1158.py create mode 100644 panel/migrations/0076_auto_20231230_0919.py create mode 100644 panel/migrations/0077_auto_20240102_0907.py create mode 100644 panel/migrations/0078_auto_20240102_1009.py create mode 100644 panel/migrations/0079_auto_20240102_1253.py create mode 100644 panel/migrations/0080_auto_20240103_1246.py create mode 100644 panel/migrations/0081_auto_20240103_1417.py create mode 100644 panel/migrations/0082_auto_20240103_1455.py create mode 100644 panel/migrations/0083_auto_20240107_1039.py create mode 100644 panel/migrations/0084_auto_20240107_1133.py create mode 100644 panel/migrations/0085_auto_20240107_1325.py create mode 100644 panel/migrations/0086_auto_20240107_2228.py create mode 100644 panel/migrations/0087_auto_20240107_2243.py create mode 100644 panel/migrations/0088_auto_20240108_0954.py create mode 100644 panel/migrations/0089_auto_20240108_1100.py create mode 100644 panel/migrations/0090_auto_20240108_1137.py create mode 100644 panel/migrations/0091_auto_20240108_2134.py create mode 100644 panel/migrations/0092_auto_20240108_2257.py create mode 100644 panel/migrations/0093_auto_20240108_2352.py create mode 100644 panel/migrations/0094_auto_20240109_1042.py create mode 100644 panel/migrations/0095_auto_20240110_0238.py create mode 100644 panel/migrations/0096_auto_20240111_1559.py create mode 100644 panel/migrations/0097_auto_20240114_1305.py create mode 100644 panel/migrations/0098_auto_20240114_1343.py create mode 100644 panel/migrations/0099_auto_20240115_1039.py create mode 100644 panel/migrations/0100_auto_20240118_1118.py create mode 100644 panel/migrations/0101_auto_20240121_1159.py create mode 100644 panel/migrations/0102_auto_20240123_1234.py create mode 100644 panel/migrations/0103_auto_20240127_0916.py create mode 100644 panel/migrations/0104_auto_20240130_1008.py create mode 100644 panel/migrations/0105_auto_20240205_1011.py create mode 100644 panel/migrations/0106_auto_20240206_1500.py create mode 100644 panel/migrations/0107_auto_20240206_1510.py create mode 100644 panel/migrations/0108_auto_20240207_1006.py create mode 100644 panel/migrations/0109_auto_20240214_0923.py create mode 100644 panel/migrations/0110_auto_20240214_1029.py create mode 100644 panel/migrations/0111_auto_20240220_0856.py create mode 100644 panel/migrations/0112_auto_20240220_1341.py create mode 100644 panel/migrations/0113_auto_20240221_1105.py create mode 100644 panel/migrations/0114_auto_20240221_1306.py create mode 100644 panel/migrations/0115_auto_20240221_1314.py create mode 100644 panel/migrations/0116_auto_20240221_1317.py create mode 100644 panel/migrations/0117_auto_20240221_1520.py create mode 100644 panel/migrations/0118_auto_20240222_1235.py create mode 100644 panel/migrations/0119_auto_20240222_1346.py create mode 100644 panel/migrations/0120_auto_20240222_1432.py create mode 100644 panel/migrations/0121_auto_20240226_1343.py create mode 100644 panel/migrations/0122_auto_20240226_1524.py create mode 100644 panel/migrations/0123_auto_20240227_1159.py create mode 100644 panel/migrations/0124_auto_20240303_1034.py create mode 100644 panel/migrations/0125_auto_20240303_1044.py create mode 100644 panel/migrations/0126_auto_20240303_1103.py create mode 100644 panel/migrations/0127_auto_20240309_1046.py create mode 100644 panel/migrations/0128_auto_20240311_1159.py create mode 100644 panel/migrations/0129_auto_20240311_1555.py create mode 100644 panel/migrations/0130_auto_20240312_1158.py create mode 100644 panel/migrations/0131_auto_20240315_2202.py create mode 100644 panel/migrations/0132_auto_20240318_1139.py create mode 100644 panel/migrations/0133_auto_20240409_1145.py create mode 100644 panel/migrations/0134_auto_20240409_1202.py create mode 100644 panel/migrations/0135_auto_20240409_1220.py create mode 100644 panel/migrations/0136_auto_20240413_1322.py create mode 100644 panel/migrations/0137_auto_20240414_1050.py create mode 100644 panel/migrations/0138_auto_20240414_1206.py create mode 100644 panel/migrations/0139_auto_20240416_1440.py create mode 100644 panel/migrations/0140_auto_20240417_1103.py create mode 100644 panel/migrations/0141_auto_20240417_1257.py create mode 100644 panel/migrations/0142_auto_20240418_1428.py create mode 100644 panel/migrations/0143_auto_20240418_1550.py create mode 100644 panel/migrations/0144_auto_20240420_0033.py create mode 100644 panel/migrations/0145_auto_20240420_1517.py create mode 100644 panel/migrations/0146_auto_20240427_1357.py create mode 100644 panel/migrations/0147_auto_20240428_1211.py create mode 100644 panel/migrations/0148_auto_20240429_1110.py create mode 100644 panel/migrations/0149_auto_20240429_1131.py create mode 100644 panel/migrations/0150_auto_20240430_1203.py create mode 100644 panel/migrations/0151_auto_20240430_1327.py create mode 100644 panel/migrations/0152_auto_20240506_1344.py create mode 100644 panel/migrations/0153_auto_20240506_1401.py create mode 100644 panel/migrations/0154_auto_20240506_1502.py create mode 100644 panel/migrations/0155_auto_20240507_1044.py create mode 100644 panel/migrations/0156_auto_20240507_1105.py create mode 100644 panel/migrations/0157_auto_20240507_1110.py create mode 100644 panel/migrations/0158_auto_20240507_2243.py create mode 100644 panel/migrations/0159_auto_20240507_2343.py create mode 100644 panel/migrations/0160_auto_20240508_1019.py create mode 100644 panel/migrations/0161_auto_20240508_1203.py create mode 100644 panel/migrations/0162_auto_20240511_1129.py create mode 100644 panel/migrations/0163_auto_20240511_1312.py create mode 100644 panel/migrations/0164_auto_20240512_1109.py create mode 100644 panel/migrations/0165_auto_20240513_1219.py create mode 100644 panel/migrations/0166_auto_20240513_1255.py create mode 100644 panel/migrations/0167_auto_20240513_1256.py create mode 100644 panel/migrations/0168_auto_20240515_1153.py create mode 100644 panel/migrations/0169_auto_20240515_1301.py create mode 100644 panel/migrations/0170_auto_20240515_1453.py create mode 100644 panel/migrations/0171_auto_20240515_1549.py create mode 100644 panel/migrations/0172_auto_20240515_2306.py create mode 100644 panel/migrations/0173_auto_20240515_2310.py create mode 100644 panel/migrations/0174_auto_20240515_2326.py create mode 100644 panel/migrations/0175_auto_20240516_0015.py create mode 100644 panel/migrations/0176_auto_20240516_1132.py create mode 100644 panel/migrations/0177_auto_20240516_1320.py create mode 100644 panel/migrations/0178_auto_20240517_1337.py create mode 100644 panel/migrations/0179_auto_20240517_1352.py create mode 100644 panel/migrations/0180_auto_20240517_2240.py create mode 100644 panel/migrations/0181_auto_20240521_1033.py create mode 100644 panel/migrations/0182_auto_20240521_1054.py create mode 100644 panel/migrations/0183_auto_20240523_1653.py create mode 100644 panel/migrations/0184_auto_20240525_1028.py create mode 100644 panel/migrations/0185_auto_20240528_1234.py create mode 100644 panel/migrations/0186_auto_20240604_1332.py create mode 100644 panel/migrations/0187_auto_20240605_1034.py create mode 100644 panel/migrations/0188_auto_20240605_1220.py create mode 100644 panel/migrations/0189_auto_20240605_1844.py create mode 100644 panel/migrations/0190_auto_20240606_1050.py create mode 100644 panel/migrations/0191_auto_20240606_1122.py create mode 100644 panel/migrations/0192_auto_20240608_1038.py create mode 100644 panel/migrations/0193_auto_20240608_2310.py create mode 100644 panel/migrations/0194_auto_20240608_2326.py create mode 100644 panel/migrations/0195_auto_20240611_0019.py create mode 100644 panel/migrations/0196_auto_20240612_0051.py create mode 100644 panel/migrations/0197_auto_20240612_1118.py create mode 100644 panel/migrations/0198_auto_20240612_1230.py create mode 100644 panel/migrations/0199_auto_20240612_1137.py create mode 100644 panel/migrations/0200_auto_20240613_1037.py create mode 100644 panel/migrations/0201_auto_20240613_1106.py create mode 100644 panel/migrations/0202_auto_20240613_1043.py create mode 100644 panel/migrations/0203_auto_20240613_1101.py create mode 100644 panel/migrations/0204_auto_20240616_0110.py create mode 100644 panel/migrations/0205_auto_20240616_0956.py create mode 100644 panel/migrations/0206_auto_20240617_1954.py create mode 100644 panel/migrations/0207_auto_20240618_1054.py create mode 100644 panel/migrations/0208_auto_20240618_1417.py create mode 100644 panel/migrations/0209_auto_20240618_1451.py create mode 100644 panel/migrations/0210_auto_20240619_1119.py create mode 100644 panel/migrations/0211_auto_20240619_1701.py create mode 100644 panel/migrations/0212_auto_20240620_1006.py create mode 100644 panel/migrations/0213_auto_20240622_1055.py create mode 100644 panel/migrations/0214_auto_20240622_1153.py create mode 100644 panel/migrations/0215_auto_20240622_1158.py create mode 100644 panel/migrations/0216_auto_20240622_1229.py create mode 100644 panel/migrations/0217_auto_20240622_1622.py create mode 100644 panel/migrations/0218_auto_20240624_1409.py create mode 100644 panel/migrations/0219_auto_20240629_1100.py create mode 100644 panel/migrations/0220_auto_20240629_1118.py create mode 100644 panel/migrations/0221_auto_20240629_1150.py create mode 100644 panel/migrations/0222_auto_20240630_1147.py create mode 100644 panel/migrations/0223_auto_20240630_1148.py create mode 100644 panel/migrations/0224_auto_20240630_1351.py create mode 100644 panel/migrations/0225_auto_20240630_1443.py create mode 100644 panel/migrations/0226_auto_20240701_1553.py create mode 100644 panel/migrations/0227_auto_20240702_1406.py create mode 100644 panel/migrations/0228_auto_20240702_1417.py create mode 100644 panel/migrations/0229_auto_20240702_1510.py create mode 100644 panel/migrations/0230_auto_20240703_0926.py create mode 100644 panel/migrations/0231_auto_20240703_1036.py create mode 100644 panel/migrations/0232_auto_20240703_1101.py create mode 100644 panel/migrations/0233_auto_20240703_1419.py create mode 100644 panel/migrations/0234_auto_20240703_1555.py create mode 100644 panel/migrations/0235_auto_20240706_1424.py create mode 100644 panel/migrations/0236_auto_20240706_1520.py create mode 100644 panel/migrations/0237_auto_20240706_1652.py create mode 100644 panel/migrations/0238_auto_20240707_1153.py create mode 100644 panel/migrations/0239_auto_20240708_1341.py create mode 100644 panel/migrations/0240_auto_20240709_1204.py create mode 100644 panel/migrations/0241_auto_20240710_1333.py create mode 100644 panel/migrations/0242_auto_20240713_0951.py create mode 100644 panel/migrations/0243_auto_20240713_1024.py create mode 100644 panel/migrations/0244_auto_20240713_1139.py create mode 100644 panel/migrations/0245_auto_20240713_1236.py create mode 100644 panel/migrations/0246_auto_20240713_1250.py create mode 100644 panel/migrations/0247_auto_20240713_1516.py create mode 100644 panel/migrations/0248_auto_20240717_1145.py create mode 100644 panel/migrations/0249_auto_20240717_1208.py create mode 100644 panel/migrations/0250_auto_20240717_1306.py create mode 100644 panel/migrations/0251_auto_20240717_1332.py create mode 100644 panel/migrations/0252_auto_20240717_1350.py create mode 100644 panel/migrations/0253_auto_20240718_1206.py create mode 100644 panel/migrations/0254_auto_20240718_1303.py create mode 100644 panel/migrations/0255_auto_20240720_1218.py create mode 100644 panel/migrations/0256_auto_20240724_1147.py create mode 100644 panel/migrations/0257_auto_20240725_1040.py create mode 100644 panel/migrations/0258_auto_20240725_1112.py create mode 100644 panel/migrations/0259_auto_20240727_1222.py create mode 100644 panel/migrations/0260_auto_20240731_2252.py create mode 100644 panel/migrations/0261_auto_20240802_1111.py create mode 100644 panel/migrations/0262_auto_20240803_1121.py create mode 100644 panel/migrations/0263_auto_20240803_1509.py create mode 100644 panel/migrations/0264_auto_20240803_1523.py create mode 100644 panel/migrations/0265_auto_20240803_1527.py create mode 100644 panel/migrations/0266_auto_20240804_1011.py create mode 100644 panel/migrations/0267_auto_20240804_1406.py create mode 100644 panel/migrations/0268_auto_20240804_2127.py create mode 100644 panel/migrations/0269_auto_20240804_2128.py create mode 100644 panel/migrations/0270_auto_20240806_2324.py create mode 100644 panel/migrations/0271_auto_20240808_1144.py create mode 100644 panel/migrations/0272_auto_20240808_1209.py create mode 100644 panel/migrations/0273_auto_20240808_1410.py create mode 100644 panel/migrations/0274_auto_20240809_1838.py create mode 100644 panel/migrations/0275_auto_20240809_1850.py create mode 100644 panel/migrations/0276_auto_20240810_0922.py create mode 100644 panel/migrations/0277_auto_20240810_0928.py create mode 100644 panel/migrations/0278_auto_20240810_1357.py create mode 100644 panel/migrations/0279_auto_20240811_1102.py create mode 100644 panel/migrations/0280_auto_20240812_1015.py create mode 100644 panel/migrations/0281_auto_20240812_1015.py create mode 100644 panel/migrations/0282_auto_20240812_1349.py create mode 100644 panel/migrations/0283_auto_20240813_0921.py create mode 100644 panel/migrations/0284_auto_20240814_1007.py create mode 100644 panel/migrations/0285_auto_20240814_1017.py create mode 100644 panel/migrations/0286_auto_20240815_1337.py create mode 100644 panel/migrations/0287_auto_20240817_1040.py create mode 100644 panel/migrations/0288_auto_20240817_1052.py create mode 100644 panel/migrations/0289_auto_20240819_1141.py create mode 100644 panel/migrations/0290_auto_20240819_1227.py create mode 100644 panel/migrations/0291_auto_20240819_1233.py create mode 100644 panel/migrations/0292_auto_20240819_1325.py create mode 100644 panel/migrations/0293_auto_20240820_1038.py create mode 100644 panel/migrations/0294_auto_20240821_0917.py create mode 100644 panel/migrations/0295_auto_20240821_1000.py create mode 100644 panel/migrations/0296_auto_20240826_1223.py create mode 100644 panel/migrations/0297_auto_20240828_1203.py create mode 100644 panel/migrations/0298_auto_20240828_1410.py create mode 100644 panel/migrations/0299_auto_20240828_1416.py create mode 100644 panel/migrations/0300_auto_20240829_0958.py create mode 100644 panel/migrations/0301_auto_20240829_1025.py create mode 100644 panel/migrations/0302_auto_20240830_1023.py create mode 100644 panel/migrations/0303_auto_20240830_1033.py create mode 100644 panel/migrations/0304_auto_20240830_1033.py create mode 100644 panel/migrations/0305_auto_20240831_1000.py create mode 100644 panel/migrations/0306_auto_20240907_1020.py create mode 100644 panel/migrations/0307_auto_20240911_1147.py create mode 100644 panel/migrations/0308_auto_20240912_0926.py create mode 100644 panel/migrations/0309_auto_20240912_1121.py create mode 100644 panel/migrations/0310_auto_20240912_1211.py create mode 100644 panel/migrations/0311_auto_20240914_1038.py create mode 100644 panel/migrations/0312_auto_20240915_1241.py create mode 100644 panel/migrations/0313_auto_20241005_1310.py create mode 100644 panel/migrations/0314_auto_20241012_1226.py create mode 100644 panel/migrations/0315_auto_20241015_1027.py create mode 100644 panel/migrations/0316_auto_20241015_1036.py create mode 100644 panel/migrations/0317_auto_20241017_1226.py create mode 100644 panel/migrations/0318_auto_20241022_1026.py create mode 100644 panel/migrations/0319_auto_20241022_1028.py create mode 100644 panel/migrations/0320_auto_20241023_1309.py create mode 100644 panel/migrations/0321_auto_20241023_1326.py create mode 100644 panel/migrations/0322_auto_20241024_0931.py create mode 100644 panel/migrations/0323_auto_20241024_2016.py create mode 100644 panel/migrations/0324_auto_20241024_2018.py create mode 100644 panel/migrations/0325_auto_20241024_2018.py create mode 100644 panel/migrations/0326_auto_20241026_0950.py create mode 100644 panel/migrations/0327_auto_20241026_1309.py create mode 100644 panel/migrations/0328_auto_20241029_1116.py create mode 100644 panel/migrations/0329_auto_20241103_0927.py create mode 100644 panel/migrations/0330_auto_20241103_0936.py create mode 100644 panel/migrations/0331_auto_20241103_0938.py create mode 100644 panel/migrations/0332_auto_20241103_0939.py create mode 100644 panel/migrations/0333_auto_20241103_0947.py create mode 100644 panel/migrations/0334_auto_20241104_1433.py create mode 100644 panel/migrations/0335_auto_20241104_2248.py create mode 100644 panel/migrations/0336_auto_20241105_0834.py create mode 100644 panel/migrations/0337_auto_20241105_2335.py create mode 100644 panel/migrations/0338_auto_20241106_1605.py create mode 100644 panel/migrations/0339_auto_20241107_1047.py create mode 100644 panel/migrations/0340_auto_20241107_1055.py create mode 100644 panel/migrations/0341_auto_20241107_1450.py create mode 100644 panel/migrations/0342_auto_20241107_1456.py create mode 100644 panel/migrations/0343_auto_20241108_1518.py create mode 100644 panel/migrations/0344_auto_20241108_1527.py create mode 100644 panel/migrations/0345_auto_20241108_1547.py create mode 100644 panel/migrations/0346_auto_20241108_1552.py create mode 100644 panel/migrations/0347_auto_20241109_1406.py create mode 100644 panel/migrations/0348_auto_20241109_1421.py create mode 100644 panel/migrations/0349_auto_20241109_1506.py create mode 100644 panel/migrations/0350_auto_20241109_1555.py create mode 100644 panel/migrations/0351_auto_20241109_2036.py create mode 100644 panel/migrations/0352_auto_20241110_1035.py create mode 100644 panel/migrations/0353_auto_20241110_1345.py create mode 100644 panel/migrations/0354_auto_20241110_1354.py create mode 100644 panel/migrations/0355_auto_20241110_2306.py create mode 100644 panel/migrations/0356_auto_20241112_1250.py create mode 100644 panel/migrations/0357_auto_20241112_1332.py create mode 100644 panel/migrations/0358_auto_20241112_1459.py create mode 100644 panel/migrations/0359_auto_20241112_1511.py create mode 100644 panel/migrations/0360_auto_20241113_1050.py create mode 100644 panel/migrations/0361_auto_20241113_1058.py create mode 100644 panel/migrations/0362_auto_20241113_1102.py create mode 100644 panel/migrations/0363_auto_20241114_1345.py create mode 100644 panel/migrations/0364_auto_20241115_1217.py create mode 100644 panel/migrations/0365_auto_20241116_0944.py create mode 100644 panel/migrations/0366_auto_20241116_1121.py create mode 100644 panel/migrations/0367_auto_20241116_1144.py create mode 100644 panel/migrations/0368_auto_20241116_1148.py create mode 100644 panel/migrations/0369_auto_20241117_1013.py create mode 100644 panel/migrations/0370_auto_20241117_1020.py create mode 100644 panel/migrations/0371_auto_20241117_1545.py create mode 100644 panel/migrations/0372_auto_20241117_2222.py create mode 100644 panel/migrations/0373_auto_20241118_0811.py create mode 100644 panel/migrations/0374_auto_20241118_0946.py create mode 100644 panel/migrations/0375_auto_20241118_1054.py create mode 100644 panel/migrations/0376_auto_20241118_2152.py create mode 100644 panel/migrations/0377_auto_20241118_2157.py create mode 100644 panel/migrations/0378_auto_20241118_2317.py create mode 100644 panel/migrations/0379_auto_20241120_0810.py create mode 100644 panel/migrations/0380_auto_20241126_1028.py create mode 100644 panel/migrations/0381_auto_20241126_1047.py create mode 100644 panel/migrations/0382_auto_20241126_1606.py create mode 100644 panel/migrations/0383_auto_20241127_0958.py create mode 100644 panel/migrations/0384_auto_20241130_1018.py create mode 100644 panel/migrations/0385_auto_20241130_1048.py create mode 100644 panel/migrations/0386_auto_20241130_1830.py create mode 100644 panel/migrations/0387_auto_20241130_1836.py create mode 100644 panel/migrations/0388_auto_20241130_1902.py create mode 100644 panel/migrations/0389_auto_20241130_2009.py create mode 100644 panel/migrations/0390_auto_20241203_0901.py create mode 100644 panel/migrations/0391_auto_20241203_0935.py create mode 100644 panel/migrations/0392_auto_20241203_0946.py create mode 100644 panel/migrations/0393_auto_20241204_1334.py create mode 100644 panel/migrations/0394_auto_20241204_1357.py create mode 100644 panel/migrations/0395_auto_20241207_1034.py create mode 100644 panel/migrations/0396_auto_20241208_1147.py create mode 100644 panel/migrations/0397_auto_20241209_1422.py create mode 100644 panel/migrations/0398_auto_20241211_0956.py create mode 100644 panel/migrations/0399_auto_20241211_1115.py create mode 100644 panel/migrations/0400_auto_20241214_1358.py create mode 100644 panel/migrations/0401_auto_20241215_1031.py create mode 100644 panel/migrations/0402_auto_20241215_1139.py create mode 100644 panel/migrations/0403_auto_20241215_1458.py create mode 100644 panel/migrations/0404_auto_20241216_1214.py create mode 100644 panel/migrations/0405_auto_20241216_1524.py create mode 100644 panel/migrations/0406_auto_20241216_1532.py create mode 100644 panel/migrations/0407_auto_20241216_1625.py create mode 100644 panel/migrations/0408_auto_20241218_1435.py create mode 100644 panel/migrations/0409_auto_20241221_1150.py create mode 100644 panel/migrations/0410_auto_20241221_1258.py create mode 100644 panel/migrations/0411_auto_20241221_1357.py create mode 100644 panel/migrations/0412_auto_20241221_1535.py create mode 100644 panel/migrations/0413_auto_20241222_1203.py create mode 100644 panel/migrations/0414_auto_20241223_1441.py create mode 100644 panel/migrations/0415_auto_20241223_1547.py create mode 100644 panel/migrations/0416_auto_20241225_1417.py create mode 100644 panel/migrations/0417_auto_20241231_1523.py create mode 100644 panel/migrations/0418_auto_20241231_2121.py create mode 100644 panel/migrations/0419_auto_20250106_1612.py create mode 100644 panel/migrations/0420_auto_20250107_1233.py create mode 100644 panel/migrations/0421_auto_20250107_1807.py create mode 100644 panel/migrations/0422_auto_20250112_1004.py create mode 100644 panel/migrations/0423_auto_20250112_1550.py create mode 100644 panel/migrations/0424_auto_20250113_1532.py create mode 100644 panel/migrations/0425_auto_20250119_1410.py create mode 100644 panel/migrations/0426_auto_20250120_0929.py create mode 100644 panel/migrations/0427_auto_20250120_0941.py create mode 100644 panel/migrations/0428_auto_20250120_1638.py create mode 100644 panel/migrations/0429_auto_20250121_0857.py create mode 100644 panel/migrations/0430_auto_20250125_1225.py create mode 100644 panel/migrations/0431_auto_20250127_1622.py create mode 100644 panel/migrations/0432_auto_20250201_1449.py create mode 100644 panel/migrations/0433_auto_20250205_1303.py create mode 100644 panel/migrations/0434_auto_20250209_0918.py create mode 100644 panel/migrations/0435_auto_20250209_1024.py create mode 100644 panel/migrations/0436_auto_20250210_1938.py create mode 100644 panel/migrations/0437_auto_20250211_1410.py create mode 100644 panel/migrations/0438_auto_20250212_0900.py create mode 100644 panel/migrations/0439_auto_20250212_0957.py create mode 100644 panel/migrations/0440_auto_20250212_1003.py create mode 100644 panel/migrations/0441_auto_20250212_1455.py create mode 100644 panel/migrations/0442_auto_20250216_1014.py create mode 100644 panel/migrations/0443_auto_20250217_1419.py create mode 100644 panel/migrations/0444_auto_20250217_1557.py create mode 100644 panel/migrations/0445_auto_20250217_1707.py create mode 100644 panel/migrations/0446_auto_20250218_0853.py create mode 100644 panel/migrations/0447_auto_20250218_1015.py create mode 100644 panel/migrations/0448_auto_20250222_1023.py create mode 100644 panel/migrations/0449_auto_20250222_1112.py create mode 100644 panel/migrations/0450_auto_20250222_1636.py create mode 100644 panel/migrations/0451_auto_20250223_0958.py create mode 100644 panel/migrations/0452_auto_20250223_1001.py create mode 100644 panel/migrations/0453_auto_20250223_1005.py create mode 100644 panel/migrations/0454_auto_20250223_1006.py create mode 100644 panel/migrations/0455_auto_20250223_1128.py create mode 100644 panel/migrations/0456_auto_20250224_1320.py create mode 100644 panel/migrations/0457_auto_20250224_1322.py create mode 100644 panel/migrations/0458_auto_20250225_1118.py create mode 100644 panel/migrations/0459_auto_20250225_1144.py create mode 100644 panel/migrations/0460_auto_20250226_0937.py create mode 100644 panel/migrations/0461_auto_20250302_1203.py create mode 100644 panel/migrations/0462_auto_20250302_1351.py create mode 100644 panel/migrations/0463_auto_20250302_1458.py create mode 100644 panel/migrations/0464_auto_20250302_1628.py create mode 100644 panel/migrations/0465_auto_20250303_1205.py create mode 100644 panel/migrations/0466_auto_20250303_1315.py create mode 100644 panel/migrations/0467_auto_20250303_1500.py create mode 100644 panel/migrations/0468_auto_20250304_1730.py create mode 100644 panel/migrations/0469_auto_20250305_1330.py create mode 100644 panel/migrations/0470_auto_20250307_1650.py create mode 100644 panel/migrations/0471_auto_20250316_2255.py create mode 100644 panel/migrations/0472_auto_20250413_1442.py create mode 100644 panel/migrations/0473_auto_20250413_1557.py create mode 100644 panel/migrations/0474_auto_20250414_1231.py create mode 100644 panel/migrations/0475_auto_20250414_1710.py create mode 100644 panel/migrations/0476_auto_20250420_1106.py create mode 100644 panel/migrations/0477_auto_20250420_1108.py create mode 100644 panel/migrations/0478_auto_20250428_1358.py create mode 100644 panel/migrations/0479_auto_20250503_1400.py create mode 100644 panel/migrations/0480_auto_20250504_1149.py create mode 100644 panel/migrations/0481_auto_20250504_1207.py create mode 100644 panel/migrations/0482_auto_20250505_1431.py create mode 100644 panel/migrations/0483_auto_20250506_1054.py create mode 100644 panel/migrations/0484_auto_20250510_1211.py create mode 100644 panel/migrations/0485_auto_20250511_1456.py create mode 100644 panel/migrations/0486_auto_20250517_0910.py create mode 100644 panel/migrations/0487_auto_20250517_1602.py create mode 100644 panel/migrations/0488_auto_20250517_1701.py create mode 100644 panel/migrations/0489_auto_20250518_1144.py create mode 100644 panel/migrations/0490_auto_20250520_1132.py create mode 100644 panel/migrations/0491_auto_20250525_1503.py create mode 100644 panel/migrations/0492_auto_20250525_1504.py create mode 100644 panel/migrations/0493_auto_20250525_1505.py create mode 100644 panel/migrations/0494_auto_20250526_0939.py create mode 100644 panel/migrations/0495_auto_20250526_1214.py create mode 100644 panel/migrations/0496_auto_20250526_1440.py create mode 100644 panel/migrations/0497_auto_20250527_0854.py create mode 100644 panel/migrations/0498_auto_20250527_1032.py create mode 100644 panel/migrations/0499_auto_20250528_1132.py create mode 100644 panel/migrations/0500_auto_20250528_1140.py create mode 100644 panel/migrations/0501_auto_20250528_1554.py create mode 100644 panel/migrations/0502_auto_20250531_1005.py create mode 100644 panel/migrations/0503_auto_20250531_1207.py create mode 100644 panel/migrations/0504_auto_20250531_1249.py create mode 100644 panel/migrations/0505_auto_20250531_1332.py create mode 100644 panel/migrations/0506_auto_20250531_1344.py create mode 100644 panel/migrations/0507_auto_20250531_1433.py create mode 100644 panel/migrations/0508_auto_20250601_1023.py create mode 100644 panel/migrations/0509_auto_20250602_1504.py create mode 100644 panel/migrations/0510_auto_20250603_1443.py create mode 100644 panel/migrations/0511_auto_20250607_0938.py create mode 100644 panel/migrations/0512_auto_20250607_1053.py create mode 100644 panel/migrations/0513_auto_20250607_1502.py create mode 100644 panel/migrations/0514_auto_20250607_1612.py create mode 100644 panel/migrations/0515_auto_20250607_1624.py create mode 100644 panel/migrations/0516_auto_20250609_1157.py create mode 100644 panel/migrations/0517_auto_20250609_1435.py create mode 100644 panel/migrations/0518_auto_20250610_1345.py create mode 100644 panel/migrations/0519_auto_20250610_1345.py create mode 100644 panel/migrations/0520_auto_20250628_1428.py create mode 100644 panel/migrations/0521_auto_20250628_1502.py create mode 100644 panel/migrations/0522_auto_20250707_0926.py create mode 100644 panel/migrations/0523_auto_20250707_0959.py create mode 100644 panel/migrations/0524_auto_20250708_0838.py create mode 100644 panel/migrations/0525_auto_20250708_1018.py create mode 100644 panel/migrations/0526_auto_20250708_1421.py create mode 100644 panel/migrations/0527_auto_20250709_1112.py create mode 100644 panel/migrations/0528_auto_20250713_1028.py create mode 100644 panel/migrations/0529_auto_20250714_1045.py create mode 100644 panel/migrations/0530_auto_20250714_1100.py create mode 100644 panel/migrations/0531_auto_20250719_0857.py create mode 100644 panel/migrations/0532_auto_20250719_0938.py create mode 100644 panel/migrations/0533_auto_20250720_1445.py create mode 100644 panel/migrations/0534_auto_20250720_1510.py create mode 100644 panel/migrations/0535_auto_20250722_1133.py create mode 100644 panel/migrations/0536_auto_20250722_1248.py create mode 100644 panel/migrations/0537_auto_20250723_0917.py create mode 100644 panel/migrations/0538_auto_20250723_1013.py create mode 100644 panel/migrations/0539_auto_20250727_0734.py create mode 100644 panel/migrations/0540_auto_20250727_1238.py create mode 100644 panel/migrations/0541_auto_20250727_1453.py create mode 100644 panel/migrations/0542_auto_20250803_0821.py create mode 100644 panel/migrations/0543_auto_20250803_1532.py create mode 100644 panel/migrations/0544_auto_20250805_0852.py create mode 100644 panel/migrations/0545_auto_20250806_1515.py create mode 100644 panel/migrations/0546_auto_20250806_1553.py create mode 100644 panel/migrations/0547_auto_20250809_0949.py create mode 100644 panel/migrations/0548_auto_20250809_1021.py create mode 100644 panel/migrations/0549_auto_20250809_1237.py create mode 100644 panel/migrations/0550_auto_20250809_1351.py create mode 100644 panel/migrations/0551_auto_20250809_1409.py create mode 100644 panel/migrations/0552_auto_20250809_1522.py create mode 100644 panel/migrations/0553_auto_20250809_1613.py create mode 100644 panel/migrations/0554_auto_20250810_1256.py create mode 100644 panel/migrations/0555_auto_20250810_1354.py create mode 100644 panel/migrations/0556_auto_20250810_1414.py create mode 100644 panel/migrations/0557_auto_20250811_0909.py create mode 100644 panel/migrations/0558_auto_20250817_0851.py create mode 100644 panel/migrations/0559_auto_20250817_1014.py create mode 100644 panel/migrations/0560_auto_20250817_1040.py create mode 100644 panel/migrations/0561_auto_20250817_1048.py create mode 100644 panel/migrations/0562_auto_20250817_1351.py create mode 100644 panel/migrations/0563_auto_20250818_0941.py create mode 100644 panel/migrations/0564_auto_20250820_1145.py create mode 100644 panel/migrations/0565_auto_20250820_1530.py create mode 100644 panel/migrations/0566_auto_20250825_1122.py create mode 100644 panel/migrations/0567_auto_20250825_1535.py create mode 100644 panel/migrations/0568_auto_20250825_1605.py create mode 100644 panel/migrations/0569_auto_20250826_0913.py create mode 100644 panel/migrations/0570_auto_20250826_0943.py create mode 100644 panel/migrations/0571_auto_20250827_1013.py create mode 100644 panel/migrations/0572_auto_20250827_1509.py create mode 100644 panel/migrations/0573_auto_20250829_0135.py create mode 100644 panel/migrations/0574_auto_20250830_0839.py create mode 100644 panel/migrations/0575_auto_20250831_0913.py create mode 100644 panel/migrations/0576_auto_20250901_0847.py create mode 100644 panel/migrations/0577_auto_20250901_1207.py create mode 100644 panel/migrations/0578_auto_20250902_1208.py create mode 100644 panel/migrations/0579_auto_20250902_1540.py create mode 100644 panel/migrations/0580_auto_20250903_0907.py create mode 100644 panel/migrations/0581_auto_20250914_1103.py create mode 100644 panel/migrations/0582_auto_20250914_1449.py create mode 100644 panel/migrations/0583_auto_20250914_1621.py create mode 100644 panel/migrations/0584_auto_20250914_1630.py create mode 100644 panel/migrations/0585_auto_20250915_0902.py create mode 100644 panel/migrations/0586_auto_20250915_1411.py create mode 100644 panel/migrations/0587_auto_20250915_1433.py create mode 100644 panel/migrations/0588_auto_20250915_1603.py create mode 100644 panel/migrations/0589_auto_20250916_0935.py create mode 100644 panel/migrations/0590_auto_20250916_1031.py create mode 100644 panel/migrations/0591_auto_20250916_1427.py create mode 100644 panel/migrations/0592_auto_20250920_0849.py create mode 100644 panel/migrations/0592_auto_20250920_0938.py create mode 100644 panel/migrations/0593_merge_0592_auto_20250920_0849_0592_auto_20250920_0938.py create mode 100644 panel/migrations/0594_auto_20250920_1257.py create mode 100644 panel/migrations/0595_auto_20250920_1554.py create mode 100644 panel/migrations/0595_auto_20250920_1648.py create mode 100644 panel/migrations/0596_merge_0595_auto_20250920_1554_0595_auto_20250920_1648.py create mode 100644 panel/migrations/0597_auto_20250920_1652.py create mode 100644 panel/migrations/0598_auto_20250921_0848.py create mode 100644 panel/migrations/0599_auto_20250922_0840.py create mode 100644 panel/migrations/0600_auto_20250922_1048.py create mode 100644 panel/migrations/0601_auto_20250922_1333.py create mode 100644 panel/migrations/0602_auto_20250922_1339.py create mode 100644 panel/migrations/0603_auto_20250924_1347.py create mode 100644 panel/migrations/0604_auto_20250924_1427.py create mode 100644 panel/migrations/0605_auto_20250925_1046.py create mode 100644 panel/migrations/0606_auto_20250925_1108.py create mode 100644 panel/migrations/0607_auto_20250925_1345.py create mode 100644 panel/migrations/0608_auto_20250925_1422.py create mode 100644 panel/migrations/0609_auto_20250925_1501.py create mode 100644 panel/migrations/0610_auto_20250927_2016.py create mode 100644 panel/migrations/0611_auto_20250927_2020.py create mode 100644 panel/migrations/0612_auto_20250927_2024.py create mode 100644 panel/migrations/0613_auto_20250927_2026.py create mode 100644 panel/migrations/0614_auto_20250927_2028.py create mode 100644 panel/migrations/0615_auto_20250927_2041.py create mode 100644 panel/migrations/0616_auto_20250929_1505.py create mode 100644 panel/migrations/0617_auto_20250929_1856.py create mode 100644 panel/migrations/0618_auto_20250929_1900.py create mode 100644 panel/migrations/0619_auto_20250930_1003.py create mode 100644 panel/migrations/0620_auto_20250930_1118.py create mode 100644 panel/migrations/0621_auto_20251001_1123.py create mode 100644 panel/migrations/0622_auto_20251004_1105.py create mode 100644 panel/migrations/0623_auto_20251005_1416.py create mode 100644 panel/migrations/0624_auto_20251006_0847.py create mode 100644 panel/migrations/0625_auto_20251006_0905.py create mode 100644 panel/migrations/0626_auto_20251006_1457.py create mode 100644 panel/migrations/0627_auto_20251006_1554.py create mode 100644 panel/migrations/0628_auto_20251007_1220.py create mode 100644 panel/migrations/0629_auto_20251007_1443.py create mode 100644 panel/migrations/0630_auto_20251007_1546.py create mode 100644 panel/migrations/0631_auto_20251008_1014.py create mode 100644 panel/migrations/0632_auto_20251012_1433.py create mode 100644 panel/migrations/0633_auto_20251018_2111.py create mode 100644 panel/migrations/0634_auto_20251021_1331.py create mode 100644 panel/migrations/0635_auto_20251021_1408.py create mode 100644 panel/migrations/0636_auto_20251021_1424.py create mode 100644 panel/migrations/0637_auto_20251021_1531.py create mode 100644 panel/migrations/0638_auto_20251021_1541.py create mode 100644 panel/migrations/0639_auto_20251022_1518.py create mode 100644 panel/migrations/0640_auto_20251025_1110.py create mode 100644 panel/migrations/0641_auto_20251025_1116.py create mode 100644 panel/migrations/0642_auto_20251026_1719.py create mode 100644 panel/migrations/0643_auto_20251026_2043.py create mode 100644 panel/migrations/0644_auto_20251026_2048.py create mode 100644 panel/migrations/0645_auto_20251027_0917.py create mode 100644 panel/migrations/0646_auto_20251027_1215.py create mode 100644 panel/migrations/0647_auto_20251028_0856.py create mode 100644 panel/migrations/0648_auto_20251028_0857.py create mode 100644 panel/migrations/0649_auto_20251028_0940.py create mode 100644 panel/migrations/0650_rename_trafic_to_traffic_code.py create mode 100644 panel/migrations/0651_auto_20251028_1219.py create mode 100644 panel/migrations/0652_auto_20251029_0933.py create mode 100644 panel/migrations/0653_auto_20251029_0954.py create mode 100644 panel/migrations/0654_auto_20251029_0955.py create mode 100644 panel/migrations/0655_auto_20251029_1055.py create mode 100644 panel/migrations/0656_auto_20251029_1609.py create mode 100644 panel/migrations/0657_auto_20251102_1322.py create mode 100644 panel/migrations/0658_auto_20251102_1437.py create mode 100644 panel/migrations/0659_auto_20251102_1614.py create mode 100644 panel/migrations/0660_auto_20251102_2037.py create mode 100644 panel/migrations/0661_auto_20251102_2044.py create mode 100644 panel/migrations/0662_auto_20251103_1453.py create mode 100644 panel/migrations/0663_auto_20251103_1525.py create mode 100644 panel/migrations/0664_auto_20251104_1353.py create mode 100644 panel/migrations/0665_auto_20251105_1111.py create mode 100644 panel/migrations/0666_auto_20251109_1151.py create mode 100644 panel/migrations/0667_auto_20251109_1443.py create mode 100644 panel/migrations/0668_auto_20251109_1448.py create mode 100644 panel/migrations/0669_auto_20251110_1001.py create mode 100644 panel/migrations/0670_auto_20251110_1100.py create mode 100644 panel/migrations/0671_auto_20251110_1101.py create mode 100644 panel/migrations/0672_auto_20251110_2116.py create mode 100644 panel/migrations/0673_auto_20251111_1150.py create mode 100644 panel/migrations/0674_auto_20251115_1354.py create mode 100644 panel/migrations/0675_auto_20251115_1509.py create mode 100644 panel/migrations/0676_auto_20251115_1709.py create mode 100644 panel/migrations/0677_auto_20251116_1459.py create mode 100644 panel/migrations/0678_auto_20251125_0840.py create mode 100644 panel/migrations/0679_auto_20251125_0843.py create mode 100644 panel/migrations/0680_auto_20251130_1538.py create mode 100644 panel/migrations/0681_auto_20251202_1539.py create mode 100644 panel/migrations/0682_auto_20251203_1617.py create mode 100644 panel/migrations/0683_auto_20251208_1617.py create mode 100644 panel/migrations/0684_auto_20251213_1632.py create mode 100644 panel/migrations/0685_auto_20251214_1635.py create mode 100644 panel/migrations/0686_auto_20251215_1654.py create mode 100644 panel/migrations/0687_auto_20251216_1653.py create mode 100644 panel/migrations/0688_auto_20251217_1648.py create mode 100644 panel/migrations/__init__.py create mode 100644 panel/models.py create mode 100644 panel/pos_helper.py create mode 100644 panel/poultry/__init__.py create mode 100644 panel/poultry/excel_processing.py create mode 100644 panel/poultry/helpers.py create mode 100644 panel/poultry/serializers.py create mode 100644 panel/poultry/views.py create mode 100644 panel/scripts/__init__.py create mode 100644 panel/scripts/database_merge.py create mode 100644 panel/temp_keys.py create mode 100644 panel/templatetags/__init__.py create mode 100644 panel/templatetags/jalali_filters.py create mode 100644 panel/tests.py create mode 100644 panel/urls.py create mode 100644 panel/validate_headers.py create mode 100644 panel/views.py create mode 100644 pdf/__init__.py create mode 100644 pdf/views.py create mode 100644 province_orderid.py create mode 100644 requirements.txt create mode 100644 samasat_cron.py create mode 100644 static/assets/fonts/BNaznnBd.ttf create mode 100644 static/assets/fonts/btitrb.ttf create mode 100644 static/assets/fonts/nazanin.ttf create mode 100644 static/assets/fonts/tits.ttf create mode 100644 static/assets/img/bazrasi.png create mode 100644 static/assets/img/bg.png create mode 100644 static/assets/img/blue_bg.png create mode 100644 static/assets/img/killhouse.png create mode 100644 static/assets/img/poultry.png create mode 100644 static/assets/img/summary_report.png create mode 100644 static/css/styles.css create mode 100644 static/css/styles_for_hatching_detail.css create mode 100644 temp_functions.py create mode 100644 temp_model.txt create mode 100644 templates/Digital_agreement_for_buying_and_selling.html create mode 100644 templates/base.html create mode 100644 templates/management_all_poultry_and_warehouse.html create mode 100644 templates/poultry_datail.html create mode 100644 templates/poultry_science_report.html create mode 100644 templates/summary_report.html create mode 100644 templatetags/__init__.py create mode 100644 templatetags/jalali_filters.py create mode 100644 ticket/__init__.py create mode 100644 ticket/admin.py create mode 100644 ticket/apps.py create mode 100644 ticket/bucket.py create mode 100644 ticket/customer_views.py create mode 100644 ticket/helper.py create mode 100644 ticket/migrations/0001_initial.py create mode 100644 ticket/migrations/0002_auto_20240612_0954.py create mode 100644 ticket/migrations/0003_alter_ticketsupport_ticket_id.py create mode 100644 ticket/migrations/0004_auto_20240612_1936.py create mode 100644 ticket/migrations/0005_messagesupport_sender.py create mode 100644 ticket/migrations/0006_auto_20240615_1418.py create mode 100644 ticket/migrations/0007_ticketsupport_to_user.py create mode 100644 ticket/migrations/0008_messagesupport_send_message.py create mode 100644 ticket/migrations/0009_ticketsupport_is_read.py create mode 100644 ticket/migrations/0010_remove_ticketsupport_is_read.py create mode 100644 ticket/migrations/0011_ticketsupport_last_message.py create mode 100644 ticket/migrations/0012_auto_20240907_1417.py create mode 100644 ticket/migrations/0013_ticketpermission.py create mode 100644 ticket/migrations/0014_auto_20240911_0853.py create mode 100644 ticket/migrations/0015_auto_20240912_1105.py create mode 100644 ticket/migrations/0016_ticketsupport_picture.py create mode 100644 ticket/migrations/0017_auto_20240912_1118.py create mode 100644 ticket/migrations/0018_auto_20240912_1258.py create mode 100644 ticket/migrations/0019_remove_ticketsupport_picture.py create mode 100644 ticket/migrations/0020_ticketsupport_role.py create mode 100644 ticket/migrations/0021_messagesupport_last_seen.py create mode 100644 ticket/migrations/0022_auto_20240917_0951.py create mode 100644 ticket/migrations/0023_auto_20241228_0919.py create mode 100644 ticket/migrations/0024_ticketsupport.py create mode 100644 ticket/migrations/0025_messagesupport_ticket.py create mode 100644 ticket/migrations/0026_messagesupport_file.py create mode 100644 ticket/migrations/0027_ticketsupport_unread_message.py create mode 100644 ticket/migrations/0028_messagesupport_read_by.py create mode 100644 ticket/migrations/0029_auto_20250126_2046.py create mode 100644 ticket/migrations/0030_auto_20250126_2122.py create mode 100644 ticket/migrations/0031_ticketsupport_referred_date.py create mode 100644 ticket/migrations/0032_ticketclosepermission.py create mode 100644 ticket/migrations/__init__.py create mode 100644 ticket/models.py create mode 100644 ticket/operator_views.py create mode 100644 ticket/serializers.py create mode 100644 ticket/tests.py create mode 100644 ticket/urls.py create mode 100644 ticket/views.py diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..24bbbce --- /dev/null +++ b/.env.local @@ -0,0 +1,24 @@ +SECRET_KEY=django-insecure-+4=r0m4tcetbuqo4cg8o%$q66-!&il++vza7*k01!#q#5z!_=s +DEBUG=True +ALLOWED_HOSTS=kubackend.rasadyaar.ir,ku.rasadyaar.ir,127.0.0.1,rasadyaar.ir,rasadyar.net,kubackend.rasadyar.com,ku.rasadyar.com,rasadyar.com +DB_NAME=kurdestan +DB_USER=postgres +DB_PASSWORD=Sf6SQuErrb8M34Lb8hZuHGR0n152Q857EYK52dP2pXf2N33GrKyDfvWQIw0GhUUE +DB_HOST=31.7.78.133 +DB_PORT=14330 +CELERY_BROKER_URL=redis://redis://localhost:6379 +CELERY_RESULT_BACKEND=redis://redis://localhost:6379 +CELERY_ACCEPT_CONTENT=application/json +CELERY_TASK_SERIALIZER=json +CELERY_RESULT_SERIALIZER=json +CELERY_TIMEZONE=Asia/Tehran +CORS_ORIGIN_ALLOW_ALL=True +CORS_ORIGIN_WHITELIST=http://localhost:8080,http://127.0.0.1:8080,http://127.0.0.1:3000,http://localhost:3000,https://kubackend.rasadyaar.ir,https://ku.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://kubackend.rasadyar.com,https://rasadyar.com +CORS_ALLOWED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080,http://127.0.0.1:3000,http://localhost:3000,https://kubackend.rasadyaar.ir,https://ku.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://kubackend.rasadyar.com,https://rasadyar.com +SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https +SECURE_SSL_REDIRECT=False +SESSION_COOKIE_SECURE=True +CSRF_COOKIE_SECURE=True +REDIS_URL=redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0 + +ENV RUNNING_IN_DOCKER=0 \ No newline at end of file diff --git a/.env.prod b/.env.prod new file mode 100644 index 0000000..20628de --- /dev/null +++ b/.env.prod @@ -0,0 +1,22 @@ +SECRET_KEY=django-insecure-+4=r0m4tcetbuqo4cg8o%$q66-!&il++vza7*k01!#q#5z!_=s +DEBUG=True +ALLOWED_HOSTS=kubackend.rasadyaar.ir,ku.rasadyaar.ir,127.0.0.1,rasadyaar.ir,rasadyar.net,kubackend.rasadyar.com,ku.rasadyar.com,rasadyar.com +DB_NAME=kurdestan +DB_USER=postgres +DB_PASSWORD=Sf6SQuErrb8M34Lb8hZuHGR0n152Q857EYK52dP2pXf2N33GrKyDfvWQIw0GhUUE +DB_HOST=31.7.78.133 +DB_PORT=14330 +CELERY_BROKER_URL=redis://redis://localhost:6379 +CELERY_RESULT_BACKEND=redis://redis://localhost:6379 +CELERY_ACCEPT_CONTENT=application/json +CELERY_TASK_SERIALIZER=json +CELERY_RESULT_SERIALIZER=json +CELERY_TIMEZONE=Asia/Tehran +CORS_ORIGIN_ALLOW_ALL=True +CORS_ORIGIN_WHITELIST=http://localhost:8080,http://127.0.0.1:8080,http://127.0.0.1:3000,http://localhost:3000,https://kubackend.rasadyaar.ir,https://ku.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://kubackend.rasadyar.com,https://rasadyar.com +CORS_ALLOWED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080,http://127.0.0.1:3000,http://localhost:3000,https://kubackend.rasadyaar.ir,https://ku.rasadyaar.ir,https://rasadyaar.ir,https://rasadyar.net,https://kubackend.rasadyar.com,https://rasadyar.com +SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,https +SECURE_SSL_REDIRECT=False +SESSION_COOKIE_SECURE=True +CSRF_COOKIE_SECURE=True +REDIS_URL=redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..765e91d --- /dev/null +++ b/.gitignore @@ -0,0 +1,136 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a templates +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ +.idea +.vscode +.code +.idea/ +.vscode/ +.code/ +.idea/KuChickenLiara.iml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b3f47cc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ + +FROM seniorkian/python39-asalian:1.0.1 +ENV TZ="Asia/Tehran" +WORKDIR /app +COPY ./requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY . . + +EXPOSE 8000 + +CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"] diff --git a/GateWay.py b/GateWay.py new file mode 100644 index 0000000..2bc758b --- /dev/null +++ b/GateWay.py @@ -0,0 +1,75 @@ +import requests + + +def PaymentGateway(deposit_id=None, amount=None, order_id=None): + data = { + "amount": amount, + "orderId": order_id, + "additionalData": deposit_id, + + } + req = requests.post( + url='https://ravandno.ir/cumulative-dynamic-pay-request/', + data=data, + verify=False + ) + if req.status_code == 200: + return {req.status_code: req.json()['refId']} + else: + return {req.status_code: req.json()['error']} + + # result = req.json()['refId'] if req.status_code == 200 else 'error' + # return result + # return {req.status_code: req.content} + + +# def PaymentGatewayZarinPal(amount=None, description=None, province_code=None, wages=None, link=None): +# data = { +# "amount": amount, +# "description": description, +# "provincecode": province_code, +# "wages": wages, +# "isLink": link +# } +# +# headers = { +# 'Content-Type': 'application/json' +# } +# +# req = requests.post( +# url='https://pay.rasadyaar.ir/zarinpay', +# json=data, +# headers=headers, +# verify=False +# ) +# if req.status_code == 201: +# return {req.status_code: req.json()['authority']} +# +# else: +# return {req.status_code: req.json()['error']} + + +def PaymentGatewayZarinPal(amount=None, phone=None, province_code=None, link=None,wages=None): + data = { + "amount": amount, + "phone": phone, + "provincecode": province_code, + "isLink": link, + "wages": wages + } + + headers = { + 'Content-Type': 'application/json' + } + + req = requests.post( + url='https://pay.rasadyar.net/sep-pay-request/', + json=data, + headers=headers, + verify=False + ) + if req.status_code == 201: + return {req.status_code: req.json()['token']} + + else: + return {req.status_code: req.json()['error']} \ No newline at end of file diff --git a/KuChicken/__init__.py b/KuChicken/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/KuChicken/asgi.py b/KuChicken/asgi.py new file mode 100644 index 0000000..071c8b1 --- /dev/null +++ b/KuChicken/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for KuChicken project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'KuChicken.settings') + +application = get_asgi_application() diff --git a/KuChicken/celery.py b/KuChicken/celery.py new file mode 100644 index 0000000..252b9cf --- /dev/null +++ b/KuChicken/celery.py @@ -0,0 +1,5 @@ +from celery import Celery + +app = Celery('KuChicken', broker='redis://127.0.0.1:6379', backend='redis://127.0.0.1:6379') +# app = Celery('KuChicken', broker='redis://45.159.115.160:6379/0', backend='redis://45.159.115.160:6379/0') +app.autodiscover_tasks() \ No newline at end of file diff --git a/KuChicken/settings.py b/KuChicken/settings.py new file mode 100644 index 0000000..ef6f786 --- /dev/null +++ b/KuChicken/settings.py @@ -0,0 +1,229 @@ +""" +Django settings for KuChicken project. + +Generated by 'django-admin startproject' using Django 4.1.5. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/4.1/ref/settings/ +""" +import socket +from pathlib import Path +import os +from dotenv import load_dotenv + +BASE_DIR = Path(__file__).resolve().parent.parent + +loc_ip = socket.gethostbyname(socket.gethostname()) + + +if not os.getenv("RUNNING_IN_DOCKER"): + dotenv_path = BASE_DIR / ".env.local" + load_dotenv(dotenv_path) + +SECRET_KEY = os.environ.get("SECRET_KEY") + + +DEBUG = os.environ.get("DEBUG") + +ALLOWED_HOSTS = os.environ.get("ALLOWED_HOSTS").split(',') + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'authentication.apps.AuthenticationConfig', + 'panel.apps.PanelConfig', + 'LiveStock.apps.LivestockConfig', + 'notification.apps.NotificationConfig', + 'oauth2_provider', + 'corsheaders', + 'rest_framework', + 'django_filters', + 'ticket.apps.TicketConfig', + 'RasadyaarBale' + +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'oauth2_provider.middleware.OAuth2TokenMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + +] + +ROOT_URLCONF = 'KuChicken.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [BASE_DIR / 'templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'KuChicken.wsgi.application' + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + 'NAME': os.environ.get("DB_NAME"), + 'USER': os.environ.get("DB_USER"), + 'PASSWORD': os.environ.get("DB_PASSWORD"), + 'HOST': os.environ.get("DB_HOST"), + 'PORT': os.environ.get("DB_PORT"), + } + +} + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +REST_FRAMEWORK = { + 'DEFAULT_AUTHENTICATION_CLASSES': ( + 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', + ), + 'DEFAULT_PERMISSION_CLASSES': ( + 'rest_framework.permissions.IsAuthenticated', + ), + 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] +} + +OAUTH2_PROVIDER = { + 'REFRESH_TOKEN_EXPIRE_SECONDS': 1800, + 'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore', + 'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}, + 'ACCESS_TOKEN_EXPIRE_SECONDS': 1800 +} + +AUTHENTICATION_BACKENDS = [ + 'oauth2_provider.backends.OAuth2Backend', + 'django.contrib.auth.backends.ModelBackend', +] + +CACHES = { + "default": { + "BACKEND": "django_redis.cache.RedisCache", + "LOCATION": "redis://:ydnW4hwzuDRYcTX3FWCHgQ1f@apo.liara.cloud:33740/0", + "OPTIONS": { + "CLIENT_CLASS": "django_redis.client.DefaultClient", + }, + "KEY_PREFIX": "You have successfully set up a key-value pair!" + } +} + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'Asia/Tehran' + +USE_I18N = True + +USE_L10N = False + +USE_TZ = False + +DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S' + +CACHE_TTL = 60 * 2 + +STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), +] + +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' +DATA_UPLOAD_MAX_MEMORY_SIZE = 50242880 + +CELERY_BROKER_URL = os.environ.get("CELERY_BROKER_URL") +CELERY_RESULT_BACKEND = os.environ.get("CELERY_RESULT_BACKEND") +CELERY_ACCEPT_CONTENT = os.environ.get("CELERY_ACCEPT_CONTENT") +CELERY_TASK_SERIALIZER = os.environ.get("CELERY_TASK_SERIALIZER") +CELERY_RESULT_SERIALIZER = os.environ.get("CELERY_RESULT_SERIALIZER") +CELERY_TIMEZONE = os.environ.get("CELERY_TIMEZONE") + +if DEBUG: + MIDDLEWARE += [ + 'debug_toolbar.middleware.DebugToolbarMiddleware', + ] + INSTALLED_APPS += [ + 'debug_toolbar', + + ] + INTERNAL_IPS = [ + "82.115.17.44", + "185.143.234.120", + "45.159.115.160", + + ] + + hostname, _, ips = socket.gethostbyname_ex(socket.gethostname()) + INTERNAL_IPS += [".".join(ip.split(".")[:-1] + ["1"]) for ip in ips] + + DEBUG_TOOLBAR_PANELS = [ + 'debug_toolbar.panels.history.HistoryPanel', + 'debug_toolbar.panels.versions.VersionsPanel', + 'debug_toolbar.panels.timer.TimerPanel', + 'debug_toolbar.panels.settings.SettingsPanel', + 'debug_toolbar.panels.headers.HeadersPanel', + 'debug_toolbar.panels.request.RequestPanel', + 'debug_toolbar.panels.sql.SQLPanel', + 'debug_toolbar.panels.staticfiles.StaticFilesPanel', + 'debug_toolbar.panels.templates.TemplatesPanel', + 'debug_toolbar.panels.cache.CachePanel', + 'debug_toolbar.panels.signals.SignalsPanel', + 'debug_toolbar.panels.logging.LoggingPanel', + 'debug_toolbar.panels.redirects.RedirectsPanel', + 'debug_toolbar.panels.profiling.ProfilingPanel', + ] + + import mimetypes + + mimetypes.add_type("application/javascript", ".js", True) + + DEBUG_TOOLBAR_CONFIG = { + 'INTERCEPT_REDIRECTS': False, + } + +CORS_ORIGIN_ALLOW_ALL = os.environ.get("CORS_ORIGIN_ALLOW_ALL", "False").lower() == "true" +CORS_ORIGIN_WHITELIST = os.environ.get("CORS_ORIGIN_WHITELIST").split(',') + +CORS_ALLOWED_ORIGINS = os.environ.get("CORS_ORIGIN_WHITELIST").split(',') + +# SECURE_PROXY_SSL_HEADER = os.environ.get("SECURE_PROXY_SSL_HEADER").split(',') +# SECURE_SSL_REDIRECT = os.environ.get("SECURE_SSL_REDIRECT") +# SESSION_COOKIE_SECURE = os.environ.get("SESSION_COOKIE_SECURE") +# CSRF_COOKIE_SECURE = os.environ.get("CSRF_COOKIE_SECURE") diff --git a/KuChicken/urls.py b/KuChicken/urls.py new file mode 100644 index 0000000..ad7b3e9 --- /dev/null +++ b/KuChicken/urls.py @@ -0,0 +1,28 @@ +"""KuChicken URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path, include + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', include('authentication.urls')), + path('LiveStock/', include('LiveStock.urls')), + path('', include('panel.urls')), + path('', include('notification.urls')), + path('', include('ticket.urls')), + path('bale/', include('RasadyaarBale.urls')), +] + diff --git a/KuChicken/wsgi.py b/KuChicken/wsgi.py new file mode 100644 index 0000000..48fba28 --- /dev/null +++ b/KuChicken/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for KuChicken project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'KuChicken.settings') + +application = get_wsgi_application() diff --git a/LiveStock/Contractor/__init__.py b/LiveStock/Contractor/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Contractor/excel_processing.py b/LiveStock/Contractor/excel_processing.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Contractor/filterset.py b/LiveStock/Contractor/filterset.py new file mode 100644 index 0000000..a0c6134 --- /dev/null +++ b/LiveStock/Contractor/filterset.py @@ -0,0 +1,20 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import Contractor + + +class ContractorFilterSet(filters.FilterSet): + class Meta: + model = Contractor + fields = [ + 'address__city__name', + 'contractor_code', + 'fullname', + 'entity_code', + 'national_id', + 'company_name', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname' + ] diff --git a/LiveStock/Contractor/helpers.py b/LiveStock/Contractor/helpers.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Contractor/serializers.py b/LiveStock/Contractor/serializers.py new file mode 100644 index 0000000..33ef9aa --- /dev/null +++ b/LiveStock/Contractor/serializers.py @@ -0,0 +1,14 @@ +from rest_framework import serializers + +from LiveStock.models import Union, Contractor +from authentication.serializer.serializer import BankCardSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import SystemAddressSerializer + + +class ContractorSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Contractor + fields = '__all__' diff --git a/LiveStock/Contractor/urls.py b/LiveStock/Contractor/urls.py new file mode 100644 index 0000000..08af05a --- /dev/null +++ b/LiveStock/Contractor/urls.py @@ -0,0 +1,14 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.Contractor import views as contractor_views +router = DefaultRouter() +router.register( + r'contractor-views', + contractor_views.ContractorViewSet, + basename="contractor-views" +) + + +urlpatterns = [ + path('', include(router.urls)), + ] \ No newline at end of file diff --git a/LiveStock/Contractor/views.py b/LiveStock/Contractor/views.py new file mode 100644 index 0000000..d592bbc --- /dev/null +++ b/LiveStock/Contractor/views.py @@ -0,0 +1,60 @@ +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.Contractor.filterset import ContractorFilterSet +from LiveStock.Contractor.serializers import ContractorSerializer + +from LiveStock.helpers import build_query, CustomPagination +from LiveStock.models import Contractor +from authentication.models import SystemUserProfile + + +class ContractorViewSet(viewsets.ModelViewSet): + queryset = Contractor.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ContractorSerializer + filterset_class = ContractorFilterSet + pagination_class = CustomPagination + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + union = user.contractor_user.all() + + serializer = self.serializer_class(union[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + contractor = Contractor.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + contractor = contractor.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + page = self.paginate_queryset(contractor) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(contractor, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + contractor = Contractor.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + + serializer = self.serializer_class(contractor) + + serializer.update(instance=contractor, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + contractor = Contractor.objects.get(key=request.GET["key"]) + contractor.trash = True + contractor.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) diff --git a/LiveStock/Cooperative/__init__.py b/LiveStock/Cooperative/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Cooperative/excel_processing.py b/LiveStock/Cooperative/excel_processing.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Cooperative/filterset.py b/LiveStock/Cooperative/filterset.py new file mode 100644 index 0000000..88c0c37 --- /dev/null +++ b/LiveStock/Cooperative/filterset.py @@ -0,0 +1,17 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import Cooperative + + +class CooperativeFilterSet(filters.FilterSet): + class Meta: + model = Cooperative + fields = [ + 'address__city__name', + 'name', + 'mobile', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname' + ] diff --git a/LiveStock/Cooperative/helpers.py b/LiveStock/Cooperative/helpers.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Cooperative/serializers.py b/LiveStock/Cooperative/serializers.py new file mode 100644 index 0000000..24360a5 --- /dev/null +++ b/LiveStock/Cooperative/serializers.py @@ -0,0 +1,66 @@ +from rest_framework import serializers + +from LiveStock.models import Cooperative, LiveStockRolseProduct +from authentication.serializer.serializer import BankCardSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import SystemAddressSerializer +from ticket.serializers import SystemUserProfileForTicketPermissionSerializer + + +class CooperativeSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = Cooperative + fields = '__all__' + + +class CooperativeForSharesSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = Cooperative + fields = ['user', 'name'] + + +class CooperativeForAllocationsReportSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Cooperative + fields = ['key','user', 'name','info'] + + def get_info(self, obj): + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + product =products[self.context.get('request').GET['name']] + cooperative_roles = LiveStockRolseProduct.objects.get(cooperative=obj,parent_product__name=product) + total_weight = cooperative_roles.total_weight + total_receipt_weight = cooperative_roles.total_receipt_weight + total_allocated_weight = cooperative_roles.total_allocated_weight + total_remain_weight = cooperative_roles.total_remain_weight + return { + "total_weight": total_weight, + "total_receipt_weight": total_receipt_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + +class CooperativeForPosSerializer(serializers.ModelSerializer): + user = SystemUserProfileForTicketPermissionSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Cooperative + fields = ['user', 'name', 'address'] diff --git a/LiveStock/Cooperative/urls.py b/LiveStock/Cooperative/urls.py new file mode 100644 index 0000000..790d887 --- /dev/null +++ b/LiveStock/Cooperative/urls.py @@ -0,0 +1,21 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.Cooperative import views as cooperative_views +router = DefaultRouter() +router.register( + r'cooperative-views', + cooperative_views.CooperativeViewSet, + basename="cooperative-views" +) + +router.register( + r'cooperative-warehouse', + cooperative_views.CooperativeWarehouseDashboardViewSet, + basename="cooperative-warehouse" +) + + + +urlpatterns = [ + path('', include(router.urls)), + ] \ No newline at end of file diff --git a/LiveStock/Cooperative/views.py b/LiveStock/Cooperative/views.py new file mode 100644 index 0000000..cf8841b --- /dev/null +++ b/LiveStock/Cooperative/views.py @@ -0,0 +1,196 @@ +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.response import Response +import requests +from django.contrib.auth.models import User, Group + +from LiveStock.Cooperative.filterset import CooperativeFilterSet +from LiveStock.Cooperative.serializers import CooperativeSerializer, CooperativeForAllocationsReportSerializer +from LiveStock.helpers import build_query, CustomPagination +from LiveStock.models import Cooperative, CooperativeProductsShare, LiveStockProduct, LiveStockRolseProduct +from authentication.models import SystemUserProfile, City, Province, SystemAddress +from authentication.views import ARTA_URL_CHANGE_MOBILE_NUMBER, ARTA_URL_REGISTER +from panel.admin import PROJECT_API_KEY + + +class CooperativeViewSet(viewsets.ModelViewSet): + queryset = Cooperative.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CooperativeSerializer + filterset_class = CooperativeFilterSet + pagination_class = CustomPagination + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="Cooperative") + city = City.objects.get(name=request.data['city']) + request.data.pop('city') + province = Province.objects.get(key=city.province.key) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if Cooperative.objects.filter(user=system_profile, trash=False).exists(): + return Response({"result": "این تعاونی قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "123456" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + address = SystemAddress(city=city, province=province, address=request.data['address'], + postal_code=request.data['postal_code']) + address.save() + system_profile.role.add(group) + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('postal_code') + products = LiveStockProduct.objects.filter(trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + cooperative = serializer.create(validated_data=request.data) + cooperative.user = system_profile + cooperative.address = address + cooperative.save() + for product in products: + share = CooperativeProductsShare( + cooperative=cooperative, + product=product + ) + share.save() + cooperative_roles_product = LiveStockRolseProduct( + cooperative=cooperative, + parent_product=product + + ) + cooperative_roles_product.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + cooperative = user.cooperative_user.all() + + serializer = self.serializer_class(cooperative[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + cooperatives = cooperatives.filter( + build_query(self.filterset_class.Meta.fields, search) + ) + page = self.paginate_queryset(cooperatives) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(cooperatives, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + cooperative = Cooperative.objects.get(key=request.data['cooperative_key'], trash=False) + address = SystemAddress.objects.get(key=cooperative.address.key, trash=False) + request.data.pop('cooperative_key') + if 'first_name' in request.data.keys(): + system_user_profile = SystemUserProfile.objects.get(key=cooperative.user.key, trash=False) + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + city = City.objects.get(name=request.data['city']) + province = Province.objects.get(key=city.province.key) + address.city = city + address.province = province + address.address = request.data['address'] + address.postal_code = request.data['postal_code'] + address.save() + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('city') + + serializer = self.serializer_class(cooperative) + serializer.update(instance=cooperative, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CooperativeWarehouseDashboardViewSet(viewsets.ModelViewSet): + queryset = Cooperative.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CooperativeForAllocationsReportSerializer + filterset_class = CooperativeFilterSet + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + cooperatives = cooperatives.filter( + build_query(self.filterset_class.Meta.fields, search) + ) + page = self.paginate_queryset(cooperatives) + if page is not None: + serializer = self.serializer_class(page, many=True,context={"request":request}) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(cooperatives, many=True,context={"request":request}) + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/LiveStock/Jahad/__init__.py b/LiveStock/Jahad/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Jahad/excel_processing.py b/LiveStock/Jahad/excel_processing.py new file mode 100644 index 0000000..4ebe9fb --- /dev/null +++ b/LiveStock/Jahad/excel_processing.py @@ -0,0 +1,1906 @@ +from datetime import datetime +from io import BytesIO +import json + +from django.db.models import Sum +from django.http import QueryDict, HttpResponse +from openpyxl import Workbook +from openpyxl.styles import Alignment + +from LiveStock.Cooperative.filterset import CooperativeFilterSet +from LiveStock.Jahad.filterset import LiveStockAllocationsFilterSet +from LiveStock.Rancher.helpers import update_one_rancher +from LiveStock.helpers import build_query +from LiveStock.models import LiveStockProduct, LiveStockAllocations, LiveStockRolseProduct, Cooperative, Rancher +from authentication.models import SystemUserProfile +from panel.ProvinceOperator.serializers import PosMachineTransactionsForLiveStockSerializer, \ + CooperativeForAllocationsReportSerializer, PosMachineTransactionsSerializer, \ + PosMachineTransactionsForLiveStockSerializerForExcel +from panel.convert_date import convert_to_shamsi +from panel.filterset import PosMachineTransactionsFilterSet +from panel.helper_excel import shamsi_date, create_header, excel_description, create_header_freez, create_value +from panel.models import PosMachineTransactions, ProductsTransactions + + +def allocation_live_stock_excel(request): + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + } + name = products[request.GET.get('name')] + + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + allocations = LiveStockAllocations.objects.filter(jahad__user=user, allocate_from="LiveStockProvinceJahad", + trash=False, product__parent_product=product).order_by( + 'id').exclude(allocate_to='LiveStockProvinceJahad') + roles_new_product = LiveStockRolseProduct.objects.filter(jahad__isnull=False, trash=False + , parent_product=product).first() + elif request.GET['role'] == 'Union': + allocations = LiveStockAllocations.objects.filter(union__user=user, trash=False, allocate_from="Union", + product__parent_product=product).order_by('id') + roles_new_product = LiveStockRolseProduct.objects.filter(union__user=user, trash=False, + parent_product=product).first() + else: + allocations = LiveStockAllocations.objects.filter(cooperative__user=user, charge=False, + allocate_to="Cooperative", + trash=False, product__parent_product=product).order_by( + 'id') + roles_new_product = LiveStockRolseProduct.objects.filter(cooperative__user=user, trash=False, + parent_product=product).first() + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + allocations = allocations.filter( + build_query(LiveStockAllocationsFilterSet.Meta.fields, value) + ) + excel_options = [ + 'ردیف', + 'وزن(کیلوگرم)', + 'تخصیص از', + 'تخصیص به', + 'ثبت کننده', + 'تاریخ ثبت', + 'مکان دریافت', + 'توضیحات', + + + ] + + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if request.GET['role'] == "LiveStockProvinceJahad": + + header_list = [ + 'ورودی به انبار', + 'تخصیص جهاد به اتحادیه ', + 'تخصیص جهاد به تعاونی ها ', + 'مجموع تخصیصات', + 'مجموع تخصیصات اتحادیه به تعاونی', + 'مجموع تخصیص به تعاونی ها', + 'توزیع به دامداران', + 'مجموع توزیع به دامداران', + 'مانده انبار جهاد استان', + 'مانده انبار اتحادیه', + 'مانده انبار تعاونی ها', + + ] + else: + header_list = [ + 'ورودی به انبار', + + 'تخصیص به تعاونی ها', + 'توزیع به دامداران', + 'مجموع تخصیص و توزیع به دامداران', + 'مانده انبار', + + ] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='C2') + + create_header(worksheet, header_list, 1, 3, height=20) + + excel_description(worksheet, 'B1', f'تخصیصات {name}', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + + l = 5 + m = 1 + if allocations: + for data in allocations: + if data.allocate_from == 'LiveStockProvinceJahad': + allocate_from="جهاد" + allocate_from_full_name=data.jahad.user.fullname + else: + allocate_from = "اتحادیه" + allocate_from_full_name=data.union.user.fullname + if data.allocate_to == 'Union': + allocate_to = "اتحادیه" + allocate_to_full_name = data.union.user.fullname + else: + allocate_to = "تعاونی" + allocate_to_full_name = data.cooperative.user.fullname + + list1 = [ + m, + data.weight, + f'{allocate_from}({allocate_from_full_name})', + f'{allocate_to}({allocate_to_full_name})', + allocate_from_full_name, + str(shamsi_date(data.create_date)), + data.place, + data.description + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + if allocations: + jahat_to_union = allocations.filter(jahad__isnull=False, allocate_to='Union') + jahat_to_cooperative = allocations.filter(jahad__isnull=False, allocate_to='Cooperative') + union_to_cooperative = LiveStockAllocations.objects.filter(union__isnull=False, allocate_to='Cooperative') + + jahat_to_union_weight = jahat_to_union.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_union_real_weight = jahat_to_union.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + jahat_to_cooperative_weight = jahat_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_cooperative_real_weight = jahat_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + union_to_cooperative_weight = union_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + union_to_cooperative_real_weight = union_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + roles_product = LiveStockRolseProduct.objects.filter(trash=False) + union_remain = roles_product.filter(union__isnull=False) + cooperative_remain = roles_product.filter(cooperative__isnull=False) + role_product_union = union_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative = cooperative_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative_receipt_weight = cooperative_remain.aggregate(total=Sum('total_receipt_weight'))[ + 'total'] or 0 + if request.GET['role'] == 'Union': + value_header_list = [ + + roles_new_product.total_weight, + + roles_new_product.total_allocated_weight, + 0, + 0 + roles_new_product.total_allocated_weight, + roles_new_product.total_remain_weight, + + ] + + else: + value_header_list = [ + + roles_new_product.total_weight, + jahat_to_union_weight, + jahat_to_cooperative_weight, + + roles_new_product.total_allocated_weight, + union_to_cooperative_weight, + jahat_to_cooperative_weight + union_to_cooperative_weight, + 0, + 0, + roles_new_product.total_remain_weight, + role_product_union, + role_product_cooperative, + + ] + create_value(worksheet, value_header_list, 4, 1) + + weight = allocations.aggregate(total=Sum('weight'))['total'] or 0 + + + list2 = [ + 'مجموع==>', + weight, + '', + '', + '', + '', + '', + '', + + + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" تخصیصات {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def warehouse_live_stock_excel(request): + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + } + name = products[request.GET.get('name')] + + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + allocations = LiveStockAllocations.objects.filter(jahad__user=user, trash=False, + product__parent_product=product, + allocate_to='LiveStockProvinceJahad').order_by('id') + roles_new_product = LiveStockRolseProduct.objects.filter(jahad__isnull=False, trash=False + , parent_product=product).first() + elif request.GET['role'] == 'Union': + allocations = LiveStockAllocations.objects.filter(allocate_from='LiveStockProvinceJahad', union__user=user, + trash=False, product__parent_product=product).order_by( + 'id') + roles_new_product = LiveStockRolseProduct.objects.filter(union__user=user, trash=False, + parent_product=product).first() + else: + allocations = LiveStockAllocations.objects.filter( + charge=True, cooperative__user=user, + trash=False, product__parent_product=product).order_by('id') + roles_new_product = LiveStockRolseProduct.objects.filter(cooperative__user=user, trash=False, + parent_product=product).first() + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + allocations = allocations.filter( + build_query(LiveStockAllocationsFilterSet.Meta.fields, value) + ) + excel_options = [ + 'ردیف', + 'وزن(کیلوگرم)', + 'تخصیص از انبار', + 'دریافت در انبار', + 'ثبت کننده', + 'تاریخ ثبت', + 'مکان دریافت', + 'توضیحات', + + + ] + + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if request.GET['role'] == "LiveStockProvinceJahad": + + header_list = [ + 'ورودی به انبار', + 'تخصیص جهاد به اتحادیه ', + 'تخصیص جهاد به تعاونی ها ', + 'مجموع تخصیصات', + 'مجموع تخصیصات اتحادیه به تعاونی', + 'مجموع تخصیص به تعاونی ها', + 'توزیع به دامداران', + 'مجموع توزیع به دامداران', + 'مانده انبار جهاد استان', + 'مانده انبار اتحادیه', + 'مانده انبار تعاونی ها', + + ] + elif request.GET['role'] == "Union": + header_list = [ + 'ورودی به انبار', + + 'تخصیص به تعاونی ها', + 'توزیع به دامداران', + 'مجموع تخصیص و توزیع به دامداران', + 'مانده انبار', + + ] + else: + header_list = [ + 'سهمیه دریافتی', + 'ورودی به انبار', + + 'توزیع به دامداران', + 'مانده انبار', + + ] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='C2') + + create_header(worksheet, header_list, 1, 3, height=20) + + excel_description(worksheet, 'B1', f'انبار {name}', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + + l = 5 + m = 1 + if allocations: + for data in allocations: + if data.allocate_from == 'LiveStockProvinceJahad': + allocate_from="جهاد" + allocate_from_full_name=data.jahad.user.fullname + else: + allocate_from = "اتحادیه" + allocate_from_full_name=data.union.user.fullname + if data.allocate_to == 'Union': + allocate_to = "اتحادیه" + allocate_to_full_name = data.union.user.fullname + elif data.allocate_to == 'LiveStockProvinceJahad': + allocate_to="جهاد" + allocate_to_full_name=data.jahad.user.fullname + else: + allocate_to = "تعاونی" + allocate_to_full_name = data.cooperative.user.fullname + + list1 = [ + m, + data.weight, + f'{allocate_from}({allocate_from_full_name})', + f'{allocate_to}({allocate_to_full_name})', + allocate_from_full_name, + str(shamsi_date(data.create_date)), + data.place, + data.description + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + if allocations: + jahat_to_union = allocations.filter(jahad__isnull=False, allocate_to='Union') + union_to_cooperative = LiveStockAllocations.objects.filter(union__isnull=False, allocate_to='Cooperative') + jahat_to_cooperative_filter = LiveStockAllocations.objects.filter(jahad__isnull=False, allocate_to='Cooperative') + jahat_to_cooperative = jahat_to_cooperative_filter.filter(jahad__isnull=False, allocate_to='Cooperative') + + jahat_to_union_weight = jahat_to_union.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_union_real_weight = jahat_to_union.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + jahat_to_cooperative_weight = jahat_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_cooperative_real_weight = jahat_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + union_to_cooperative_weight = union_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + union_to_cooperative_real_weight = union_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + roles_product = LiveStockRolseProduct.objects.filter(trash=False) + union_remain = roles_product.filter(union__isnull=False) + cooperative_remain = roles_product.filter(cooperative__isnull=False) + role_product_union = union_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative = cooperative_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative_receipt_weight = cooperative_remain.aggregate(total=Sum('total_receipt_weight'))[ + 'total'] or 0 + if request.GET['role'] == 'Union': + value_header_list = [ + + roles_new_product.total_weight, + + roles_new_product.total_allocated_weight, + 0, + 0 + roles_new_product.total_allocated_weight, + roles_new_product.total_remain_weight, + + ] + if request.GET['role'] == 'Cooperative': + value_header_list = [ + role_product_cooperative_receipt_weight, + roles_new_product.total_weight, + + 0, + + roles_new_product.total_remain_weight, + + ] + else: + value_header_list = [ + + roles_new_product.total_weight, + jahat_to_union_weight, + jahat_to_cooperative_weight, + + roles_new_product.total_allocated_weight, + union_to_cooperative_weight, + jahat_to_cooperative_weight + union_to_cooperative_weight, + 0, + 0, + roles_new_product.total_remain_weight, + role_product_union, + role_product_cooperative, + + ] + create_value(worksheet, value_header_list, 4, 1) + + weight = allocations.aggregate(total=Sum('weight'))['total'] or 0 + + + list2 = [ + 'مجموع==>', + weight, + '', + '', + '', + '', + '', + '', + + + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="انبار {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def live_stock_transaction_excel(request): + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + } + name = products[request.GET.get('name')] + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'mobile', + 'natcode', + 'fullname', + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + filters = {} + + + + + + excel_options = [ + 'ردیف', + 'تاریخ', + 'خریدار', + 'کد ملی خریدار', + 'موبایل خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'وضعیت', + 'محل تحویل', + 'کالا', + 'کد ملی فروشنده', + 'دام سنگین', + 'دام سبک', + 'وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + + + ] + header_list = [ + 'تعداد تراکنش ها', + 'مجموع دام سنگین', + 'مجموع دام سبک', + + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + + ] + sheet_names=['تراکنش های موفق'] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + for name in sheet_names: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if sheet_name == 'تراکنش های موفق': + cooperative_key = request.GET.get('cooperative_key') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + state = request.GET.get('state') + filters = {} + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + "sheep_concentrate": "کنسانتره گوسفندی", + "high_cow_concentrate": "کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate": "کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate": "کنسانتره گوساله پرواری", + } + product = products[request.GET.get('name')] + + filters['paid'] = True + + + cooperative_key = request.GET.get('cooperative_key') + if role in ('LiveStockProvinceJahad', 'Union'): + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + + else: + transactions = PosMachineTransactions.objects.filter(trash=False, live_stock=True).order_by('-date') + + + elif cooperative_key: + cooperative = Cooperative.objects.get(key=cooperative_key) + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + else: + + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).order_by('-date') + + + + else: + cooperative = Cooperative.objects.get(user=user) + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + + else: + + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).order_by('-date') + + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + transactions = transactions.filter(**filters).order_by('-date') + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + transactions = transactions.filter(**filters).order_by('-date') + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + + create_header(worksheet, header_list, 5, 3, height=20) + + excel_description(worksheet, 'B1', f'تراکنش های موفق محصول {name}', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + + l = 5 + m = 1 + if serializer: + for data in serializer: + date = datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + shares=data.get('shares') or {} + additional = json.loads(data['additional']) if data.get('additional', '').strip() else {} + if additional.get('isTaavoni'): + tavanoni='تعاونی' if additional['isTaavoni'] == True else 'کارخانه' + else: + tavanoni='-' + list1 = [ + m, + str(convert_to_shamsi(datetime=date)), + data['fullname'], + data['natcode'], + data['mobile'], + data['pos']['cooperative']['name'] + '('+data['pos']['cooperative']['user']['fullname'] +')', + data['pos']['cooperative']['user']['mobile'], + data['result'], + tavanoni, + data['products'][0]['name'], + data['natcode'], + additional.get('cur_heavy', 0), + additional.get('cur_light', 0), + data['products'][0]['cur_weight'], + data['price'], + shares.get('totalCooperativePrice') or 0, + shares.get('totalUnionPrice') or 0, + shares.get('totalCompanyPrice') or 0, + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + cur_heavy = sum(json.loads(data['additional']).get('cur_heavy', 0) for data in serializer) + cur_light = sum(json.loads(data['additional']).get('cur_light', 0) for data in serializer) + + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + cooperative_price = sum(data.get('shares', {}).get('totalCooperativePrice') or 0 for data in serializer) + union_price = sum(data.get('shares', {}).get('totalUnionPrice') or 0 for data in serializer) + total_company_price = sum(data.get('shares', {}).get('totalCompanyPrice') or 0 for data in serializer) + + value_header_list = [ + len(transactions), + cur_heavy, + cur_light, + cur_weight, + price, + cooperative_price, + union_price, + total_company_price, + + ] + create_value(worksheet, value_header_list, 4, 5) + + + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + cur_heavy, + cur_light, + cur_weight, + price, + cooperative_price, + union_price, + total_company_price, + + + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + # else: + # cooperative_key = request.GET.get('cooperative_key') + # if role in ('LiveStockProvinceJahad', 'Union'): + # transactions = PosMachineTransactions.objects.filter(trash=False, live_stock=True).order_by('-date') + # elif cooperative_key: + # cooperative = Cooperative.objects.get(key=cooperative_key) + # transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + # live_stock=True).order_by('-date') + # + # + # else: + # cooperative = Cooperative.objects.get(user=user) + # transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + # live_stock=True).order_by('-date') + # + # if date1 and date2: + # date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # + # filters['date__date__gte'] = date1 + # filters['date__date__lte'] = date2 + # + # if 'search' in request.GET and 'value' in request.GET: + # transactions_list = [] + # if request.GET['search'] == 'filter': + # if request.GET['value'] != "" and request.GET['value'] != 'undefined': + # for item in filterset_fields: + # query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + # if (filterset_class( + # data=query, + # queryset=transactions + # ) + # ).filter(): + # ps = filterset_class(data=query, queryset=transactions) + # transactions_list = ps.filter() + # transactions = [] if len(transactions_list) == 0 else transactions_list + # transactions = transactions.filter(**filters, paid=False).order_by('-date') + # serializer = PosMachineTransactionsForLiveStockSerializerForExcel(transactions, many=True).data + # + # if 'date1' in request.GET: + # date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from_date1 = shamsi_date(date1) + # to_date1 = shamsi_date(date2) + # excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + # + # create_header(worksheet, header_list, 5, 3, height=20) + # + # excel_description(worksheet, 'B1', f'تراکنش های ناموفق', color='red', row2='C1') + # + # create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + # + # l = 5 + # m = 1 + # if serializer: + # for data in serializer: + # date = datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + # + # additional = json.loads(data['additional']) + # if additional.get('isTaavoni'): + # tavanoni = 'تعاونی' if additional['isTaavoni'] == True else 'کارخانه' + # else: + # tavanoni = '-' + # list1 = [ + # m, + # str(convert_to_shamsi(datetime=date)), + # data['fullname'], + # data['natcode'], + # data['mobile'], + # data['pos']['cooperative']['name'] + '(' + data['pos']['cooperative']['user']['fullname'] + ')', + # data['pos']['cooperative']['user']['mobile'], + # data['result'], + # tavanoni, + # data['products'][0]['name'], + # data['natcode'], + # additional.get('cur_heavy',0), + # additional.get('cur_light',0), + # data['products'][0]['cur_weight'], + # data['price'], + # additional.get('cooperative_price',0), + # additional.get('union_price',0), + # ] + # m += 1 + # l += 1 + # create_value(worksheet, list1, l + 1, 1, border_style='thin') + # + # cur_heavy = sum(json.loads(data['additional']).get('cur_heavy', 0) for data in serializer) + # cur_light = sum(json.loads(data['additional']).get('cur_light', 0) for data in serializer) + # cooperative_price = sum( + # json.loads(data['additional']).get('cooperative_price', 0) for data in serializer) + # union_price = sum(json.loads(data['additional']).get('union_price', 0) for data in serializer) + # cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + # price = sum(data['price'] for data in serializer) + # + # value_header_list = [ + # len(transactions), + # cur_heavy, + # cur_light, + # cur_weight, + # price, + # cooperative_price, + # union_price, + # + # ] + # create_value(worksheet, value_header_list, 4, 5) + # + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # cur_heavy, + # cur_light, + # cur_weight, + # price, + # cooperative_price, + # union_price, + # + # ] + # create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های محصول {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def cooperative_warehouse_excel(request): + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + } + name = products[request.GET.get('name')] + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + cooperatives = cooperatives.filter( + build_query(CooperativeFilterSet.Meta.fields, search) + ) + + serializer = CooperativeForAllocationsReportSerializer(cooperatives, many=True,context={'request':request}).data + excel_options = [ + 'ردیف', + 'نام تعاونی', + 'کاربر', + 'استان', + 'شهر', + 'موبایل', + 'کد ملی', + 'سهمیه دریافتی', + 'وزن تحویلی', + 'وزن فروش رفته', + 'مانده انبار', + 'تعداد تراکنش ها', + 'جمع تراکنش ها', + 'وزن کل تراکنش ها', + + + ] + + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'سهمیه دریافتی', + 'وزن تحویلی', + 'وزن فروش رفته', + 'مانده انبار', + 'تعداد تراکنش ها', + 'جمع تراکنش ها', + 'وزن کل تراکنش ها', + + ] + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='C2') + + create_header(worksheet, header_list, 3, 3, height=20) + + excel_description(worksheet, 'B1', f'گزارش فروش {name}', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + + l = 5 + m = 1 + if serializer: + for data in serializer: + + + list1 = [ + m, + data['name'], + data['user']['fullname'] if data['user']['fullname'] else '-', + data['user']['province_name'] if data['user']['province_name'] else '-', + data['user']['city_name'] if data['user']['city_name'] else '-', + data['user']['mobile'] if data['user']['mobile'] else '-', + data['user']['national_id'] if data['user']['national_id'] else '-', + data['info']['total_receipt_weight'] if data['info']['total_receipt_weight'] else '-', + data['info']['total_weight'] if data['info']['total_weight'] else '-', + data['info']['total_allocated_weight'] if data['info']['total_allocated_weight'] else '-', + data['info']['total_remain_weight'] if data['info']['total_remain_weight'] else '-', + data['info']['transactions'] if data['info']['transactions'] else '-', + data['info']['total_transactions_price'] if data['info']['total_transactions_price'] else '-', + data['info']['total_transactions_weight'] if data['info']['total_transactions_weight'] else '-', + + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + if serializer: + + total_receipt_weight = sum( + item['info'].get('total_receipt_weight', 0) for item in serializer) + total_weight = sum( + item['info'].get('total_weight', 0) for item in serializer) + total_allocated_weight = sum( + item['info'].get('total_allocated_weight', 0) for item in serializer) + total_remain_weight = sum( + item['info'].get('total_remain_weight', 0) for item in serializer) + transactions = sum( + item['info'].get('transactions', 0) for item in serializer) + total_transactions_price = sum( + item['info'].get('total_transactions_price', 0) for item in serializer) + total_transactions_weight = sum( + item['info'].get('total_transactions_weight', 0) for item in serializer) + value_header_list = [ + + total_receipt_weight, + total_weight, + total_allocated_weight, + total_remain_weight, + transactions, + total_transactions_price, + total_transactions_weight, + + + + ] + create_value(worksheet, value_header_list, 4, 3) + + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + total_receipt_weight, + total_weight, + total_allocated_weight, + total_remain_weight, + transactions, + total_transactions_price, + total_transactions_weight, + + + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش فروش {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def safe_get_additional(data): + additional_str = data.get('additional') + if additional_str in [None, '', 'null', 'undefined']: + return {} + try: + return json.loads(additional_str) + except (json.JSONDecodeError, TypeError): + return {} + + +def management_live_stock_excel(request): + sheet_names=['اطلاعات کلی توزیع تعاونی ها'] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + for name in sheet_names[:1]: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if sheet_name == 'اطلاعات کلی توزیع تعاونی ها': + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + + serializer = CooperativeForAllocationsReportSerializer(cooperatives, many=True).data + excel_options = [ + 'ردیف', + 'نام تعاونی', + 'کاربر', + 'استان', + 'شهر', + 'موبایل', + 'کد ملی', + 'سهمیه دریافتی', + 'وزن تحویلی', + 'وزن فروش رفته', + 'مانده انبار', + 'تعداد تراکنش ها', + 'جمع تراکنش ها', + 'وزن کل تراکنش ها', + + ] + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'سهمیه دریافتی', + 'وزن تحویلی', + 'وزن فروش رفته', + 'مانده انبار', + 'تعداد تراکنش ها', + 'جمع تراکنش ها', + 'وزن کل تراکنش ها', + + ] + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='C2') + + create_header(worksheet, header_list, 3, 3, height=20) + + excel_description(worksheet, 'A1', f'اطلاعات کلی توزیع تعاونی ها', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + if serializer: + for data in serializer: + if data['info']['transactions'] >0 and data['name'] not in sheet_names: + sheet_names.append(data['name']) + list1 = [ + m, + data['name'], + data['user']['fullname'], + data['user']['province_name'], + data['user']['city_name'], + data['user']['mobile'], + data['user']['national_id'], + data['info']['total_receipt_weight'], + data['info']['total_weight'], + data['info']['total_allocated_weight'], + data['info']['total_remain_weight'], + data['info']['transactions'], + data['info']['total_transactions_price'], + data['info']['total_transactions_weight'], + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + if serializer: + total_receipt_weight = sum( + item['info'].get('total_receipt_weight', 0) for item in serializer) + total_weight = sum( + item['info'].get('total_weight', 0) for item in serializer) + total_allocated_weight = sum( + item['info'].get('total_allocated_weight', 0) for item in serializer) + total_remain_weight = sum( + item['info'].get('total_remain_weight', 0) for item in serializer) + transactions = sum( + item['info'].get('transactions', 0) for item in serializer) + total_transactions_price = sum( + item['info'].get('total_transactions_price', 0) for item in serializer) + total_transactions_weight = sum( + item['info'].get('total_transactions_weight', 0) for item in serializer) + value_header_list = [ + + total_receipt_weight, + total_weight, + total_allocated_weight, + total_remain_weight, + transactions, + total_transactions_price, + total_transactions_weight, + + ] + create_value(worksheet, value_header_list, 4, 3) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + total_receipt_weight, + total_weight, + total_allocated_weight, + total_remain_weight, + transactions, + total_transactions_price, + total_transactions_weight, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + # elif sheet_name == 'اطلاعات کلی خریداران': + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + # excel_options = [ + # 'ردیف', + # 'دامدار', + # 'کدملی دامدار', + # 'شهر', + # 'تعداد تراکنش ها', + # 'مجموع دام سنگین', + # 'مجموع دام سبک', + # + # 'مجموع وزن(کیلوگرم)', + # 'مبلغ تراکنش(ریال)', + # 'سهم تعاونی(ریال)', + # 'سهم اتحادیه(ریال)', + # + # ] + # header_list = [ + # 'تعداد دامداران', + # 'تعداد تراکنش ها', + # 'مجموع دام سنگین', + # 'مجموع دام سبک', + # + # 'مجموع وزن(کیلوگرم)', + # 'مبلغ تراکنش(ریال)', + # 'سهم تعاونی(ریال)', + # 'سهم اتحادیه(ریال)', + # + # ] + # ransactions = PosMachineTransactions.objects.filter(trash=False, + # live_stock=True, paid=True, + # ).order_by('id') + # natcpdes = ransactions.values_list('natcode',flat=True).distinct() + # + # ranchers=Rancher.objects.filter(trash=False,national_id__in=natcpdes).only('name','national_id') + # print(len(ranchers)) + # if 'date1' in request.GET: + # date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from_date1 = shamsi_date(date1) + # to_date1 = shamsi_date(date2) + # excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + # + # create_header(worksheet, header_list, 5, 3, height=20) + # + # excel_description(worksheet, 'A1', f' تراکنش های موفق {name}', color='red', row2='D1') + # + # create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + # + # l = 5 + # m = 1 + # if ranchers: + # for rancher in ranchers: + # transactions = ransactions.filter(natcode=rancher.national_id).order_by('id') + # + # serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + # cur_heavy = sum(json.loads(data['additional']).get('cur_heavy', 0) for data in serializer) + # cur_light = sum(json.loads(data['additional']).get('cur_light', 0) for data in serializer) + # cooperative_price = sum( + # json.loads(data['additional']).get('cooperative_price', 0) for data in serializer) + # union_price = sum(json.loads(data['additional']).get('union_price', 0) for data in serializer) + # cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + # price = sum(data['price'] for data in serializer) + # list1 = [ + # m, + # rancher.name, + # rancher.national_id, + # len(transactions), + # cur_heavy, + # cur_light, + # cur_weight, + # price, + # cooperative_price, + # union_price, + # + # ] + # m += 1 + # l += 1 + # create_value(worksheet, list1, l + 1, 1, border_style='thin') + # transactions = ransactions + # + # serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + # cur_heavy = sum(json.loads(data['additional']).get('cur_heavy', 0) for data in serializer) + # cur_light = sum(json.loads(data['additional']).get('cur_light', 0) for data in serializer) + # cooperative_price = sum( + # json.loads(data['additional']).get('cooperative_price', 0) for data in serializer) + # union_price = sum(json.loads(data['additional']).get('union_price', 0) for data in serializer) + # cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + # price = sum(data['price'] for data in serializer) + # + # value_header_list = [ + # len(natcpdes), + # len(transactions), + # cur_heavy, + # cur_light, + # cur_weight, + # price, + # cooperative_price, + # union_price, + # + # ] + # create_value(worksheet, value_header_list, 4, 5) + # + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # len(transactions), + # cur_heavy, + # cur_light, + # cur_weight, + # price, + # cooperative_price, + # union_price, + # + # ] + # create_value(worksheet, list2, l + 3, 1, color='green') + for name in sheet_names[1:]: + last_part = name.rsplit(' ', 3)[-3:] + new_name = ' '.join(last_part) + sheet_name = new_name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + excel_options = [ + 'ردیف', + 'تاریخ', + 'خریدار', + 'کد ملی خریدار', + 'موبایل خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'وضعیت', + 'محل تحویل', + 'کالا', + 'کد ملی فروشنده', + 'دام سنگین', + 'دام سبک', + 'وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + header_list = [ + 'تعداد تراکنش ها', + 'مجموع دام سنگین', + 'مجموع دام سبک', + + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + cooperative = Cooperative.objects.get(name=name) + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True,paid=True).order_by('-date') + + + + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + + create_header(worksheet, header_list, 5, 3, height=20) + + excel_description(worksheet, 'A1', f' تراکنش های موفق {name}', color='red', row2='D1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + if serializer: + for data in serializer: + date = datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + + additional_str = data.get('additional') + if additional_str in [None, '', 'null', 'undefined']: + additional = {} + else: + try: + additional = json.loads(additional_str) + except (json.JSONDecodeError, TypeError): + additional = {} + + if additional.get('isTaavoni'): + tavanoni = 'تعاونی' if additional['isTaavoni'] == True else 'کارخانه' + else: + tavanoni = '-' + list1 = [ + m, + str(convert_to_shamsi(datetime=date)), + data['fullname'], + data['natcode'], + data['mobile'], + data['pos']['cooperative']['name'] + '(' + data['pos']['cooperative']['user']['fullname'] + ')', + data['pos']['cooperative']['user']['mobile'], + data['result'], + tavanoni, + data['products'][0]['name'], + data['natcode'], + additional.get('cur_heavy', 0), + additional.get('cur_light', 0), + data['products'][0]['cur_weight'], + data['price'], + additional.get('cooperative_price', 0), + additional.get('union_price', 0), + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + cur_heavy = sum(safe_get_additional(data).get('cur_heavy', 0) for data in serializer) + cur_light = sum(safe_get_additional(data).get('cur_light', 0) for data in serializer) + cooperative_price = sum(safe_get_additional(data).get('cooperative_price', 0) for data in serializer) + union_price = sum(safe_get_additional(data).get('union_price', 0) for data in serializer) + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + + value_header_list = [ + len(transactions), + cur_heavy, + cur_light, + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, value_header_list, 4, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + cur_heavy, + cur_light, + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش جامع تعاونی ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def fix_rancher(request): + ransactions = PosMachineTransactions.objects.filter(trash=False, + live_stock=True, paid=True, + ).values_list('natcode',flat=True).distinct() + + ranchers=Rancher.objects.filter(trash=False,national_id__in=ransactions,has_script=False) + + for r in ranchers: + update_one_rancher(r) + + return HttpResponse('ok') + + +def rancher_management(request): + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + + excel_options = [ + 'ردیف', + 'دامدار', + 'مجوز فعالیت', + 'کدملی دامدار', + 'تلفن دامدار', + 'شهر', + 'مجموع دام سنگین هویت', + 'مجموع دام سبک هویت', + 'مجموع سهمیه دام سنگین(کیلوگرم)', + 'مجموع سهمیه دام سبک(کیلوگرم)', + 'فروشنده', + 'تلفن فروشنده', + 'کد ملی فروشنده', + 'تعداد تراکنش ها', + 'تاریخ تراکنش ها', + 'مجموع دام سنگین', + 'مجموع دام سبک', + + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + header_list = [ + 'تعداد دامداران', + 'تعداد تراکنش ها', + 'مجموع دام سنگین هویت', + 'مجموع دام سبک هویت', + 'مجموع سهمیه دام سنگین(کیلوگرم)', + 'مجموع سهمیه دام سبک(کیلوگرم)', + 'مجموع دام سنگین(واقعی)', + 'مجموع دام سبک(واقعی)', + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + ransactions = PosMachineTransactions.objects.filter(trash=False, + live_stock=True, paid=True, + ).order_by('id') + natcpdes = ransactions.values_list('natcode',flat=True).distinct() + + ranchers=Rancher.objects.filter(trash=False,national_id__in=natcpdes,has_script=True).only('name','national_id', + 'heavy_livestock','light_livestock','city','mobile') + + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + + create_header(worksheet, header_list, 5, 3, height=20) + + excel_description(worksheet, 'A1', f'دامداران مغایرت دار', color='red', row2='D1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + if ranchers: + for rancher in ranchers: + transactions = ransactions.filter(natcode=rancher.national_id).order_by('id') + + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + cur_heavy = sum(safe_get_additional(data).get('cur_heavy', 0) for data in serializer) + cur_light = sum(safe_get_additional(data).get('cur_light', 0) for data in serializer) + cooperative_price = sum(safe_get_additional(data).get('cooperative_price', 0) for data in serializer) + union_price = sum(safe_get_additional(data).get('union_price', 0) for data in serializer) + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + + cooperative_list_name = list({data['pos']['cooperative']['name'] for data in serializer}) + cooperative_list_mobile = list({data['pos']['cooperative']['user']['mobile'] for data in serializer}) + natcode_list = list({data['natcode'] for data in serializer}) + + cooperative_names_str = ' / '.join(cooperative_list_name) if cooperative_list_name else '' + cooperative_mobiles_str = ' / '.join(cooperative_list_mobile) if cooperative_list_mobile else '' + natcode_list_str = ' / '.join(natcode_list) if natcode_list else '' + + date_list=[] + for data in serializer: + date = datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + date_list.append(str(convert_to_shamsi(datetime=date))) + date_str = ' / '.join(date_list) if date_list else '' + type_rancher='روستایی' if rancher.type=='rural' else 'صنعتی' + list1 = [ + m, + rancher.name, + type_rancher, + rancher.national_id, + rancher.mobile, + rancher.city, + rancher.heavy_livestock, + rancher.light_livestock, + rancher.weight_quota_heavy, + rancher.weight_quota_light, + cooperative_names_str, + cooperative_mobiles_str, + natcode_list_str, + len(transactions), + date_str, + cur_heavy, + cur_light, + + cur_weight, + + price, + cooperative_price, + union_price, + + ] + l += 1 + m += 1 + + create_value(worksheet, list1, l + 1, 1, border_style='thin') + transactions = ransactions + + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + cur_heavy = sum(safe_get_additional(data).get('cur_heavy', 0) for data in serializer) + cur_light = sum(safe_get_additional(data).get('cur_light', 0) for data in serializer) + cooperative_price = sum(safe_get_additional(data).get('cooperative_price', 0) for data in serializer) + union_price = sum(safe_get_additional(data).get('union_price', 0) for data in serializer) + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + heavy_livestock = ranchers.aggregate(total=Sum('heavy_livestock'))[ + 'total'] or 0 + light_livestock = ranchers.aggregate(total=Sum('light_livestock'))[ + 'total'] or 0 + weight_quota_light = ranchers.aggregate(total=Sum('weight_quota_light'))[ + 'total'] or 0 + weight_quota_heavy = ranchers.aggregate(total=Sum('weight_quota_heavy'))[ + 'total'] or 0 + value_header_list = [ + len(natcpdes), + len(transactions), + cur_heavy, + cur_light, + heavy_livestock, + light_livestock, + weight_quota_heavy, + weight_quota_light, + + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, value_header_list, 4, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + heavy_livestock, + light_livestock, + weight_quota_heavy, + weight_quota_light, + '', + '', + '', + len(transactions), + '', + cur_heavy, + cur_light, + + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="دامداران مغایرت دار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def gasgdasd(request): + ransactions = PosMachineTransactions.objects.filter(trash=False, + live_stock=True, paid=True, + ).order_by('id') + natcpdes = ransactions.values_list('natcode', flat=True).distinct() + + ranchers = Rancher.objects.filter(trash=False, national_id__in=natcpdes,has_script=False).only('name', 'national_id', + 'heavy_livestock', 'light_livestock', + 'city', 'mobile') + for r in ranchers: + update_one_rancher(r) + + return HttpResponse('ok') + + +def live_stock_product_excel(request): + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + + excel_options = [ + 'ردیف', + 'دامدار', + 'مجوز فعالیت', + 'کدملی دامدار', + 'تلفن دامدار', + 'شهر', + 'مجموع دام سنگین هویت', + 'مجموع دام سبک هویت', + 'مجموع سهمیه دام سنگین(کیلوگرم)', + 'مجموع سهمیه دام سبک(کیلوگرم)', + 'فروشنده', + 'تلفن فروشنده', + 'کد ملی فروشنده', + 'تعداد تراکنش ها', + 'تاریخ تراکنش ها', + 'مجموع دام سنگین', + 'مجموع دام سبک', + + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + header_list = [ + 'تعداد دامداران', + 'تعداد تراکنش ها', + 'مجموع دام سنگین هویت', + 'مجموع دام سبک هویت', + 'مجموع سهمیه دام سنگین(کیلوگرم)', + 'مجموع سهمیه دام سبک(کیلوگرم)', + 'مجموع دام سنگین(واقعی)', + 'مجموع دام سبک(واقعی)', + 'مجموع وزن(کیلوگرم)', + 'مبلغ تراکنش(ریال)', + 'سهم تعاونی(ریال)', + 'سهم اتحادیه(ریال)', + + ] + ransactions = PosMachineTransactions.objects.filter(trash=False, + live_stock=True, paid=True, + ).order_by('id') + natcpdes = ransactions.values_list('natcode',flat=True).distinct() + + ranchers=Rancher.objects.filter(trash=False,national_id__in=natcpdes,has_script=True).only('name','national_id', + 'heavy_livestock','light_livestock','city','mobile') + + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + to_date1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ {from_date1} تا {to_date1}', color='red', row2='D3') + + create_header(worksheet, header_list, 5, 3, height=20) + + excel_description(worksheet, 'A1', f'دامداران مغایرت دار', color='red', row2='D1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + if ranchers: + for rancher in ranchers: + transactions = ransactions.filter(natcode=rancher.national_id).order_by('id') + + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + cur_heavy = sum(safe_get_additional(data).get('cur_heavy', 0) for data in serializer) + cur_light = sum(safe_get_additional(data).get('cur_light', 0) for data in serializer) + cooperative_price = sum(safe_get_additional(data).get('cooperative_price', 0) for data in serializer) + union_price = sum(safe_get_additional(data).get('union_price', 0) for data in serializer) + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + + cooperative_list_name = list({data['pos']['cooperative']['name'] for data in serializer}) + cooperative_list_mobile = list({data['pos']['cooperative']['user']['mobile'] for data in serializer}) + natcode_list = list({data['natcode'] for data in serializer}) + + cooperative_names_str = ' / '.join(cooperative_list_name) if cooperative_list_name else '' + cooperative_mobiles_str = ' / '.join(cooperative_list_mobile) if cooperative_list_mobile else '' + natcode_list_str = ' / '.join(natcode_list) if natcode_list else '' + + date_list=[] + for data in serializer: + date = datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + date_list.append(str(convert_to_shamsi(datetime=date))) + date_str = ' / '.join(date_list) if date_list else '' + type_rancher='روستایی' if rancher.type=='rural' else 'صنعتی' + list1 = [ + m, + rancher.name, + type_rancher, + rancher.national_id, + rancher.mobile, + rancher.city, + rancher.heavy_livestock, + rancher.light_livestock, + rancher.weight_quota_heavy, + rancher.weight_quota_light, + cooperative_names_str, + cooperative_mobiles_str, + natcode_list_str, + len(transactions), + date_str, + cur_heavy, + cur_light, + + cur_weight, + + price, + cooperative_price, + union_price, + + ] + l += 1 + m += 1 + + create_value(worksheet, list1, l + 1, 1, border_style='thin') + transactions = ransactions + + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True).data + cur_heavy = sum(safe_get_additional(data).get('cur_heavy', 0) for data in serializer) + cur_light = sum(safe_get_additional(data).get('cur_light', 0) for data in serializer) + cooperative_price = sum(safe_get_additional(data).get('cooperative_price', 0) for data in serializer) + union_price = sum(safe_get_additional(data).get('union_price', 0) for data in serializer) + cur_weight = sum(data['products'][0].get('cur_weight', 0) for data in serializer) + price = sum(data['price'] for data in serializer) + heavy_livestock = ranchers.aggregate(total=Sum('heavy_livestock'))[ + 'total'] or 0 + light_livestock = ranchers.aggregate(total=Sum('light_livestock'))[ + 'total'] or 0 + weight_quota_light = ranchers.aggregate(total=Sum('weight_quota_light'))[ + 'total'] or 0 + weight_quota_heavy = ranchers.aggregate(total=Sum('weight_quota_heavy'))[ + 'total'] or 0 + value_header_list = [ + len(natcpdes), + len(transactions), + cur_heavy, + cur_light, + heavy_livestock, + light_livestock, + weight_quota_heavy, + weight_quota_light, + + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, value_header_list, 4, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + heavy_livestock, + light_livestock, + weight_quota_heavy, + weight_quota_light, + '', + '', + '', + len(transactions), + '', + cur_heavy, + cur_light, + + cur_weight, + price, + cooperative_price, + union_price, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="دامداران مغایرت دار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response diff --git a/LiveStock/Jahad/filterset.py b/LiveStock/Jahad/filterset.py new file mode 100644 index 0000000..f356321 --- /dev/null +++ b/LiveStock/Jahad/filterset.py @@ -0,0 +1,35 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import LiveStockAllocations, CooperativeProductsShare + + +class LiveStockAllocationsFilterSet(filters.FilterSet): + class Meta: + model = LiveStockAllocations + fields = [ + 'product__name', + 'jahad__user__mobile', + 'jahad__user__first_name', + 'jahad__user__last_name', + 'jahad__user__fullname', + 'union__user__mobile', + 'union__user__first_name', + 'union__user__last_name', + 'union__user__fullname', + 'cooperative__user__mobile', + 'cooperative__user__first_name', + 'cooperative__user__last_name', + 'cooperative__user__fullname' + ] + + +class CooperativeProductsShareFilterSet(filters.FilterSet): + class Meta: + model = CooperativeProductsShare + fields = [ + 'product__name', + 'cooperative__user__mobile', + 'cooperative__user__first_name', + 'cooperative__user__last_name', + 'cooperative__user__fullname' + ] diff --git a/LiveStock/Jahad/helpers.py b/LiveStock/Jahad/helpers.py new file mode 100644 index 0000000..6703ac3 --- /dev/null +++ b/LiveStock/Jahad/helpers.py @@ -0,0 +1,45 @@ +from django.db.models import Sum, Q + +from LiveStock.models import LiveStockAllocations + + +def jahad_warehousing(product): + allocations = LiveStockAllocations.objects.filter(jahad__isnull=False,product=product, trash=False) + # allocations = LiveStockAllocations.objects.filter(jahad=product.jahad, trash=False) + input_allocations = allocations.filter(union__isnull=True, cooperative__isnull=True) + output_allocations = allocations.filter(Q(union__isnull=False) | Q(cooperative__isnull=False)) + + input_weight = input_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + output_weight = output_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.total_weight = input_weight + product.total_receipt_weight = input_weight + product.total_allocated_weight = output_weight + product.save() + + +def union_warehousing(product): + allocations = LiveStockAllocations.objects.filter(union=product.union,product__parent_product__name=product.parent_product.name, trash=False) + input_allocations = allocations.filter(jahad__isnull=False) + output_allocations = allocations.filter(cooperative__isnull=False) + + input_weight = input_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + output_weight = output_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.total_weight = input_weight + product.total_receipt_weight = input_weight + product.total_allocated_weight = output_weight + product.save() + + +def cooperative_warehousing(product): + input_allocations = LiveStockAllocations.objects.filter(cooperative=product.cooperative,product__parent_product__name=product.parent_product.name, trash=False).values_list('id',flat=True) + total_receipt_weight = input_allocations.filter(charge=False).aggregate(total=Sum('weight'))[ + 'total'] or 0 + real_input_weight = input_allocations.filter(charge=True).aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.total_receipt_weight = total_receipt_weight + product.total_weight = real_input_weight + product.save() diff --git a/LiveStock/Jahad/serializers.py b/LiveStock/Jahad/serializers.py new file mode 100644 index 0000000..a1dde3d --- /dev/null +++ b/LiveStock/Jahad/serializers.py @@ -0,0 +1,54 @@ +from rest_framework import serializers + +from LiveStock.Cooperative.serializers import CooperativeSerializer, CooperativeForSharesSerializer +from LiveStock.Union.serializers import UnionSerializer +from LiveStock.models import LiveStockProvinceJahad, LiveStockRolseProduct, LiveStockAllocations, LiveStockProduct, \ + CooperativeProductsShare +from authentication.serializer.serializer import BankCardSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import SystemAddressSerializer +from ticket.serializers import SystemUserProfileForTicketPermissionSerializer + + +class LiveStockProvinceJahadSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = LiveStockProvinceJahad + fields = '__all__' + + +class LiveStockProductSerializer(serializers.ModelSerializer): + class Meta: + model = LiveStockProduct + fields = '__all__' + + +class LiveStockRolseProductSerializer(serializers.ModelSerializer): + parent_product = LiveStockProductSerializer(read_only=True) + + class Meta: + model = LiveStockRolseProduct + fields = '__all__' + + +class LiveStockAllocationsSerializer(serializers.ModelSerializer): + product = LiveStockRolseProductSerializer(read_only=True) + union = UnionSerializer(read_only=True) + cooperative = CooperativeSerializer(read_only=True) + jahad = LiveStockProvinceJahadSerializer(read_only=True) + + class Meta: + model = LiveStockAllocations + fields = '__all__' + + +class CooperativeProductsShareSerializer(serializers.ModelSerializer): + cooperative = CooperativeForSharesSerializer(read_only=True) + product = LiveStockRolseProductSerializer(read_only=True) + + + class Meta: + model = CooperativeProductsShare + fields = '__all__' diff --git a/LiveStock/Jahad/urls.py b/LiveStock/Jahad/urls.py new file mode 100644 index 0000000..5915366 --- /dev/null +++ b/LiveStock/Jahad/urls.py @@ -0,0 +1,59 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.Jahad import views as jahad_views +from LiveStock.Jahad.excel_processing import allocation_live_stock_excel, warehouse_live_stock_excel, \ + live_stock_transaction_excel, cooperative_warehouse_excel, management_live_stock_excel, rancher_management, \ + live_stock_product_excel +from LiveStock.Jahad.views import get_user_live_stock + +router = DefaultRouter() +router.register( + r'profile', + jahad_views.LiveStockProvinceJahadViewSet, + basename="profile" +) + +router.register( + r'live-stock-role-products', + jahad_views.LiveStockRolseProductViewset, + basename="live-stock-role-products" +) +router.register( + r'live-stock-allocation', + jahad_views.LiveStockAllocationsViewSet, + basename="live-stock-allocation" +) +router.register( + r'live-stock-product', + jahad_views.LiveStockProductViewset, + basename="live-stock-product" +) +router.register( + r'dashboard-live-stock-allocation', + jahad_views.DashboardLiveStockAllocationsViewSet, + basename="dashboard-live-stock-allocation" +) +router.register( + r'live-stock-warehouse-charge-allocation', + jahad_views.LiveStockWarehouseChargeAllocationsViewSet, + basename="live-stock-warehouse-charge-allocation" +) + +router.register( + r'cooperative-shares', + jahad_views.CooperativeProductsShareViewSet, + basename="cooperative-shares" +) + + +urlpatterns = [ + path('', include(router.urls)), + path('get_user_live_stock/', get_user_live_stock), + path('allocation_live_stock_excel/', allocation_live_stock_excel), + path('warehouse_live_stock_excel/', warehouse_live_stock_excel), + path('live_stock_transaction_excel/', live_stock_transaction_excel), + path('cooperative_warehouse_excel/', cooperative_warehouse_excel), + path('management_live_stock_excel/', management_live_stock_excel), + path('rancher_management/', rancher_management), + path('live_stock_product_excel/', live_stock_product_excel), + ] \ No newline at end of file diff --git a/LiveStock/Jahad/views.py b/LiveStock/Jahad/views.py new file mode 100644 index 0000000..6f2e1e0 --- /dev/null +++ b/LiveStock/Jahad/views.py @@ -0,0 +1,690 @@ +import threading +from datetime import datetime + +from django.db.models import Sum, Q +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.Jahad.filterset import LiveStockAllocationsFilterSet, CooperativeProductsShareFilterSet +from LiveStock.Jahad.helpers import jahad_warehousing, union_warehousing, cooperative_warehousing +from LiveStock.Jahad.serializers import LiveStockProvinceJahadSerializer, LiveStockRolseProductSerializer, \ + LiveStockAllocationsSerializer, LiveStockProductSerializer, CooperativeProductsShareSerializer +from LiveStock.Rancher.helpers import update_quota_rancher_threading +from LiveStock.Rancher.serializers import RancherSerializer +from LiveStock.Union.serializers import UnionSerializer +from LiveStock.helpers import CustomPagination, build_query +from LiveStock.models import LiveStockProvinceJahad, LiveStockRolseProduct, LiveStockAllocations, Union, Cooperative, \ + Rancher, LiveStockProduct, CooperativeProductsShare +from authentication.models import SystemUserProfile + + +class LiveStockProvinceJahadViewSet(viewsets.ModelViewSet): + queryset = LiveStockProvinceJahad.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockProvinceJahadSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + jahad = user.jahad_user.all() + + serializer = self.serializer_class(jahad[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockRolseProductViewset(viewsets.ModelViewSet): + queryset = LiveStockRolseProduct.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockRolseProductSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + name =products[request.GET.get('name')] + + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + products = LiveStockRolseProduct.objects.filter(jahad__isnull=False, trash=False + , parent_product=product).first() + elif request.GET['role'] == 'Union': + products = LiveStockRolseProduct.objects.filter(union__user=user, trash=False, + parent_product=product).first() + + else: + products = LiveStockRolseProduct.objects.filter(cooperative__user=user, trash=False, + parent_product=product).first() + serializer = self.serializer_class(products) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockAllocationsViewSet(viewsets.ModelViewSet): + queryset = LiveStockAllocations.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockAllocationsSerializer + pagination_class = CustomPagination + filterset_class = LiveStockAllocationsFilterSet + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + product = LiveStockRolseProduct.objects.get(key=request.data['product_key']) + + allocator = request.data['allocator'] + receiver = request.data['receiver'] + request.data.pop('allocator') + request.data.pop('receiver') + request.data.pop('product_key') + + if allocator == 'LiveStockProvinceJahad': + jahad = LiveStockProvinceJahad.objects.get(user=user, trash=False) + jahad_roles_product = LiveStockRolseProduct.objects.filter(jahad__isnull=False,parent_product__name=product.parent_product.name,trash=False).first() + if receiver != 'LiveStockProvinceJahad': + if request.data['weight'] > jahad_roles_product.total_remain_weight: + return Response({"result": "مقدار وارد شده بیشتر از باقی مانده انبار است !"}, + status=status.HTTP_403_FORBIDDEN) + + elif allocator == 'Cooperative': + cooperative = Cooperative.objects.get(user=user, trash=False) + cooperative_roles_product = LiveStockRolseProduct.objects.get(cooperative=cooperative,parent_product__name=product.parent_product.name, trash=False) + if receiver != 'Cooperative': + + if request.data[ + 'weight'] + cooperative_roles_product.total_remain_weight > cooperative_roles_product.total_receipt_weight: + return Response({"result": "مقدار وارد شده بیشتر از سهمیه دریافتی است !"}, + status=status.HTTP_403_FORBIDDEN) + + + + else: + union = Union.objects.get(user=user, trash=False) + union_roles_product = LiveStockRolseProduct.objects.filter(union__isnull=False,parent_product__name=product.parent_product.name, trash=False).first() + if request.data['weight'] > union_roles_product.total_remain_weight: + return Response({"result": "مقدار وارد شده بیشتر از باقی مانده انبار است !"}, + status=status.HTTP_403_FORBIDDEN) + if receiver == 'LiveStockProvinceJahad': + pass + elif receiver == 'Union': + union = Union.objects.get(key=request.data['buyer_key'], trash=False) + request.data.pop('buyer_key') + + else: + if allocator == 'Cooperative': + pass + else: + cooperative = Cooperative.objects.get(key=request.data['buyer_key'], trash=False) + request.data.pop('buyer_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation = serializer.create(validated_data=request.data) + allocation.product = product + if allocator == 'LiveStockProvinceJahad': + allocation.jahad = jahad + allocation.allocate_from = "LiveStockProvinceJahad" + + elif allocator == 'Cooperative': + allocation.cooperative = cooperative + allocation.allocate_from = "Cooperative" + + else: + allocation.union = union + allocation.allocate_from = "Union" + + if receiver == 'LiveStockProvinceJahad': + allocation.allocate_to = "LiveStockProvinceJahad" + allocation.charge = True + allocation.state = 'accepted' + + + elif receiver == 'Union': + allocation.union = union + allocation.allocate_to = "Union" + + else: + allocation.cooperative = cooperative + allocation.allocate_to = "Cooperative" + if allocator == 'Cooperative': + allocation.charge = True + + allocation.save() + + if allocator == 'LiveStockProvinceJahad': + jahad_warehousing(product) + + elif allocator == 'Cooperative': + pass + else: + union_warehousing(product) + if receiver == 'Union': + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, union=union) + + union_warehousing(reciver_product) + elif receiver == 'Cooperative': + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, + cooperative=cooperative) + cooperative_warehousing(reciver_product) + + else: + pass + return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + allocation = LiveStockAllocations.objects.get(key=request.data['allocation_key'], trash=False) + request.data.pop('allocation_key') + if allocation.charge == True: + if allocation.allocate_from == 'LiveStockProvinceJahad': + if request.data['weight'] < allocation.weight: + + allocations = LiveStockAllocations.objects.filter(jahad=allocation.jahad,product=allocation.product, trash=False) + charge = (allocations.filter(charge=True).exclude(id=allocation.id).aggregate(total=Sum('weight'))[ + 'total'] or 0) + request.data['weight'] + jahad_alocations = allocations.filter(charge=False).aggregate(total=Sum('weight'))['total'] or 0 + + if charge < jahad_alocations: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + allocations = LiveStockAllocations.objects.filter(cooperative=allocation.cooperative,product=allocation.product, trash=False) + charge = (allocations.filter(charge=True).exclude(id=allocation.id).aggregate(total=Sum('weight'))[ + 'total'] or 0) + request.data['weight'] + + if request.data['weight'] < allocation.weight: + + if charge < allocation.product.total_allocated_weight: + return Response( + {"result": "به علت عدم همخوانی موجودی و فروش امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + elif request.data['weight'] > allocation.weight: + if charge > allocation.product.total_receipt_weight: + return Response( + { + "result": "به علت عدم همخوانی سهمیه دریافتی و موجودی انبار امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if request.data['weight'] > allocation.weight: + if allocation.allocate_from == 'LiveStockProvinceJahad': + jahad_products = allocation.product + dif = request.data['weight'] - allocation.weight + if dif > jahad_products.total_remain_weight: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + + else: + union_products = allocation.product + dif = request.data['weight'] - allocation.weight + if dif > union_products.total_remain_weight: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + elif request.data['weight'] < allocation.weight: + dif = allocation.weight - request.data['weight'] + + if allocation.allocate_to == 'Union': + union_role_product = LiveStockRolseProduct.objects.get(union=allocation.union,parent_product=allocation.product.parent_product, trash=False) + if dif > union_role_product.total_remain_weight: + return Response( + {"result": "به علت عدم همخوانی موجودی مقصد امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + elif allocation.allocate_to == 'Cooperative': + cooperative_role_product = LiveStockRolseProduct.objects.get(cooperative=allocation.cooperative,parent_product=allocation.product.parent_product, + trash=False) + + if dif > (cooperative_role_product.total_receipt_weight - cooperative_role_product.total_weight): + return Response( + {"result": "به علت عدم همخوانی موجودی مقصد امکان ویرایش با این وزن وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(allocation) + serializer.update(instance=allocation, validated_data=request.data) + product = allocation.product + if allocation.allocate_from == 'LiveStockProvinceJahad': + jahad_warehousing(product) + + elif allocation.allocate_from == 'Cooperative': + pass + else: + union_warehousing(product) + if allocation.allocate_to == 'Union': + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, + union=allocation.union) + union_warehousing(reciver_product) + elif allocation.allocate_to == 'Cooperative': + + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, + cooperative=allocation.cooperative) + cooperative_warehousing(reciver_product) + else: + pass + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + name =products[request.GET.get('name')] + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + allocations = LiveStockAllocations.objects.filter(jahad__isnull=False, allocate_from="LiveStockProvinceJahad", + trash=False, product__parent_product=product).order_by( + 'id').exclude(allocate_to='LiveStockProvinceJahad') + elif request.GET['role'] == 'Union': + allocations = LiveStockAllocations.objects.filter(union__isnull=False, trash=False, allocate_from="Union", + product__parent_product=product).order_by('id') + + else: + allocations = LiveStockAllocations.objects.filter(cooperative__user=user, charge=False, + allocate_to="Cooperative", + trash=False, product__parent_product=product).order_by( + 'id') + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + allocations = allocations.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = LiveStockAllocations.objects.get(key=request.GET["allocation_key"]) + product = allocation.product + + if allocation.allocate_from == 'LiveStockProvinceJahad': + if allocation.allocate_to == 'LiveStockProvinceJahad': + roles_product = allocation.product + elif allocation.allocate_to == 'Union': + roles_product = LiveStockRolseProduct.objects.get(union=allocation.union,parent_product=allocation.product.parent_product) + else: + roles_product = LiveStockRolseProduct.objects.get(cooperative=allocation.cooperative,parent_product=allocation.product.parent_product) + + if allocation.weight > roles_product.total_remain_weight: + if allocation.allocate_to == 'Cooperative': + if roles_product.total_receipt_weight >= allocation.weight: + pass + else: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + elif allocation.allocate_from == 'Union': + if allocation.allocate_to == 'Union': + roles_product = allocation.product + else: + roles_product = LiveStockRolseProduct.objects.get(cooperative=allocation.cooperative,parent_product=allocation.product.parent_product) + + if allocation.weight > roles_product.total_remain_weight: + if allocation.allocate_to == 'Cooperative': + if roles_product.total_receipt_weight >= allocation.weight: + pass + else: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + + + else: + + cooperative_roles_product = allocation.product + if allocation.weight > cooperative_roles_product.total_remain_weight: + return Response( + {"result": "به علت عدم همخوانی موجودی و تخصیصات امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + allocation.trash = True + allocation.save() + if allocation.allocate_from == 'LiveStockProvinceJahad': + jahad_warehousing(product) + + elif allocation.allocate_from == 'Cooperative': + pass + else: + union_warehousing(product) + if allocation.allocate_to == 'Union': + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, + union=allocation.union) + union_warehousing(reciver_product) + elif allocation.allocate_to == 'Cooperative': + + reciver_product = LiveStockRolseProduct.objects.get(parent_product=product.parent_product, + cooperative=allocation.cooperative) + cooperative_warehousing(reciver_product) + else: + pass + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class CooperativeProductsShareViewSet(viewsets.ModelViewSet): + queryset = CooperativeProductsShare.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CooperativeProductsShareSerializer + pagination_class = CustomPagination + filterset_class = CooperativeProductsShareFilterSet + + def update(self, request, pk=None, *args, **kwargs): + share = CooperativeProductsShare.objects.get(key=request.data['share_key'], trash=False) + request.data.pop('share_key') + + serializer = self.serializer_class(share) + serializer.update(instance=share, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + shares = CooperativeProductsShare.objects.filter(product__name=request.GET['name'], trash=False).order_by( + 'id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + shares = shares.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(shares) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(shares, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockProductViewset(viewsets.ModelViewSet): + queryset = LiveStockProduct.objects.all() + permission_classes = [AllowAny] + serializer_class = LiveStockProductSerializer + + def list(self, request, *args, **kwargs): + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + name =products[request.GET.get('name')] + + products = LiveStockProduct.objects.filter(trash=False, name=name).first() + serializer = self.serializer_class(products) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + products = LiveStockProduct.objects.get(key=request.data['key']) + request.data.pop('key') + serializer = self.serializer_class(products) + serializer.update(instance=products, validated_data=request.data) + # todo:اگه نیاز شده با ترد بنویس تا همه دامدار ها اپدیت بشن + # send = threading.Thread(target=update_quota_rancher_threading) + # send.start() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DashboardLiveStockAllocationsViewSet(viewsets.ModelViewSet): + queryset = LiveStockAllocations.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockAllocationsSerializer + filterset_class = LiveStockAllocationsFilterSet + + def list(self, request, *args, **kwargs): + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + role = request.GET.get('role') + name =products[request.GET.get('name')] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + allocations = LiveStockAllocations.objects.filter(jahad__isnull=False, trash=False, + product__parent_product=product).order_by('id') + roles_new_product = LiveStockRolseProduct.objects.filter(jahad__isnull=False, trash=False + , parent_product=product).first() + + + elif request.GET['role'] == 'Union': + allocations = LiveStockAllocations.objects.filter(union__user=user, trash=False, + product__parent_product=product).order_by('id') + + roles_new_product = LiveStockRolseProduct.objects.filter(union__user=user, trash=False, + parent_product=product).first() + + else: + allocations = LiveStockAllocations.objects.filter(cooperative__user=user, trash=False, + product__parent_product=product).order_by('id') + roles_new_product = LiveStockRolseProduct.objects.filter(cooperative__user=user, trash=False, + parent_product=product).first() + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + allocations = allocations.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + jahat_to_union = allocations.filter(jahad__isnull=False, allocate_to='Union') + jahat_to_cooperative = allocations.filter(jahad__isnull=False, allocate_to='Cooperative') + union_to_cooperative = LiveStockAllocations.objects.filter(union__isnull=False, trash=False, allocate_to='Cooperative') + if role == 'Union': + union_to_cooperative = LiveStockAllocations.objects.filter(union__isnull=False,trash=False, allocate_to='Cooperative') + + jahat_to_union_weight = jahat_to_union.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_union_real_weight = jahat_to_union.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + jahat_to_cooperative_weight = jahat_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + jahat_to_cooperative_real_weight = jahat_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + union_to_cooperative_weight = union_to_cooperative.aggregate(total=Sum('weight'))[ + 'total'] or 0 + union_to_cooperative_real_weight = union_to_cooperative.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + + if role =='Union': + role_product_union = roles_new_product.total_remain_weight + role_product_cooperative = 0 + role_product_cooperative_receipt_weight = 0 + + elif role == 'Cooperative': + role_product_union = 0 + role_product_cooperative = roles_new_product.total_remain_weight + role_product_cooperative_receipt_weight = roles_new_product.total_receipt_weight + + else: + roles_product = LiveStockRolseProduct.objects.filter(trash=False, parent_product=product) + union_remain = roles_product.filter(union__isnull=False) + cooperative_remain = roles_product.filter(cooperative__isnull=False) + role_product_union = union_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative = cooperative_remain.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + role_product_cooperative_receipt_weight = cooperative_remain.aggregate(total=Sum('total_receipt_weight'))[ + 'total'] or 0 + + if allocations: + dict1 = { + "total_weight": roles_new_product.total_weight, + "jahad_to_union": jahat_to_union_weight, + "jahat_to_union_real_weight": jahat_to_union_real_weight, + "jahat_to_cooperative": jahat_to_cooperative_weight, + "jahat_to_cooperative_real_weight": jahat_to_cooperative_real_weight, + + "allocation_count": roles_new_product.total_allocated_weight, + "union_to_cooperative": union_to_cooperative_weight, + "union_to_cooperative_real_weight": union_to_cooperative_real_weight, + "total_remain_weight_jahad": roles_new_product.total_remain_weight, + "total_remain_weight_union": role_product_union, + "total_remain_weight_cooperative": role_product_cooperative, + "role_product_cooperative_receipt_weight": role_product_cooperative_receipt_weight, + "total_remain_weight": roles_new_product.total_remain_weight, + } + else: + dict1 = { + "total_weight": 0, + "jahad_to_union": 0, + "jahat_to_cooperative": 0, + + "allocation_count": 0, + "union_to_cooperative": 0, + "total_remain_weight_jahad": 0, + "total_remain_weight_union": 0, + "total_remain_weight_cooperative": 0, + "total_remain_weight": 0, + "jahat_to_union_real_weight": 0, + "union_to_cooperative_real_weight": 0, + "jahat_to_cooperative_real_weight": 0, + "role_product_cooperative_receipt_weight": role_product_cooperative_receipt_weight, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class LiveStockWarehouseChargeAllocationsViewSet(viewsets.ModelViewSet): + queryset = LiveStockAllocations.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockAllocationsSerializer + pagination_class = CustomPagination + filterset_class = LiveStockAllocationsFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + products = { + "bran":"سبوس", + "barley":"جو", + "soy":"سویا", + "corn":"ذرت", + "sheep_concentrate":"کنسانتره گوسفندی", + "high_cow_concentrate":"کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate":"کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate":"کنسانتره گوساله پرواری", + } + name =products[request.GET.get('name')] + product = LiveStockProduct.objects.filter(trash=False, name=name).first() + if request.GET['role'] == 'LiveStockProvinceJahad': + allocations = LiveStockAllocations.objects.filter(jahad__isnull=False, trash=False, + product__parent_product=product, + allocate_to='LiveStockProvinceJahad').order_by('id') + + elif request.GET['role'] == 'Union': + allocations = LiveStockAllocations.objects.filter(allocate_from='LiveStockProvinceJahad', union__isnull=False, + trash=False, product__parent_product=product).order_by( + 'id') + + else: + # allocations = LiveStockAllocations.objects.filter( + # allocate_from__in=('LiveStockProvinceJahad', 'Union', 'Cooperative'), cooperative__user=user, + # trash=False, product__parent_product=product).order_by('id') + allocations = LiveStockAllocations.objects.filter( + charge=True, cooperative__user=user, + trash=False, product__parent_product=product).order_by('id') + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + allocations = allocations.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def get_user_live_stock(request): + type = request.GET['type'] + if type == 'Union': + unions = Union.objects.filter(trash=False).order_by('id') + serializer = UnionSerializer(unions, many=True) + + else: + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + serializer = RancherSerializer(cooperatives, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/LiveStock/LiveStoksAndPoultry/__init__.py b/LiveStock/LiveStoksAndPoultry/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/LiveStoksAndPoultry/excel_processing.py b/LiveStock/LiveStoksAndPoultry/excel_processing.py new file mode 100644 index 0000000..089a5c3 --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/excel_processing.py @@ -0,0 +1,174 @@ +import datetime +import hashlib +from io import BytesIO + +import openpyxl +import requests +from django.contrib.auth.models import Group, User +from django.db.models import Q +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.models import LiveStock, Rancher, Cooperative + +#todo:فعلا چون دامدار تکراری داریم نمیشه ثبت کر باید از طریف آدرس بریم +from authentication.models import SystemUserProfile, Province, City, SystemAddress +from authentication.register import ARTA_REGISTER +from panel.admin import PROJECT_API_KEY +from panel.convert_date import convert_to_shamsi + + +def add_rancher_to_live_stock(request): + livestock=LiveStock.objects.filter(trash=False) + for l in livestock: + rancher=Rancher.objects.filter(trash=False,herd_code=l.herd_code).first() + l.rancher=rancher + l.save() + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def create_live_stock_and_rancher_from_excel(request): + file = request.FILES['file'].read() + read = openpyxl.load_workbook(BytesIO(file), data_only=True) + sheet = read.active + group = Group.objects.get(name='Rancher') + password = '123456' + result_list=[] + yesterday= datetime.datetime.now().date() - datetime.timedelta(days=1) + birth_day=convert_to_shamsi(day=yesterday.day, + month=yesterday.month, + year=yesterday.year).replace('-','/') + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 1: + continue + first_name = row[1] + last_name = row[2] + rancher_name = row[3] + type_rancher = row[4] + herd_code = row[5] + epidemiological_code = row[6] + postal_code = row[7] + type_live_stock = row[8] + gender = row[9] + national_id = row[10] + mobile = row[11] + city = row[12] + range_live_stock = row[13] + if not herd_code: + herd_code = '0000' + str(national_id) + mobile = str(mobile) + + if len(mobile) < 10: + continue + if len(mobile) == 10: + mobile = '0' + mobile + + try: + city_id = City.objects.filter(trash=False, name=city).first() + province = Province.objects.filter(trash=False,key=city_id.province.key).first() + + if not Rancher.objects.filter(Q(herd_code=herd_code) | Q(user__mobile=mobile) | Q(mobile=mobile) + ,trash=False).exists(): + if not SystemUserProfile.objects.filter(trash=False, mobile=mobile).exists(): + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": national_id, + "role": "Rancher", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name+' ' + last_name, + user=user, + base_order=base_id, + password=password, + birthday=datetime.datetime.now().date(), + city=city_id, + province=province + ) + system_profile.save() + system_profile.role.add(group) + address = SystemAddress( + province=province, + city=city_id, + address='', + + ) + address.save() + system_profile=SystemUserProfile.objects.filter(trash=False, mobile=mobile).first() + cooperative = Cooperative.objects.filter(trash=False, address__city=city_id).first() + rancher = Rancher( + user=system_profile, + cooperative=cooperative, + name=rancher_name, + mobile=mobile, + fullname=first_name + ' ' + last_name, + city=city, + herd_name=rancher_name, + postal_code=postal_code, + epidemiological_code=epidemiological_code, + herd_code=herd_code, + national_id=national_id, + type='rural' if type_rancher == 'روستایی' else 'industrial' + + + ) + rancher.save() + rancher = Rancher.objects.filter(Q(herd_code=herd_code) | Q(user__mobile=mobile) | Q(mobile=mobile) + ,trash=False).first() + if rancher: + live_stock_count = LiveStock.objects.filter(trash=False, herd_code=rancher.herd_code, + type=type_live_stock)\ + .count() + if live_stock_count > int(range_live_stock): + new_range = live_stock_count - range_live_stock + for _i in range(new_range): + live_stock = LiveStock.objects.filter( + herd_code=rancher.herd_code, + type=type_live_stock, + trash=False + ).first() + live_stock.trash = True + live_stock.save() + elif live_stock_count < int(range_live_stock): + new_range = range_live_stock - live_stock_count + for _i in range(new_range): + live_stock = LiveStock( + herd_code=rancher.herd_code, + type=type_live_stock, + birth_day=birth_day, + birth_day_gh=yesterday, + gender=gender, + + ) + live_stock.save() + except: + result_list.append(rancher_name) + + return Response(result_list) diff --git a/LiveStock/LiveStoksAndPoultry/filterset.py b/LiveStock/LiveStoksAndPoultry/filterset.py new file mode 100644 index 0000000..ef04645 --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/filterset.py @@ -0,0 +1,22 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import LiveStock + + +class LiveStockFilterSet(filters.FilterSet): + class Meta: + model = LiveStock + fields = [ + 'national_id_livestock_code', + 'herd_code', + 'type', + 'gender', + 'contractor_code', + 'unique_identifier', + 'agent', + 'registering_user', + 'rancher__user__mobile', + 'rancher__user__first_name', + 'rancher__user__last_name', + 'rancher__user__fullname' + ] diff --git a/LiveStock/LiveStoksAndPoultry/helpers.py b/LiveStock/LiveStoksAndPoultry/helpers.py new file mode 100644 index 0000000..e1a8021 --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/helpers.py @@ -0,0 +1,30 @@ +from django.http import HttpResponse + +from LiveStock.helpers import convert_to_miladi +from LiveStock.models import LiveStock, LiveStockRolseProduct, LiveStockProduct, Rancher + + +def add_birthday(reqeust): + live_stock=LiveStock.objects.filter(trash=False,birth_day_gh__isnull=True).only('birth_day') + for l in live_stock: + birth_day=l.birth_day.split('/') + birth_day_gh=convert_to_miladi(year=int(birth_day[0]),month=int(birth_day[1]),day=int(birth_day[2])) + l.birth_day_gh=birth_day_gh + l.save() + return HttpResponse('ok') + +def add_live_stock(request): + rancher=Rancher.objects.get(herd_code='139894930',trash=False) + lve_stock=LiveStock.objects.filter(herd_code=rancher.herd_code,trash=False).first() + for _i in range(110): + live_stock=LiveStock( + herd_code=lve_stock.herd_code, + national_id_livestock_code=lve_stock.national_id_livestock_code, + type=lve_stock.type, + birth_day=lve_stock.birth_day, + birth_day_gh=lve_stock.birth_day_gh, + gender=lve_stock.gender, + + ) + live_stock.save() + return HttpResponse('ok') diff --git a/LiveStock/LiveStoksAndPoultry/serializers.py b/LiveStock/LiveStoksAndPoultry/serializers.py new file mode 100644 index 0000000..9b1c401 --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/serializers.py @@ -0,0 +1,36 @@ +from django.db.models import Sum +from rest_framework import serializers + +from LiveStock.Cooperative.serializers import CooperativeSerializer +from LiveStock.Rancher.serializers import RancherSerializer +from LiveStock.models import LiveStock, Rancher +import datetime + +class LiveStockSerializer(serializers.ModelSerializer): + rancher = serializers.SerializerMethodField('get_rancher') + age = serializers.SerializerMethodField('get_age') + + class Meta: + model = LiveStock + fields = '__all__' + + + + def get_rancher(self,instance): + rancher=Rancher.objects.filter(herd_code=instance.herd_code).first() + ser_data=RancherSerializer(rancher) + return ser_data.data + + def get_age(self,instance): + if instance.birth_day_gh: + now=datetime.datetime.now().date() + age=(now - instance.birth_day_gh.date()).days + return age + else: + return None + +class PosLiveStockSerializer(serializers.ModelSerializer): + cooperative=CooperativeSerializer(read_only=True) + class Meta: + model = Rancher + fields = ['key','fullname','cooperative','mobile','city','herd_code','national_id','allow_buy','weight_allocation_heavy','weight_allocation_light'] diff --git a/LiveStock/LiveStoksAndPoultry/urls.py b/LiveStock/LiveStoksAndPoultry/urls.py new file mode 100644 index 0000000..afc3a59 --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/urls.py @@ -0,0 +1,28 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.LiveStoksAndPoultry import views as live_stock_views +from LiveStock.LiveStoksAndPoultry.excel_processing import create_live_stock_and_rancher_from_excel +from LiveStock.LiveStoksAndPoultry.helpers import add_birthday +from LiveStock.LiveStoksAndPoultry.views import dashboard_live_stock +from LiveStock.Rancher.excel_processing import get_rancher_excel, get_union_excel, get_cooperative_excel + +router = DefaultRouter() +router.register( + r'live-stock-view', + live_stock_views.LiveStockViewSet, + basename="live-stock-view" +) +router.register( + r'pos-live-stock', + live_stock_views.PosLiveStockViewSet, + basename="pos-live-stock" +) + + +urlpatterns = [ + path('', include(router.urls)), + path('dashboard_live_stock/', dashboard_live_stock), + path('add_birthday/', add_birthday), + path('create_live_stock_and_rancher_from_excel/', create_live_stock_and_rancher_from_excel), + +] \ No newline at end of file diff --git a/LiveStock/LiveStoksAndPoultry/views.py b/LiveStock/LiveStoksAndPoultry/views.py new file mode 100644 index 0000000..d67ff5f --- /dev/null +++ b/LiveStock/LiveStoksAndPoultry/views.py @@ -0,0 +1,459 @@ +from datetime import datetime, timedelta + +import jdatetime +from dateutil.relativedelta import relativedelta +from django.db.models import Count, Q +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.LiveStoksAndPoultry.filterset import LiveStockFilterSet +from LiveStock.LiveStoksAndPoultry.serializers import LiveStockSerializer, PosLiveStockSerializer +from LiveStock.Rancher.helpers import update_one_rancher +from LiveStock.helpers import build_query, CustomPagination, convert_to_miladi +from LiveStock.models import LiveStock, Rancher, LiveStockProduct, LiveStockRolseProduct, Cooperative, Union, \ + CooperativeProductsShare +from authentication.models import SystemUserProfile +from panel.models import POSMachine, PosMachineTransactions +from panel.validate_headers import PosDeviceValidator + + +class LiveStockViewSet(viewsets.ModelViewSet): + queryset = LiveStock.objects.filter(trash=False).order_by('-birth_day_gh') + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockSerializer + filterset_class = LiveStockFilterSet + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + role = request.GET['role'] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type=request.GET.get('type') + if type == 'archive': + live_stocks=LiveStock.objects.filter(trash=True,archive=True).order_by('-birth_day_gh') + else: + live_stocks=LiveStock.objects.filter(trash=False).order_by('-birth_day_gh') + + if role == 'Cooperative': + # todo:فعلا چون دامدار تکراری داریم نمیشه از طریق دامدار پیداکرد باید از طریف آدرس بریم + cooperative = Cooperative.objects.get(user=user, trash=False) + ranchers = Rancher.objects.filter(city=cooperative.address.city.name).values_list('herd_code', + flat=True).distinct() + live_stocks = live_stocks.filter(herd_code__in=ranchers) + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + live_stocks = live_stocks.filter(birth_day__gte=date1, birth_day__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + live_stocks = live_stocks.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + page = self.paginate_queryset(live_stocks) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(live_stocks, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + rancher = Rancher.objects.get(key=request.data['rancher_key']) + request.data.pop('rancher_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + live_stock = serializer.create(validated_data=request.data) + live_stock.rancher = rancher + live_stock.herd_code = rancher.herd_code + live_stock.contractor_code = rancher.contractor_code + live_stock.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + user=SystemUserProfile.objects.filter(trash=False,user=request.user).first() + + filter_kwargs = {'key': request.data['live_stock_key']} + if 'return_from_archive' in request.data.keys(): + filter_kwargs['trash']=True + filter_kwargs['archive']=True + else: + filter_kwargs['trash'] = False + + live_stock = LiveStock.objects.get(**filter_kwargs) + live_stocks = LiveStock.objects.filter(herd_code=live_stock.herd_code, trash=False) + rancher = Rancher.objects.get(herd_code=live_stock.herd_code) + + request.data.pop('live_stock_key') + serializer = self.serializer_class(live_stock) + if 'herd_code' in request.data.keys() and request.data['herd_code']: + rancher.herd_code = request.data['herd_code'] + rancher.save() + live_stocks.update(herd_code=request.data['herd_code']) + if 'return_from_archive' in request.data.keys(): + live_stock.archive = False + live_stock.trash = False + live_stock.returner_from_archive=user.fullname + live_stock.return_from_archive_date=datetime.now() + live_stock.save() + request.data.pop('return_from_archive') + + serializer.update(instance=live_stock, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + user=SystemUserProfile.objects.filter(trash=False,user=request.user).first() + live_stock = LiveStock.objects.get(key=request.GET['live_stock_key'], trash=False) + if not live_stock.birth_day_gh: + year, month, day = map(int, live_stock.birth_day.split('/')) + live_stock.birth_day_gh = convert_to_miladi(year, month, day) + live_stock.save() + live_stock.trash=True + live_stock.archive=True + live_stock.archiver=user.fullname + live_stock.archive_date=datetime.now() + live_stock.age_of_archive=(datetime.now().date() - live_stock.birth_day_gh.date()).days + live_stock.save() + + return Response({"result":"با موفقیت بایگانی شد."}, status=status.HTTP_200_OK) + +class PosLiveStockViewSet(viewsets.ModelViewSet): + queryset = Rancher.objects.all() + permission_classes = [AllowAny] + serializer_class = PosLiveStockSerializer + + def get_transactions_month(self,natcode): + import json + transactions = PosMachineTransactions.objects.filter(natcode=natcode,paid=True,live_stock=True, trash=False) + + has_month_data = False + last_month = None + earliest_transaction_date = None + + for transaction in transactions: + try: + additional_data = json.loads(transaction.additional) + if 'month' in additional_data and isinstance(additional_data['month'], list): + has_month_data = True + for month in additional_data['month']: + if last_month is None or month > last_month: + last_month = month + except (json.JSONDecodeError, AttributeError): + pass + + if hasattr(transaction, 'create_date'): + created_date = transaction.create_date + if earliest_transaction_date is None or created_date < earliest_transaction_date: + earliest_transaction_date = created_date + + future_months = [] + + if not transactions: + base_date = jdatetime.date.today().togregorian() - relativedelta(months=1) + include_current = True + elif has_month_data and last_month: + year = int(str(last_month)[:4]) + month = int(str(last_month)[4:6]) + base_date = jdatetime.date(year, month, 1).togregorian() + include_current = False + else: + if earliest_transaction_date: + base_date = earliest_transaction_date + else: + base_date = jdatetime.date.today().togregorian() + include_current = False + + start_offset = 0 if include_current else 1 + + for i in range(start_offset, start_offset + 6): + future_date = base_date + relativedelta(months=i) + jd_future = jdatetime.date.fromgregorian(date=future_date) + future_months.append(int(f"{jd_future.year}{jd_future.month:02d}")) + + + + return future_months + + + def list(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + if pos.cooperative is None: + return Response({"result": "دستگاه شما برای مدیریت امور دام تعریف نشده است!"}, + status=403) + + if int(validator.device_version) < 218: + return Response( + {"result": "لطفا جهت بروزرسانی نسخه دستگاه کارت خوان با پشتیبانی دستگاه ارتباط بگیرید!"}, + status=status.HTTP_403_FORBIDDEN) + + if 'nath_id' in request.GET: + ranchers = Rancher.objects.filter(national_id=request.GET['nath_id'], trash=False).first() + if not ranchers: + return Response({"result": "دامدار یافت نشد!"}, + status=403) + + union = Union.objects.filter(trash=False).first() + if 'product_key' in request.GET: + product = LiveStockRolseProduct.objects.filter(key=request.GET['product_key'], trash=False).select_related( + 'parent_product').only('parent_product__price', 'parent_product__name', 'parent_product__image', + 'parent_product__light_wight', 'parent_product__heavy_wight', + 'parent_product__shipping_price', 'parent_product__union_price', + 'parent_product__cooperative_price').first() + else: + product = LiveStockRolseProduct.objects.filter(cooperative=pos.cooperative, trash=False).select_related( + 'parent_product').only('parent_product__price', 'parent_product__name', 'parent_product__image', + 'parent_product__light_wight', 'parent_product__heavy_wight', + 'parent_product__shipping_price', 'parent_product__union_price', + 'parent_product__cooperative_price').first() + main_product = product.parent_product + share = CooperativeProductsShare.objects.get(product=main_product, cooperative=pos.cooperative, trash=False) + + if ranchers.type == 'rural': + heavy_rate= product.parent_product.heavy_wight + light_rate= product.parent_product.light_wight + else: + heavy_rate= product.parent_product.heavy_wight_industrial + light_rate= product.parent_product.light_wight_industrial + + + + month_list = self.get_transactions_month(request.GET['nath_id']) + shares_list = [] + if share.union_price > 0: + + shares_list.append({ + "name":'union', + "shaba":union.account, + "price":share.union_price, + }) + if share.company_price > 0: + + shares_list.append({ + "name":'company', + "shaba":"IR170150000003100050545702", + "price":share.company_price, + }) + + if pos.cooperative.first_sub_cooperative_price > 0: + + shares_list.append({ + "name":'first_sub_cooperative', + "shaba":pos.cooperative.first_sub_cooperative_account, + "price":pos.cooperative.first_sub_cooperative_price, + }) + + if pos.cooperative.second_sub_cooperative_price > 0: + + shares_list.append({ + "name":'second_sub_cooperative', + "shaba":pos.cooperative.second_sub_cooperative_price, + "price":pos.cooperative.second_sub_cooperative_price, + }) + + + + dict1 = { + "title": [ + {"key": "نام و نام خانوادگی", "value": ranchers.fullname if ranchers.fullname else ranchers.user.fullname}, + {"key": "موبایل", "value": ranchers.mobile}, + {"key": "وزن کل خریداری شده", "value": str(ranchers.total_weight)} + ], + "key": ranchers.key, + "herd_code": ranchers.herd_code, + "national_id": ranchers.national_id, + "fullname": ranchers.fullname if ranchers.fullname else ranchers.user.fullname, + "type": ranchers.type, + "mobile": ranchers.mobile, + "allow_buy": ranchers.allow_buy, + "more_than_inventory": True, + "pos_owners": [], + "allow_buy_message": " ", + "real_light_livestock": ranchers.light_livestock, # تعداد تعیین شده دام توسط سامانه + "real_heavy_livestock": ranchers.heavy_livestock, # تعداد تعیین شده دام توسط سامانه + "real_dhi_livestock": 0, # تعداد تعیین شده دام توسط سامانه + "weight_quota_heavy": ranchers.weight_quota_heavy, # سهمیه قابل دریافت + "weight_quota_light": ranchers.weight_quota_light, # سهمیه قابل دریافت + "weight_quota_dhi": ranchers.dhi_amount, # سهمیه قابل دریافت + "heavy_rate": heavy_rate, # نرخ تبدیل جهت دریافت سهمیه + "light_rate": light_rate, # نرخ تبدیل جهت دریافت سهمیه + "dhi_rate": product.parent_product.heavy_wight_dha, # نرخ تبدیل جهت دریافت سهمیه + "round_rate": 1, # مضرب رند کردن فروش + "total_weight": ranchers.total_weight, # کل خرید دامدار ریم د دمش + + "product_total_weight": product.total_weight, + "product_total_allocated_weight": product.total_allocated_weight, + "product_total_remain_weight": product.total_remain_weight, + "product_name": product.parent_product.name, + "product_image": product.parent_product.image, + "product_price": share.price, + "cooperative_price_with_shipping": share.price + share.shipping_price + share.cooperative_price, + "cooperative_price_without_shipping": share.price + share.cooperative_price, + "union_price": share.union_price, + "union_shaba": union.account, + "shares": shares_list, + "cooperative_shaba": pos.cooperative.account, + "month_list": month_list, + + } + return Response(dict1, status=status.HTTP_200_OK) + + return Response({"resut": "کد ملی وارد نشده است!"}, status=status.HTTP_403_FORBIDDEN) + + +# class DashboardLiveStockViewSet(viewsets.ModelViewSet): +# queryset = LiveStock.objects.filter(trash=False) +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = LiveStockSerializer +# filterset_class = LiveStockFilterSet +# +# def list(self, request, *args, **kwargs): +# role = request.GET['role'] +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# if role == 'Cooperative': +# # todo:فعلا چون دامدار تکراری داریم نمیشه از طریق دامدار پیداکرد باید از طریف آدرس بریم +# cooperative = Cooperative.objects.get(user=user, trash=False) +# ranchers = Rancher.objects.filter(city=cooperative.address.city.name).values_list('herd_code', +# flat=True).distinct() +# live_stocks = self.queryset.filter(herd_code__in=ranchers) +# else: +# live_stocks = self.queryset +# date1 = request.GET.get('date1') +# date2 = request.GET.get('date2') +# if date1 and date2: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# live_stocks = live_stocks.filter(birth_day__gte=date1, birth_day__lte=date2) +# +# value = request.GET.get('value') +# search = request.GET.get('search') +# if value and search == 'filter': +# if search != 'undefined' and search.strip(): +# live_stocks = live_stocks.filter( +# build_query(self.filterset_class.Meta.fields, value) +# ) +# sheep = live_stocks.filter(type='گوسفند').count() +# goat = live_stocks.filter(type='بز').count() +# cow = live_stocks.filter(type='گاو').count() +# horse = live_stocks.filter(type='اسب').count() +# camel = live_stocks.filter(type='شتر').count() +# light_livestock = live_stocks.filter(type__in=('بز', 'گوسفند')).count() +# heavy_livestock = live_stocks.filter(type__in=('گاو', 'اسب', 'شتر')).count() +# +# dict1={ +# 'live_stocks_count':live_stocks.count(), +# "sheep":sheep, +# "goat":goat, +# "cow":cow, +# "horse":horse, +# "camel":camel, +# "light_livestock":light_livestock, +# "heavy_livestock":heavy_livestock, +# +# } +# return Response(dict1, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def dashboard_live_stock(request): + role = request.GET['role'] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type = request.GET.get('type') + if type == 'archive': + live_stocks = LiveStock.objects.filter(trash=True, archive=True).only('type') + else: + live_stocks = LiveStock.objects.filter(trash=False).only('type') + + if role == 'Cooperative': + cooperative = Cooperative.objects.get(user=user, trash=False) + ranchers = Rancher.objects.filter(city=cooperative.address.city.name).values_list('herd_code', + flat=True).distinct() + live_stocks = live_stocks.filter(herd_code__in=ranchers) + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + live_stocks = live_stocks.filter(birth_day__gte=date1, birth_day__lte=date2) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + live_stocks = live_stocks.filter( + build_query(LiveStockFilterSet.Meta.fields, value) + ) + counts = live_stocks.values('type').annotate(total=Count('id')) + count_dict = {item['type']: item['total'] for item in counts} + + light_livestock = count_dict.get('بز', 0) + count_dict.get('گوسفند', 0) + heavy_livestock = count_dict.get('گاو', 0) + count_dict.get('اسب', 0) + count_dict.get('شتر', 0) + + result = { + 'live_stocks_count': sum(count_dict.values()), + "sheep": count_dict.get('گوسفند', 0), + "goat": count_dict.get('بز', 0), + "cow": count_dict.get('گاو', 0), + "horse": count_dict.get('اسب', 0), + "camel": count_dict.get('شتر', 0), + "light_livestock": light_livestock, + "heavy_livestock": heavy_livestock, + } + + return Response(result, status=status.HTTP_200_OK) + +from datetime import date, timedelta + +def archive_live_stock(request): + today = date.today() + archive_msg = 'بایگانی خودکار به علت سن بالا' + + stocks_to_convert = LiveStock.objects.filter(trash=False, birth_day_gh__isnull=True) + for stock in stocks_to_convert: + try: + year, month, day = map(int, stock.birth_day.split('/')) + stock.birth_day_gh = convert_to_miladi(year, month, day) + stock.save() + except: + continue + + archive_conditions = Q( + Q(type__in=['بز', 'گوسفند'], gender='نر') & Q(birth_day_gh__lte=today - timedelta(days=425)) | + Q(type__in=['بز', 'گوسفند'], gender='ماده') & Q(birth_day_gh__lte=today - timedelta(days=1825)) | + Q(type='گاو') & Q(birth_day_gh__lte=today - timedelta(days=3285)) | + Q(type='اسب') & Q(birth_day_gh__lte=today - timedelta(days=4380)) + ) + + archived_count = LiveStock.objects.filter( + trash=False, + birth_day_gh__isnull=False + ).filter(archive_conditions).update( + trash=True, + archive=True, + archiver=archive_msg + ) + + + + return HttpResponse('ok') \ No newline at end of file diff --git a/LiveStock/Rancher/__init__.py b/LiveStock/Rancher/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Rancher/excel_processing.py b/LiveStock/Rancher/excel_processing.py new file mode 100644 index 0000000..68b682a --- /dev/null +++ b/LiveStock/Rancher/excel_processing.py @@ -0,0 +1,592 @@ +import datetime +import hashlib + +import requests +from django.contrib.auth.models import User, Group +from django.db.models import Count +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from openpyxl import Workbook +from openpyxl.styles import Alignment +from rest_framework import status +import openpyxl +from io import BytesIO +from rest_framework.response import Response +from rest_framework.decorators import permission_classes, api_view +from rest_framework.permissions import AllowAny + +from LiveStock.Rancher.helpers import update_one_rancher +from LiveStock.helpers import convert_to_miladi +from LiveStock.models import Rancher, Cooperative, Union, Contractor, LiveStockRolseProduct, LiveStockProvinceJahad, \ + LiveStock +from authentication.models import SystemUserProfile, Province, SystemAddress, City +from authentication.register import ARTA_REGISTER +from panel.admin import PROJECT_API_KEY +from panel.helper_excel import create_header, excel_description, create_header_freez, create_value + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_rancher_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Rancher") + system_user = SystemUserProfile.objects.filter(trash=False) + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 1: + continue + herd_code = row[0] + epidemiological_code = row[1] + postal_code = row[2] + unit_id = row[3] + herd_name = row[4] + national_id = row[5] + name = row[6] + mobile = row[7] + city = row[9] + lng = row[10] + lot = row[11] + registering_user = row[12] + mobile = str(mobile) + + if len(mobile) < 10: + continue + if len(mobile) == 10: + mobile = '0' + mobile + + full_name = name.split(':') + if not system_user.filter(mobile=mobile).exists(): + if not User.objects.filter(username=mobile).exists(): + hashed_password = hashlib.sha256(str('1404').encode()).hexdigest() + data = { + "username": mobile, + "first_name": full_name[0], + "last_name": full_name[1], + "password": hashed_password, + "national_code": national_id, + "role": "Rancher", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + province = Province.objects.filter(trash=False).first() + user = User(username=mobile, first_name=full_name[0], last_name=full_name[1], + password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + city_id = City.objects.filter(trash=False, id=city).first() + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=full_name[0], + last_name=full_name[1], + fullname=name, + user=user, + base_order=base_id, + password='1404', + birthday=datetime.datetime.now().date(), + city=city_id, + province=province + ) + system_profile.save() + system_profile.role.add(group) + address = SystemAddress( + province=province, + city=city_id, + address=city, + postal_code=postal_code + + ) + address.save() + cooperative = Cooperative.objects.filter(trash=False, address__city=city_id).first() + if not Rancher.objects.filter(trash=False, herd_code=herd_code).exists(): + rancher = Rancher( + user=system_profile, + address=address, + cooperative=cooperative, + name=name, + registering_user=registering_user, + lng=lng, + lot=lot, + mobile=mobile, + fullname=name, + city=city, + herd_name=herd_name, + unit_id=unit_id, + postal_code=postal_code, + epidemiological_code=epidemiological_code, + herd_code=herd_code, + national_id=national_id, + + ) + rancher.save() + + return Response({"result": "ok"}, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_union_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Union") + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 3: + continue + type = row[4] + address = row[5] + + name = row[2] + mobile = row[6] + + mobile = str(mobile) + + if len(mobile) < 10: + continue + if len(mobile) == 10: + mobile = '0' + mobile + print(mobile) + full_name = name.split(' ') + if not SystemUserProfile.objects.filter(trash=False, mobile=mobile).exists(): + hashed_password = hashlib.sha256(str('1404').encode()).hexdigest() + data = { + "username": mobile, + "first_name": full_name[0], + "last_name": full_name[1], + "password": hashed_password, + "national_code": '0', + "role": "Union", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + province = Province.objects.filter(trash=False).first() + user = User(username=mobile, first_name=full_name[0], last_name=full_name[1], password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + city_id = City.objects.filter(trash=False, name='همدان').first() + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=full_name[0], + last_name=full_name[1], + fullname=name, + user=user, + base_order=base_id, + password='1404', + birthday=datetime.datetime.now().date(), + city=city_id, + province=province + ) + system_profile.save() + system_profile.role.add(group) + address = SystemAddress( + province=province, + city=city_id, + address=address, + + ) + address.save() + if not Union.objects.filter(trash=False, user__mobile=mobile).exists(): + union = Union( + user=system_profile, + address=address, + name=name, + mobile=mobile, + type=type, + + ) + union.save() + # role_product=LiveStockRolseProduct(union=union) + # role_product.save() + + return Response({"result": "ok"}, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_cooperative_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Cooperative") + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 3: + continue + city = row[3] + address = row[5] + + name = row[4] + mobile = row[6] + national_id = row[7] + + mobile = str(mobile) + + if len(mobile) < 10: + continue + if len(mobile) == 10: + mobile = '0' + mobile + print(mobile) + full_name = name.split(' ') + if not SystemUserProfile.objects.filter(trash=False, mobile=mobile).exists(): + hashed_password = hashlib.sha256(str('1404').encode()).hexdigest() + data = { + "username": mobile, + "first_name": full_name[0], + "last_name": full_name[1], + "password": hashed_password, + "national_code": national_id, + "role": "Cooperative", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + province = Province.objects.filter(trash=False).first() + user = User(username=mobile, first_name=full_name[0], last_name=full_name[1:], password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + city_id = City.objects.filter(trash=False, name__contains=city).first() + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=full_name[0], + last_name=full_name[1], + fullname=name, + user=user, + base_order=base_id, + password='1404', + birthday=datetime.datetime.now().date(), + city=city_id, + province=province + ) + system_profile.save() + system_profile.role.add(group) + address = SystemAddress( + province=province, + city=city_id, + address=address, + + ) + address.save() + if not Cooperative.objects.filter(trash=False, user__mobile=mobile).exists(): + cooperative = Cooperative( + user=system_profile, + address=address, + name=name, + mobile=mobile, + national_id=national_id, + + ) + cooperative.save() + # role_product=LiveStockRolseProduct(union=union) + # role_product.save() + + return Response({"result": "ok"}, status=status.HTTP_200_OK) + + +def hgsahgsad(request): + rancher = Cooperative.objects.all().order_by('id') + for r in rancher: + m=LiveStockRolseProduct( + cooperative=r + ) + m.save() + return HttpResponse('ok') + + +import random + + +def generate_random_phone_number(): + prefix = "0908" + used_numbers = set() + + while True: + suffix = ''.join([str(random.randint(0, 9)) for _ in range(7)]) + full_number = prefix + suffix + + if not SystemUserProfile.objects.filter(mobile=full_number): + used_numbers.add(full_number) + return full_number + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_contractor_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Cooperative") + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 1: + continue + contractor_code = row[0] + first_name = row[1] + last_name = row[2] + full_name=first_name+ ' ' + last_name + entity_code=row[3] + city=row[4] + national_id=row[5] + postal_code=row[7] + company_name=row[8] + + mobile = str(generate_random_phone_number()) + + + if not SystemUserProfile.objects.filter(trash=False, mobile=mobile).exists(): + hashed_password = hashlib.sha256(str('1404').encode()).hexdigest() + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": national_id, + "role": "Contractor", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + province = Province.objects.filter(trash=False).first() + user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + city_id = City.objects.filter(trash=False, id=city).first() + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=full_name, + user=user, + base_order=base_id, + password='1404', + birthday=datetime.datetime.now().date(), + city=city_id, + province=province + ) + system_profile.save() + system_profile.role.add(group) + address = SystemAddress( + province=province, + city=city_id, + postal_code=postal_code, + + ) + address.save() + if not Contractor.objects.filter(trash=False, user__mobile=mobile).exists(): + contractor = Contractor( + user=system_profile, + address=address, + contractor_code=contractor_code, + fullname=full_name, + entity_code=entity_code, + national_id=national_id, + company_name=company_name + + ) + contractor.save() + # role_product=LiveStockRolseProduct(union=union) + # role_product.save() + + return Response({"result": "ok"}, status=status.HTTP_200_OK) + + +def kjdfjsd(request): + live=LiveStock.objects.filter(birth_day_gh__isnull=True).count() + return HttpResponse(live) + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_live_stock_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + + existing_codes = set(LiveStock.objects.filter(trash=False).values_list('national_id_livestock_code', flat=True)) + + live_stocks_to_create = [] + l = 0 + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 1: + continue + + national_id_livestock_code = row[0] + if national_id_livestock_code not in existing_codes: + birth_day = row[3].split('/') + birth_day_ghamari = convert_to_miladi( + year=int(birth_day[0]), + month=int(birth_day[1]), + day=int(birth_day[2]) + ) + + live_stock = LiveStock( + national_id_livestock_code=row[0], + herd_code=row[1], + type=row[2], + birth_day=row[3], + birth_day_gh=birth_day_ghamari, + gender=row[4], + contractor_code=row[5], + unique_identifier=row[6], + agent=row[7], + registering_user=row[8], + registering_date=row[9], + ) + live_stocks_to_create.append(live_stock) + l += 1 + + LiveStock.objects.bulk_create(live_stocks_to_create) + + return Response({"result": l}, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_cooepritive_or_rural_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + rancher=Rancher.objects.filter(trash=False).only('national_id','type') + l=0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + national_id= row[0] + + new_rancher=rancher.filter(national_id=national_id) + if new_rancher: + if len(new_rancher) >1: + for r in new_rancher: + r.type='industrial' + r.save() + else: + n=new_rancher.first() + n.type = 'industrial' + n.save() + l+=1 + + return Response({"result": l}, status=status.HTTP_200_OK) + + +def rancher_repetitive_excel(request): + + + duplicates = Rancher.objects.filter(trash=False).values('national_id').annotate( + count=Count('national_id') + ).filter(count__gt=1) + # حالا رکوردهایی که national_id تکراری دارند را استخراج می‌کنیم + duplicate_records = Rancher.objects.filter( + national_id__in=[item['national_id'] for item in duplicates], + trash=False + ) + + + + + excel_options = [ + 'ردیف', + 'نام دامدار', + 'شماره ملی', + 'کد گله', + 'تعداد دام سبک', + 'تعداد دام سنگین', + + + ] + + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + + + excel_description(worksheet, 'B1', f'انبار', color='red', row2='C1') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + + l = 5 + m = 1 + if duplicate_records: + for data in duplicate_records: + + while True: + update_ranchers = update_one_rancher(data) + if update_ranchers: + break + list1 = [ + m, + data.fullname, + data.national_id, + data.herd_code, + data.light_livestock, + data.heavy_livestock, + + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="تکراری.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response \ No newline at end of file diff --git a/LiveStock/Rancher/filterset.py b/LiveStock/Rancher/filterset.py new file mode 100644 index 0000000..33e4cae --- /dev/null +++ b/LiveStock/Rancher/filterset.py @@ -0,0 +1,25 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import Rancher + + +class RancherFilterSet(filters.FilterSet): + class Meta: + model = Rancher + fields = [ + 'fullname', + 'herd_code', + 'mobile', + 'city', + 'national_id', + 'herd_code', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'registering_user', + 'unit_id', + 'epidemiological_code', + 'postal_code', + + ] diff --git a/LiveStock/Rancher/helpers.py b/LiveStock/Rancher/helpers.py new file mode 100644 index 0000000..8b800bc --- /dev/null +++ b/LiveStock/Rancher/helpers.py @@ -0,0 +1,111 @@ +from django.http import HttpResponse +from django.db.models import Count, Q + +from LiveStock.models import Rancher, LiveStock, LiveStockProduct + + + +def update_quota_rancher_threading(): + rancher=Rancher.objects.filter(trash=False).only('trash').order_by('id') + for rancher in rancher: + rancher.save() + + +def get_live_stock_info(request): + rancher=Rancher.objects.filter(trash=False,has_script=False).only('cow','sheep','goat','horse','camel','light_livestock','heavy_livestock','has_script' + ) + rachers=rancher.values_list('herd_code',flat=True).distinct() + live_stocks = LiveStock.objects.filter(trash=False,herd_code__in=rachers ).only('type') + for r in rancher: + live_stock=live_stocks.filter(herd_code=r.herd_code).only('type') + if live_stock: + sheep=live_stock.filter(type='گوسفند').count() + goat=live_stock.filter(type='بز').count() + cow=live_stock.filter(type='گاو').count() + horse=live_stock.filter(type='اسب').count() + camel=live_stock.filter(type='شتر').count() + light_livestock = live_stock.filter(type__in=('بز', 'گوسفند')).count() + heavy_livestock = live_stock.filter(type__in=('گاو','اسب','شتر')).count() + product = LiveStockProduct.objects.filter(trash=False, name='سبوس').first() + + r.sheep=sheep + r.horse=horse + r.camel=camel + r.light_livestock=light_livestock + r.heavy_livestock=heavy_livestock + r.goat=goat + r.cow=cow + r.has_script=True + r.weight_quota_heavy = product.heavy_wight * heavy_livestock + r.weight_quota_light = product.light_wight * light_livestock + r.save() + + return HttpResponse('ok') + + +def update_rancher(rancherss): + for ranchers in rancherss: + live_stocks = LiveStock.objects.filter(trash=False, herd_code=ranchers.herd_code).only('type') + + sheep = live_stocks.filter(type='گوسفند').count() + goat = live_stocks.filter(type='بز').count() + cow = live_stocks.filter(type='گاو').count() + horse = live_stocks.filter(type='اسب').count() + camel = live_stocks.filter(type='شتر').count() + light_livestock = live_stocks.filter(type__in=('بز', 'گوسفند')).count() + heavy_livestock = live_stocks.filter(type__in=('گاو', 'اسب', 'شتر')).count() + product = LiveStockProduct.objects.filter(name='سبوس', trash=False).first() + + ranchers.sheep = sheep + ranchers.horse = horse + ranchers.camel = camel + ranchers.light_livestock = light_livestock + ranchers.heavy_livestock = heavy_livestock + ranchers.goat = goat + ranchers.cow = cow + ranchers.weight_quota_heavy = product.heavy_wight * heavy_livestock + ranchers.weight_quota_light = product.light_wight * light_livestock + ranchers.save() + return True + + +def al_get_live_stock_info(request): + rancher = Rancher.objects.filter(trash=False, has_script=False).only('cow', 'sheep', 'goat', 'horse', 'camel', + 'light_livestock', 'heavy_livestock', + 'has_script' + ).count() + return HttpResponse(rancher) + + +def update_one_rancher(ranchers): + if not ranchers.has_script: + counts = LiveStock.objects.filter( + trash=False, + herd_code=ranchers.herd_code + ).aggregate( + sheep_count=Count('id', filter=Q(type='گوسفند')), + goat_count=Count('id', filter=Q(type='بز')), + cow_count=Count('id', filter=Q(type='گاو')), + horse_count=Count('id', filter=Q(type='اسب')), + camel_count=Count('id', filter=Q(type='شتر')), + light_count=Count('id', filter=Q(type__in=('بز', 'گوسفند'))), + heavy_count=Count('id', filter=Q(type__in=('گاو', 'اسب', 'شتر'))) + ) + + product = LiveStockProduct.objects.filter(name='سبوس', trash=False).first() + + ranchers.sheep = counts['sheep_count'] + ranchers.goat = counts['goat_count'] + ranchers.cow = counts['cow_count'] + ranchers.horse = counts['horse_count'] + ranchers.camel = counts['camel_count'] + ranchers.light_livestock = counts['light_count'] + ranchers.heavy_livestock = counts['heavy_count'] + + ranchers.weight_quota_heavy = product.heavy_wight * counts['heavy_count'] + ranchers.weight_quota_light = product.light_wight * counts['light_count'] + + ranchers.has_script = True + ranchers.save() + + return True diff --git a/LiveStock/Rancher/serializers.py b/LiveStock/Rancher/serializers.py new file mode 100644 index 0000000..085deba --- /dev/null +++ b/LiveStock/Rancher/serializers.py @@ -0,0 +1,40 @@ +from rest_framework import serializers +from LiveStock.models import Rancher, LiveStock, LiveStockProduct +from authentication.serializer.serializer import BankCardSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import SystemAddressSerializer + + +class RancherSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + # address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Rancher + fields = '__all__' + + +class RancherForBazrasiSerializer(serializers.ModelSerializer): + heavy_livestock = serializers.SerializerMethodField() + light_livestock = serializers.SerializerMethodField() + + class Meta: + model = Rancher + fields = [ + 'herd_code', + 'fullname', + 'mobile', + 'lot', + 'lng', + 'heavy_livestock', + 'light_livestock', + 'type' + + ] + + def get_heavy_livestock(self, obj): + heavy_counts = self.context.get('heavy_counts') or {} + return heavy_counts.get(obj.herd_code, 0) + + def get_light_livestock(self, obj): + light_counts = self.context.get('light_counts') or {} + return light_counts.get(obj.herd_code, 0) diff --git a/LiveStock/Rancher/urls.py b/LiveStock/Rancher/urls.py new file mode 100644 index 0000000..95c8485 --- /dev/null +++ b/LiveStock/Rancher/urls.py @@ -0,0 +1,38 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.Rancher import views as rancher_views +from LiveStock.Rancher.excel_processing import get_rancher_excel, get_union_excel, get_cooperative_excel, hgsahgsad, \ + get_contractor_excel, kjdfjsd, get_live_stock_excel, get_cooepritive_or_rural_excel, rancher_repetitive_excel +from LiveStock.Rancher.helpers import get_live_stock_info +from LiveStock.Rancher.views import get_detail_rancher, dashboard_rancher + +router = DefaultRouter() +router.register( + r'rancher-view', + rancher_views.RancherViewSet, + basename="rancher-view" +) + +router.register( + r'bazrasi-rancher-view', + rancher_views.RancherForBazrasiViewSet, + basename="bazrasi-rancher-view" +) + + +urlpatterns = [ + path('', include(router.urls)), + path('get_rancher_excel/', get_rancher_excel), + path('get_union_excel/', get_union_excel), + path('get_cooperative_excel/', get_cooperative_excel), + path('hgsahgsad/', hgsahgsad), + path('get_contractor_excel/', get_contractor_excel), + path('get_live_stock_info/', get_live_stock_info), + path('get_detail_rancher/', get_detail_rancher), + path('dashboard_rancher/', dashboard_rancher), + path('kjdfjsd/', kjdfjsd), + path('get_live_stock_excel/', get_live_stock_excel), + path('get_cooepritive_or_rural_excel/', get_cooepritive_or_rural_excel), + path('rancher_repetitive_excel/', rancher_repetitive_excel), + +] \ No newline at end of file diff --git a/LiveStock/Rancher/views.py b/LiveStock/Rancher/views.py new file mode 100644 index 0000000..091c75d --- /dev/null +++ b/LiveStock/Rancher/views.py @@ -0,0 +1,352 @@ +from django.db.models import Sum, Count, Q +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.Rancher.filterset import RancherFilterSet +from LiveStock.Rancher.serializers import RancherSerializer, RancherForBazrasiSerializer +from LiveStock.helpers import CustomPagination, build_query +from LiveStock.models import Rancher, Cooperative, LiveStock +from authentication.models import SystemUserProfile, City, Province +from LiveStock.Rancher.helpers import update_rancher, update_one_rancher +from django.contrib.auth.models import User, Group + +from authentication.views import ARTA_URL_REGISTER, ARTA_URL_CHANGE_MOBILE_NUMBER +from panel.admin import PROJECT_API_KEY +import requests + + +class RancherViewSet(viewsets.ModelViewSet): + queryset = Rancher.objects.filter(trash=False).only('herd_code', 'epidemiological_code', 'postal_code', 'unit_id', + 'herd_name', 'national_id', + 'fullname', 'mobile', 'contractor_code', 'city', + 'registering_user', 'light_livestock', 'heavy_livestock', 'cow', + 'goat', 'sheep', 'horse', 'camel', 'lot', 'lng', + 'allow_buy').order_by('id') + permission_classes = [TokenHasReadWriteScope] + serializer_class = RancherSerializer + pagination_class = CustomPagination + filterset_class = RancherFilterSet + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + rancher = user.rancher_user.all() + + serializer = self.serializer_class(rancher[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] == 'Cooperative': + cooperative = Cooperative.objects.get(user=user, trash=False) + ranchers = Rancher.objects.filter(trash=False, city=cooperative.address.city.name).only('herd_code', + 'epidemiological_code', + 'postal_code', + 'unit_id', + 'herd_name', + 'national_id', + 'fullname', + 'mobile', + 'contractor_code', + 'city', + 'registering_user', + 'light_livestock', + 'heavy_livestock', + 'cow', + 'goat', 'sheep', + 'horse', 'camel', + 'lot', 'lng', + 'allow_buy').order_by( + 'id') + + else: + ranchers = Rancher.objects.filter(trash=False).only('herd_code', 'epidemiological_code', 'postal_code', + 'unit_id', 'herd_name', 'national_id', + 'fullname', 'mobile', 'contractor_code', 'city', + 'registering_user', 'light_livestock', + 'heavy_livestock', 'cow', + 'goat', 'sheep', 'horse', 'camel', 'lot', 'lng', + 'allow_buy').order_by('id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + ranchers = ranchers.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(ranchers) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(ranchers.first()) + # serializer = self.serializer_class(ranchers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="Rancher") + city = City.objects.get(name=request.data['city']) + request.data.pop('city') + province = Province.objects.get(key=city.province.key) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if Rancher.objects.filter(user=system_profile, trash=False).exists(): + return Response({"result": "این اتحادیه قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "123456" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + system_profile.role.add(group) + request.data.pop('first_name') + request.data.pop('last_name') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + rancher = serializer.create(validated_data=request.data) + rancher.user = system_profile + rancher.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + rancher = Rancher.objects.get(key=request.data['key'], trash=False) + if 'first_name' in request.data.keys(): + # system_user_profile = SystemUserProfile.objects.get(key=rancher.user.key, trash=False) + # system_user_profile.first_name = request.data['first_name'] + # system_user_profile.last_name = request.data['last_name'] + # system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + # system_user_profile.save() + # first_mobile_number = system_user_profile.mobile + # second_mobile_number = request.data['mobile'] + # if first_mobile_number != second_mobile_number: + # if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + # return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + # status=status.HTTP_403_FORBIDDEN) + # data = { + # "first_mobile_number": first_mobile_number, + # "second_mobile_number": second_mobile_number, + # } + # req = requests.post( + # url=ARTA_URL_CHANGE_MOBILE_NUMBER, + # data=data, + # verify=False + # ) + # if req.status_code == 200: + # second_mobile_number = second_mobile_number + # user = User.objects.get(id=system_user_profile.user.id) + # user.username = second_mobile_number + # user.save() + # system_user_profile.mobile = second_mobile_number + # system_user_profile.save() + request.data.pop('first_name') + request.data.pop('last_name') + + serializer = self.serializer_class(rancher) + serializer.update(instance=rancher, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + + def destroy(self, request, pk=None, *args, **kwargs): + rancher = Rancher.objects.get(key=request.GET["rancher_key"]) + rancher.trash = True + rancher.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + + # def update(self, request, *args, **kwargs): + # rancher = self.queryset.get(key=request.data['key'], trash=False) + # request.data.pop('key') + # + # serializer = self.serializer_class(rancher) + # serializer.update(instance=rancher, validated_data=request.data) + # return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def get_detail_rancher(request): + ranchers = Rancher.objects.filter(herd_code=request.GET['herd_code']).first() + while True: + update_ranchers = update_one_rancher(ranchers) + if update_ranchers: + break + dict1 = { + "light_livestock": ranchers.light_livestock, + "heavy_livestock": ranchers.heavy_livestock, + "sheep": ranchers.sheep, + "goat": ranchers.goat, + "cow": ranchers.cow, + "camel": ranchers.camel, + "horse": ranchers.horse + } + return Response(dict1, status=status.HTTP_200_OK) + + +class RancherForBazrasiViewSet(viewsets.ModelViewSet): + queryset = Rancher.objects.filter(trash=False, type='industrial').only( + 'herd_code', + 'fullname', + 'mobile', + 'lot', + 'lng', + 'industrial', + 'heavy_livestock', + 'light_livestock' + ).order_by('-industrial', 'id') + permission_classes = [AllowAny] + serializer_class = RancherForBazrasiSerializer + + def list(self, request, *args, **kwargs): + type_filter = request.GET.get('type') + queryset = Rancher.objects.filter(trash=False).only( + 'herd_code', + 'fullname', + 'mobile', + 'lot', + 'lng', + 'industrial', + 'heavy_livestock', + 'light_livestock', + 'type' + ).order_by('-industrial', 'id') + + if type_filter in ('industrial', 'rural'): + queryset = queryset.filter(type=type_filter) + + herd_codes = list(queryset.values_list('herd_code', flat=True)) + + heavy_counts = {} + light_counts = {} + valid_herd_codes = set() + if herd_codes: + heavy_types = ('گاو', 'اسب', 'شتر') + light_types = ('بز', 'گوسفند') + livestock_counts = ( + LiveStock.objects.filter( + trash=False, + herd_code__in=herd_codes, + type__in=heavy_types + light_types + ) + .values('herd_code', 'type') + .annotate(total=Count('id')) + ) + for item in livestock_counts: + herd_code = item['herd_code'] + livestock_type = item['type'] + total = item['total'] + if livestock_type in heavy_types: + heavy_counts[herd_code] = heavy_counts.get(herd_code, 0) + total + elif livestock_type in light_types: + light_counts[herd_code] = light_counts.get(herd_code, 0) + total + + valid_herd_codes = set(heavy_counts.keys()) | set(light_counts.keys()) + + if valid_herd_codes: + queryset = queryset.filter(herd_code__in=valid_herd_codes) + else: + queryset = queryset.none() + + serializer = self.get_serializer( + queryset, + many=True, + context={ + 'heavy_counts': heavy_counts, + 'light_counts': light_counts + } + ) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def dashboard_rancher(request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + + ranchers = Rancher.objects.filter(trash=False).values_list('herd_code', flat=True).distinct() + + live_stocks = LiveStock.objects.filter(trash=False, herd_code__in=ranchers).only('type') + + if role == 'Cooperative': + cooperative = Cooperative.objects.get(user=user, trash=False) + ranchers = Rancher.objects.filter(trash=False, city=cooperative.address.city.name).values_list('herd_code', + flat=True).distinct() + live_stocks = live_stocks.filter(herd_code__in=ranchers) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + ranchers = ranchers.filter(build_query(RancherFilterSet.Meta.fields, value)) + + counts = live_stocks.values('type').annotate(total=Count('id')) + count_dict = {item['type']: item['total'] for item in counts} + + light_livestock = count_dict.get('بز', 0) + count_dict.get('گوسفند', 0) + heavy_livestock = count_dict.get('گاو', 0) + count_dict.get('اسب', 0) + count_dict.get('شتر', 0) + total_ranchers = len(ranchers) + dhi_amount = ranchers.filter(dhi_amount__gt=1,trash=False).aggregate(total=Sum('dhi_amount'))['total'] or 0 + + result = { + 'rancher_count': total_ranchers, + 'live_stocks_count': sum(count_dict.values()), + "sheep": count_dict.get('گوسفند', 0), + "goat": count_dict.get('بز', 0), + "cow": count_dict.get('گاو', 0), + "horse": count_dict.get('اسب', 0), + "camel": count_dict.get('شتر', 0), + "light_livestock": light_livestock, + "heavy_livestock": heavy_livestock, + "dhi_amount": dhi_amount, + + } + + return Response(result, status=status.HTTP_200_OK) diff --git a/LiveStock/Union/__init__.py b/LiveStock/Union/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Union/excel_processing.py b/LiveStock/Union/excel_processing.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Union/filterset.py b/LiveStock/Union/filterset.py new file mode 100644 index 0000000..0b6bee6 --- /dev/null +++ b/LiveStock/Union/filterset.py @@ -0,0 +1,17 @@ +from django_filters import rest_framework as filters + +from LiveStock.models import Union + + +class UnionFilterSet(filters.FilterSet): + class Meta: + model = Union + fields = [ + 'address__city__name', + 'name', + 'mobile', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname' + ] diff --git a/LiveStock/Union/helpers.py b/LiveStock/Union/helpers.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/Union/serializers.py b/LiveStock/Union/serializers.py new file mode 100644 index 0000000..30f3dd2 --- /dev/null +++ b/LiveStock/Union/serializers.py @@ -0,0 +1,15 @@ +from rest_framework import serializers + +from LiveStock.models import Union +from authentication.serializer.serializer import BankCardSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import SystemAddressSerializer + + +class UnionSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = Union + fields = '__all__' diff --git a/LiveStock/Union/urls.py b/LiveStock/Union/urls.py new file mode 100644 index 0000000..af4dc07 --- /dev/null +++ b/LiveStock/Union/urls.py @@ -0,0 +1,14 @@ +from rest_framework.routers import DefaultRouter +from django.urls import path, include +from LiveStock.Union import views as union_views +router = DefaultRouter() +router.register( + r'union-view', + union_views.UnionViewSet, + basename="union" +) + + +urlpatterns = [ + path('', include(router.urls)), + ] \ No newline at end of file diff --git a/LiveStock/Union/views.py b/LiveStock/Union/views.py new file mode 100644 index 0000000..c2bc706 --- /dev/null +++ b/LiveStock/Union/views.py @@ -0,0 +1,181 @@ +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import viewsets +from rest_framework import status +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from LiveStock.Union.filterset import UnionFilterSet +from LiveStock.Union.serializers import UnionSerializer +from LiveStock.helpers import build_query, CustomPagination +from LiveStock.models import Union +from authentication.models import SystemUserProfile, City, Province, SystemAddress +from django.contrib.auth.models import User, Group + +from authentication.views import ARTA_URL_REGISTER, ARTA_URL_CHANGE_MOBILE_NUMBER +from panel.admin import PROJECT_API_KEY +import requests + + +class UnionViewSet(viewsets.ModelViewSet): + queryset = Union.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = UnionSerializer + filterset_class = UnionFilterSet + pagination_class = CustomPagination + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + union = user.union_user.all() + + serializer = self.serializer_class(union[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + unions = Union.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + unions = unions.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + page = self.paginate_queryset(unions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(unions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="Union") + city = City.objects.get(name=request.data['city']) + request.data.pop('city') + province = Province.objects.get(key=city.province.key) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if Union.objects.filter(user=system_profile, trash=False).exists(): + return Response({"result": "این اتحادیه قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "123456" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + address = SystemAddress(city=city, province=province, address=request.data['address'], + postal_code=request.data['postal_code']) + address.save() + system_profile.role.add(group) + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('postal_code') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + union = serializer.create(validated_data=request.data) + union.user = system_profile + union.address = address + union.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + union = Union.objects.get(key=request.data['union_key'], trash=False) + address = SystemAddress.objects.get(key=union.address.key, trash=False) + request.data.pop('union_key') + if 'first_name' in request.data.keys(): + system_user_profile = SystemUserProfile.objects.get(key=union.user.key, trash=False) + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + city = City.objects.get(name=request.data['city']) + province = Province.objects.get(key=city.province.key) + address.city = city + address.province = province + address.address = request.data['address'] + address.postal_code = request.data['postal_code'] + address.save() + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('city') + + serializer = self.serializer_class(union) + serializer.update(instance=union, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # def update(self, request, *args, **kwargs): + # union = Union.objects.get(key=request.data['key'], trash=False) + # request.data.pop('key') + # if 'city' in request.data: + # city_key=request.data['city'] + # request.data.pop('city') + # city=City.objects.filter(key=city_key,trash=False).first() + # union.address.city=city + # union.address.save() + # serializer = self.serializer_class(union) + # + # serializer.update(instance=union, validated_data=request.data) + # return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + union = Union.objects.get(key=request.GET["key"]) + union.trash = True + union.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) diff --git a/LiveStock/__init__.py b/LiveStock/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/admin.py b/LiveStock/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/LiveStock/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/LiveStock/apps.py b/LiveStock/apps.py new file mode 100644 index 0000000..2494717 --- /dev/null +++ b/LiveStock/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class LivestockConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'LiveStock' diff --git a/LiveStock/helpers.py b/LiveStock/helpers.py new file mode 100644 index 0000000..e76a4f8 --- /dev/null +++ b/LiveStock/helpers.py @@ -0,0 +1,21 @@ +import jdatetime +from rest_framework.pagination import PageNumberPagination + + +class CustomPagination(PageNumberPagination): + page_size = 10 + page_size_query_param = 'page_size' + max_page_size = 100 + + +def convert_to_miladi(year=None, month=None, day=None): + date = jdatetime.datetime(year, month, day).togregorian() + return date + + +def build_query(fields, value): + from django.db.models import Q + query = Q() + for field in fields: + query |= Q(**{f"{field}__icontains": value}) + return query diff --git a/LiveStock/migrations/0001_initial.py b/LiveStock/migrations/0001_initial.py new file mode 100644 index 0000000..1805112 --- /dev/null +++ b/LiveStock/migrations/0001_initial.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-02 12:03 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('authentication', '0060_auto_20250302_1203'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0461_auto_20250302_1203'), + ] + + operations = [ + migrations.CreateModel( + name='LiveStockProvinceJahad', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_jahad_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockprovincejahad_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockprovincejahad_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_jahad_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_jahad_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_jahad_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0002_livestockprovincejahad_name.py b/LiveStock/migrations/0002_livestockprovincejahad_name.py new file mode 100644 index 0000000..625b1ad --- /dev/null +++ b/LiveStock/migrations/0002_livestockprovincejahad_name.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-02 12:12 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='livestockprovincejahad', + name='name', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/LiveStock/migrations/0003_auto_20250302_1254.py b/LiveStock/migrations/0003_auto_20250302_1254.py new file mode 100644 index 0000000..272d2ef --- /dev/null +++ b/LiveStock/migrations/0003_auto_20250302_1254.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-03-02 12:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0002_livestockprovincejahad_name'), + ] + + operations = [ + migrations.AddField( + model_name='livestockprovincejahad', + name='account', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='livestockprovincejahad', + name='mobile', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='livestockprovincejahad', + name='national_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='livestockprovincejahad', + name='type', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/LiveStock/migrations/0004_cooperative_union.py b/LiveStock/migrations/0004_cooperative_union.py new file mode 100644 index 0000000..53fb988 --- /dev/null +++ b/LiveStock/migrations/0004_cooperative_union.py @@ -0,0 +1,67 @@ +# Generated by Django 3.2.13 on 2025-03-02 13:51 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0462_auto_20250302_1351'), + ('authentication', '0061_auto_20250302_1351'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('LiveStock', '0003_auto_20250302_1254'), + ] + + operations = [ + migrations.CreateModel( + name='Union', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=200, null=True)), + ('type', models.CharField(max_length=200, null=True)), + ('account', models.CharField(max_length=200, null=True)), + ('national_id', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Cooperative', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=200, null=True)), + ('type', models.CharField(max_length=200, null=True)), + ('account', models.CharField(max_length=200, null=True)), + ('national_id', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0005_livestockallocations_livestockproduct_livestockrolseproduct_rancher.py b/LiveStock/migrations/0005_livestockallocations_livestockproduct_livestockrolseproduct_rancher.py new file mode 100644 index 0000000..34a0795 --- /dev/null +++ b/LiveStock/migrations/0005_livestockallocations_livestockproduct_livestockrolseproduct_rancher.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-03-02 14:58 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0062_auto_20250302_1458'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0463_auto_20250302_1458'), + ('LiveStock', '0004_cooperative_union'), + ] + + operations = [ + migrations.CreateModel( + name='LiveStockProduct', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('image', models.CharField(max_length=500, null=True)), + ('unit', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockproduct_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockproduct_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Rancher', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=200, null=True)), + ('type', models.CharField(max_length=200, null=True)), + ('account', models.CharField(max_length=200, null=True)), + ('national_id', models.CharField(max_length=100, null=True)), + ('unit_id', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LiveStockRolseProduct', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('total_weight', models.BigIntegerField(default=0)), + ('total_allocated_weight', models.BigIntegerField(default=0)), + ('total_remain_weight', models.CharField(max_length=500, null=True)), + ('cooperative', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_product', to='LiveStock.cooperative')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockrolseproduct_createdby', to=settings.AUTH_USER_MODEL)), + ('jahad', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_product', to='LiveStock.livestockproduct')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockrolseproduct_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent_product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parents_product', to='LiveStock.livestockproduct')), + ('rancher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_product', to='LiveStock.rancher')), + ('union', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_product', to='LiveStock.union')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LiveStockAllocations', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(default='pending', max_length=200)), + ('weight', models.BigIntegerField(default=0)), + ('real_weight', models.BigIntegerField(default=0)), + ('cooperative', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_allocation', to='LiveStock.cooperative')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockallocations_createdby', to=settings.AUTH_USER_MODEL)), + ('jahad', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_allocation', to='LiveStock.livestockproduct')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestockallocations_modifiedby', to=settings.AUTH_USER_MODEL)), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_allocation', to='LiveStock.livestockrolseproduct')), + ('rancher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_allocation', to='LiveStock.cooperative')), + ('union', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='union_allocation', to='LiveStock.union')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0006_auto_20250302_1627.py b/LiveStock/migrations/0006_auto_20250302_1627.py new file mode 100644 index 0000000..a7d167b --- /dev/null +++ b/LiveStock/migrations/0006_auto_20250302_1627.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.13 on 2025-03-02 16:27 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0005_livestockallocations_livestockproduct_livestockrolseproduct_rancher'), + ] + + operations = [ + migrations.RemoveField( + model_name='cooperative', + name='wallet', + ), + migrations.RemoveField( + model_name='livestockprovincejahad', + name='wallet', + ), + migrations.RemoveField( + model_name='rancher', + name='wallet', + ), + migrations.RemoveField( + model_name='union', + name='wallet', + ), + migrations.AddField( + model_name='rancher', + name='cooperative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_cooperative', to='LiveStock.cooperative'), + ), + ] diff --git a/LiveStock/migrations/0007_auto_20250303_0931.py b/LiveStock/migrations/0007_auto_20250303_0931.py new file mode 100644 index 0000000..2ae0952 --- /dev/null +++ b/LiveStock/migrations/0007_auto_20250303_0931.py @@ -0,0 +1,37 @@ +# Generated by Django 3.2.13 on 2025-03-03 09:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0006_auto_20250302_1627'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockallocations', + name='jahad', + ), + migrations.RemoveField( + model_name='livestockrolseproduct', + name='jahad', + ), + migrations.AddField( + model_name='livestockallocations', + name='allocate_from', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='livestockallocations', + name='allocate_to', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='livestockallocations', + name='date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + ] diff --git a/LiveStock/migrations/0008_auto_20250303_0933.py b/LiveStock/migrations/0008_auto_20250303_0933.py new file mode 100644 index 0000000..bb7f52d --- /dev/null +++ b/LiveStock/migrations/0008_auto_20250303_0933.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.13 on 2025-03-03 09:33 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0007_auto_20250303_0931'), + ] + + operations = [ + migrations.AddField( + model_name='livestockallocations', + name='jahad', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_allocation', to='LiveStock.livestockprovincejahad'), + ), + migrations.AddField( + model_name='livestockrolseproduct', + name='jahad', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_product', to='LiveStock.livestockprovincejahad'), + ), + ] diff --git a/LiveStock/migrations/0009_auto_20250303_1021.py b/LiveStock/migrations/0009_auto_20250303_1021.py new file mode 100644 index 0000000..ac25922 --- /dev/null +++ b/LiveStock/migrations/0009_auto_20250303_1021.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2025-03-03 10:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0008_auto_20250303_0933'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockallocations', + name='rancher', + ), + migrations.RemoveField( + model_name='rancher', + name='account', + ), + migrations.RemoveField( + model_name='rancher', + name='type', + ), + migrations.AddField( + model_name='rancher', + name='city', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='rancher', + name='epidemiological_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='rancher', + name='fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='rancher', + name='herd_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='rancher', + name='herd_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='rancher', + name='lng', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='lot', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='postal_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='rancher', + name='registering_user', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/LiveStock/migrations/0010_livestockallocations_rancher.py b/LiveStock/migrations/0010_livestockallocations_rancher.py new file mode 100644 index 0000000..741a6a0 --- /dev/null +++ b/LiveStock/migrations/0010_livestockallocations_rancher.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2025-03-03 10:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0009_auto_20250303_1021'), + ] + + operations = [ + migrations.AddField( + model_name='livestockallocations', + name='rancher', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_allocation', to='LiveStock.rancher'), + ), + ] diff --git a/LiveStock/migrations/0011_remove_livestockallocations_rancher.py b/LiveStock/migrations/0011_remove_livestockallocations_rancher.py new file mode 100644 index 0000000..7a83f4a --- /dev/null +++ b/LiveStock/migrations/0011_remove_livestockallocations_rancher.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.13 on 2025-03-03 12:05 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0010_livestockallocations_rancher'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockallocations', + name='rancher', + ), + ] diff --git a/LiveStock/migrations/0012_remove_livestockrolseproduct_rancher.py b/LiveStock/migrations/0012_remove_livestockrolseproduct_rancher.py new file mode 100644 index 0000000..cb8c9a2 --- /dev/null +++ b/LiveStock/migrations/0012_remove_livestockrolseproduct_rancher.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.13 on 2025-03-03 15:00 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0011_remove_livestockallocations_rancher'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockrolseproduct', + name='rancher', + ), + ] diff --git a/LiveStock/migrations/0013_livestock.py b/LiveStock/migrations/0013_livestock.py new file mode 100644 index 0000000..b966bb2 --- /dev/null +++ b/LiveStock/migrations/0013_livestock.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.13 on 2025-03-04 13:43 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('LiveStock', '0012_remove_livestockrolseproduct_rancher'), + ] + + operations = [ + migrations.CreateModel( + name='LiveStock', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('national_id_livestock_code', models.CharField(max_length=200, null=True)), + ('herd_code', models.CharField(max_length=100, null=True)), + ('type', models.CharField(max_length=200, null=True)), + ('birth_day', models.DateField(null=True)), + ('gender', models.CharField(max_length=100, null=True)), + ('contractor_code', models.CharField(max_length=100, null=True)), + ('unique_identifier', models.CharField(max_length=100, null=True)), + ('agent', models.CharField(max_length=100, null=True)), + ('registering_user', models.CharField(max_length=200, null=True)), + ('registering_date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestock_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestock_modifiedby', to=settings.AUTH_USER_MODEL)), + ('rancher', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='LiveStock.rancher')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0014_auto_20250305_1331.py b/LiveStock/migrations/0014_auto_20250305_1331.py new file mode 100644 index 0000000..ac05bc0 --- /dev/null +++ b/LiveStock/migrations/0014_auto_20250305_1331.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-05 13:31 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0013_livestock'), + ] + + operations = [ + migrations.AlterField( + model_name='livestock', + name='birth_day', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='livestock', + name='registering_date', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/LiveStock/migrations/0015_rancher_allow_buy.py b/LiveStock/migrations/0015_rancher_allow_buy.py new file mode 100644 index 0000000..96cbe6d --- /dev/null +++ b/LiveStock/migrations/0015_rancher_allow_buy.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-05 16:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0014_auto_20250305_1331'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='allow_buy', + field=models.BooleanField(default=True), + ), + ] diff --git a/LiveStock/migrations/0016_auto_20250305_1701.py b/LiveStock/migrations/0016_auto_20250305_1701.py new file mode 100644 index 0000000..bd94cda --- /dev/null +++ b/LiveStock/migrations/0016_auto_20250305_1701.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-05 17:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0015_rancher_allow_buy'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='weight_allocation_heavy', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='weight_allocation_light', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0017_auto_20250306_0033.py b/LiveStock/migrations/0017_auto_20250306_0033.py new file mode 100644 index 0000000..2c5a9cd --- /dev/null +++ b/LiveStock/migrations/0017_auto_20250306_0033.py @@ -0,0 +1,48 @@ +# Generated by Django 3.2.13 on 2025-03-06 00:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0016_auto_20250305_1701'), + ] + + operations = [ + migrations.AddField( + model_name='livestockproduct', + name='cooperative_percent', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='livestockproduct', + name='price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='union_percent', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='rancher', + name='total_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='weight_quota_heavy', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='weight_quota_light', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='livestockrolseproduct', + name='total_remain_weight', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0018_auto_20250306_1106.py b/LiveStock/migrations/0018_auto_20250306_1106.py new file mode 100644 index 0000000..7d808b5 --- /dev/null +++ b/LiveStock/migrations/0018_auto_20250306_1106.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2025-03-06 11:06 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0066_auto_20250306_1106'), + ('LiveStock', '0017_auto_20250306_0033'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='contractor_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.CreateModel( + name='Contractor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('contractor_code', models.CharField(max_length=100, null=True)), + ('fullname', models.CharField(max_length=200, null=True)), + ('entity_code', models.CharField(max_length=200, null=True)), + ('national_id', models.CharField(max_length=100, null=True)), + ('company_name', models.CharField(max_length=200, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_user', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0019_auto_20250306_1921.py b/LiveStock/migrations/0019_auto_20250306_1921.py new file mode 100644 index 0000000..343aa93 --- /dev/null +++ b/LiveStock/migrations/0019_auto_20250306_1921.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-06 19:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0018_auto_20250306_1106'), + ] + + operations = [ + migrations.AddField( + model_name='livestockproduct', + name='heavy_wight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='light_wight', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0020_auto_20250307_1118.py b/LiveStock/migrations/0020_auto_20250307_1118.py new file mode 100644 index 0000000..6e31b98 --- /dev/null +++ b/LiveStock/migrations/0020_auto_20250307_1118.py @@ -0,0 +1,60 @@ +# Generated by Django 3.2.13 on 2025-03-07 11:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0019_auto_20250306_1921'), + ] + + operations = [ + migrations.RemoveField( + model_name='rancher', + name='address', + ), + migrations.RemoveField( + model_name='rancher', + name='cooperative', + ), + migrations.RemoveField( + model_name='rancher', + name='user_bank_info', + ), + migrations.AddField( + model_name='rancher', + name='camel', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='cow', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='goat', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='heavy_livestock', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='horse', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='light_livestock', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rancher', + name='sheep', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0021_auto_20250307_1312.py b/LiveStock/migrations/0021_auto_20250307_1312.py new file mode 100644 index 0000000..688b347 --- /dev/null +++ b/LiveStock/migrations/0021_auto_20250307_1312.py @@ -0,0 +1,34 @@ +# Generated by Django 3.2.13 on 2025-03-07 13:12 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0020_auto_20250307_1118'), + ] + + operations = [ + migrations.AddField( + model_name='contractor', + name='cooperative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='contractor_cooperative', to='LiveStock.cooperative'), + ), + migrations.AddField( + model_name='contractor', + name='heavy_livestock', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='contractor', + name='light_livestock', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='contractor', + name='number_of_rancher', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0022_rancher_has_script.py b/LiveStock/migrations/0022_rancher_has_script.py new file mode 100644 index 0000000..1f223ca --- /dev/null +++ b/LiveStock/migrations/0022_rancher_has_script.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-07 13:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0021_auto_20250307_1312'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='has_script', + field=models.BooleanField(default=False), + ), + ] diff --git a/LiveStock/migrations/0023_rancher_cooperative.py b/LiveStock/migrations/0023_rancher_cooperative.py new file mode 100644 index 0000000..93961ee --- /dev/null +++ b/LiveStock/migrations/0023_rancher_cooperative.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2025-03-07 15:25 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0022_rancher_has_script'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='cooperative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rancher_cooperative', to='LiveStock.cooperative'), + ), + ] diff --git a/LiveStock/migrations/0024_auto_20250307_2117.py b/LiveStock/migrations/0024_auto_20250307_2117.py new file mode 100644 index 0000000..5012292 --- /dev/null +++ b/LiveStock/migrations/0024_auto_20250307_2117.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-03-07 21:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0023_rancher_cooperative'), + ] + + operations = [ + migrations.AddField( + model_name='livestockproduct', + name='company_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='cooperative_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='shipping_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='union_price', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0025_auto_20250307_2128.py b/LiveStock/migrations/0025_auto_20250307_2128.py new file mode 100644 index 0000000..122fc22 --- /dev/null +++ b/LiveStock/migrations/0025_auto_20250307_2128.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.13 on 2025-03-07 21:28 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0024_auto_20250307_2117'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockproduct', + name='cooperative_percent', + ), + migrations.RemoveField( + model_name='livestockproduct', + name='union_percent', + ), + ] diff --git a/LiveStock/migrations/0026_auto_20250308_1507.py b/LiveStock/migrations/0026_auto_20250308_1507.py new file mode 100644 index 0000000..cd82b7a --- /dev/null +++ b/LiveStock/migrations/0026_auto_20250308_1507.py @@ -0,0 +1,28 @@ +# Generated by Django 3.2.13 on 2025-03-08 15:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0025_auto_20250307_2128'), + ] + + operations = [ + migrations.AddField( + model_name='cooperative', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='livestockallocations', + name='description', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='livestockallocations', + name='place', + field=models.TextField(null=True), + ), + ] diff --git a/LiveStock/migrations/0027_livestockrolseproduct_total_receipt_weight.py b/LiveStock/migrations/0027_livestockrolseproduct_total_receipt_weight.py new file mode 100644 index 0000000..8178423 --- /dev/null +++ b/LiveStock/migrations/0027_livestockrolseproduct_total_receipt_weight.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-09 09:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0026_auto_20250308_1507'), + ] + + operations = [ + migrations.AddField( + model_name='livestockrolseproduct', + name='total_receipt_weight', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0028_auto_20250309_1036.py b/LiveStock/migrations/0028_auto_20250309_1036.py new file mode 100644 index 0000000..31be0f7 --- /dev/null +++ b/LiveStock/migrations/0028_auto_20250309_1036.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-09 10:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0027_livestockrolseproduct_total_receipt_weight'), + ] + + operations = [ + migrations.AddField( + model_name='livestockallocations', + name='charge', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='livestockallocations', + name='code', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/LiveStock/migrations/0029_livestockrolseproduct_total_allocated.py b/LiveStock/migrations/0029_livestockrolseproduct_total_allocated.py new file mode 100644 index 0000000..c5e50b1 --- /dev/null +++ b/LiveStock/migrations/0029_livestockrolseproduct_total_allocated.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-09 14:06 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0028_auto_20250309_1036'), + ] + + operations = [ + migrations.AddField( + model_name='livestockrolseproduct', + name='total_allocated', + field=models.BigIntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0030_remove_livestockrolseproduct_total_allocated.py b/LiveStock/migrations/0030_remove_livestockrolseproduct_total_allocated.py new file mode 100644 index 0000000..b2d39b1 --- /dev/null +++ b/LiveStock/migrations/0030_remove_livestockrolseproduct_total_allocated.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.13 on 2025-03-09 14:23 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0029_livestockrolseproduct_total_allocated'), + ] + + operations = [ + migrations.RemoveField( + model_name='livestockrolseproduct', + name='total_allocated', + ), + ] diff --git a/LiveStock/migrations/0031_cooperativeproductsshare.py b/LiveStock/migrations/0031_cooperativeproductsshare.py new file mode 100644 index 0000000..973a2d5 --- /dev/null +++ b/LiveStock/migrations/0031_cooperativeproductsshare.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-03-10 10:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('LiveStock', '0030_remove_livestockrolseproduct_total_allocated'), + ] + + operations = [ + migrations.CreateModel( + name='CooperativeProductsShare', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('price', models.IntegerField(default=0)), + ('shipping_price', models.IntegerField(default=0)), + ('union_price', models.IntegerField(default=0)), + ('cooperative_price', models.IntegerField(default=0)), + ('cooperative', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_share_product', to='LiveStock.cooperative')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperativeproductsshare_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperativeproductsshare_modifiedby', to=settings.AUTH_USER_MODEL)), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_share_product', to='LiveStock.livestockproduct')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0032_auto_20250310_1639.py b/LiveStock/migrations/0032_auto_20250310_1639.py new file mode 100644 index 0000000..52bf468 --- /dev/null +++ b/LiveStock/migrations/0032_auto_20250310_1639.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-10 16:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0031_cooperativeproductsshare'), + ] + + operations = [ + migrations.AddField( + model_name='union', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='livestockallocations', + name='description', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/LiveStock/migrations/0033_auto_20250310_1747.py b/LiveStock/migrations/0033_auto_20250310_1747.py new file mode 100644 index 0000000..5945905 --- /dev/null +++ b/LiveStock/migrations/0033_auto_20250310_1747.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-10 17:47 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0032_auto_20250310_1639'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='rancher', + name='active', + field=models.BooleanField(default=True), + ), + ] diff --git a/LiveStock/migrations/0034_auto_20250311_1002.py b/LiveStock/migrations/0034_auto_20250311_1002.py new file mode 100644 index 0000000..07923cd --- /dev/null +++ b/LiveStock/migrations/0034_auto_20250311_1002.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-11 10:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0033_auto_20250310_1747'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='birth_day_gh', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='livestock', + name='registering_date_gh', + field=models.DateTimeField(null=True), + ), + ] diff --git a/LiveStock/migrations/0035_posseller.py b/LiveStock/migrations/0035_posseller.py new file mode 100644 index 0000000..9c6ef80 --- /dev/null +++ b/LiveStock/migrations/0035_posseller.py @@ -0,0 +1,37 @@ +# Generated by Django 3.2.13 on 2025-03-11 13:30 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('LiveStock', '0034_auto_20250311_1002'), + ] + + operations = [ + migrations.CreateModel( + name='PosSeller', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('full_name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=50, null=True)), + ('national_id', models.CharField(max_length=50, null=True)), + ('city', models.CharField(max_length=100, null=True)), + ('cooperative', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='seller_pos_cooperative', to='LiveStock.cooperative')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posseller_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posseller_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/LiveStock/migrations/0036_rancher_type.py b/LiveStock/migrations/0036_rancher_type.py new file mode 100644 index 0000000..010c971 --- /dev/null +++ b/LiveStock/migrations/0036_rancher_type.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-12 11:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0035_posseller'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='type', + field=models.CharField(default='rural', max_length=200), + ), + ] diff --git a/LiveStock/migrations/0037_auto_20250312_1146.py b/LiveStock/migrations/0037_auto_20250312_1146.py new file mode 100644 index 0000000..185d04b --- /dev/null +++ b/LiveStock/migrations/0037_auto_20250312_1146.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-03-12 11:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0036_rancher_type'), + ] + + operations = [ + migrations.AddField( + model_name='livestockproduct', + name='heavy_wight_dha', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='heavy_wight_industrial', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='light_wight_dha', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='livestockproduct', + name='light_wight_industrial', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0038_auto_20250312_1422.py b/LiveStock/migrations/0038_auto_20250312_1422.py new file mode 100644 index 0000000..67a3666 --- /dev/null +++ b/LiveStock/migrations/0038_auto_20250312_1422.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-03-12 14:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0037_auto_20250312_1146'), + ] + + operations = [ + migrations.AddField( + model_name='rancher', + name='dhi_amount', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='rancher', + name='industrial', + field=models.BooleanField(default=False), + ), + ] diff --git a/LiveStock/migrations/0039_alter_rancher_dhi_amount.py b/LiveStock/migrations/0039_alter_rancher_dhi_amount.py new file mode 100644 index 0000000..05eef66 --- /dev/null +++ b/LiveStock/migrations/0039_alter_rancher_dhi_amount.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-03-12 14:40 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0038_auto_20250312_1422'), + ] + + operations = [ + migrations.AlterField( + model_name='rancher', + name='dhi_amount', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0040_auto_20250409_1829.py b/LiveStock/migrations/0040_auto_20250409_1829.py new file mode 100644 index 0000000..657fe94 --- /dev/null +++ b/LiveStock/migrations/0040_auto_20250409_1829.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-04-09 18:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0039_alter_rancher_dhi_amount'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='archive', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='livestock', + name='archiver', + field=models.CharField(max_length=250, null=True), + ), + ] diff --git a/LiveStock/migrations/0041_livestock_archive_date.py b/LiveStock/migrations/0041_livestock_archive_date.py new file mode 100644 index 0000000..3f34be2 --- /dev/null +++ b/LiveStock/migrations/0041_livestock_archive_date.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-04-12 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0040_auto_20250409_1829'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='archive_date', + field=models.DateTimeField(null=True), + ), + ] diff --git a/LiveStock/migrations/0042_auto_20250414_1544.py b/LiveStock/migrations/0042_auto_20250414_1544.py new file mode 100644 index 0000000..47248dd --- /dev/null +++ b/LiveStock/migrations/0042_auto_20250414_1544.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2025-04-14 15:44 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0041_livestock_archive_date'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='return_from_archive_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='livestock', + name='returner_from_archive', + field=models.CharField(max_length=250, null=True), + ), + ] diff --git a/LiveStock/migrations/0043_livestock_age_of_archive.py b/LiveStock/migrations/0043_livestock_age_of_archive.py new file mode 100644 index 0000000..c024edc --- /dev/null +++ b/LiveStock/migrations/0043_livestock_age_of_archive.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-04-14 15:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0042_auto_20250414_1544'), + ] + + operations = [ + migrations.AddField( + model_name='livestock', + name='age_of_archive', + field=models.IntegerField(default=1), + ), + ] diff --git a/LiveStock/migrations/0044_cooperativeproductsshare_company_price.py b/LiveStock/migrations/0044_cooperativeproductsshare_company_price.py new file mode 100644 index 0000000..d3dfe20 --- /dev/null +++ b/LiveStock/migrations/0044_cooperativeproductsshare_company_price.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-05-27 12:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0043_livestock_age_of_archive'), + ] + + operations = [ + migrations.AddField( + model_name='cooperativeproductsshare', + name='company_price', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/0045_auto_20250810_1102.py b/LiveStock/migrations/0045_auto_20250810_1102.py new file mode 100644 index 0000000..90fe16c --- /dev/null +++ b/LiveStock/migrations/0045_auto_20250810_1102.py @@ -0,0 +1,33 @@ +# Generated by Django 3.2.13 on 2025-08-10 11:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0044_cooperativeproductsshare_company_price'), + ] + + operations = [ + migrations.AddField( + model_name='cooperative', + name='first_sub_cooperative_account', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='cooperative', + name='first_sub_cooperative_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='cooperative', + name='second_sub_cooperative_account', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='cooperative', + name='second_sub_cooperative_price', + field=models.IntegerField(default=0), + ), + ] diff --git a/LiveStock/migrations/__init__.py b/LiveStock/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/LiveStock/models.py b/LiveStock/models.py new file mode 100644 index 0000000..ee55f85 --- /dev/null +++ b/LiveStock/models.py @@ -0,0 +1,372 @@ +import datetime + +from authentication.models import BaseModel, SystemUserProfile, SystemAddress, BankCard +from django.db import models + + +class LiveStockProvinceJahad(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="live_stock_jahad_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="live_stock_jahad_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="live_stock_jahad_bank_info", + null=True + ) + name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=200, null=True) + type = models.CharField(max_length=200, null=True) + account = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(LiveStockProvinceJahad, self).save(*args, **kwargs) + + +class Union(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="union_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="union_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="union_bank_info", + null=True + ) + + name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=200, null=True) + type = models.CharField(max_length=200, null=True) + account = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(Union, self).save(*args, **kwargs) + + +class Cooperative(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="cooperative_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="cooperative_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="cooperative_bank_info", + null=True + ) + name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=200, null=True) + type = models.CharField(max_length=200, null=True) + account = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + first_sub_cooperative_price = models.IntegerField(default=0) + first_sub_cooperative_account = models.CharField(max_length=200, null=True) + second_sub_cooperative_price = models.IntegerField(default=0) + second_sub_cooperative_account = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(Cooperative, self).save(*args, **kwargs) + + +class Rancher(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="rancher_user", + null=True + ) + # address = models.ForeignKey( + # SystemAddress, + # on_delete=models.CASCADE, + # related_name="rancher_address", + # null=True + # ) + # user_bank_info = models.ForeignKey( + # BankCard, + # on_delete=models.CASCADE, + # related_name="rancher_bank_info", + # null=True + # ) + # contractor = models.ForeignKey( + # Contractor, + # on_delete=models.CASCADE, + # related_name="rancher_contractor", + # null=True + # ) + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="rancher_cooperative", + null=True + ) + name = models.CharField(max_length=200, null=True) + registering_user = models.CharField(max_length=200, null=True) + lng = models.FloatField(default=0) + lot = models.FloatField(default=0) + mobile = models.CharField(max_length=200, null=True) + fullname = models.CharField(max_length=200, null=True) + city = models.CharField(max_length=200, null=True) + herd_name = models.CharField(max_length=200, null=True) + unit_id = models.CharField(max_length=100, null=True) + postal_code = models.CharField(max_length=100, null=True) + epidemiological_code = models.CharField(max_length=100, null=True) + herd_code = models.CharField(max_length=100, null=True) + national_id = models.CharField(max_length=100, null=True) + allow_buy = models.BooleanField(default=True) + weight_allocation_light = models.IntegerField(default=0) + weight_allocation_heavy = models.IntegerField(default=0) + weight_quota_heavy = models.IntegerField(default=0) + weight_quota_light = models.IntegerField(default=0) + total_weight = models.BigIntegerField(default=0) + contractor_code = models.CharField(max_length=100, null=True) + sheep = models.IntegerField(default=0) + goat = models.IntegerField(default=0) + cow = models.IntegerField(default=0) + horse = models.IntegerField(default=0) + camel = models.IntegerField(default=0) + light_livestock = models.IntegerField(default=0) + heavy_livestock = models.IntegerField(default=0) + has_script = models.BooleanField(default=False) + active = models.BooleanField(default=True) + type = models.CharField(max_length=200, default='rural') + industrial = models.BooleanField(default=False) + dhi_amount = models.IntegerField(default=0) + + + def save(self, *args, **kwargs): + # live_stocks = LiveStock.objects.filter(trash=False, herd_code=self.herd_code).only('type') + # light_livestock = live_stocks.filter(type__in=('بز', 'گوسفند')).count() + # heavy_livestock = live_stocks.filter(type__in=('گاو', 'اسب', 'شتر')).count() + # product = LiveStockProduct.objects.filter(trash=False, name='سبوس').first() + # self.weight_quota_heavy=product.heavy_wight * heavy_livestock + # self.weight_quota_light=product.light_wight * light_livestock + super(Rancher, self).save(*args, **kwargs) + + +class LiveStock(BaseModel): + rancher = models.ForeignKey(Rancher, on_delete=models.CASCADE, null=True) + national_id_livestock_code = models.CharField(max_length=200, null=True) + herd_code = models.CharField(max_length=100, null=True) + type = models.CharField(max_length=200, null=True) + birth_day = models.CharField(max_length=200, null=True) + gender = models.CharField(max_length=100, null=True) + contractor_code = models.CharField(max_length=100, null=True) + unique_identifier = models.CharField(max_length=100, null=True) + agent = models.CharField(max_length=100, null=True) + registering_user = models.CharField(max_length=200, null=True) + registering_date = models.CharField(max_length=200, null=True) + active = models.BooleanField(default=True) + birth_day_gh = models.DateTimeField(null=True) + registering_date_gh = models.DateTimeField(null=True) + archive=models.BooleanField(default=False) + age_of_archive=models.IntegerField(default=1) + archiver=models.CharField(max_length=250,null=True) + archive_date=models.DateTimeField(null=True) + returner_from_archive=models.CharField(max_length=250,null=True) + return_from_archive_date=models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(LiveStock, self).save(*args, **kwargs) + + +class LiveStockProduct(BaseModel): + name = models.CharField(max_length=200, null=True) + image = models.CharField(max_length=500, null=True) + unit = models.CharField(max_length=200, null=True) + price = models.IntegerField(default=0) + light_wight = models.IntegerField(default=0) + heavy_wight = models.IntegerField(default=0) + company_price = models.IntegerField(default=0) + shipping_price = models.IntegerField(default=0) + union_price = models.IntegerField(default=0) + cooperative_price = models.IntegerField(default=0) + light_wight_industrial = models.IntegerField(default=0) + heavy_wight_industrial = models.IntegerField(default=0) + light_wight_dha = models.IntegerField(default=0) + heavy_wight_dha = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(LiveStockProduct, self).save(*args, **kwargs) + + +class CooperativeProductsShare(BaseModel): + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="cooperative_share_product", + null=True + ) + product = models.ForeignKey( + LiveStockProduct, + on_delete=models.CASCADE, + related_name="cooperative_share_product", + null=True + ) + price = models.IntegerField(default=0) + shipping_price = models.IntegerField(default=0) + union_price = models.IntegerField(default=0) + cooperative_price = models.IntegerField(default=0) + company_price = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(CooperativeProductsShare, self).save(*args, **kwargs) + + +class LiveStockRolseProduct(BaseModel): + parent_product = models.ForeignKey( + LiveStockProduct, + on_delete=models.CASCADE, + related_name="parents_product", + null=True + ) + jahad = models.ForeignKey( + LiveStockProvinceJahad, + on_delete=models.CASCADE, + related_name="jahad_product", + null=True + ) + union = models.ForeignKey( + Union, + on_delete=models.CASCADE, + related_name="union_product", + null=True + ) + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="cooperative_product", + null=True + ) + # rancher = models.ForeignKey( + # Rancher, + # on_delete=models.CASCADE, + # related_name="rancher_product", + # null=True + # ) + name = models.CharField(max_length=200, null=True) + total_weight = models.BigIntegerField(default=0) + total_receipt_weight = models.BigIntegerField(default=0) + total_allocated_weight = models.BigIntegerField(default=0) + total_remain_weight = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + self.total_remain_weight = self.total_weight - self.total_allocated_weight + super(LiveStockRolseProduct, self).save(*args, **kwargs) + + +class LiveStockAllocations(BaseModel): + product = models.ForeignKey( + LiveStockRolseProduct, + on_delete=models.CASCADE, + related_name="product_allocation", + null=True + ) + jahad = models.ForeignKey( + LiveStockProvinceJahad, + on_delete=models.CASCADE, + related_name="jahad_allocation", + null=True + ) + union = models.ForeignKey( + Union, + on_delete=models.CASCADE, + related_name="union_allocation", + null=True + ) + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="cooperative_allocation", + null=True + ) + state = models.CharField(max_length=200, default='pending') + weight = models.BigIntegerField(default=0) + real_weight = models.BigIntegerField(default=0) + date = models.DateTimeField(default=datetime.datetime.now) + allocate_from = models.CharField(max_length=200, null=True) + allocate_to = models.CharField(max_length=200, null=True) + place = models.TextField(null=True) + charge = models.BooleanField(default=False) + code = models.CharField(max_length=200, null=True) + description = models.TextField(null=True, blank=True) + + def save(self, *args, **kwargs): + super(LiveStockAllocations, self).save(*args, **kwargs) + + +class Contractor(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="contractor_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="contractor_user", + null=True + ) + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="contractor_cooperative", + null=True + ) + contractor_code = models.CharField(max_length=100, null=True) + fullname = models.CharField(max_length=200, null=True) + entity_code = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=100, null=True) + company_name = models.CharField(max_length=200, null=True) + number_of_rancher = models.IntegerField(default=0) + heavy_livestock = models.IntegerField(default=0) + light_livestock = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(Contractor, self).save(*args, **kwargs) + + +class PosSeller(BaseModel): + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="seller_pos_cooperative", + null=True + ) + full_name=models.CharField(max_length=200,null=True) + mobile=models.CharField(max_length=50,null=True) + national_id=models.CharField(max_length=50,null=True) + city=models.CharField(max_length=100,null=True) + + def save(self, *args, **kwargs): + super(PosSeller, self).save(*args, **kwargs) \ No newline at end of file diff --git a/LiveStock/sms_management.py b/LiveStock/sms_management.py new file mode 100644 index 0000000..d011b65 --- /dev/null +++ b/LiveStock/sms_management.py @@ -0,0 +1,29 @@ +import requests + +from LiveStock.models import Cooperative +from authentication.sahandsms.sms import USERNAME_SMS, PASSWORD_SMS, USERNAME_SMS_FINANCIAL, PASSWORD_SMS_FINANCIAL +from panel.helper import check_mobile_number + + +def send_sms_for_cooperative(request): + cooperative=Cooperative.objects.filter(trash=False) + for c in cooperative: + mobile=c.user.mobile + password=c.user.password + message = 'کاربر گرامی' \ + f'\n' \ + f'اطلاعات کاربری شما در سامانه به شرح زیر میباشد:' \ + f'\n' \ + f'\n' \ + f'نام کاربری: {mobile}' \ + f'\n' \ + f'رمز عبور: {password}' \ + f'\n' \ + f'(سامانه رصدیار)' \ + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + diff --git a/LiveStock/tests.py b/LiveStock/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/LiveStock/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/LiveStock/urls.py b/LiveStock/urls.py new file mode 100644 index 0000000..8fe1824 --- /dev/null +++ b/LiveStock/urls.py @@ -0,0 +1,10 @@ +from django.urls import path, include + +urlpatterns = [ + path('jahad/', include('LiveStock.Jahad.urls')), + path('union/', include('LiveStock.Union.urls')), + path('cooperative/', include('LiveStock.Cooperative.urls')), + path('rancher/', include('LiveStock.Rancher.urls')), + path('live-stock/', include('LiveStock.LiveStoksAndPoultry.urls')), + path('contractor/', include('LiveStock.Contractor.urls')), +] diff --git a/LiveStock/views.py b/LiveStock/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/LiveStock/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/README.md b/README.md new file mode 100644 index 0000000..13093a6 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# KuChicken +repositori backend for KuChicken diff --git a/RasadyaarBale/__init__.py b/RasadyaarBale/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/RasadyaarBale/admin.py b/RasadyaarBale/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/RasadyaarBale/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/RasadyaarBale/apps.py b/RasadyaarBale/apps.py new file mode 100644 index 0000000..bc83851 --- /dev/null +++ b/RasadyaarBale/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class RasadyaarbaleConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'RasadyaarBale' diff --git a/RasadyaarBale/helper.py b/RasadyaarBale/helper.py new file mode 100644 index 0000000..731807e --- /dev/null +++ b/RasadyaarBale/helper.py @@ -0,0 +1 @@ +Token="1799324940:4dUGkugC2MtQEddIoZRALD68tzdwAXzOci9lRkE3" diff --git a/RasadyaarBale/migrations/0001_initial.py b/RasadyaarBale/migrations/0001_initial.py new file mode 100644 index 0000000..3b3b273 --- /dev/null +++ b/RasadyaarBale/migrations/0001_initial.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:05 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='User_Bale', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('chat_id', models.BigIntegerField(unique=True)), + ('first_name', models.CharField(blank=True, max_length=100, null=True)), + ('last_name', models.CharField(blank=True, max_length=100, null=True)), + ('phone_number', models.CharField(blank=True, max_length=20, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_bale_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_bale_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/RasadyaarBale/migrations/0002_user_bale_super_admin.py b/RasadyaarBale/migrations/0002_user_bale_super_admin.py new file mode 100644 index 0000000..d48eded --- /dev/null +++ b/RasadyaarBale/migrations/0002_user_bale_super_admin.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-05-26 15:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('RasadyaarBale', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='user_bale', + name='super_admin', + field=models.BooleanField(default=False), + ), + ] diff --git a/RasadyaarBale/migrations/0003_user_bale_rasadyar_user.py b/RasadyaarBale/migrations/0003_user_bale_rasadyar_user.py new file mode 100644 index 0000000..c4a9062 --- /dev/null +++ b/RasadyaarBale/migrations/0003_user_bale_rasadyar_user.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.13 on 2025-05-27 11:54 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0070_auto_20250527_1154'), + ('RasadyaarBale', '0002_user_bale_super_admin'), + ] + + operations = [ + migrations.AddField( + model_name='user_bale', + name='rasadyar_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rasadyar_user', to='authentication.systemuserprofile'), + ), + ] diff --git a/RasadyaarBale/migrations/__init__.py b/RasadyaarBale/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/RasadyaarBale/models.py b/RasadyaarBale/models.py new file mode 100644 index 0000000..9137fcb --- /dev/null +++ b/RasadyaarBale/models.py @@ -0,0 +1,19 @@ +from django.db import models + +# Create your models here. +from authentication.models import BaseModel, SystemUserProfile + + +class User_Bale(BaseModel): + rasadyar_user = models.ForeignKey(SystemUserProfile, on_delete=models.CASCADE, + related_name="rasadyar_user", + null=True) + chat_id = models.BigIntegerField(unique=True) + first_name = models.CharField(max_length=100, null=True, blank=True) + last_name = models.CharField(max_length=100, null=True, blank=True) + phone_number = models.CharField(max_length=20, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + super_admin = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(User_Bale, self).save(*args, **kwargs) diff --git a/RasadyaarBale/tests.py b/RasadyaarBale/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/RasadyaarBale/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/RasadyaarBale/urls.py b/RasadyaarBale/urls.py new file mode 100644 index 0000000..b6ec301 --- /dev/null +++ b/RasadyaarBale/urls.py @@ -0,0 +1,15 @@ +from django.urls import include, path +from rest_framework.routers import DefaultRouter + +from RasadyaarBale.views import bale_set_webhook, BaleWebhookView + +router = DefaultRouter() + + + +urlpatterns = [ + path('', include(router.urls)), + path('set_webhook/', bale_set_webhook), + path('webhook/', BaleWebhookView.as_view()), + +] \ No newline at end of file diff --git a/RasadyaarBale/views.py b/RasadyaarBale/views.py new file mode 100644 index 0000000..ecb8681 --- /dev/null +++ b/RasadyaarBale/views.py @@ -0,0 +1,230 @@ +import json + +import requests +from django.http import HttpResponse +from rest_framework import status +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from rest_framework.views import APIView + +from authentication.models import SystemUserProfile +from general_urls import base_url_for_sms_report +from panel.convert_date import convert_to_shamsi +from panel.models import PosCompany, ProductsTransactions +from .helper import Token +from .models import User_Bale + + +class BaleWebhookView(APIView): + permission_classes = [AllowAny] + + def post(self, request): + try: + data = request.data + + if 'message' in data: + message = data['message'] + chat_id = message['chat']['id'] + user_info = message.get('from', {}) + + user, created = User_Bale.objects.update_or_create( + chat_id=chat_id, + defaults={ + 'first_name': user_info.get('first_name'), + 'last_name': user_info.get('last_name'), + } + ) + + text = message.get('text', '') + contact = message.get('contact', '') + + if text == '/start': + welcome_message = "سلام! به ربات هوشمند سامانه رصدیار خوش آمدید. لطفاً برای ادامه شماره تلفن خود را ثبت کنید." + + keyboard = { + "keyboard": [[{ + "text": "📱 ارسال شماره تلفن", + "request_contact": True + }]], + "resize_keyboard": True, + "one_time_keyboard": True + } + + self.send_message( + chat_id, + welcome_message, + reply_markup=keyboard + ) + elif contact: + phone = contact['phone_number'] + if phone.startswith('98'): + phone = '0' + phone[2:] + system_user=SystemUserProfile.objects.filter(trash=False,mobile=phone).first() + if system_user: + user.rasadyar_user=system_user + user.phone_number = phone + user.save() + + keyboard = { + "keyboard": [ + [{"text": "ℹ️ درباره ما"}, + {"text": "📬 تماس با ما"} + ] + ], + "resize_keyboard": True, + "one_time_keyboard": False + } + + self.send_message( + chat_id, + f"شماره شما ثبت شد: {phone}", + reply_markup=keyboard + ) + elif text == "ℹ️ درباره ما": + self.send_message( + chat_id, + "ربات هوشمند ساخته شده با پایتون \n\n" + "توسعه دهنده: شرکت هوشمندسازان فرآیند های نوین ماداکتو" + ) + elif text == "📬 تماس با ما": + self.send_message( + chat_id, + "برای ارتباط با ما:\n\n" + "📧 ایمیل: info@mnpc.ir\n" + "☎️ تلفن: 28421237-021\n" + "🌐 وبسایت: https://mnpc.ir/ \n" + ) + + else: + self.send_message(chat_id, f"لطفا از دکمه های راهنما استفاده کنید.") + + return Response({'status': 'ok'}, status=status.HTTP_200_OK) + + except Exception as e: + print("خطا:", e) + return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) + + def send_message(self, chat_id, text, reply_markup=None): + url = f"https://tapi.bale.ai/bot{Token}/sendMessage" + payload = { + "chat_id": chat_id, + "text": text + } + + if reply_markup: + payload["reply_markup"] = reply_markup + + headers = {'Content-Type': 'application/json'} + + try: + response = requests.post(url, data=json.dumps(payload), headers=headers) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + print("خطا در ارسال پیام:", e) + return None + + +def bale_set_webhook(request): + response = requests.post( + f"https://tapi.bale.ai/bot{Token}/setWebhook", + json={"url": f"https://{base_url_for_sms_report}backend.rasadyaar.ir/bale/webhook/"} + ) + + return HttpResponse(response.json()) + + +def send_message_for_bale(chat_id, text, reply_markup=None): + url = f"https://tapi.bale.ai/bot{Token}/sendMessage" + payload = { + "chat_id": chat_id, + "text": text + } + + if reply_markup: + payload["reply_markup"] = reply_markup + + headers = {'Content-Type': 'application/json'} + + try: + response = requests.post(url, data=json.dumps(payload), headers=headers) + response.raise_for_status() + return response.json() + except requests.exceptions.RequestException as e: + print("خطا در ارسال پیام:", e) + return None + + +def send_transaction(transaction, chat_ids): + try: + if transaction.paid or transaction.status in (0, 1): + pos_company = PosCompany.objects.filter(trash=False, en_name__exact=transaction.posProvider).first() + if pos_company: + pos_company_name = pos_company.name + else: + pos_company_name = 'ناشناس' + if transaction.pos.kill_house: + dict_info = { + 'name': transaction.pos.kill_house.name, + 'mobile': transaction.pos.kill_house.kill_house_operator.user.mobile, + 'fullname': transaction.pos.kill_house.kill_house_operator.user.fullname, + 'city': transaction.pos.kill_house.kill_house_operator.user.city.name, + 'province': transaction.pos.kill_house.kill_house_operator.user.province.name, + 'national_code': transaction.pos.kill_house.kill_house_operator.user.national_code, + 'type': 'کشتارگاه', + } + elif transaction.pos.guild: + dict_info = { + 'name': transaction.pos.guild.guilds_name, + 'mobile': transaction.pos.guild.user.mobile, + 'fullname': transaction.pos.guild.user.fullname, + 'city': transaction.pos.guild.user.city.name, + 'province': transaction.pos.guild.user.province.name, + 'national_code': transaction.pos.guild.user.national_code, + 'type': 'صنف', + } + else: + dict_info = { + 'name': transaction.pos.cooperative.name, + 'mobile': transaction.pos.cooperative.user.mobile, + 'fullname': transaction.pos.cooperative.user.fullname, + 'city': transaction.pos.cooperative.user.city.name, + 'province': transaction.pos.cooperative.user.province.name, + 'national_code': transaction.pos.cooperative.user.national_code, + 'type': 'سامانه دام', + } + + price = "{:,}".format(int(transaction.price)) + + alert_message = ( + f"*---* {transaction.result} *---*\n" + f"{dict_info['type']} : *{dict_info['name']}*\n" + f"آدرس : *{dict_info['province']}* - *{dict_info['city']}*\n" + f"درگاه : *{pos_company_name}*\n" + f"زمان : *{convert_to_shamsi(datetime=transaction.date, in_value=True)}*\n" + f"مبلغ کل : *{price}* ریال\n\n" + ) + products = ProductsTransactions.objects.filter(trash=False, transaction=transaction) + for prd in products: + if prd.live_stack_products: + fi_prd_price = "{:,}".format(int(int(prd.cur_price) / int(prd.cur_weight)) if prd.cur_weight > 0 else 0) + else: + fi_prd_price = "{:,}".format(int(prd.price)) + cur_weight = "{:,}".format(int(prd.cur_weight)) + cur_price = "{:,}".format(int(prd.cur_price)) + if prd.cur_weight != 1: + alert_message += ( + f"*{prd.name}* (فی {fi_prd_price} ریال)\n" + f"وزن خریداری شده:({cur_weight}{prd.targetunit}) \n" + f"مبلغ: *{cur_price}* ریال\n\n" + ) + else: + alert_message += ( + f"*{prd.name}* \n" + f"خریداری شده : *{cur_price}* ریال\n\n" + ) + + for i in chat_ids: + send_message_for_bale(chat_id=i, text=alert_message) + except: + pass diff --git a/assets/img/img-min.png b/assets/img/img-min.png new file mode 100644 index 0000000000000000000000000000000000000000..b2cae356bd016993c61bfa32ba126cf6b3f48992 GIT binary patch literal 796204 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�YsU%my^a|Bbu;ytA{?0h&lx~mF!F4bW-hRrr+@fmyBSD-nH za%V8xq9~PXaSR64jxZ}wVW%#ncvL;sZpyIm6ALp%)vu2*WjChijXbRdv9bg>x>Pcj z;85+JU$MLHtte0k`-W(gPKdVwxB<(O&YTl>R!FUb1I}Th{m0o9mN^dwH#x1eo#G-~ z|4O=Ma?|(JHFb5pz+Z3iyIL6J|>6ZB1+?RWSls8 zZMDQjRwL>@UQ2p=ZM%ZS?jB&q>+oWc6u$uYwhT!46mn;-61?NuweDD|daR9HH)j_Y z7F2@Tb9~G)6i>Mg$l$P2@RiO#Eu7fc8z^+jQ;v;l-7ft7FR=FZtX$YsQ!Ob4@E7=g z2)#l%Vb3bIY)&6pyu~4+T@2`xC z`8<=a!`edGJ1(%|b6X??jS4j`%e!?o(q;cB*-N@)stSzM(N?y({7JXWE~kk;WL8Ao z5Ghc86McjB$Mb`FS@^7X*te9ILAAUo7f)vH$|47~jOdRj|6^$PPi*u~_9k3D|KVHs zu`DJry!NV2Zt6v_s)~zkbew=Wioc_ayhe@D(I{Sr%AnRKHhPSAJ6T~ueDOvd-WPyf zT=X%fLPzXr_NI-`*w92jQ!YB&$Nt+qrUCY}&wzUyA^jhQ@_a@uNmUH32 z0^~{?B@c0X-e`oQzBeK$;c_X(gLEuD@IaoN1P)Cs0pqdqCHy-UNTpuo;p>JR7AS}1d%5}b zsJA2HmmyCMl2}X`K}cCNqGWe5qiyCZ)PQ&@krC(>#OI`Ofgk)V44Lfs?KUYg)bs1t zw^U6p5|GRQVoV|Jq+5yA>`A*V)QJ?KsbMTO$?e7(CGXivVV8T15V5Ga zH-t^W>rCCjDN!qzD7WD=ze&CaOQBv#W^cDDnmm&9t2=`>zR(w#7Fi#^;I`lG@JHCp zxz$*zQ0K}1Z0&j}MWPvIy*xIw@~0#T4x%$^D>A z@vN-7=Fet8KDfB{0mYt>kkFDx)$+ur-j?jer@X{+VB0J%E;F^DzSfSZV|_=zVJ!0ZN4t(i>~`QcIa{aq^_}ER7`UOx00NJ z-WX|B%syeCzd7QXu!+`Onf#r1QcI4sAbn^6818!hco|6qdR~ND5QEU23Pq(gylXHH z&gSu0w&x)9(NlkEJDb_G`QN|qJD4r?fexheyKW(`Kb{I@3%Et#4<%SsB2e2SNCpIa z?pvHj{5XrV)c-puN^LiPOu?N&E=AVfpp>p>=_%%C<+}C3455?%1EWH^XpwGf=*iu; z&nUAp(-^sFRlm=}HVQ^CM9H?&OXCp}?~`Lgv>9r&f|=X^0`ff%{)3OHmbQ-P~}Lc)Zsc9I&WW#n?oO+ zAuqu(-Finh!;P6OgLjw~L#QMq^ZU|21#ya^i=U+!HR!d!*8hK9=nN}|T9ggCjVZaO zpnI0~}n{q^=&`sO{xZ$VR5oKYDqPFm$y4RxXeypYnLTelW3WGwMlM@HJ; zPNIDpoH;4x)XyIyy?%sU&hUsn-&+L2wyCd9+s-~e&5!G9jtQX$Ph7jNh-&E^S^0%j zrWEEh%DkCXN)5D7T-BeNIlH6w5pE1@7hMDTiw#$w8T^WlrZd-OI8Y;0T2aNaU^J*G@*(Pq#|RZ|T41+w<6FCLRXy)DEnb9+(STS7dYVG)PJiQ8X#1E*-!4xLhyM zY)x8*!`zq8Yb0MG()gYDW#H$%N3r`&U_XOD|H+u`$`JJ4!Kw5PAWb6-ote$e^)<}{ zFe57(r=b?mhDQ!jzFH#)mmAsg2Z1K?2yTK#1%nKuqB^oFZZ7u!YB6e;k)3tZOR*Gv zQ?g{&qzbp%XOIigu&0=mc^~`BpXbvTH&O4YuopH?Zw6eBE*Gi-uiL~-I(>KjnyZX_ zcudv>KPgI)@$CaaWq$I50o zJ4PwkH~hX-01ESo&kjiXOH+Di9>^+;5sp^MEmt_D)Z>`X(7hngFE~Es;Kg{fiz2PY zF`E-T7^6npZRH%QvIbA2e%?QWo;ZU?*PpjUE`{kQ-9qjbmq^raUIvO$&r1&$ZsPy> zLFNcD<{@l0p66~lkn`*Qy}tD=HevGfRVqyb3BMA!YRb=V#sbiTQB z;BURPfFR%a$_m9v>qk?$6BwOw+f40M2kAkYcYGG8+$ppoHerGLGis)?;>S^(pD^TWb{+g(+Nq)86~Su^_+{yDU+T;=5hH5Aq(QWC6_Qv1TxqCX)INol$(;^KGE zUN-5@?v8zDm81!HkVGmMvSIN_F?EOxaY!Y5Bb?ZH18x18$hrLj70`xX5E0`PIQ-my z>A^Wu;wip5tckCI=KtjN-q#QS?%$MUr_G6@Xi=Z8TWoKkI6a*P%!{^taJ?d8sVr>% ztV%d1A%iH+;!Z+`oX9fz`-%cG!ti-f@YV0O{Kh@1p}7({7a2k;*XNPx^oggPU(W3} ze6l72@JV3CTkV^5!GQ4E`Q`Rqcq>+gyeiutTZBMO0uJF1pl=tIQT7WH(2UpU34n6? zUl4?$w@V$~%B@@5Zj0!_cK!0p_4}v#z^w?8V|b20fDn9e^d4?u#)n|Tj$|`=RZ1nE znlRY85KXJ*QTn*JR%Ll;6)cKIA+w;dk85g=!K-8H16^FQrtSwGjv2S@-R> zu{V^PReVRsAft5C(As4sB$Eu$m^$h=+|-_O_sHtEUzx(EsC`OP(tQ!H^xXyP{g|*< zW?ywKXmSKlaC>S;k-|BlQw$pL9ZsFrYT3wMeG^QWJJR9ZqGvl7GS>}4hM^VP8Z3LDS zY0Zx0&i?3FeY9Y_4RMV*513{{6uO&sdh=TdOz!!f&8sb5%q}O88sQV{*WT63$5p$_ zaxYKkMMv^nWWOBvoJEt`AHRJSzqsna+Q&P--s=f6RNtY!Z>BcQ%h@7+X=nZrA^%4q z=c`^Uc9)%vHvkA$i_xIC4=yZo8>Ud==@?%?3%Vn-IzTyvj{ zstOSJD zW=V6fUMs(e>1^zHYaE}w^Rk}C+T&cA$ zZk%`Ubx7c1gqgzUN!X1&JA7N#ED&`j<+Ey1gOvoSFrySTdTZPd>+8_oSvej?&L=*Z zQEgR%upST*u`5o~gH&2t+Wk)bBot!uoDII;6uZp214qhnhmI?`ylY+l&O^9-nreA% zxV8N9c=kg6S!i-{&zoCE#DFlt1D4wWI)D5C^3SmMoV|4s#x#fNXO|q|7Aurt)3)*+&^1qmbOqm?S#pI z7NJiW*hFtl9c8WiPp)5n=|&4@r#FBBAV1 zGmO@d1Kx%nTN3pxNr`f9GFi!Rrf6M|yG2give*7ZDn|?D&L9^fH-Bc;Xjd*Z9f>MBsKsVT?+UP{hO`@{&)wJKKu@hlzk`SUmVHxHr{( zhCAYlnEal}y5y_bQS1g*UiJC%`g2+r)C4@q9(aLOW!NUqPHjGmygX7?o-B`|XfC(J zDjdJ*g06+3|25*a%B+4|py}%V*gx;@ZsvX2o!I@unKP(w4Y8Z}=KRd_1on26J=zhW z_}6p7`k(>rsg-U5B;(Am^y0>wWE-*1>1=&ee7#bt@7{}VS*&wy+k9xdgyY!bS*!|F zv+(@h&oJa_yJQ~TuDq0zh; zJocq1jFnIHo|2i5E%};PSMi0cK1ScTmO7gDP)cOJJIjPMmtxwC0^4>6y+`I4J*_ml zrOA(S&5if_V_{}q56VaV2Vl{gJp=I5ir4ycfxz9&K$)|Z!%vjfRXz7tanBNXcRI=Q zy-po@=7*v5GEQ2Y!XR`zyM=99U~K2_A$;W7A1M7_<~R0`c@ zyE!hvM5Z~5d}~3w`g812X2Zs>S_8_iid; z>(B{OB}qTNsxkXgM?`?k690`Vs|^r`K9w(*Uw-~UR_?ezeot|p9DX<1>P6E z)YH>5vvd<7I^rTL6(@}wR{zOE(6bp*icMv*>)}xw*03sb(~Gna&%Pz$^sG!Jgb2H+ zQc18EKm7^ooE2Xm?dBO&BpEd62T@aBZKK}a2VC75M~tTnfIY9a_>TD4^kc!3F8tXa zG5#tscvE!RL=W^WR-kX>;(-#NSGuPJ&Ye4x(|@iJv$C=@Lq!>sGVQQ2Ay}Hb7*(|O z(MV{-_e;#|R}(_(n?mcpS@qVF93modBRFQUgXJf_pb=S%*7B`0`^-VIx9<|$xSIB6 z^Hs+lMX#Ikn`K;|nE2S*hsIxmhi1OVwCwu1Ys9gN$PDxb*+^-j%9oz&o4x$m&zbDE z^vPYWrXcj~i%edroQR_*GhIwFzn%RPsE#r0??rXMle2Q*6HFzZTEvfZ4|UBRlbGhG zgH;XhJct4Z=|ow?3PFesgiH8G1{AakG2{{>3LAp_uRY~bixjW(b1l@wC5%fpjxGvi zr^BXTt*w!x#eefAi&*rbJ}aHg-}z*4e1VU59%sp4fm*4EUhW84x=@}tXPY5LUO)du zUwJV$)vUan0Y;Avs!!gg%kPG)!qkam3bF2$QFhmjxawM$XW@fs{Of}{WpR9|2aVU2 z`P=4LECievTJ|A#K&u@kTZ*BV+0TuNNbZx+rf_$^@ihT@p#qP}d%i9;Z1oM_bos*0 z4aBd+J2flV;R9Zy^2g)^$)`EbQ~(O(4u`K4Np+DUd9Botc9r}XYRJE}L%P@6-4~0s zddxgqa(tv7@J{N>xxpWl+Mxz~9Bi+TVW+sgNN*kzmO59fk}UN^xq9>ec1F(8*u2Hg z9NNYMZ7;()a=p_-hhPD738XzCPoH^6VDX#!4vxX|HWud0l82o5<_Nv*V)?617I9`A zBpajAfbw}hA#`@Wm*xEVUd3eh7bJJv9YTVEN{A^~+(7sZv)rtkSMEmq9H*Laa4?=q zhvC9|$$M{#wqR&}Zq)F3ylv%iU+UDjJ!oyQA3M^$BjEsy0$dCD=bLXCF5Na~_8#vL9A!>nGv+H_lI4;7=F7AIByu&0aAW#p?eS zyyvE|i7A)vEkQ4|!$d|j7Bfst{#EmyLNgj*cnjm1z7ksrizBQ8KWqvq zq_aOe>xezCnpCZ~dam8@S$%DPjV!wi$v%7)(O1BP8L7>+BtwHeDR7(6`+|Z(7^D}W!N^P^za$dAW-ynJ?3a zqMw|?%O`^Uc_*q@<>kLCFio`F>u!+-*Y6!QY1tgQM0===gl{KY!41JJUYI@GIq>bm zk2IiIzss*X(~g*4zUN*Mf9@WiqC8f8;sR4#aa3_4Yms5Md$;tfz~h=MASy7yJlhm7!>u^!{g$dlC^J0cPTbKX0wdU z(QSk3>V^BWtd#Y1i4U0b3#OJCM{t-1Z(kyPA(2Y5G|O+)2WUZlrmUaTVvpl5CpvE9y1?6&d~jX?*F!Jb zzo_z3^F0S)`ni=fAYkO(|Ae9j3R)LK0Rn+KeCAKSJVpOYJH!M13qV{HJNCq;Ug$f5 zaiC6A2<|mfsIskV-Bla;_*@Onfp4Bw;1^)_(^a3*%C+3HGyym5$PCpaZGknvn~USo z6w9c}&sK`2Oc)IT2u|YY2&FHylIxUvbAqj<^h)CMc2lc6dNy^|dOM)JF<6lqoQ^EP z&oVC!e3$gFQop<#kN+x)_3W}9<7_2 zBCw-hibGC(f0z7+IJ%sDn4ehg|o(aE@<4y5X` z;yD?kD@3&$q(LknA^=hG0sSMzU5D_LkktKmjNp4sjf5JSh8Cvt&3hd_xhno^0(?yJ z#O<~woMB0b3!(cC3>3o!drib0N8Szds$x8?ln=Aydg3hKPS z+WPx-*N`Gk^lyhm z2jOvjvI*_ry(8zRb@q;@3HTrO_G<;jK^b=X452TDJWD1RwetvUrw-0d)h75uX6Y%J ztKKt4EXbQCh?A|9wI=@wE=BCt0S?HIk*l8*sfGHp5O*=7KYwg&oYOPteC!=p5reG_ zbv^HP{en(Ef@fSqrE<)FyOVHKOWL%le-CBlA{IHNp6tXHCt_Oa?A8oOE>y9j&`XQI)Jl0~QZ)9q%KI zkxf@kWPkoJz&YIPbRJ^@3jxC(|6xN9gbM(iY;PZ<-5jcpVQed3jXoHngdw5!3$yj< z+YS~7OE=o9tbG6Lep1U?iGmb~#~`)ob8JzfGV;UA;9ie75a^f@l;W4&I(ukH zM|iMwyQkJ3hntN}OeB{u{`1F;k8_HNO#+@6;7x-*D-khq?fi^W^MSkIKUdv}C-A`Q z+5;~(lpP(mnek3>BpkU#Vy6Yv341p4zc|-qQT>6|AQoQ8Ak)0(_8*HV5LjhgJ+!w+ zXJB9e@KDi(8@DIR*pX6AO-;Ih4a>qJ)VNybF2bvJ=!wQgorG%87;z$38ugCg+bxO7 zZc&>q0EdZJe0HB0*ybhj!E^X|pe8YeTBIQ_tc3@PlY7;Aq;r&#OH!Mn6CWOqvIc<7 z7uMig>vo_)qR2Ga*?>{7R-kKzk11x0k+W*_{ zej9&9*c`o*j&a8Tdwag$kU|-ec2;XAnk)Q@lTV01P2Zxgw#66~A@4Sq$!b2}hdoV% z9XGTR%t_FPFs~mn?OlC-^I_44Av*b>2EmI>!?5-Gw($;pQ|;`3zudLbe)0E6u9H)& zq7lP~>Sv?(vU*=)4I#Dwqt;T7{wT(c9(Nd%(k82MBg0ox)U~=p*1m@E;QDHp+i^Yt z=);15%dNnlV}uBX&*^R-EyK7XP7b-_mR}(P0YUm2KC+p`oDy%mQ=+$hRCifeSucuA z;1PLn800^t5Sah(_{6K*?J%yjML+f}w+G-Ms2cE)5}m@rHtmmO4qh6_e>^<9Ya@Pj zt(Bd>ytKS}o%)|x1Ug$4&9S>Rm7STQKViY5xkA+`h4LBxoywltH{K4CCEK0q`wxCH zYv<;;FYRwwql8R_ooT48o~ABf4qT4MwUPlPmgK$ z$*z{Rj?S-uM%=8dGOr>X!DM z+^ce2X~Z+T;8pHMLPUPqG!8Q6H9tv08m`##BaSeBQSOT?8Aq(WHNSGs#{kLmA1F0B zkV&MyLcew-)e~3$J3%o1cWQpIL6o2WhS|=6S6Q$*lP5ywjvFGtwMLO6gt{MQx7BVx z`1QxpE6qNNU$!ug_u!**fYTH>f3OD!>@BZDlSEy&Uad+; z5MsMYo0r-g5tIih^UC00-c#JMY6v^j;M56nH0J`vJopA zJ{tZqcu^yZobnHU+1vbo{;R_z+z#t35x165GM{$(y*gCYjnEi;|H?A-6z|?|dhfOV zlC)BNsb?W9Y|a+sTaZDTMN`p2$)2%ERo9;O(`$#%rq8pt--X6dgJIMQ)kgkVH;-to zbK2kDT9bVQ8Zu2P?C(x$mPSmoR{5{m@5UTD6-s9dL>k389Os+mwcV7s8pS>Lk=LPo z@c4u6Nekt?h`%TwSpu@u7-JAiL{znwbAe1-yRRf~DGxo?5AU{jvb%4N7NC*T&op9B z2P#m239JX;1{XK{nXltQbfllF?>l9(#vs2c7$#|=_y$8kbh}V z_qU{~q5hx|mA#xZZc{_YZ`@}(7O3rRIO|KiL1i@f4fDE`>te?@M<X$~KLl6x^*~(~%)znEG}kn|YskIV=@T9NwqLuh zHrc(c_A)aTUswULd!j7Tb+ex&)atmS(NvY`Jzg*e1J*wRzN@u&a1b@msIwn%Uh|!; zM#*e<_^ot-^HLkNd^@Oq{tRj?YfwtFWFSx1Ng*s?kt-=Vat~X=eLucf3nXs+WG%3- zRkVLm#iqJ%5rCvbIX&}77+vUX;><}>M^^CNPb^T{>SUHxRk9_iv>K3H_HX76z90to z+;zbNjC~K@0gvOyNRedPH?^E|fN`DaGP{sr{}ZdC2Bg<7rD`@#viku&Hs)-1#rc5%?W{(J`Myjjf~8>i~X6;euKe&t-tko*ZrvfDmRUY|d8qXyd* z`vFBGhoSr3zckn`_Wv;*`6qAz>-7$N&Tub~R&>`Z)bzc!A1D%kSC{kN&GJ zN1D9z5k@@8$3y}ot_7qVB$S_PC17ap)o40f;MrdF+GF#m*J*&Yt?dDF>g>r+rR9?S zCGs!Tzp-h53^J*p6N(a);l6MX^2%PWF!+hnbe=;x6B?;2?2%S)0*;xj?v${;V6gJV ztK+>-;b1sdworV<9F!p7orAR_jrU@OTY~v_=n&KR(mY+)!(8>fGkm-2s*n0P@o1rX z$nJ^P7dq6}lZAV7@z&v`wHK1ripKNrK5NggvD5RNGbq$u7Ef5rR`_8=$@|$zFRrRc zo-vyfA60<{N4K%VNQ5MjrB8T#tj^r#>-^1$FdUl$_i(!B_aPnnQHNT&WgyJKf(4wmmk+i=68IoM;nf3B z>cKd2VApYdymfS1Z5;@YA^rt$MimtmKu>Y`z_0(c-(HpG=fTMZkz{w%@kjr%ayx>X znLmsq4$??`qg=_fq=dr`$h6Jd*E2g6PEswbyCRsDUQkQEKD*f; z8%r!<1ezAjzBfb4Ia_FA_Xz9Hx6RO(@CWv9xw$2)Yn_RfH{Uq6M=Qe#XAQr`MvZHa z@DK=e>{_yc&kfe#b1J`{E+WG!dG=CDx3ToA3M&YVO4YQY$kNJitChTPJ`t>K#=TY2 z$aXWEVo#ygT%3A4UHRGUc^@)l!Vgcd?u1r$O|0ENObYlOvoY>y1vyX=o4-%};3vsL zt10zLA(s2XQaDKqv0NHGlZk|B>szzcXXR!MReT^&6>ueL|Bv2wl6RZ<*~pDqHX^_g zG|&D+2IS%-2`W1|1^ll#Jvf2`%p$KqO!=P^?LLmaX<8J&Nhe)tbKRRCxa+#RKg#&H_# z+^eF#`1LS`rPyX8zw1*C;a1G2uY-}p+s$8d9I>g(hzp8dt3UW+Gs{S07vNnYvUxYm z6n*&u(rmm30#iBy^MJsCe+J5bTgvez;XmqSS3w8pg11j+M6|WFNw8z0E-Va|rHQi6 z9FS=s6tg*O696n03sK)yEei3&NX-;>_Qcfv4?%gxXAv^sG))e)J3BrTF8u!Dn%Hm7 z=j|cT(Jq+6^HUf6uKj*1rr0*R-29JHVPWD7dYk+a!}a_P%}*}Vh}!l1yP99}x}D(EA74Sa2Ek$>F%p}2{KS-RS)67iWr4n(D zxB|-SHPjglIaBF?&YQ3cgD;IbTx>i>8*Awz?#ac&5p}LPHPt{iDZ+#nAVk#20*dc~ z{|YSN>iF+l4F2m}@7?rQ0mNV%9TZ23%0NIzX0SFyr#wAJVN~|!&)NrRF&>*j5u^En zr6?{E%$Y)J$`o=1m#g04HtMI_wuQCFzwoB(zq0EUO{Y2Xl)Pq4xQb&h=+wd^%fn0$ zDIQesZ23GCShfM9W~dpA&MCf|ZFQ3r#fLTd#t8ph4x_ za_^~_UssciWqfNhOe>N<1Ma1Oord1|z@P4*;O8#53Bcjc9Nk$E-m|RU+C++LVZ9yi zZ@;kOHCr&*Ko@cGAEZ9hlNMnyE?bV$g5tDnE!UPWaDrzAekvnhji)yx?&B}&gNMTB67>`T6iR3p^Ws*@sctvyz0`i|$#R23n{N#J*4=6lP{-UTO7- zG-!5mz1mZ%GHM(AXZZCxqoOwH5ax2}a5KIB-9ku;C08P1BOdEXfx3%=TLIiG*M0J>!FK zSH1SFNc+tEm3}dx7t0rD6?LG*s@)6zuDE_DFQh-8Px2YEXPL%swBscP#|u4L*k5l| zZfhPuu;BkvaI$rCcBQO1puUtu8m=Auli{PhtTt+iJ5jp=N#WmXeO80j(fGXkjk&YH zqiU1;uV+tQ0k_Lt(bB3S1imaiSd z2tvmu-C!?Fl4ZveCI+LX5Ol-wxJI`jUtqPzt0S^h^-eWaLbdUy%6FmN|Atku>GW#? zIPc*0<$|xW*3bFCSA4L^E@;=kwR)ha0+gJIM}7o8Urm=${h0C>i5E>@wkwxz?WFE% z-UgZc2|Wnl(OXed@#L}lrhM~`LN<_q~q z!@KWmrbj!uDvi(FCUQ<*93B#?q z8t;zR4z5(z#-dYV`tYsn4#>;6QaM|BDQb-7Ta{ggQG2D}Cr#zn@5se90nB=x);b4( z$c@oZDzDR(&E9Y--| zG++R++xXbl^z;pgN9}_Wtr|@%xA_;P!XP~yxAr>Z^B0A)=j2@#u>yU4b30XzN<_J2 z7mGk9HU*)EYV^*x<8EBUHbT;)mzOljBUME-?T^}!H;A`y6DBwW}V~_a1Ob77pmfWvtvqI$ec>m&n z?=nq&No^9glJY^*tOld*%ryQoVx2jqkz?;3*Gi{5f0yflim1;WG2H6u@cS9-YRf~& zM8&OUGx-wlfKGhfHB*>iq_NLZ)L^DJz%>@WH7zYUFw-kXtoT)Utmt;Uvf%yLw!U}0 zux90b%Z+iuKO9FytKEE<7`C6mZ5zv38H5-qyJ;siP}t(X%_Ii95W8pwKQ_aTt;M!a z$FmaY0J&*~{91O64?^*@iEE;@$o+lQ>8tbZ@*wAO5@`J8sj(5LA#f^)6x{AbeQS5! zv5hG1#{9H%cLr-z6WT)&lCp_35SbB#FZrot5c5N1eEw$LoqbhQa^2sMh^H2t_&aOO z517{2J6+;|3@EqDdsiSCs($wUC*JvcFSBL3Nkbk+evX6jM!7o2p9$p6Yuh@6BPhih zs?kUUF+~34|!#JvzddPx3TS1Scu}{ukqFwuTsA2Z}E2VyS zYLoQzq62gVrne*HQq|M+Jn?<##pqYX0EYr5)SDq%_BxZy+ml zj2dAwG+$JICt{LZWMiq}K64=cgM`KTM`dNfd+T^((WiMn_;Y3RI`r%zoG);2tl-@k zc07?mkGQpv_rRc5e*|JLE~vD`bG6!T$Y=VvF9#e0dVP%cKkmD!$@^RR!W3U@)i9i* z_A-D6Qz`BWMkk9;7uWx2X8`&bIwOtD7l8KAWa zzVS|&RQQfaD;Kj_gQLP@>Z-ZR;X6^E(lEO>Kf)x!V&;_emA#_}>fF`Wqtk_fM)W$v zibEt$Y9PdkNxCBFvqyZ_jO!jr_m7|j&Yi~Y+Lf4-spla$bR7zv1WzQup`}0B*uOUE z10iF^L@7SXUY=G2pRw`}qrC9S0~oN#(8Ln4&mb(g3TF?wX>LlbNn37Y+&`e!JNg)}Z_ znv=AMC7OhCilnY6%>%WPFx<+$W7;Bv{Hg8}KSfa>?Pz zO1VOdH}(h44Dhyvu18|H#VxQbrLC=a&>|k*AcB0_o&M8z0xshJx;+aB5*D)pL|1Ar z#iRTpdqX6m5l|myNE9VZc-o@E|21bK?xCbZBcDqE;{&J>8`TUI81r z$Kzo|rCHbNJe2{8J{^YMyp|;)$+bdzG}U$RaxALV>fo5YRKW|Wmq)2@4TQVhoM9O3 zfk%`?6S?#PE(APnAFJ}+T`4K2m$S-shgZ1g=~R7QYHO%ZSAR}>tnj}-pocBMq2P;` z@bi}|9Su!Kfwq!+viPTwWBB;+ed>8Nzn)0yVA-znp%?9FI)zaiBw7bAm!ZpX%^n;i zs%e~>27g;4y-%b)c594dP6#6ESQxKbRr5FjZQpfkpHn$cbR3Jly}P2ibA-9Ny%%s> zeLGW3V$vWtnodOJDEp=_sy|K1yoPOXQh+1p+@xcxq`GW8sTSO_^o1HeK6W%|!%fv? zG&W7gKu}es|CgY~zOxClR=243ug%Ti?DLaur;kQZ6@$4YY|m9Mjm5cYJDYsB7MO49 zqKHjeI7StI`)x%1vg_rWjhrlg?eQkwLF49SO3DiD3hDpk`7O>&k>HF?3^hgA$^+<6 z`x-&9qPuXfQY6l}GAEs4gD|#t8AX(m%i8AAQ|8hqZn}=U<&YllobZc2!?fx91z%bw zZxdoCZd8--hnokaMpHh)^}|Oq(vEe5r*B*?2Q%;f$p$KG0qjKN?fw};UZ<)%QZ;D} zsd4Q)$UUhd!f@ljrE>EoL1&Ao}p^I!dT9GyK3}25#%6|7)9aCI^#|% z14RuIlSuE_OXEBs?TF9#kqmsJ10KkOL-X98;gf55GQ%Flwwa3-o;oJx130*^#ets? za`fca5-v(ra(hb|dIl9sZr=8=9iv*JQB3li}a%{CKTAAK6SA4ce z9$sk)0e!@!t#$72q`|FdTVGWaJ6Q6+<=4x`RETc2Qv*yVk!bWJS#_WA!v`>wE7o@~Y>Mx@5 z<`$e5ad`Q;h%3f8jSvK}-2D0j-^c68WDB*lRAJ44BI^-q1`NY&RZ#>bemfaOZCz~D z8eeZ&B~XD}++<#YT7svMK)x5!@wdn|9T1qWWC>!94Hw2tDg#FC2qyx@I7f-Pt1GA9 zH7y2iMz1Ri#b`v7g5ksQM!8g*Sil3UVAaGiTj-VppE&ZVSk5GEzm?{-;s>%14DV_w zsfVia!|-Oauw~=QvLS#dsUh)^g>{cbzxRA**?S*KY&tBj+fD&P=zi09R2)D2B7}Re zaW%OhpZg2^Qu z;Txk>h3c;=Bf59;KjMjkJY^)4uq|y08QzX2RHzS2zbGO}MrMh5?vWrG%bJ{;!krYp z!j2(gHNTP9*rX;S>vb)u=nQDmX^J2iLXZ)js-tZ^cXP(in-!cqLhd)4rPXZ`S&hsU z(~g+`&g8GQ%U<5jzeZ?LI9;3}cP_F(qoH>&k+`!?Y(hU_{2Co`aA=5>l$5ax_zeu} zVq;^0TMH#{-TlK05;Z_flUTNnsXJ0>MR+{R4;SCZ;ml(gP zWx<-fD$}metk7ag#mt46E%O3$VyXHM4i1j)?rzZ2(-Srh4i^W9c%#0hO@4&qa*M!s zWBI6XOML`TY6U!9N9O1iOjUkb=V%g~)0h*@kO5Mw;K}(inHX!SW{qMD@eH2fg;2{t zpDc!P6lB6(sYw#lCvrtbpPwH8wt2AwnS5J-NjO{3EpxcG_L9t7pk7wcGg4VL?So~A zm`3lybK4eNokL^f$QlrQ5I~hYRos~fuJ60+SmuA~^^LN3jlEY99!9cvDpIcwtx-*S z8dPx6vr>w^N$x@99hWY2^myGqkL^E50aXpgqN~vA1mJR=Vk|UG>FH3d6~p!5b~x z3U%09{Vm=1zXGhM6y-O5<}`lYyZZ&nxY@KjvYAesdG^t-)4Swp5Q4HBS9c5)6L+*^ z6rq7uvVn)d$@Cf&Wb8k^jj2{~WGME@js&D1fRO_!xhGf1t6BgBTzs#bWRoYc!2@`*zvc zdbQPK#cQ&I#iVn^VTlrL-L-lu1<3^~Iw1E?nw*A2AG_xMGSkKh)1~~U67@X#6KQij zP1BeU>gd6&C%ipi=@PC)s!H18zYedEgKLZJc{6MjryY0&-1l+gWI`3vWm{Y}5sBFh z8Sr7R(a~oQ0&j3kgC{h)s%CEhc|%<5O9t$5L=uG$0FtryhNsr(daE#r^> z4wMRsn(lN5w*O$jfd#T2HAtS7D!iCo1S6uYZZZ3>{Za@xbozUhRIn;8&xwZnJDSVd0eqgOEkrX^=q z1+RRTLw%=XvflZEy2nXHKpUvQ4zWLQrZARf>c5tlG4{BNFsd4+!C6^%tQX;wF^JHq zjjq%EhxYOAH1Og4RHch<{o%CUm034~Hp)Wo<&bMbC1pX1WHF{~a2#@KVIlJ9NSPp& zWMLs_P-f(n@%UC9V*niECe`i7ee?h$J}dlJ%ygsy3$X zHIYl8d5X$Q>WyyeNNB|wobX?asK+z6XJrCPUufc|20HpL+u#0B=DHd_cY=ccI`&qL zgBZ-|Zqb5FZshfU9i*NaZu>7V5Bj0mbaz0kHhyWRCnVh!m!wK7w+f`Ts9e)H9utS>=rmqwmfVX;r4rtA zVA~?I($UkCl9Lxr+qm5C*wVc6x^>7{Nr;c<;^LLBnC`w&3P~!*Zjjme^I$GTYXrx% z|CNmSQ!^4v+}2}pErdp>CxpxFcULsT3kiAm&WLcQVm$qHfgK@)H>u@zofxjelzIv2 z?W|M$7RI4%uTJLF$aO-p7yd%JbITVS8@tAI&3|t)Z?YG9rPpAC7emZ$Wn=RtwRuIp zQrp7CB~iaJ0@AwJ6rOs^9g29$ z4jGQ%0u74{`*dOnY5LHA!oS*XkFC}_1ODkU0P5&+d2PEjtyZ@18toV6{D-y;V+7qs zou_4p#PsLSjrWnLpu*Svbu8tbVyvH*?C?$?u2 zUB7r`gDyo*M(xfujd1GtLlf#$vRztv96`2Sh`((Hm# z-}P(@(kw}TaFM@Nu%jR-=ZU&@ROO5{riC6)QPSU@`QA=FBbiW(cz)_@AI5s}k=9vm zik#7>jiSTPXGQDMFCZ-`X6m~%D&EDV<&?n1{gGm78f59UJ`_OCTX!A*n0S>g>B#ou z{980i)v(Fb4x(yMDqUG|_;2psn-?ltlJD(Y_s1~SmTnQi!11TOc~_)HiSTbDt09UU zt~iN?2gTuyAaUPc-|K41diwkNfb)qh{I%43FZz59Go%HNAHJQ_>K{v=mK>4si;6U# zm_kECS&VBE=PGpS&H7NO{Ldwv+D>>;?NZ|pb&?FB@d$JyhDpj1fuy#Od&_SNAFnDvxywe2vk&3GP13CgS5{_mCbd>^9H)D?u;?SZ05jIusfP&zRdfoZ|S4O zHuV{QyetRah<-4>3%{jx)Y z|9}7>#`-@~f<{N7uV25$#>dat@s59k=wqH#vY{yCgOCjucpk{qyvL8;8x(qXu)Vrv zVMRY#Xy8Yy9K^t6pRtJNv$Ie`NF3u7PO~?BgU>E2F4}~VcU8Y-KbeXO7YP9?xw%#(Ru4r2q z+_)#WI|O%khv4q+PH+ttEVz4uTX1)GcXzko5Zroky6TK5SQi?29#^phD@M42BSqArJ8^c@sFmzHHhOoyxdwT|g(iL@<%S&Z~C64T>`Sb5~+MxVuEAVs8 zom;}c&DQg8n2h?7hkK;ouoa=G);31|7D>z2%x)TRzP=v2_;ntqP0;Vx)X6RD`G1k= zclYOFhcif~G*?a^4DWbBFfjpoeFuPt|42QUMjQNpV|g=7O-+M{VP)AHBrgf@crP@t zL}Ck!&Hwreh(RTYPA^aDaUm=|Kc1N}z67*?S7h9-HZVFo zo%pEIU@UA@r<;u?J1*+kXw_R|ARLSrb#`{nQ4^0lp$xaV^QsjL2ql}1;SjRjFskgc zTMPbVlfO=euFQ+d<}yz5Gw{B)iDVtv+an)0Pkp#HuSw&J6;`Q67O0%Ek*c61e?bK8s{KoK!j_?* zuCp0Qa~{0{!k(XR`9FVq8Lr{ISRVM@Pqsfy6RbQNiBy0d{=3=4b)z%*sBCI>YeV+l zlM^DJ*9+Jr?2VH9zh;9xpLQyavqiKtSrk~8Zy-z5GelMJgk2^_&+g;)Rzm)}={v?4 zZ?~hchneMlH|LpiG@Oo$6K0znpuSMrD51cy(+()1B*Tw~47ax#gbP84#@pWRWI%TVH&h(;Fr<) zy776b^8`c_c~uVIfJyb`k9wq>Y5?hoGOFyRTe3xmdOB%kHC^KTc4^cm-Sho2O;ats z)S1B6I%c4@jd4bz&t1KAQh`j0)BF1Ubr;0vD(m2!yL&YoRd1MIR@PM$w?J^(h1n#} zIz+g%E3P=V&|INftXaP2=Q@=e9xoHuiC1~G3UzA)6LE-z3=yX z?JI*;9KU4c<#ThX?w@N$NA%*lF!|fGCeVjw&}$HBnZx{)t~gCfhFlnYj}AB@WHlas z#N!xR%nmy{e(LwYO8OhUIIcq<9@JHNXE5Dq;BCNnXq{8vK>^CHXE>ak$A*@|O&sK( z)!-HPp|AtbaO?2n#OrD}b6SIsEr1Yni1M&V7dryaM*&Y;z4}rPt%=!SxBV>Od@yFz zAC6I`<;p9QOt<~^d~O7^N&N_zEPQ;CwBwKPvcU~6orcja>tX8MQ|iD<_dcx&QU`*3 zyIJ_C5x;Iwj-g2Ci#PpGb9`q2%lb&;1B7Br?cX_D-OfJpw}IrP;yLIlyH-=^#Cew! zp2f`*NKjh^Ciy&+zh*KDhz@mwiaqJ7M=f_D5qb<6ep@8lIG3)g+!Gk+uL~@)b{-G2 z4v)tbrtRm$WjdU!{nxE654QB69n6H-3m>0&n5$(iG;EQ z<>+CL(WpBprL=RZRbBDdUVIgjD5k^3%(#3p&Q@A*D2(%&!&Gi{8Y}hdPa4#0{1`Hy zEB!d^H`)l?%B^YMxzT>$r%EB*Coq7BXU#Ktll3+h`wy*nVHMX-*1LqbH`@8l7&|~8 zWAeli7>JX}E5enrV`w_#rT3QcRNB1okT;?VoeK~F=W=t)dtbe%5Oq9`rc9o1-mD$P zL6p)sZjD#7*R%D=fZJ&$r@Ev7>*!}mD&VVUsms{98d-D~%}6b$b}Dj4qy~!Y9WKR>YmoNU}%+1KCFW!Krq?(Elhy@3;2v{6Iva;omj! zSbGaug&J%EnfypID?S5I~C8D|inlP@wS4JvW3JH$3j5 zgKC#!<%LRv$pNI#Kx`S$H@%v~?rve4Xq6UDe@Ce)ts?C2R-%g(5*nc)R^@TxP&zn$ z*?)TC?_X$VKCRfs4zS@O4Ges|?x);MSpdIKvzrj}G5TVCWk3-}31bPXJ5%L3K3S-1 zPhLnT-%LGmd-jjtu_Mzdk$w1K74GM&mpF8MqNnzT7^MzxutI?7|LyjoN1%FDzRV+w z=^XM?OXme9hRtUZ$T};Iv40+o9NicsGqi*@?;8!g)NkwaV{9zMUzsPvN8ETzb9qUu z{mQu%9_XbGmkOlLdtzhkecNmCW2*{0U*9@#5isctZ%0;}f&4eEYGbI;6h@2XnF7Sm zpH(UsBE!AE?P^xZg*!Ut{qEl5YK9h{@U21&EpVBT9qwd2NT?!Du1i&>IIbPWk?1Oz zR{Eg(fOwzf8Z(5iF@$Eoc<>SGLMP|w{7ak!^4PWHVG|ZaEQQKaE?pjV_jn#z@X+zO zfp`I>dZm$lnT*LG7B4mKfD(-Ob4P(=qdzZ!No zlnae)IN|;8D-5B>mi>A2dk3eDk55rJ2k{iS(%dxoRCmBI7--RL#B*~ZzzXKIq91g0 zM*aOtJoLXEk4_oz9C;q~^?Si|_)SR!Oq@Rjg;u)qLQJ>a6RH)!hy!mzLA>(!bpbPURKNjH+ZFwn0_t5x;BckZb9%s=wY z-+JTMrpZPS8rzlJ7T6_aJV#*d*d_UhTPvw(?nu|kjQ=>4U? zlmGYW%48P1x##=xLFEx9%2D_-hp*NGu)gipiRR+RIcCapTczNt#W(ySiB{6eEwV2V z0Dz^}k_d%>dHK=5Sx%FxmuvUiHLec;HMvgIx>*c19sjo^lE*gJCwXdQ!xioPu~n6D zS)wU<=|YyoAskfA1K;jYOnE4JiLYO|UzU~JPM5kHJ_{ILY_$LG^oZj^taj#v8m)GA zlboO$UbI}jx#6a|*_?&zGnIO4`U_H=p_@RP!}mv9-%YKQS-x!!9m9kQ6r=9n+9Hk- zc%s^T7~u3ctsYDjnSku}ce@MkLqv$I{5SOG7ukDgVfD!8a{RXexrySQiZxdW}@R2?v5jCk%imPS9P~fpwr~0V7F| zjC@lC!yNK|*g1audhgSA1-#t`&EAHavwvsORzr4VzY7Otcnv%DOCgy;msE6~_F)cN-cA)c)+$(~ z7@N71smtk<<e+WE`x)OON!gt0K0ey1`6+M_i2j=;!>jk zYrzF6PS0|yOCXGHPa$$liRm_SgsZ@%Z6 zp1gP*wuZX{QET5X0N}GGF`r$^&ri_poFZE>RM(z=lqHvn#%GCsl!o^COTXSqHpy`D zSz!%>R3gyMDplg4bV5qjCQ6hJ_eWrH1Br>inxlh5`}R?w9&&sAqXGgH$*k+g!Vc{q z#XozyW7v7g8*HZkK2B3>5wwSWUqOsoR^6z?0u7y>tflJ3VY~4I%JDy~1C@B7so>lv zH2}fVf48RjyZQ$v@yR*m4Lv&mHxkl~j&vp>-paMp8_MQEly_l~MbVjzp5 zSWIM?0Ny6s_e;@_ElLv#0w1evr~pLi5StQ=Q?O71`5-dbyUnynJy@>$=(sLVWyR8g z3+iT%2o^+D_Adx|->b&38$9#-Id`Vto2R~q16g1o1ck*yY=Kn8cjY6+KUUi^1=8m7 zbG9sQj*yQhe!az_S&k2v!U4t57=wj>AGv5msiGEeXyixk5X2>rAz?>z)k}|ur-nd8yGZW1v)yQ!D04hws6TlixB46yNH#)pD4Hk& zqZ0%Q$0XgPA^rmpT?bMBt>*tBx*~1BKxpcbVmoA44v1u2!<+^OG2M;bEZQe<1MYfp zC}t?^CoEcg!+YImpY@(B??;Ood|rC?HhSHg%d=NBuIffex0~X}=1plRW~*}!5rW6q z8vg7wtC0@w82@$>kdGC0Zr;y))^u82Uwa)gr-8W1*8VvMHVTceh%6^-v`DKNZAUXI zZN$w|`OvFr5R)pKn9>B!et z=~lf5wxwSQQk%?qwfe1t2LK=nw7;hpP9b*H9F^WX-uv7;E&gTayB;F5ZMyJHrq>C% zSfV11G!D_lVxwXY%)s5lsGS&;!4+g$wr1g)vY${AWwlKETfCe7Ljv6a$br2(-5dls zAa3tHSl~k62kLmFZcET6=iD@w0SKx8dFFv)mui}4Mzf4Bel4C{MFdT@^bP`KSMT$$bB(>oJu(AUZ2x@-O%Gz8vy zWgKR%jLif`XtjH>)2f#l0-{`Ca>ZZe*a;Bt!4U%lApQ4pYFeV`1I@19p9;0reee7NV>a0gwbFg!AUo}`H}OGma- zBv%vGK^5#9YV9Y_bk%BwBsKOWo~U90;^GT86MF!0frI=D0Rdv8psdFK37q1adPe@q z2%yPTQ4suLvn*Sm&LwF*A8y4>vxvJ(nlqbAxd{$=+-Jss&)=7$;O^jb|A|5YUrbit zxFU&pvc75-nc&cltRbexM|nS%Mw0&L+-?0XS04?)5R#nCM~t2~KcBJ3@ZAP>v!865 zZ`)z9l*%LIVV%HVf@HoH77W)2uWD$j>Q65#3H)v($GFdEl807g^m2swUqdO%t~RJE z6~ov_srxS^D7?9XT@}9yT?rL!6n*k~iprRPmAl^JxI4y8;AZ(d@0*nO-X7W8{=nsy zs#quBANk2;ZOj`WNs+GwIrG4cP)sshC7whVER}@nf${WBZ{jZur_-}2-gd)kcX@!? z4_UMZHf8OmBwrPyFk=yx7wvv384HOr8cE|%1l(g2dRf=+FOBaZ)x}Z+6qK;>p>ztE zwu|IbSE?>PCaVoEK;m#Fmu?i8q8J!R*D>mvsCViio3~?;nlMC)OIszOP$XG!^M+5I zzB6i&$nW=8Lhn#Dn{&hCo_@rI6HOsnjf{JKEV!oSI_0)quF#6fN2c)6kz6|+g8nAD z(b(wV8Dw##8k7#i~GdDpmMM zP-m)v;dz#uwRf^vNRnb5n_TqHJd&s(&# zNPM=2Svwo8yeAY$){lXU#I(Mmr2FPa1|erMI2bSf?8B1Z{z_k>JZ(^Hq=jje zifXd!@tO}$kq2qf1?uWi(x&b&I7qZyQfFzqu7HR*_qx1wRcL!KvFHxJUl$OakJ&{} z>-)zGzs+Syg2JUi@p9IHQW!`^1Y&=M(a!rXOJ3SOxW~ z;?#|GD$zz3njSC%d)=ZgoRP&% zr2;NgEA4F&tetiCJAB&I7ALCkV2?UD*5PIV4jzERsxT6Jtj`t|#OML|9bjAz-kvWG zkBc&mfu@2km9z8ZSGY#ENUE=ULA8_k8=K5k)lCP)h+K(0OATLId_}N2^bm5-pIR&z zy#lsfsXhRS`KVsc_ZJp}6B*u5$3-9fI}_rl{$jv{eXIO(EfBl-cTvXYM-Qc*bl9)w zJ{Vz#+v`q$Rrg38)p!{o*b%=eS%lUqluVOMaFhG=2Zf zOzWQ04$iI>LHJ6`4vX}go!aA_*z!FAUV8tfbZM14k z;UFL&RB1Z6J5_h7VrNtz6UfudtC@W0+*0I4aYM}dHwcc%#?g&z*H~;<4^EeBUk)g1mBC34R&>o?!X1Cvfg4zm zONo@5ulNH*+O%V&3cDSawoN)(!rar-CH_y(n}e(CQGt&paPX+Hr9I0ZFXO zra8}h>YV4{Z}h2etXd6*FY;eIvDzP=!~QS*MM^m+%oNm$1|rswt%O$=O2Ga>LE2Mm zk#hRxFvvP6xb}E<^YhIuK@j8f%1Z8Lh037#AZ}9H=P0ps$o?9POnQe|^krL8Jh?>W zNXDj=r*z&X`(7_-!X~2R4RDMU$kcdL;fzr9V*0;5MIsEknIP~1amo1`Db<06a-GK* zzsHo9mqWqBmmzV!&B1c@k<2GHxiDuuTBnw(@=CoQ8T3E?egn(q%{hMZO!hv3mv)aQ z*Gvw!`9)3&3vN<===tyV_G*so^VO0`%+;KVf+N7BC_BE?{4~gkl~m4%@0TjpKI8dD zZM|RAY?gH-9UUYjDfOFzfM&@t{-g8)mnRMY2Y&7J4pb0)P2~T6$HdN_q~eTp36vTs zh8;63=_})vPm`fof1OzMK@d>Lii+v0mAx3apiUEzVZ#a0q_S|9-L6YJ$UjN%`R3gV z%zt^ux^nY%6)4BG%Z3wfFXh>e!TrRtt#ow|lECltnG@QlCMV%jDN0GllmF4>Vu&Iw zsmE=k)9-0S|Gm;(e-~GId zqig|sLt?%VZRFD1Hq1vkcHda-fg$qlT4n`y0JXjOK0Q69+BTR2H|@;}Ky$(edy_!= zGI#(v4S?gB4Nr_x3y7u)WF z?Bb}Zc2h~xNX6h2$S#)&2R>bxOg7wOb9=`cIwd~72F~%t{8=U)WwEZuMJlz{{^}A) z7lB;Sb&bzYV#|;pjjdEs!qC2ZG}F59{xb3X{QZ}jdzr7y!bvuoC5KdLL|krEjv{_3 z&=i!Rf~cs-`9axO2ERYhI}2d)!^8g1b6-;-tYLBlT@vZnSnx1aPh6bsSVfYcIF$I_ zpM-qvyS;QB><)S}VtM3-+*C%<^wg^T^byA2TW@>Iz3*E$ z_iq;s4tJJompT**%xRv3>9v+k&Uu=LR5vKssEq|qmR>phXh&uy=gAT>e9pCP%DmI! zR>)bD(BmYSlg*fy1iRANZ9IT9kmaUr;dA}^0AL*3I&@hkA3uKKHbf34Nj6J5L`q`eHPe@#Sk{;!Cfe!m9QED#=3oOrir>G|NWG zM=N}nvAeD2i_rlBiFq?vg}a~CDu*L}N;!^HJaPz0#R;G*>ncFN>UKT;_^ZFvOQDL5 zKN_26AB^`MgBJw#&4&2>(Qn;GEv)5J9dx>UJ>+EYD)|mqd_IJO#imV#3$XiiIx!BSvkct(m5QK9@EBU%QSw5!QH447$ z88Eim&oZVpzCfyD?0Z^{3QLA1azNpy9tV73U(Yd1s0GW0H1yIL`Tuh>D7)z({}EbL zZu&M5NVzx;mJJ0H<@g~u_|Wa#duL0>-uJnuD2wl$W4C#fulP`2Pl);pg{icmsQOK8 zrf3;U53!lNt3TV=kg{;HFqzaJ#Brluvd_+=y9&J_gR-c(NuDO7(2d5?Qaa>3qM96V z$Tm?KS)-Pv-GCSOvHNq!B=1FA??eW#lJxZA;@9-TAV)T5!DidWSQXgY`=WsLw??yq zmGmz^&}VzR#D{FtIrRQ9ZF-F=6MjEs&h&nPJ8wB*z+})J5-OKp2QN^wQdwZgrVL_Q zWV&dkM-60?lQDZISLSMt)k`-e_atSWPBnIMNt~1?v;a`oHXy0l`{im7z^%F!Q)mm* zvCK=zhG}R@wR~l@{VipVhQBA*(utbkWL}O~n?0YP^N&M8WQWoUTvQ~0IkbbiY&raD zeFO{`L0hYfRuDt3Ey!a#CidgWTa(bpV;pZ%OG?X(>um5(?RE;3S1qi=0Eelq1p`u~ zn6x6vwZO4}N2<68T<9yul$0t^&kG-X`hLD&JxI6nx~Qb^e1>MM&qJ)5q2@hpER_V)tGD>%5%p#HJMMh=j`(B>LfP#-( z3ctX?UGvoDW@TO(1JK53OQ_l~DEIeuqc_X|;+gj+;bQ!sAQXfDt0 z%NAB178)s6uU9}qt+30o94=DH$vy+(@ph|jQa(wc*H@&})Tl@xyI-b@&iHhrEU$07 z37SAC);2d^ixt{0!i}Nb7{Q5fvqt4|RT+M2xS_E>#K7RN*Q@_@LctM=oO<#Gk98%}zbpa*zto;YeMo?p5PiI^x-4J=Xwfj;-Lqou}#X zY53skX06ZLL>(r%i~dC#B>JjB<10c}^((D@Er0l|=#S#n1?B@Ss_rNz!7lqOw*jpPGb>1i2@4)n!go=zsGx1-dy2bx zujMw1%3-_Ig{HvQ-R@p)ay+Ah{b#<4%KNk%wHf*={&uVW;LCKb9H+444&bFfif0p! zbJZmL_Ugg;{qA(Tym4bEFGgTzWk+-8mWQ?2cb z1)9|<^koa#kj=rFEQ$<-Hfg=llGr#VtwzOOOvf#OzUMv$00Bu9DChk3&wz?8%wK^n z4R9i!M=ms%a)FwIj18)bCNjOaGjP5Pbm#Va~79etISCiSIn4AFq zsv)|srP4%Xb5_d`D$d{9cLSl^H=YA;EBW4`lYZ!lz z#6X2QqU*1%;1}qO`91;oL;ed|ya+H10Mf#P=+Z9_{gbuyW8$RnF61TsHlx&5EW2#XL=xTCJri@KXml}!$8A%pgU~~#NNgF8&n9Ga-S?*M?=x^hIaAs z!S3C)$<;gJrcSc^_*JEPDWEL5V)e(&Sgd@0$faUY+td}!eRhQhW%I+GgCyxn+ZtHa z9@#aBHt*`stx<;4h!|04+$4~6;Xt8u_Uv6CR2sQRehWWAh|~5dHU;hT6(S^Q3CZAVFgniH{l}?FNNZz@6+F4@BwQ+_hd@4pU|U zm?Td6I0ZoV^f~HUd)5WUoteyb!`nbWn!8q~nklgTf;CUo=&6JT0jgdu24Q4k)^Pv{ z93pzZBD&d2P+)O)2<@;1*D6Maqz-esgrO0mW+OW)1;cs3(UgM7l}hE4*&Wgsc-SJ4 z_pS@vM??$AJ zG;Ye~R1;Wep;5LqaaCoVJT9(TR|P!YmKyFm6YzQ892~A(=4(_+AUcvWk?CzhK|fi?nfe>W>f4}LeC&91MfJw&-SKoFOQN) zx7J8;L|=14>`=v=5v@?s2AQqWcUl;dNR422$SI_a|IT~Cp|R~^0%B@>9+yzSB6@S< z-so`oVICC#(qL|JqYrVm1y&1_R3Z@E1JCEX(vd)^X5MF7wpHPMm9M1)AW3J(`n&vU zJ;^HV^5kK8-b=Nog2VAX@oO!yIOKYR_gp)$aujg{@x0(VyF80nN_n?808s<(NBqI= zdmmt$s@IN^E(kdE)J*Q*@pR_lJB?U~G=5Vpoj-2Qc&~UZO%pQ{(f@4{$3$BI+Y6+^ z1HxjeaNs8TGcOr&_Fm=Q5E*lLncnl&cTBcmcwio3A$OIRq>! zFC5Q-X{7bnJ|bX=2lR0LlMQv2K)l>uZge^3ymnNIzE{|V_f6L2o{7S&L3M0{(Y%7J zZ0a3?4wLUA%j>HvSsSc`<4k;C_0DBn-p8CQ)A`0dajX*R@>^VOT!=%MMIfMD`D0iP z#|Ya`;8Dwy%0=DD50;K>+DqFOPmobxZ@=BRz4x?)=c>GW0$yE~Y%sB4lu)QRi-gBlNt@5!TP_k8E_>Zq!NlgjS;wQL+ooQv#(1Z+BD z;}lCAK0ZEWy48^%2sg0bHj~|E0f3er3W5(kn!NxWOq|1Oj26z}fM8CN3)L+h{FJPPB zY#_Y5<_jK!;<9?q!f8E50B;@OVsv?Tb_h>rwn|R!k`$hGC)l(!4(s>%; z0AT$f3M3f7V*vq&%-q~ow#NfwJ^~xIiCrRKxB&ZuDjrL|^~_BxELV$4hv4KNM9csd z>jo;y7@z+1r+yMDZ-*%D>XFxXVhkGOQY#-$1?GSKlaz4PhzEBJNCyD1{E)WIr>H}xX$VPlmhU}beRh~;D0+!O!) zx;xrN0xIU}*It5`r^U{Ll+HJdgcL>AAN zQmFhybsBbuE9dHM^|$Xm!JSVFRH@?+aeWaz(@=a(ghcXsT5`93Z*y(KW!xO&j6&)x zwV!?aLZv^pb9(Ou+a8PV?R$5Wx|$LMHjKu0E<#rhF&K(UJ-abL>B>9fNfPTc{pKqh89zMS6rm&ap=Q_ z0x4}YOat+t$^xS;l#XI<^3V&BjgF=iU{Hz%!FzwPJ!>5QOQSiliK&^{->7wASU==8YT(? zs!6@;>73Mu=A+X0#zx?A4{bu9O94|HcCkRad?r%lC0uEXp`=z_{-?b?(Q&k~u8-## zuDVux+X~m@PP}5D?7W^om37kGWt!L);62VADNhoS3_EFQs)zu5UMDBCXb&A70?^RV z*o1_Ifa}NYOdGg(037|_;et)SMuD<0`7(yjaX&WZAXyLJEe*G~a0R%y(+R$Zp!)1^TzqlXZiMJ8vrtkf=sLP6TFZ zDDWlLEwKHPqZ`estc;-ww~UN5M4GSwl199r@eHdoeNG${kgc$=5~bj6Z@K>Dp4zxax|D5~ScM#|V6>9sx)IDedcC;neE0t$ zw{#*a0S(P%Yt*;xnsc$vqmvHpU^clT@xS4J<-gZQ+2T_$IKTBx4}SXQd7%R%=y5-4 z>|)x_lvehW{;!Blh8U@eIm9ndhP2(88f8_AxG?eLrMek(wNghw-2trWG@M>*~!7kD$OqC@x}{<9C>eZ_JYZRhz^q zEg&by>al;NW=~r(@dym`^+E3L?tTO_0E{0CGjn%`C`?* zg7K0IBX6}b*esN71N)_S(kL@c$J5ynZ;=dnQ8gr4PiD{)C%V5luNkE}3tfk|5BU)l zr2~i4C;PLE5Hx@s#}V)f?f~$C@n}Q&M}(E+ukQthAUG1~yRTs2x(Z_@D27-ulZYTo zyWbo@iB&E}7KbZ0N9$BJ0y_8K?QA~|J@btMzb}^WcfK*cK^b`cg?pmm=%72*XGIp! zPHj#HIU1unP^zn*BJRNb%TZW<{gvftd9vDPl5%`g>i-+sZ5FWrw~3~ww@xCs!2kr( zl`pV_WhB&Wu)f#B17@<3TRcBqoi!=R31o!$!%RS335(6uFh`R)8eTIV-+y$I3cNIF=y^gj_oKAbTV#!>_ zgQ>oSYnoch#7p6o>q^?alm%4M0G$+%(YkKQcj<+$9p^SgxCBqIit}% zQ(_j`**sNCyFUZIuKrxgYQ2$ z4uBzA>N*(zwcO^(TB=dTbb<7b*={$bkXl4VT^KyJfKkk2v%ml zH*fU{-QjQyTFo{O=HA|3pzG6JHDfwaEr5{@b}c~9wD?=S4(`!^&!Dm4+*(Z(#N^y$^MS{(iDC6z1||A7Nq(qXQoz@_Z<;6IO$%{x!B;<*O2IDl-@C znz^A_4c$Bl<_+BbYajeU66?CDa_T1_Nnb`muzxm2uv-+5&=ioDjHR)L4zW3+?!cC| zG3F;0OqnOsQEP zQZ(4aiU?A(+L~FW?)W4bbBo8!e~L&5&!OP*08Y zqhPen4TfKDoNQwTmL^w!n@u@d{r4r+8DWSfYOJ^R*$Ipn0wft6$Da(>)ITt3^u8hb za#r4D|%W&!uV;nEz}${Wq&1H`%&t_*i(TspAeVg3%5?)1ku29SSgd0HnDNKx@&mMx<~>=6C=4J-ywBUd@?OMjf9 z8naQ&8dE8)Z6bX9z6M)-Stvm=)+dz5PB1a*P|5Gm{f(>l*&u>k&`UkXaTUV7uF zKQG*~@b?tymd3`j93)83#Gw!jdM$l`-ugq7`f-SWAcv2TSXPS(KmgVA@W5q+yv5~1 zaAIlL+3$jb~P%#0aoq8Q-9I=jRUGQkAsv@oVcf< z%0N|M2a{`8Hk%FzZo3?-^?uyPYPPw>4GDqy^9Zdf?Nri{VR1(@YYCRjPQS1mj*)3& zd)On1M?A&6m^UrW?Q}r(v2;uDd3kcF-UbVp`?A>^cDFn?%ANx^*+Ix(iyz10XFy;h zWj`C#EW6o|&?L2&k`-7HNo2LYZ$fzA*ccotyd8bUu2?9RiFFJpVyU8Mt?Z4JVKJ<- z2U@^Eieg?4k)=PcL{3NR22Kxw2Fe*NK^fTeDEZ=LkU4CihnFiA3BpB4HY+la+}TpZ2CkuKm!2ck1nxJaT!b#+(! z1c*&XqPB%AY;J+q*uPPK7I+|zNM`tAT@M=&+MPpEMQ#<3+%J)_;Ra+(pomFnsb&2B zz32CI18m#!dz2A)xfBgT{@{j)0V4)Y(nuNJSkGq5_pyk|?B$l7`~G{7TZa->a`1jD zRXN-Yb}*O%i&2TOIMhmYq@sGVim3|i#BmNh2Bj)N%=h!Qh{}!!v&@Yb$oukEJOrZ> zm;URx!oK2S?589Fm&9yH%?7y;i6vBe;u-O4Gmd{MT0?zvYJ9~dAP-TH{G0C43py@pf(k~o;ikZIRv1gkv8{IQYl!|&J* zx{~!TaSHDjQe<1JCKF=R0PLX_;xvecCvPY&y z$wpC0s>b8*QzxXV6Jtf3y#lRE~N;{=wGJ@+RiCLok5(? zYwP-umMHk$v2OT2+sS8j`XdKO8+01!XeMh}>;zfYhr8GUAj55&xZz5nqu09RY@Kda z(K4&m;1jcsF>~p-o$$BmjCZWbl{zc5_v5S=O7CMCgWLn|FHG^|0N2D4Vo(VYPd=NE ztGfz?k-$OmXnS9D>iL}Vd*v0yIW&zH_1_RTjZ)y-n{WD~r*y$pew4|o#a4NQk!w$ zjMM{$17)L@-vtg*y^wXm=nOPyvJIp!UV?apUa_m30>amO8c|E>CkNJ}s2PQ3BBk}* zn_O}Llxw|S1@3!up!4#W_0HY7+#CpWAGuVyKyXOQ0EL20)S;(2gm?K>eXDm%D~G5O za`NWnzoryQ!n6g`8Q3~ARNKXFNBo_&5L!4<bJX`G^0#VOsb6wIXCH>j%Mk>| ztF_rlhr#fqe~)VT2sZJ#_umw&_}9%g%=n zrWfBf)~^YH{MY@ixL$HJw0}qpbZVDI+M!k1B|w?xYB*Yo#mb^MgLB#5)hE9^Q+uEr zK6KH!tzQqBbjnE65@At5A2MK-%Fh0}_>{_O@u~L}0$3sEL#NvmJKtDo3}jr;0jd(< zKh8JVjY6zVk3UGAM*pQNmdL<ZN7xIGL*l&xI6 z_1s~EEeV5ggM-Shv+vm2z&gG+RD+5v$zP;e7^Bjk=6v{ZeGB@$9@?(AB+VW&f)vZ= zFMYDOusD;V!EjvBU6)whAVBilq{`qwGa|!*%Z0eW^lb_sU?Roe5(MAS&RcBcq~fa~ zn;;=oRQjYEW zlSrdk@E3~&m<(bWFjJ z2R9_2hOHT@kHA5x6jNrTCxG=Vbo2hEQ|W&o+rNf^yM;M{$pEl8q`uojBtsjua40o9 zJ1iZ{+S0BrjZxz%8y$5-Ln(>a%H-Rl7;@x3CA$IWi(4;lXpq;2~+UFY%#m zcQxZ^@VE|W?=MCViwXzzNBJDb(V}G!{#|elR4!iW^=bof)z&q3KDE37(NcI(mT$Vf z55O!u8u=cJdxhriB=MG82?TeF=u#J#dGQRln`f{DpxmQ%# zIWV2~)vBL_Mow6|O&Usun*jYbZAGX8qhS>;8(k?PWXZ(Nh+^9!)VI-2rwy+05HXe6|#BvPVM7Vh(}ct+RoQNtZ@`jayha}%o=kKN3gVKEL;i36LW8zjF2 z+SZSlAh#VzAn54BiXe;7eUp!`-%?`w1b_sb@q1&3-C1jd~w`GIwTGSyC9%RTrh7pW!g z$*UnFZSzAD29(1wtWx8zCtlF7+>QtMKR**4%xASv0N2pq`RjA6vhoR0m!qtKFES)m z($2H*GLNZm(Pb$H07QK9@moI53<(p+wi2r4g`Bl`-f;jc%uBJdxRrm!k2@L1)Vt*_mbo&Sii1go}PG3j}u z1cN4YIP*^uKS723u$btcAr9xJ7+afd_9+Q_*LZpPIl} z-ZDH^M=?q}fD2f^WbvfW#7esX-QYv%g>Tk}g8b^rF+Z`dc`HLXoQorKOFTjde^BF- zrbb<(rpr6w3e|ufUcQqF4jzzO+_t&Mf_DPx%r|e1K>{gdN;O0kOlFt7;e=4CQF-wB zZEv+quQge%aU(iH9K8`)TIJST*9fH_rJ}9~EsgZr+A9%z-iuaaTfTk=csXp>ufQ%k zI)fMeuAmPmfeyi1xp>i$h7iz5nx<7Bhx_qP*Ph4T(cztz)%MKEIlA@N&Fi%y=|5kr zq`}@=M*)gm=TZ7bCiipQOwYg606sBTqm#^Hzrj~BPZPbnwTj6ROEbg*)lAexU#>ic z$TWsnxcd43Ve2iUqW;S;%e8!vvUZlvL$74ue z*lZm8PvOy`M{;g#(qSHnIqzCf9Y(w_3xg_PHxQ02nq}3nO?+;%fEgv^aZ=HCwKdr@ zKyo+!Glx!c%EOo|#TIoI0ya09B1Q}rT`e=p%wVmfX)aNX*$}bsd8#4wFDg}~&8cWi zC_1alE*J0%ri`!vLMkT;cR}>-qAG$?4Pkxu+I^8V37c(eZr#n_yUDN_kl**ZLEx1W z=3U=5G8E%%JwpWF7lH?Su@BF`SqBOQNnt{Tj5v~eCUVX59GoUSvo{AxJtb!kB^(a)5yI-AHukwMUYd!FLq*mG6ixooJ#s#L&;F?yX#B z(s(G$RvYg`F$5jAL1I3~uCQGPSg`)XHQAtbT_?~wM;<4}E#^402Qoh_TGV7$LlqKp zY--f$iK~rxzA?b;I>Ob0|Ek>fdS!&rm8oH8C?%V|B!1>HWMAQ)ZH9AR9L0VD+E%}+ zfTxi0=SLOfUB<>@Xmf}$4bYd0{u@8b9EYBxlgDe|1VvFA-v$6IHl?0v~G8Y)OpOw$) z(AlZiHBgWsAZw@GT&8+Xgqeu=|z>BK{I<>VPozOuQ3i!K-62%fWp0N;=qxkLiM=O~FX@b`BDvmC=!7g) z^+VUqZ(UK7`6&%=5+=-nPWgTv0Q;t`EQcOLYBlG0)SO}6ox>f^<8C?HAErCk<~f83 zzFir-e^@jBb6TxnGI|gPfi?MM#WP~*j@AZ5%8k6$RA3)zt*%}avj(l7wn!I|@XG%0 z0u)ebHfHSO=?=A)i!y_&!SKQ zlZ)|e60z^cb?{ox?HbMlOcK-(2CUB_=|ytLPD8dy2VF1m`(Dn|O7@gh&uJ(Oz1?vL80!xZIb~T@wF-O8(yq3YnNz1AElg|yW#UHBBmrnu9Q3h5q zdgIfs*eb~^5z&YUN_AGk9Wy`HOh@scOm0uM&`q zch!4)LXeRn-RAz{?))ZKo+fYBzy5wS_{BSLe?$9|U559)JV*!O7INod$;bEf*_dlv zklH$8!!zNWFfC=hvr01U?j%ak%j0csA}6;-Rgss!AgS!n=M||xAHAFj&+%r{lUzy8 zR5zn_5G}@$V3XSfHii#mz&I-v7$MQ^ zG9g0_qou73vd6@zQ7p}-+X3DDwtP)J1ODLav8lbWXS;~+*}oFog=%2?bP`A{etpBs z#Rbf50Ka`TJ6nnC@we>*>zjDmpDWN4otIO|jd2zE!geczYb4g2cb+J8g=hbKf_vL- zU%8iQ4?T+&yKu#Zi>LEWHMe2Xasn@wOwzr$TXWOP=2mh zgE04uO=oGDew~ZBH|H~^&kEv6tb5{Un=gwPrI-N`^JdRKAAI}Qu*S3x=NTn7Nu4Di zB2}l8Pn04Mq+|G=>gF-c9Olbo*|M!@Y}lSweOjz z#VS1dzF*ot)bw5_R`49TGYtK!)UHlwr;;ANoB>jK(3A!8INcPpY-9$`f`rbN!-|bEjVvRL%R+>+K zX)_rq%^Pkdv@T4v+dvWXW#U`*fw0mdqSp!H$wF;tONIwVLMhjGq)wD}sysCgeV+Z`H4EKW%He9fmabv6*4p(NAi3CXYeKz{z6wU1GZvA+LMusqH`HW5}C)KckeT4(znN%wwk9`Wd)BDKu)o z^4Fpr#xMbU!s>Ywyo@C+t{507@lptpg|eDd4w;|A+d(|jHAHAZNorGfYv=^LK6fMb zu$;-M3-9okJJ|+EP^b@RJ`P81I+hJ{JHkb{fMpqMF~s0e`6aXX=j6R zGEc399UW_Y%O|3p`l&%1_kuyWq}}WbY?2#24*@|<#12n9r)~Jnb`20o zrhDpGV5)p?s%P|zh$W(>oig^_F*=CIN0rz_#^`3kG>4e|=B)X@+Lti&4@R^^7>$l| zMTy+vtv&9(y_+QXq*|uo7%gW!s&6BQKUHmHlPmhMK-CV|vM$DanY5(UBWoM}OBZqn zkc)0-bR8~$3Yc3|Ao$RedF?cbghxz_ZLKo_V_Sbyb7yU7l*pyrr+kDDzF4wdl_Cnx zCyeBKKW!;F^l6GP-YknR-a39qF|i5|3k%pU_ZNRIX}nqe+<50=Yen}vA3J$E1uNn+ zp@YTkpGh|h2S;~NmFsB3yXi;txw$PdUH^AWDe#BYfcuu!TcRt&2$|i`Mh$&v!fgD&;~LurA+cUP+31L zGuI(4>hYHoSw#xEF?C22k|CowlAWmf642{F%Q3X1K?FCb8WaEyJDLfvG0q0Lk15ab20^y8WNb z6vDMBFU}Uxy1SfzhY}Nuia<;CMH(Y_-B#V>>v-HT8f?o0=sJa>TW7NkLX|sjViYa3Eo~?$ zjTpFT=Vn=4%>sd~S{{Dw&OaH_Fd17}Xkz)}`Uz9!!%%+eYjApgLps3duhdhU>mia+ zQDsmW=x`DrdUZ|ME`51j+t#Rgi4RYG_aC2W)np<31n4A_22ipBi2N2FV~VXn;)=O4 zwm;6Yh$N-_Ple^M(6Vac!ggpwNrj#k-pDq9Z;zUA8=h1T_kYORn9|MoQXUqkQ&+15 z8ly!@*HwHhWhYZd=)54Mp!oW26ERfti=w^RUDv0|iz+532g8tZ?1@QNlQ&M#F~3@( zEuFA18zgk6+z)zG+nYV%txu!x9(xQQQBLiAr~tq)E)F2$Rb4gpG5i`@eUkND~UjbMM8okx$Pl7sxqq zMFmk)hR|bSe_=xY*z-0g#WQH>^CCU0M`W;$p1tqIkOTwzWVMommw=tIcC+)gsE4$4 z^H;1LvEbzFCAvUubuR0>Jx+u5$2+L^jfI#QKwdgptP3}C#vi&-RGi{dcA}tT{4#$* z1TB&~v$IMB>sESWU@FsemwseU?$^aC=fQqMqj>FSrY-Z18m&?!3J}E!thta>v|eC5 zPo)6K4)TwKyNbrw5@^pna#GTcYGh;5-1r=wD`>VRef?489z`;#DZu^rhNFUqbOBw_ z&V*`kaLBp!XGTUwG)8g{A0NQ}|7s2)o@}C{b*2a;yBMTYK{S}4r3^zTeO0Tvhyc>& z%?T>6t&CUZnlU=*5P>|6fIG$Dx!}<@_Z8^`7LiZ*ePI(-;lRoXFCvGi7B8L*|3@an zI7L9LtYDid+ruh2HT*%;%)VVw+OI#^S;vN#i9JNalFaF6JwWoC8$7Y#nWTSmiCVoL zr>iJmxZJ+kUGqAfRS`y($co2QpyS2lj`i$-k>ZI%s6X~T?1GfYL1k$EpfsiN;&sLS}+w*t;j$23t z_J1BdrPv8Hs*bakf!fl-UNJB_)!UKJIlUx{k(&C6Xll6k4mo)<{bqIN?P=>s39vB% z=DNwP-mmhy$Mg}xkf~1=YwCDGqPU=}eTt})rg=c-pJ`uKCl89rtK}wG6r}h%P)oXg zcE)wH;==hnH{uj|pn&d-&otF`UoIs zo?C!BQWIn8M)=!1jJMG_J=tR=uB!KiKm5mP8iu;-DxyY{MG8y||GMf=^6}@S8~-dE z7JdTowr5ur;B+S7?+A>K*F8BR85AbO%dmbLVJ;Zo9Nc-fh{x=_!7WhmIh$7%eY#YK zJUq3VFV)-W3A?;-u>7gBCeA`uyqR==1~OWN*e+%Gvb%pxK86vVd<$xSXl((D(Y;xX z0s_0m=drM{a?~xAKXR*-)O?%3hvCAH!DDQkkgt)la(P?hX=&_z>c5tP$+QCcgNf0% z22gNp!BOg`w#K%7Ozdd1#EfKPqj+DxvYHH{EFlErzb54pQ31;;mG{v-&|Ed8T}TFHw>PUethBhuV^*zoe;NSd=b*GmjYbYT1M z837-q{x#5hRf7OpY3uKisif0b(mH3e0{NNe{PDn7k(wZcebtR_g(;W1H~u3V|#qp|ir0J=yta8o}*kc>ulze@c8d4TTo51c!t;QA7a+ zavGyhm$A;J6(gu)B9jxLg$#+>j-W8b>hW_5&=r&)s+DOfM?Fmw#>0H=n|6pH(Bq1l zgN+E=<;LG(j;hR)%sgQa&WqROO0D5HBNt&GS&KA%YEg1cV~@lf{Tk|9hYlSc(~hZ* zxnQGBMq1hHD<{>CZ$MdFj}?fZykhk`2x-W51>o>lM~ETxTwki ze+8Jv*KMZH3)FGSXU_*x`MF2*d-n}%5f3^zCxS8PxM{wV5u28^$-yVBJ3qp3hVyYx zxtcYozXaxqB0BVo-zckqz?Y^R1k$jlOWFmf263TQ31)iz`2R8xddZynEi!$20T0pe z?D5j`J_Shap~aG%lC#%F>*F|8?{h-yEr?FA%C@TTB{4Mw`DtM?h^;+xg8C#>D)ESB z2-Ne1A%_nlw;eAa=MfHPfL*fk>i~W*>b;zL1R>c{%vX7tl9|CD8ktMb`pAJeictW`_C(_3{UDLLu=;AFy6Mf@#e zNi|et^)(2SdenxkwA`T1ZiHa$u@7jMFZQ008qy-`=oM{Q6_PZGP8S7IpV22^stHrX z|4IING+o2G-WE#?SmS`6#a;u+mbFF(*c}HAwhU`9q2EuS4=!D2MOm#*~-u z)1lbQJ{$*}R01UJ1Ql01y8)$cC#;0tqFX&2oxFsoIWdwFf&QQ>##{oL1`geUHe8X; zoWx9HBiI|2^ADIg8e7do9W?TM!m6G-3Z_dj)BZ@ZxaaNOH}Ihw$jy5WgOn_TiY-sZ z^C((V@b>&`fGA@}MPbrwt>iA@Ro6%c!uu*OyU7-AqpBj3Ox&lY@Vl2A@K3TOz1HOSD?s@r50%awn_?K?H>bhT{W8OP z1ryC3q}&nR@$@%EpV}j18(eG1wDBBW*&63J2x`7l0)a?hh?i-0-T0Ui%-Y7#qXSz( z&({E>1pT?|02YQo?8t9Y9Ih%nRg&sVGNe%60vjq}sq9ogVAf}4H5(ClZ$Cd>r)#+EDHhdm{ zJOkk5;f50#K#Wa!uZW;kt79Iw?!qKQy~X=#ZWB&o1znu%`h;778Az&s*azFXf2()>Q1 zBDq7KK{5jmqaDd8nB@vD=aZkV{X>$XyjZ6ntePF^I?%C+{26aPQ3_KK$d z8^j(c26@ZyPYyHrLBIsz@h_AKAXh+ofbZl%g~m_+7yNU5)wca5zaqJOE`shMhs|h( zXBA^VLilnfEGyyT7Om&KkI)A;n@ro5N2v-f!Q6o?CeCA-Pm_Hb%9}gv_ z>=1wO_CI(%>nze7T=MPRK3UDho#z-B5BZM_l1P;6&FYXMXInR2lt`yfi31R`kQrw9 zA-C${wXff-Ml1wErtl#_Ytq(=rmP+#wx6GUaV_)U@azExG<^NYdA|oe{k}E#9n#TEvB=gKAnvd)Vh?m)a@%8V|3_mv(=TnD44m78ksJLljB z)XKo*F%}kK2U%w`4)#A+wfROjuB;?6_4PS=@(@AuGX63t08FC=(~eHzryE+q@NQSg z!54k!l=gPbJ9cjERw&c=o<&{Rl)pH}YUBMFug?vDS@{mCu~s3>B$)$&FmCW@r0&2U zwxSs609)IcNE8=V=oX$L`T5MZ>c2=)BHfAYk7kg&s|uHg;|57chH$xbPyI__h6vhC z_BqZoENG73=Yr1p#+TEqd1R}r)$yl3r(UgByYB$cKfcJ6ze+7*o|R5{fP4%f2<9I% z++M`h(nVTA@JrqwmN-5oQR5NX-gYi=58l~wJRZ?T|}|FbMnWT8*q1_7fvjCxI&u@U8`K3^0bwS zEd>h$QA5m4#x6PEd*yR}(^#!+%aV=}ydFXQ2n0Nx<^XGhpFdghqm!#LV=zu25B9JF zD%i{CE)p92V!)67*Q;ynYHsBgJLtKhx}$BJCSL&Y#~xXQ)PX;Lfi`3$6&UZ}8u~no zCOgfM^hnz6Z85u;0|k4_XRz8nOA_~Vt0EU!=RWG}h*-h@iNa5qN9UZ6*pSN?!I7!T zd3#mBYVaA6qW|MZ2xQQD*W8w+Paj9TV1CpNK2q z|43|CAnCk&V~Au!(0+-a{!@lzt3bb*hO+Gv!zWhG_A^?SkdP!X5!5lKXvJGk|e58&yU-zem{m>%qG$ezPYm8%PDaoi~m;HJ40!AhptZcPxoieiC&mRLaBRb0~c;Mj=C0P>|c1l175G(5Ozj$M^*x2a2 zMnGD_5b>rs?o!J}uh|i2%&BQB@^kCOWTNNY4(GFDRAlS}Q&`xra0Pi5zH%wgxPV)a z3=3UYN&!p#79R4;_WO}kZ}`L7UgGJ~qF?M_V;$j~^zN}jO(=E3p)bwC_-7Q(zE1|| zv`GE(@^v~WOZ$ydR(?CeUm)590h&l}QR_z@V?^M?HIMEID&kpqP zIqzWQAaVISK!8>-vyKhQa+MSL{u}xr=Cj*>T?RjTERV_<<4DUiROGQ1?sfe&5*HIk zWYg#LM_V)o1At3rS!*P)n=Rx|ZORWk z=&tQ?!nX{e_crYto&EH6FyP?^xV{=MMuMyUa2&9cIH=K{67g?(0v_(#r1yWDb*`wW zo!%k5$S2GzP+(H)p|qJht4nO}eA|AftjVcsesP~RXpQ7%Es&I8mQ1f@RZY)L?z2?D z%`flc2*OTl^2oq-_w5FDmR--2mh$&4e=mNQ+X&q0kSjpqc7hvgTNHTvmEHw82<hILgG=YIoR_$$ECtrQ-ngxzQ`D9qr9z*o22So;I zNjkeB5QtS$F873+hkFo+JH9=)5wid|PtSZ)ATH?}+Kc+74gEKSykldVFjjnUpHn6K zkj7Iknz6k18k6;bcbmW{wZy0J(*t_IIl7J}Un3+<%(U#(XAOZ}RX_oiQ1yL%{N+1R zk{1YhEM$1~pR%b_F{aE^lU(WVE?)MgR8?{NUJPk@Ud?EE0vt;f?cTFAAqLX}okPQy z!Z$=m<`Q)cLfa$`GN2Aj5jsm|-as4jA^kEr=OxjlszCv)HD?tC0s)=UcK7#y1|FuE z@i^)-KR?`+k4uh-Rm9m-8Xpj&38k&aa$>_DP21>PYTxYkI-LTL!+bx*^DK3L^p7`( z$`O4=&M=cSH`e8sXek~;Q`C#L-!Ic^b6rvV^wblOn&G40-?X7 zIi>mv8QqRQo)Y$D&3Z=2mx~T_`?iOdyBy82%+=_UbSF$aHBD7egCQ>Nr^2FfCBA~& zOn4%A%%-BPH-zex&u43f%!z_v@81K?oJ_EVZe}S5yx59Z>h~Ao>CdrzvQ{x#e{AWB z0UCkkSk<5A*XpJOfm;O2z*fuq&}MBtb?ug{fdhgv$BQu)6!axd3NX<#c*o`BWdL>L zDwbT8=-c-QaD4{|6xKirujJ7vRu1AAiC3kmpD$1dD!!nOn5fF;xJr3 zg~kr^9lVK1T7xo{o~WYeTX_aY>EsV;>EASknTfr5th{BEXaL_UKREbU7>76pD=18< zy>@0bLzRp3;wE-;5i4N<rYEm-$+5`(nkl*m@zfv8XHP> zTFb8*ti(Nbx<;bOy|;a)$bxpsB};qdxH>j+JhmH2OoEJ|wq`V;nnt>E6fiOH`RScI z{AA6^67KtAZ&TPZgC@=bXl#_Oq5c^~lj7bs6BoGp1 z3!jG%r|oc2-Fn-N^}hj1N=hKcADl5an@Jdc;x-Yw{GU(gx!W!y(+X}$%1|7yd=wDG z0f7c9WJ|EIToKsM*o^qxtn>i|`yC1VXbgCbLv%*o$b+oXvg>kAgruA#W?Vti_<@$` z8=4maKbR4a#57$nfG>K9uukBFxGvlW~6GfT2mNIhPx{GZ_6 zk@uC(UGKp)+u$oP@S5w&d(Bxy${(=~)P(D^Xl1NnR%-r*e>GY1WKLyTe9V`d{YI0I z!Y!~okI$3&&8-lQdQJt*yVk-F9l#%}CII2!|A|=wb%;TL229Qt3Dn=3vy1?;RBmEu z0tNtl9rd9+Aw^%dG}t_F_PGi?z2TFwRBcyBJ5N-P8~FiLcGZ1_te;sN1Ci|n3X+HM zcuZBa<E-b|!z4@EGl^2EwnhsLx?5b3z98k9kXDA8nx4L$E<^*)iW-gjs|Zaw z!?q|>i;ov#ur;_t>(z-@nix2Pn%m9eRp;gO-k!03*i(cK8)$6|0Arm zQO_QW*Vil!5K?UU(R!J_v|6HbdLL**V1q*<)f+U$L{VYKh+)hE@?zp?y@K_U<7xm~ zT3&}|18U!wRR3P89aBHx;>Cf?xmg?ZB)-et0G_zr{d9 z4WT(dncZJABe(c7(_7X3!Nws=g>dmf2V5)l=KKIlo67EezVS~-iUdx>QPU`q!KqJT zBW>>Gra&XHcH?BX_11uk4?seF$jKqj*o#L4t8%mN-r1t7@F+&Xl!z{`g*LcGj4Ihf zD~DlqFJDNhcK6RSCvxa-Ud%JA626q8aiUN^J+%P5^XzH7{V@!RqB_k@gm=*qzSu*xg>Is{jCxN;L0)d&v|1_T`qq#Soa@2-jC((-WLp(E}q=6qgr8% z-D?A}AI!_zT0dMEg-`2ZqLZa$S_}*2NZ$QK6t^Q@fQPu|b{imeiv$~jAAv^zmqZoc zmvVahAdm7iH$0Znin0jvdW>&>sew^cv^g0|A;GAeWQsYx&>Juh|DhylaN2vXglCTD zMhI24%^U|10i^5igA!qgRs$o_xKj$;sbfi!q5Tv|*~d~c2i5{*8DSG*WeY}zcHtRo z1Ivx#J+cB66Fq*932J}^NDpd^0!2=UcyTh-(TH7MZy&|LVUp8YkRAj2_IF%O zi?JE-@KzdG;wbKNZiC@#@KcZLfj+BRi5JBMoMPeXdUK3`SWK6!uSBI_Q?xEYb*EV&uxP+hck>*Ll^oKHg*J3@_sZg(W@R5tdN-++~?3XVEn&6LGD=Ie`ZDXqs zM^~j5?`_f`y6xRjz8;vssLt5&PZUH4Wy&_D=cTl!oLpkLBA6O4!yN-|}95|)I5kL~n7>!&`D@g+4T3;ZncEf4?94SwJs4qzj@&hl` zgFvmdb_gJkm%zvEUCkW`ROAfu%b<=yvBd#h=EWg>p@C8;-Dpnn0%Ha?F<$3~)LTq0&0(GPOnU%7mdyVM8_f104HUe9ls zafy6W1#UKdL@0V?f&^GhySp?Zc95>HPZ7S~S~yp|{NbPLsXfngwE zx%+q<`EI_&ol{mem{Kk~FBcUlUoEsoz<&1^@927QN%S!8KCw)$7@KKL_pYj{03Yp$>1@Q!h{FA+JgJoBU2%^w18^wS@h2e}3}ZB`;g%>|?}efz^l$m2}KdG5Q@toJ-ht~(0Azu(l&v>ErZxyblrU?DIXQ1M#I`zZfK%r0?x!$*36D#ABj? zsHmLLj8vX;MJ+#>y1~xe{^IFOIK(*=PH z7N2j2pTNiC<3c+jD0&C#rpH-L<>JCKYUhY96*vH%h~?L(X?FU9?oi#0 zVQxi5g>JLcO7RY$sBlH_Yf{ZJKy@q6b@*jmys$6By!V>&-m&l1!J{3g__(F85#y-Z z;;{g5wilXQn3i6zjzZeJ^z9=?TuRGO*exRrSyfr%<;cs2Hwu(f8)5f{o?GN={ROUv zq?sA!fRf~~9SDASmP}CyJ2wu&k|@Xnm;=>{nBX0>0e)tR3C_F87S4Y?_nxI<37q=7 zwA+J113!T8O>zY$6afU?{W!QKd-Tpt1jG0Av^vCzhXl0m4dxUa&%SnF-C9V#xrv-H zkiGEusM2R_`PP&*-efNJXG|LRdP}^q?e{SK7Pl&wy;urS@1&xlqGe}M3x zHih8+o$`iY!5idPS3iV&Ahq;v1|x?4NB1s+(V=Bo(?!^j=iIy1f&4`M!O83%<~Mjn zAJ7h&A6Kwr-&HVwb7B7Y#yCZV`JQw=yYKa$msn%`>GGvMz_6Ay^-jyu$=54y=I3!M zVxR==2JVTC?W8psz(t^SA)y33hidAp@EU#nFC@;(wbhFw&=oaPW4E2U+Q^|9r#cxY(2iFMjJX z=$T0E-$Re~jYCQKMQ3nig|&`U#0zb>4k*L(`jsfa1-XcD@QDRXUWo1c&d2X%i-?>V zKecTESu}Ru@NKh{-DAV#cXCX4NYgqK)=kR3`D#wJ3nF6mIwj}3hvj<_6+V=6dM?=U zYN3M4p{aHvZ&(tCR%{ppT?}%&g&rvT{xH0!KRf#IwCu4J;r*n$_7#9FOQ~+>SP1P1 zD64mx6V&GDIn@qm=Kk12SvlPYp|r7pR+QsKAOR$n4L?p*pq~vAg>mR)sT}IERE)AJ zGC!ASI`tM6Ryl3S0Aw=gvRMNHCviB3^Wj~b0>gbVzgFkq(2pM`6BEr)a?ie(O0jMv zO8Z2(M}iNO$3G&kgrU8pd8d@_UGtvh(5Cd88(3LgLVfxGZ~5FIaEt?=Yv|z<{pUj! z@_O|nX>hG%;-Y_=lX+R4Myn|3-xW&&hyEb;+vSdTtLHeceJ+h*eehca#K40_3-X9jZ@)5lkv{||`K|N~i*SM5c@?Z#I|HgiMjA@E}!g?adrtEdYHk}-$AV7Q6D8oHlM zODG94TK+2sr5cwx-er#|ch7%Ch4WQVtKQz;H0Z4Q-YVyJ;1+aREV6JM)znuPhsqwsAO0@r_@F8FAZ?`ACh=n=56>L6C1l1tARonreq?7lPkC_?`G>sqf@XC8|*)f9IwY6w)(jso4B@>Ef;<8eMS3qj{od`&PfjXBpx#@EqHHnr zG6sp;rj1HW7ptR%ebpZPoY|N&q|1c*67o^_#;ZBVT`U`? z$4-RCL#TQHhg?Xe4(jSRH9X$sr?FF~qmOYfoYbBl`^o=DD`2<%>t|fr#`FjZ=sR#_ zvABTOR2J<%1ZTc{IBnih9$R^6yGd>PWLUHmQOrlopx8+k%Kf7RJDuTHAcx+hcJ>$J zn}35@_lY%+%Zfr<|FqOs?s=H6V)GeH*tmPu&h+0O(Wmti^s>Nphc;9$x(Pm=9ee_( zq}n&5v!zWD2cZLHw4h7zghET&%Q`y7seEC0i=lYt16U~T9H8;G+2KFVW5>8b;gha| z;XO`D_`%eA8Z{csj<7ob2vAb7(Fz^iikqGT4wTVin6zF}Mkk<1)?-79xt1n;9 zR7i05Ll-Eci5keLk&yxdo`c2zX|)6NxO&Hf{6ye6F3bv|{-`FBKM^AoM%dSk8G0uM zAZs5SBcaK=CaI2(uypc`^p?=fA#uUrU7IK(vLj`L);Hsfe3q@-13u=YXvxRpI2;qm&z`bz=bxFKn!v~hc7mzkl8?YH0u zQ$6<)wzK1-e)#g8&>F1xuyt`kT->5l_jiCfgy&hO`16T(N^K>^v?73xJA;}YYR{D0!DrJMo> zvc6#Ht$ignrF2Xu6BHKxTPAi(lXg&MtGxNa*!UVN1rsz(*_Ce1{T|GH z*v9m*w54s!GigrnnIo&r@ldIzry%0+4hmn(bR6g*ss3j45?^xK{@rZ!^9Bky1$Zo{(h~8e}KnK%zIL;Zq+3c zoHWmYbPK(^-A{HR@X3mq;9`NgbWNGamy;9J)i_C4fgid=dNMrb6&+zN_Ni#WzEWHOp`Cts6PL~J9H+%RF-^6qa!GW|;ow|0#-|pn@s3L>`67Hs= zhVb;^(tq2IDfVJlIy73}Bk8n=trw~p^gMUsTem1r*Z(P&XC?iJHsV=|U?($e#_?A} zG+p*GhoA)a$#`r6LXm$__FKED4!a$(pK?%9iwG5!aBwA4)O72y#-M-Z4)r(K496^A zT9$?8+>(N_v_1$OI(Y=))hrv*ATJKv*5@$O+BB$Ui~(99LDw#s)w6=PRXdlwf?L0M znOWt{(|#ru60vd$+4%|nYR1XjJ1`AxquiA@Z!s}hRL@)Z#oEGMkjjQrgL3q7n>y5B z@AtyQ#@0@pTh#JI+1{^TCu`sCRasCYxsa@nykJ7Ux4BeK(2=*#>5xEWTy#}&g2*%? zgH(+sg3Caos9wu7zK!!ag(h%k8k^j6NO!f{#sEq-Td_88=i;zb`;B33QZU{1qwwzv zvusMHmr?MWWs+K*{~6+<{6A802^D5SQc7~*LCaS_NX^rG3S+y4!Y`R@4O*Hozsn27 zj>j>j4l8DJ4kLbYrht0D^80H#r9|h1sl!I6xW7Xxa=VPn@=1~NT=s8t6k^x`OUe0D z%jq64YTSLsvIC(L$i_9HhU{w0#1lGG0Gr9MODOU4Xw8oz4OXBGSUj$`k%@}kFLo8o znkKNA)f?t8Ie))yok|wz-4=3vrR4~8oGwA*Rdhz6BA-ndn6lTEeVE($N5R}2?khw=8C!ySTeLB1X_E^kj z;6)Iwc{=7V9SAX(vG3kYH6I|FbAV&5^}R9YGr=8Duu01; zxOH99e}6JGsM;UbGPI^gc(r+(2GIabEcH92yO@J`Q@i&8ddDJ}2HXiX2VO zt*Fq0g9FF=uH@@=P=$~AFrAGHU7tou37O}=PoD2pA=T!5!1MfKy*vKNFVH7K&0$V_ zDIYWj27RpQcj0KqBeS#Qm^UZOgH2za1gKu`2AeM$semNHP-cRausIT-Z0$50AlXhC zDC)a>Zd+MV&Ne)#5H`0Qm$R$vmAv&ZWv{SGhO7>75iC@D@l|>6vU#mPt_>ouzru1h z@8Ich8U?2W(~rXhoq-^MLOjg7ImlcdPeslt6K&o^1A4W;1N++rJvvsK(b#WDOn+f5 z%z$7s$e+&|{`{W27d<&_Gucg}Rpjq2x-y%9nf`mI)&R8JeocXg8YT5IPm^D~l@ zYNZ<#3@i*k2fGC`X+T;IN1qf)6<54#B*jR^!v&3Iok(=69G*h1Vm!-(^V%j zb3^@i=G+6cxFOe!pd`(T>!2FF?DY0a!yVz6_hJ+8A5{^~u_bP@efQr}nOy=+Qo!q_ zva%{|gM5;%eZ=KoPunz{JJ=;H{=orTxzD~8%~u6VttV%{&(@Bnk7B6K&i7!%T%Hg3 zRabnq99LY8)9y14yW|^7zW5-LmmFP-H4MIoZuvNkJFpU>l`mC;>n0@9D?T>W+Rd`^ znrCEW02*44(uX>=ucvoHdw3JIR&@tIw(g&%4LkzUHMbBuj-ZpU1fjv^6p%>#2?{bY zvvsieivQq=*z?s4f>ak^rDG;m4AD?%(3WEheK&dHXTBQABCo;A!)#J*H|E@E?1{>z zTV>^I7HsW)DnlF>@G5L&JmyvWxbJEIR}Hp@VVWn+!q~eOp7w1?NzK65iB%8Wh9wLv z%xbd(Ua^y@Aw()51>u_AYY6xO-0c2)8 zaytVsZFm+Df}xAZski4)8ogQ^`v#k^!2 zT@14EPGZbDERbavbzv(3-@2!nR1?}+lARD?n&90rloKj!Y7Nut?~D(j6KtFIEBO($ z`(5M-qFmsPlRNd?c#c&XX}x=#CPk~S1` z$b=PZbm%}!78<|FOtOS6@wR z5WX1W3Mb-)(MZ({CAWgNJYLUln;&10Z5y+HILBf{Ps18-;Hth&^q)cn994E|j0J`v zxFLj|HUvEtCYcP8OaJDRt2xfzcuN(nrhZ9$6Qc27UQGge9x%ym`orME!|uy~F0Au4 zd_s#%PsWU))U|o0;Js0L?lqg~?zH98b-*K=vD+$JrlY_DFslSIi=jYTlZ;{s=H{aW zz%MriOhe^*HNnotZwl&OQvXmi#)h)H?cUX&jY+|Dk1V?U_4J9#8`$zS2a`nd>6UjE#~^H%(1&R|{m7_?Q7>}Vem%&=t zIf;AE#BJ}KI8hW$cGC}u%Al>M9Q5X5wUUbVQb|*iz0@F8hrLkmbKvskm7=m(AM{aR8xl!xlzR0! z5FcBc{ohONE@t672bU?TE|>5P=FN2NqX~K_Q?~_=ZL92f!p>xewTb`PNmBr|@73TJ z$~SMs`}Jba(%E%TVN6(<-pNUmG=M%wvEGrG;A`9ExSci|x~`V}06PgYgI4SkY(sU+ z^S^Gnk;VU*l2O9$%+JXB;WC5mxXbr?MAiJ<;S;e<;s%GHbmci+m-A3*o+;Y4pzp^I z%#j`3d$^A^e~X6CWkIx5XmtM);gM<0kR;bwOwq304G5keb-o-uZHcadN)63ieM!C} zSa!xF;l<`SJ$+`PMF%ATDHa#-d7Fv2jxG0A68FPuf3K_jz5(jX{Q4O}n`L3vH5bvI zaohDA_hMVcQtd+>S%qzs)Gw7qDXQ%)+6A4R>mS}k7@fL=yFWEHb>`l-L&g795W64d zjVFNh_M1RzhM;MzDt{VV2{$){TTLnR54L0_oN;_~`@d+8By>*4!ynFk#g z{m(S9@-+74Z&%}I-^b9p#&Q z=r{5k9)_Z--uz4hn~xo@D1U>+ZkCr^;PcLJzNW8>mg)a0mjY%pUyG1mt8!zwSC{ae zqk)mz3kSSAX~hR^EbK;~@kL+)Pb!mP7+s3qMfbx2>l0-a<$rSzpmvk5TimfEHc_Zs ze1`^VR+nbm{h3Qb%@^^mm4;DDK}s~PMzO|q(QI7&3~pTLQ5k597V9oqbakrL_k*wE zy7yrA&0c)DU@8C}=W7l++;72`8E}8|WqK}U^4y1-DNW~%E`Q3^7jD}u0N72$+K-37 zy{$dMa4xo`ldX*sRTM}cdNJknfc!8iU2VF`8l{ok>ysy!nGmdCE6BLg{L>$rABkXM zP+u#pXp2uHJ9;=`!)DZZv@xV^;`XVw#p-!YXk4NEU0Kdp8lRzeKb@#U#=W9K&ub9O zOYrL}UqfEV$<~4|aC-w{|DR1;8-X#ZT(jXWhE!PL2XqWF6or~to+n7;4Tds>mG`63 zJTMVL7Q~SBy*;}6o>)Ym)K#^~#-U91eL4gWQ>>Vpyg!+yhKqzH4JAEqp!R63yFl=T zbytOJ5Q!niB-j~qH+{I4#GY0W4-PL1{0`K+2EF;a`^7(7&F|uJ#pzWbNe8Z<42;?O zQU?=~8dqy4n%$ym)4mNedg>CFC5}%cIW@JYjU+Y6VV_QqYMZ6Wd}m=BJgf-`)M*bI z!q7E*;q||q_m92pylu~MdC>P%kV(?KLi>Y8D28xdYFn?<2a1uUZJ@`WRK??EI7f$- z{B^|nvI!i+?Yt-Y+f@(A3ZVfu1dF+8ho)|=x}|jYIur~foL_e*0pQY}*dwC>^~?0v-z!ZV*vp+4^>t8Bg@`|k^W z56y{{DJW;7Ne@F^x~$GcUv(OfI~XJ#2{@ZV7irJG>HPGxo0sRG5YPoO0TaU{aB}SL z-;oHe`Qi({ZV1E#N>@l{kv&mUf0nn%>?elXB1pAb5Gt(FE9T*e`ttplnAv+A79l~i zc{y4SS%|$%zF%qoOfKm6`Y6_HjvT9lPKcoW_*es$FP!aRBO=Ys*r@b5 z+YS1>Y%|C+s#{@Z^9d&!p1h$-T{FRAZq|4{_;&{Bp~IQb(SZkpq22Guxa4@sAn7fo zL3*B2S*0MZPha!%X4!Q9X6YJDgt?XEL+BlvY~PainUXW)8?vi^5okR?R-K^%xW7Wx zyckdpbK3)_7o*;;D9#$l98~6|$10kB^gI{_9uPrzowjVNc6f|(lz(grx+WK#iZhRK zKG3N_AoT3Bl}_pR>2q~^joY~N zhxJ3&HPV<4`ugpKi%KTHiqUL{*A@33AKl7B+22vo?Wfkz0%4;Pz0!?)iEz0vuO}d0 zJm8%Ay;6Fu!WB^(#tP+xDII$Bgcufk8n<4Loql8Qq8s|BBP>f{+rBpFnT z5`+pGDSW(yAG|v0A&p_wpH1cSI8sV(%0FyRU}55_cqxUsKT1WmT&SZ3gKP8ORF`N; znMs_NxICLAaKOMwYW@EMIp3vWXZTe2@#%#Ma5;p^bh=JTa_O{0!P<^~&} zqJ~o}fOI7kq)O987UHPcQu=Ptyj-~CZL^s?Gm73E!*X@$luKpMMeNKQblHf1JBi40$G8_&Q&#YZ4Amkbt)UUDPI14y?yqh(7=B{eHF?e8m z+rvz+C_NHN+X2OwqXFTyK5TgT-SG4AXLArwX-1vION^`s?D0L_zTWGuxXl{@L=nx3 z*&jM(s|Hu0(m~n_+h7l_*?_rAmmIdDOW)Nt1l`tIT8E|!-@J|>*f4BL1Qt|QLRI~y zxTcO>4nWxY1bgN^-?~t5N|%}+Sk*8SJH#tSM$-@_Wu{|;Ietmm}WPXbJ z`?~%!r&R(UW0x&ghL~oN?{HMAeU08f_zwWFS7bp84Fm|1FIN*UA(s=YQQAqRks#Kh z0&@a-(xsU}ne+IAb>e;M*FPr#H7AIT6A84TJLl&bz+t`hx~dsGSCVZrd$-~|%d4Cu zoF$nM#?x_zFSuO)k)thmME^|^``cCT8_m5-MMXdZAhi)R%*{xLwhSEInA?s=qa33t zK&mWGA>^C#N747BX7jk>3Y&9l4Y`qL)h?O#{97RXs6w5pCA#2Q*|%>%Xv!2gBVR;F zp~%3^>&8i$Ko$c71BP#7x7#{zw*#390yy8yW?9p?jDt%E21K9}mpL-H@xmqI(Nw@oPaQVJhKA_t7P<*Tqklu~)JrV?bv{~>8 z!@igGQz9S);dAja78vLC+!E-TxV-JW{7AKJbml2auBsnS6kI)9e2kd#4aO3Yariuj zIsp-aQ(u>%9i&e7=8l4rd^3B!HL~-iwR0OC@EXfwQ-uVp)fmz!;~AWw?0VU(GpTB& zs1I#F;ji}AP#W^91`m-T1qTm%~mi3ukF4VDh3X#o6WM;cy zze8$tSo!^_NU=MZcrZdoX2n6;iWv!3N}aZ00M=GEPsmP_m5AFm#I`9>zvtdMZ}@Tj zMPLNmFMP9v^1B`0gV@-9kYD-n+4i3qHM%UvYL8pW+CMm+64JI?^zhlbNK(^|f`*_8 zJ46}=;JXB&W+sT3387cARa3*aBuzCSBt)ps!n~pK1v#9oM*jnY*Wl?k3+(b5xe7DhWK5CFEuwnktGZraELaWOL{S{Ln6Q3qkdg~F^ zHf!pKAdJ*{LBFz^s>bONbPbtuhg{GfdDF*X&6y}vGg29p1tL$OuVb;rqxl?#M_tjc z8wWe(81hFEw&cr7mn_t%?_JTrpB?%_`S46|4rFd#J|KV!L@|T)9?0}U_uZnG0t4X2 z_Ora-DJR;uxPwL|=>4=~a=oeU*J7?4_>8C%ZzTG}u_Xf0;8caLF<6Uuo$5~D&^nX| zlMz+efgMO@oWT#X)KqK7el{-XR3Yv*W*&9+04w$parF{YO%l6+UN)|Rl<=gPx2tjl z|AlgE&CSpYH0=s~io$^BPCJlRN+cJK?@@x&Cj*wL{e{WznyDJl$ynR{|2i2pQQV?A z;c8pXFl5dBoWIMs+>IzE_!3RlV|=%3*U|B-9ut`Ic|JG1T&UlYm|#K(o9S{G71%q{ zAhyaR%~{>0+U26==;=nctVo=mq;{WpBCl=OLYeYc9eMRQw?Uvkap#bC$gp&D^7otA z0Yk4(%bk|X!1^*P=N+xyBJCa+GpUN`yLIgDl1i|kU(8Whtk>py-*mbl}as$`CuTpKPlyqqdaWwL#{%GjdE z9^6oW=mwc9H|Pik*ahuRbA$fLCjL;a8ixzK!!aaHHnCD}J;e^SERptLdJt|;>9zk%=@d`OqBhDO?lTZ_NQ4Q9&x4Mp9n7NOd)%)vCNdGN;;)Q?5cq`ll#@_67)=(u(=S!9>G+N3eZWOVs=ISG-ucZ|-IhQ!%sI{97^IMWgzy7yOjo z$EaBGD!*2oDnMf~31umGM&~WK=gd(LoI>$rt=F5MS~Mb#5a0S~9{>zx%h)a|r*~ zN}}Z**xj2&5%{-8(>csXg`r;oXB(gKmjrrL`8Wz1yPZ!8IIeHu_KJc=7tIwG7H?w# zJ}e-8acYknb2El$st(eOqQK<=w9>8`#8bev1NJ^-`T6_-5C|ypd_C%Xn^_i;PbdJ2 zBvXMjKzd5_Tm!Wz$cZ=(p|zu&ma|z6^~;~b1_v{M%tJf7X;dmAG*vo!6=(OZ;|p<< z$lvClZ=Rhh8w@ytrC~euj`tSXiWH_(0Cf+g*SD8ZKE;zx8Ol)t2a|JuPy>VT&6^&5kV$TeJ@T(zGj8H(j@~(y16Po7yC0EqE23I9N}o%Cj=SO7aEp|cN-js>DW)L z1@9NHKR-VJ0x3HA_!b{^V-9*%Jm2-a(DgS}+IvqJFw0|)#0h){R+K&+XQx3(A==FA z@^-P4WV`nvD*db2Vk4VY-)5l>1-$Bom5eyX3JlcYeFmW8@5n8oj*tvs&B6;*rq5^8ejw8s8(X-pOfRVriA{U3jc+1Sh?q9(txLK8tU0kNq zeW_`1x~l3dON>1z@B6tlnLh|$9s9o=R=tEx_@25@kW%$~MiIQX;tMJH@gUKG^P}(k za}Ac2px*Bnh9f!S%NvgzEVjQY(sL)_+j2vqyG#B6FWJCe@B z4C#|5$4m*1@8>gZJ6u`sz?#7A-~PS3LhJ`o54k1+;NG#F&pS+a%WA&CfL^pvJdfT* z^?gle-fz7&YJkVzb6`9DN4;EU3M_AKNA`-KIJmlUu3CSK0Ha=KG>8qi#Z0TD$r*4z zdcXa8C;x9*yY=TfyXM!!p5jl#w#q`8Q=6gOr#XI5wToS?hx2-TfM1+X^9$(>oNhJo zub}9PLaJMxx&76MrXHdZEt@~(VjmdZpvy4E1tpO(2{EP6k883Pp((QVF!#+<_K199 zLLq>BDj?9G1lGg!X%IfBhgdRKJw_Kgd*Pk5%a92(3{Exy8=?;oFnzZA*Kc58(1;AV zK(yFz!o{zOU!X3>XO0Mx5Q7yz={TofYk_M0Wp$)QCA(WIMn#Qp^@n*DX3vDW-R;H z-L#T^vojED!t?g+Z0yU#5jDl--(x0iaQ0eJCSB{erF^QSidMNR!$W;Z4S4WsM+jT| zj@o18!aVHZVX@5=oq?v%K>KzK8}TGi|9-?3GLV9%5jAarPJ z7e2>-M208+m+Aq`Jt$sOVQOlr)H|qCRy|5Ao!Gest7GS ze9)F$m-6ixUOmBx)zo2$`?224l4mpY@g-5QhYqVu||( zHQ#*y`SkUr&c_!*`<`C+P&-p)`a_Y8cWx|?7s7?9lf>jP^Mmz*U6*#KCvL>mn-3;i zNsFi*?5EPum3hX!1)-~XQP>`NTR)nn)D*W?1#z~;yhj>H_>z$Nb!w?kojC;u z%ou~;!;e_RZGf{J(`Th;A5j;3AI)!vViv)EU?3L8{It{(Adxdg&eSIucR%ucHYijFrKoyZwylD|%T@1_ zEF~f_A6q1|LZ9>`QCKN6y+)EA ztC=~dNJatVkiQzI;B<9NuYyvTkgwjSr&RVvlNpJcAu~vujh6)kfp8*xW*CAX9GDgj zpoB`%gvb?uw3LV}wUsQj3#xTCP$T8O$H-Wo-V(g0ymPUI8)%8b9iWc=zH@K$wUj3} z2@WlU%VqeK(|YjQUNGw5K@Ih-i^A@o#YDa(Tul)jW$43iVTfi#+eDm?1swjzYSlh1 zY6WvBg)IZmz^(?MvCXoy&@2CXy{%<_uFgj&nt>b2cW=OO`9iGMlt!9e^*OD4vFFfm zuvbL>qig8_EmQo?61DJtI6*|t8dXVJ!Q8?Ex47_F`|avPohVrP`Z_T&i0OO20)(cH z$AXlBcigZc%AT_w=gTYZ&dr2|#9sva-vlKb2hhKmC12N;FcEZ|?>01gnBSAiPTkt7 z#%KtHnfN}JdEVbcx8f-*0N@}`seD-`^%MaNeppIv#&99>Lbd-}>o10*edja)+s;Wj zEr~WF_ML6s3v(eW{fu$4a(zOmfKF2>ghzxgLOF70wViOuw&apL|FojA`5M<|WIQb#XRDiPCPFmIex9rGFcg^AY+q$T>Fdp;)!g9rC4fL@qaJ z=#$1&sImop@`S9+l3(*nLb_xW&=0b-A_YvO4NstpQ#^6X%9GH?t4B)HGE~#P0_mWr zw4ooe-F+zyHLTz?TXQ?hqv33U$^^Rpr9esA6pA^75RrV2{LhFrP76u3NXqy!D74); zcycQB?31{a&(NnjCOyG`Epym+o~BmTB)+GVTa~-VcJzb94~Erw?f<%+f-w_(uWn;I zt3HfbHTU#)`>4;;j|pOusy}_5lra@_gH;tl=5~fLVoi_JB~7c3FXGFmK6MT;9M`># z%(g7`bF}pd2Z8l^h@YyBnNZ-0V=ZY_N%h*}l&V_6d|VwEtCAtI8kN_{R$+35pzkCb zw(<0_MtzE26uBhOkAnZUhKE`JkmZd6OX(kgF%est1O1^b? zRNsyEP2)Ed@^m)48o(M8#gKkP(vPdZ^!jVS48!iF7OZ-AE1`aUv1DCNZxW{aPOCCd+PvLq+k_sU7LOU2+$D+L z=sDDJNt$xDelD1Rlb2b%hu*@$Ij1I)$6c~1KAh4!B3IO-7BCus{U1oN#9ze#n~BUx z1U1TjRoZzyF#6@RM>e3 z1)x6yOO_-&HCta3t#dckTQ|RC2Bc&Qz3syhI;Tr@@ZEm>n>eaPQ81F!+1{X;b?We8 z+uFhC+C<*tq6=Vdu&j}~$1BaLBats9uk-Sj6Xenb`A&F@=OnB?T+q6kEB;XRvHDuT z?&87%!W$Hm`Xx-<&&-f06=-SICMChy`VOC(#x9(MZ4yim;y7^+NkCgqR`}%IGJe|b z)BJqex)5;3-C{`JD>CsNUucB49`|m*d3ZDk@-8Hd;*>%3{U}o z!;6$ot_x+qW@yRHn@^r*QDzlXqy#o^#7ERkFpChJP`hwKF>ARQ?2AH9GU)L`#&B3= znTco|g2wd9#gpj27a{7~4JpfIkpR}m0Tz2fp++@-skq1`=(Z|Kdem25rI~u4iVs*a z6D`K~Eo&N%f&&Sbq_$Z}km28#_gPc9aW&Djd$e>-gmw}=h6cDb{u2e?7&=@rW64FdEN91+W%$3KUO1V&qGoxA&G83Tqz5s6q_Ii{eH7i&0 zYLE_;97yQgFl>`;=8e)N-Im7y@7fMsRSlgyF>!q(F9|Jfuuz>0D7Z({UUj1cHMuPP za$$kr4a0t1BL1>6fWw}%4da368_Q&zmZAiK@5FAjBH+R%A=hFjSQHiM`HxBX1klu6 zpsKp??RxZa+xp{Q2Q?1-*o$1Jy4J=zQ!CfJ9gS{FtO@@Y;?f672Q6e~?JkvJ)6T_{e7X|#9y_@#W@ zUm)+x`Sm^azuzltkcotfib;9JO@ld@I-i6f4$KY!ohhcY3*ZL4t+ zAN1_G3hS?56J8WCO_a2$L41)o37Zte!V_54#4sXjo(d`gM-9!{i^kREk4sKrvlr9v z_xxWk*!g*aFsr2#EKqsXZCH5Tu|=ZJWB}2AUo9*aB8v&p05&=ihfz<#616cd9(-wy zr{X69{$-l6MtqMWp>X);w@8X_U5hXnUCQy_WeLX$t5O|wAv2(E$1GT+up(kqKW<1d zlJ$xKaPwndU*wr}srmKrAmA7__H13qXF>*xjv-0a=q{;GQ ziYVmi$5P5OozCSwstW>ebsa@QvD+^UfDWeW>%5i^uIwk<&~M-#euD%Onc;8&48{Hi zV(_58HF&iB_Vae)i6|*4d2ypN3qEf*n$2StQO!rDDA`(}tx7 zr;YG=!_Dyw9aB($0%K65uO(Zi*njx9m3n>3d*xeh`T`6q9XHzQCPJhmhlEbx+u*jf z@NH;HwH3W=#iUFEBs1SC(EK_*WYZ5A5s|oD4A^nWd!&%R6<7Ma$jh3_3b=f#2{qVL zaSWzx_*-1>esg@e2i@jufW}{$nqT>sF@e>xZ5AE_&m0-p>sUkL`hfAoD%#|}>#>w* z6l0FHzBlFYlVr!7a;(avAb$c~Ag=eA-MHV$$6>{{jjMl++^K}S4wH&g8dxBoeUrEJ zqY2?A2&#VuYmYRlFk+pM>*osiUo~d2{#1d`>NQ$@%(utUj!YeZQ8}SGPtdE6oMM#u zf%xjvO>}H+3v7gfITku0ZaX z{D(#b@X7^!-qWFA^FeX;!sQ>WKVf0asfs|wu-8!c&AcG5eM-^eg{$00B+i8?4}Wvy zC6nFK+YZf$`RlX2$skwzC2{j!6x#up4)?E!#NX@PFn=O&_m(E z<0$rCkSPHS+Y_VY-NlKrnwscaTNc#V6OpmpF|)yg;lBnKOm(W`g?&6&TSAAmsA3aG zyzpK5=!n`I-x`!vm8*d;og1;5!pCO-oC{mNjI&11aKv4qtCb(W?_Nk zR?L&DY29DcWBnBdNI14~a1M4a+;ol(g;D#KawiqZuaZfT2bAe~)&O&P#bbW8?RXm9 z>+)!=Yao_fzr}*ZK&gN^zQZf)K_T~}V{>R#z|lvsn;m@RIdU2Os6VVjO`0yyXZ?`SxSi)Hl5IVvU$tsA{&erL$ecD~($9k|u7~1W-0BeMrLoRdOe{E4^XST$`9*JmIgqw(o(BAvBKC zX?FvSVF^4?W)V{1q_A=2q6!66uw1%EUL5P4yYf%l)~|ws5;d^^>c3QTgl-`5BUOwP zODq;#L8Q~aM3z&pd-1lHhN@mR1f#H%^2#x~J4w_+?lDckT>4MhapcDIiFi;(Lneuy zBA0?LigxM5T`;d>e)CKQDq6(^;yrT9gRy6*5Go)I?_=ymvDpnECO`*nN>XvyyB3=O zGpo4|>$gVrk{EA<65u;ahg+nhxcY#g4V^N#!YhrXy}Xx$JWqg;;d$G-KE~B~LQIir z?8VHG3x2Quj#Y|6Rxiiu8$pu0s5BA0K>5esf2MmxV#BWWm*@2wpwO4YqAFgQA1vsP zwiU=$ZI=|fUt01J_X&8l%_x{#I`w0WqD6W{RtNr%&%0nHE+W;cA2Untqa~kRkn9LO z)TTcb#B_AS8q8oSKEs~KB^NXd6)82JN3k(Clz1JFQ%#FKQFOQ;$7AK^?#{j`uhCOO zqd@>DLiNihyFm8zEmw@3G&o?aEF@s0>pkP>J6p}84S%MZgsLwC(rN7*&%MA?75sep znFet~wmy^~Fd%x4<|7+ILD{&&(4`IEx5>)!S~t=b1yhY_S{@s6DgOSenOmdFp;(h& zn_ao<-m8E2^j-}t%YUjx;xQ<|FA;Q?ZKVIyGX)jeI^bQHYiy+)nM_!oJux6P=7eMZ zv}lnzOdqxgOdt!QRpHGV6HpXJevD+If>ymeRNYTEb@l>z%Csd9@*02Ks71*?3%x8f z%+bnnYFf8G-0mp5h5NbEg7I+XQg86Q;#y!7-u=p&_urs_l)c8Puslk1y7ywPoUh$F zomlE>UicR5@mosf=ktTgLNVYxP7RXv6>2zdjUK5H)Xo;iB%i7RcB&*UK$I&Tx!fv~ zL27oGC(ICacDH3`v8daNK2#s0S)m% z22_5#Xwm7M#Rg?O+(JXOyQBMMvnbmUz-UWR7TC6Dx?x2AlVGL%u{agBx7kTNA1|)E z1?H|sOqz;|MT_a9mLt2o{bso0@j_~VK7H=;ROV${Xz!nEF?Z+@(71rDGQ z|Djs}vnzS4S)z22wB;w5TsB=cwQWQRO}6608L@zU>WSl(ez4yJjd)%Wn+|P#{3Ip* zHPZTHH#VT6xyidfobT*5U#2V|l_RkK08kZ1*_{Xql_)jY;MV1BRgxHGw6rKlC4k#~ zy1n>3!6PQ7TzB$7uV|JKrTmNRDoDiZQ54G-8Rt+&K~%EjXlC{03qRRvp>dT~)jV*t zfs1%+Sg2aK`1S0wfK6kTO;Ky!I_bCEbQJQlJe3^J1 z7?iwl0((C3fR|q>w#SG}vz$F0VoGj~HzP~HX3K@~wN5i~4@8(eViE(;*IVMdBQ?L^ zGyhi~vA=hPVs+MnfT>d`Ui<+C0ED^wpZ8MLUS^g|^}~(MmFH_7ymy-&w`QC3u)t0F zjgv)i;6>ln$V3UPdwtBi`wd8>vcI&Z8il*__}+OjlDQ$M|AiAnXKf$|b@rMW;3>tx zu|mxr7mB^)YE79;*LHj+^F8J1L+2N&!=oedCwp|tXhn(rbJh;1lQPB$AE1@E-^VDThb7=8kI?S@qp~7ViRV(G9&2HPd>ZMN5G>6_Til30)9iN_x`l5f(At@X;j^& z-oO&V5j03>w?Sx~>T;hjG&ekLdaPzj14593hV^b}y02(%=Rim&kT95CZI#;$2~W&8 zG$XGMt)JFZ(66UAAu)>}g?^Ox=5&3q@nl)Q)$vW)d^sF-U2tNJ22vQ3!ZvPjlG;ux zYOFM7MZwu0bOkneimVJsYM%|c7Bx+Rqr{TJrzAXSB$l}LHr`O=LVise{ zsSk>QCn#`x**@^1RQ`7#;@6+su`$mUE);vJlStk>#O&|oLqY4gIXl2-k3<0ABeZQ1 zR&Df@Rhk_flzck}Euk)XWJ8!$G{8N#47Tk1M{M5$ThBUxq1wZj=99+dj3}cJHG7r9 zDe73-kp_eLgQGofzSe^7R~Bw1`&GB%@&=ii8HEXG6dNb>ZIv(K8DQNgC30qZLwtg= z{22|bR#b(ZElR1sxBoNMjxgwxuU!(5*OH{>dzkz$PYH@e*)wqoS{`E@x%@F}2jT2m zh^==o*n5-R6r*3MzG}*AQ=x$ZC{j;!MkARk42L%gXn@7o-1@}E26e-W1n{Ogkrg%! z7(|~vV%%T@#oQ!o$?wOYWs65C)$bmX-@3#l^;pNFt~@B7qyP|)$%KiAi z)TB|Zr!CRYyZ~^aeEi?;+kgb1R!Q%;Vvu+~P^+^(lPDohNSBT&`0)`>Gj&vEP9sqZ z{rUMh$7NhNC*V|PTo_6*SE<(z{3&S|SX1lk@mx7+@2uI9NY90Ur*He!b6ohH3E0?K z%)LuZ6W@^6=hCM@I}l%A4mo8Ac+mk-^0W;<2?@!@vCFt=?UaRuMTmR5lm!QC`~npa zYV-{myVm(r#3)y1&gQ0R$6Y^H?PHC+ODcCfWa{g7?`4;PTzL3myN}?%1Up~foDOF~ z$%*b$M+h{h3hL!KV(svA+~{_-cfR8S)A4@lbIcnFj1GBQ{nUEBz6pe&R2wv z6caj#xu)x$J~9Dd4vm6Nm6~A3Ilc*_xwsSRqL0gcI~9Q^9~S%_+^d4Q$BfPqrLD-7L#Xy<3K z`<-M53CmdW_tF$vlZACi6M_;V_CDc^Yx-3p7=a3{KH6D)zeUVjiFXdG;Y2!bB{&a* z%@Jg1PUsnV(wJ3%t`yjg0vh~P$JU8>e6njIjk^AwKLqBzbjmSt&1a~+rz=wig?@tw zD81*9lk5qgPJBO_26VST;53ls+{5j<-BcCN<-3XgPfGqYe)c4A=6S@$z4$}xFMJqM zSVm43q^fF(Fk2}JLO$En)z?R0ozoJz{&KRu_lHjvs+IRZfW6|ug$Y0?%Yb2^!RsX{ zhUBoHz$hC~wGSAFG>b};dDnjaLo5~7O;}vYzo2|LEKz4SFOol`_u$q^Dkie*N=KXcCM2-p zcJ}6JmPulqL-L7I4lOFRKg4vwjaJl5+2u`u`EPbb7wftonJ48WiJ}q$#F)ns(Yw1N zBF{5kh8PyJ_55X2#%;&zE*?)(&)xH8o zrOW;*-^}4*5F`1RAv(>Gr6=sEwT}d zISCApR7Y|3{#To8PlU%y&+^^Ayo9otNdM&EYfk9}YKYS|SB&9!i!LW#iqd{9+ttS{QbRxaC&vJSeYzR(|M9_EceQb8PiEpXvoKPo;bFwH7qo$3~op% zAi-y#MnpWBt`ZZIxa-FLD-Wp5uRhq@u;HMIO?|wc+IfAo*e=n%s}glrmSfxnVg;bW znM~yqh*+%w$-)(ZLTbG{io5rxr+!W;?pmN}eg+3wh-qJ6-~XWLtfJyLf&@+(zNyp-?K&W2gwScK zigmzXC(zMMp?rnP#3LN!MR|k7nqG6P08_HBDD=RJk~xU^9hZ3%W3Qux_}IvXp2`5Z z9wCQ1iimJ*)!slerS553^mRy<7X7S?JR-GyOTgrQ`^>+`7>7pXtzu~GyK_7VeM%mA9~bKrk=+DjB;W60{U zz-tfM-#>I-jyHY0%wim$p!mx3ovlU%?hy(^(V?jd4a0oI;8@dWI+5q9FAu^cD(t35JI-K za&X7V!?UE#dR`Ab#|9+zJw-&|6BF+N>C<~fkt91ud4dE+t#K|a#n#uoKn;_^#s*eI z$2^Yv_W}33-Voo7p|y=W9+kEFtZy{}uts}((_kv{CIse>2K=%uDVh#fV+YX*4uV-d z0iOHfvh?c)$EkB!c?ukwt@b09>xcRLWkCS;V`TB9s8@c53zj@C>fIhi`qth z1L3)y+gj;$dMagGZhSQ5G~W@3KR~ggKppCRV@?!#!+(G1fH)tcJHnFF=`j8z4i-le zZ-~M{riL>RXpLT&fR>)Ck)|NEn$w$Jap5`0YfD@DiSwGcA?yDwo6hdw1S?IKH@S2q zX*Evgx5p8ujlzOmvK0FqpA#bo5|n{l2AUaDX4Wmsw1(8ytenI@^_)efHgQn|L2UyiWMg-cY-VXwWg(wfi2mt=co$CSJidI zxK6K30Iv7(#<-FpO292v)NJWA4j_2{ahcx{O_2V;)DMGVuv=G{UA8t&R!Bxt&gRdKt|OZv#B9+Ec#??#^Tclt&3wZGc}~lNlZKJh zyHqNTe%`P9acig%eqX_DYO{V^8mfTp<1l`*#>Yn5K-x#dS z6evya0{@Rb_c~hf`{cADY~)c~H1xxRdTGv@&_rKqRjipN7-LnF$m{TIdE;%7HJ~|g z&9jbC`2*hbPO1ndMijD5aWrT6jpENzFN?&81pdshG3~0Ar~Nk9rB8vFEe?#|rNfi~ zCWivc zl)M8sV}pr(?|7Z|&p*;wj25F?4Rgl|Fw{UW&8el%N?al#@|?yVM`bUw=kL&@UiZHG z#)eYgzA|*m;k3}xCHCLDLU=_}5#Z*j%yIKKT5BnV=;aPyXp?lG(xFRmol0P$j~{Bf?R@NQGZ zLI(JUZ=Th9Twn-yrRxVlZSsAAL50d(i!bULMP-9}y6Z&-Kb*$l@tkkDm({AYygW8V zWMpO7moQ{8;p@VZVt(RRV*m>W4gry169$Y5difKnjYcMEkX%Y;Fm>$XBCvaUe`9?Q z*EMmbwoR|;mo0|c1R+aoqeLfCVT6d$!xX9Enj=iaWc_iWRxv=hkjj~_4Xs^p-V7}6 z6SVxmzu`*z_-t0IoK6uZzPBrGketY>NG9Z0i9wI5Gm+~%LSVPvm{z0^e|bqCflgec zaS>fk$U;iNU2W8wyZJn|xes|eOkDBV$9+PvU@(SO<@;AVP4JQMyIb);3BJT~M5r+i zMY|95>F=*Cbr(m04~RQVWopdxx!F>)GU*kY&S-Fn-j7?dne`9h?^!N_t!`rlAOjI&~M7RRO6wQkgmBmS@*_ z3STs>1SVg{lKv;3j=rBUsR9txViWRF%MJ@eAC93%U@GJaM>vhzy`HqJe1 z>HFAqbuPZe7&^@EaVZw9EiCL0k1y^wA zlVS|B^E630|E$d6Y1%t!x)jFC(&m4#YC@%lmnWiJe9_Nc_g!=z`R$)MiL*51PmP?)b(>*cpg&7#Ql3vtXn_V({EooqY!3$nNtr(yT91$+IpVD|nV=cOU zA-BgWMeBBKJOV0&v^Xg6t5Y;t4LB&$Vo7BLSkYL>N-+}ysuh`s&6omW-zPMgjimF9 zF^2fN*t5FOaZqq3Kcb30a&YjBq`OX2k4dYh{DQU*7(g_O%2pPtVOQAR+g$v{ zb97#Hd6m%<=U$OJ`0yM5`A!H$Y)kMI+w9sm3a9pjjB^>`@LT*%W9okGryksJ`+D56 zG}mg^@|-(=jTFpC0MzlvUyUK#bZiL7fjs;Rm(hFT61G6qP+TZx1!KSZpa2la#EX_x zzX~&anl7uijw>pQ*$M5u(wV=IVVWBySF>biNb08nY$!xd=89Zg$*cOm9uVH8P*W)A%Mv zQJo^($TOsnp{WniP>4-;nJ&v{y3Mv#XI%cW8^@IlmqsX$HUDk&Avm#N=34}Sy+H&P zSm$qN=MRH;ePTVvql}NuB}qyKPft&BLn)ecs{6U1+2q&bj>MQ1(VCWo@t`t|N+3ZN zc&k&%8`b(2dLJ8ZOne}HW5fIGROFfoPq!_1sX*WDm-4A?4Un5o+Z;Pr4L8fT12eIQ zUsfVRHEkOcV~5|@)Z|u_?K9m2@+Q*@3UFy5v%eavyKL@+63IZFWD*!~Tot48pFZf+ zm_TGjUaDTs&fi!vK6@b<_%>%x)t>bu$2W4;QiUvq?o?Lv=RKFs^A=L^7GAK+pfz$qCY1nFE3t`*=VC#wKAsl|?XP4e!x2LcH`06gtJo|FA88f;XtOPJSJ8VtS zg52_RV4?7j4?CUx`p>SkPrR-vjSRMq6+@|VO3JxGcfC`4fRz8ec5+f&$ zYrH9xfYGx4fCE%r#>eEIFC|K7Xwa3Y}2N20hb%$M>S@&$KvdVGnf=8wx-ixk#P*w$qo3`S2i!Yw%rZ*mt;!OoW zloozG7_bX-hf8eX#gb7sIDZLA2lwC4u1Yda0l?8*|GSmuRr|ZMwNbYol_H~JZf@mo zsA&fARLaRKcBe^?Q2iaga%&c5ZusI&YZWf#Y3vBm$5j9hfTp4xpOnDjcqK!f9;tX{ zr`Z*ra%c$k!v}T81x!%$+ycV4>Pl_4TO_n|?}&PlfjI+$^-K@I)zGO%l>%my7gtnh z$+iza-6^_^ZkeB|Z#Dn264hos9H13lj%f|gFll)Nb=!Jr4t4U*ZulGANB3Vc!*Mg< zPnG`f+h#tJK#tkLgQwI84uU>O4KL13KBB)3CbCf ztOn~-900T+GH4R`;`p#>@`&}E4AF1h|k-2e>>A&Zm zX!c4OA7@MvZb)D-mcZAH3H$-8L8I?B$M8@B?~2<$BbaJH2go?#CGTFnRvvRxG~q`F!_K^4=5~QBFD~4ug?WjlQy#3i@aM*9Drm=a7@nek| zhKkIX2X2eJ3>zcI26PgQ=L>yz*Oz- zM!{NAHMlLo0YI+Nw;yQ?3O8T;`JuK(+J!8YA1l#Zua=4Twx~vl;KcFoQ`sJq4W!aZ z5j@Qf>)TOr{6=*qIjq}OQ&9jp8>_|j{`~K5XV@XxNF+o1@`_`JX#>S{sxJe}B>6vu zm*ou)*>bCW-!d1VGrd(n)ym0wO4(m)ii~~$Rib%~96~DeGw=S-iCgRXd z4?RLLJPf{MeOpZP$2ZC8`smCKue`}rO9BH1AyG2BRssSN%k!pZJ}>JSMOJVAmPRrM zo+RfK1(W#XZOR3N3`}3>4<#7l!B;WvUazom&4xm{q$R*mo18KgZ1ZuZT#N!Xl?6jD z7B8~cL`o-)goUakQuny}v$0lX!i=u4+Jd&$*9+v0Y7fCy-E*4T$7$ zI#De!+w!FzITrxVAXhc;Y2NQ~(!}!X*N}lCapZ6q?05kU#_kYRKJM@e6&4uYK;*EK zxgcp0=o9}FZ;~mWJTB!+{{p@kc8QBC05LA>@W4j;l!jjKvf_f8&ZTSwN9{SGTx+mS zFO4^flwZM)aMp8g{J(&S71n@!V5O9t9k<#KC9Zb3RL6pYT-xy~&~sm({rF`c+w|J6 zuPW+uO(&My)VMtIA_LxMA9~Wqu@3;AVspyd%5iv^MDx~0sBA_9EXA2Rg6$vc7JBk? zRLJtcd$R8#URTf3=q&4T=I8)bam!ne{yT4WA&#w1^_Qa`X{nPI`2jw>K-V+<5qZtN z`9Pfs2iU3OOi({PKR+&_2WGxMAO_0SXjt0Wg%s*hIYi?4pZ|SLn=);`VHuG4azGEu z2Mo7HprD9pWv9J19TbaOAo~fmX-r;>eW`;f|0f|GeRw zK9ik~z>IIy8wn?P~JekM`W>*s$I1*!w|#0-zm?Qr?Toaq)*=jU-iy zm$KN8$Wn|`{*y_fmtHd{-;EltpOUH?*Xx-c`^&exn?fYaHU;!ILuQnyi3v__cA49= zm@+c5_$2%j3qRrJOG=t6j!RE*X;8^y0IBi>hmdK5snnbU_9(dxE)cUsqk$L#Q`u0e zBiTTzN&Mx0jB2ewH13LPgyu7pSd>b30*y@@efosa`-CnB7h6=ia8orb6zDP}eBrg9%%%qlU(OeFBmud+>|bU|*<0FRbHf&l^HhaLYhDogvJ1^_A-a9M~Jd))@ z5WF|xj}_T)&rjqO^`-o)^VU||*?HNElW>_;qVrvW zx$;At-o8FJUo$aBCpnh!Y_f~PO7)nw>6O3cdQ9c7L#}_82)5t-%h0S!Ble|MrboY- zN5(F_ljDdQ!Y7q~R}23T`^4s)H}3EIz4bHq2YotB+6XGwJiTl5YV_eA0oEu3&UkH9q$~tY}fqW$2>*1-w;e8-7lGOjO^WTk@O(B_`KF&|K z2GU>|dUR@`>R;AbapmFkr`W6}lQwleD7Ll!)C;)tQPiz7kixlAgf{3Z9P0&IOa`$k z3Ur~~_`a8i_pNk8hXGB(zJJ)3n9h?JUeJ}?Qt@zoGY1l^tfjAC?;r#%mIq$p&Qdi7 zlnG`u322;LTw})@FP0m(`JS%B(iz1;e0FAyzwD_nN-K{9-bN$@m68og6yXz=a{l-n z*Z94~nruxAo=YJRQc{VlNr4tWo=wJ;t)p2v2zk(CU|AkEUuR*c{QV)qEzQLda&m5U zERA;w#3*DR*8+J{(*h}6iqV5Sy;`W+wsco+3tW=>Dyez98SeMQv_(HUc|CsizPTH) zq+~Q1JEb~Xa-f)7su`%`s8y%hlqXy|4P;q0IqwmUBqUsykiJHZKXCy&#N>t~Ham4D zFKg8=b|a%APwEa2Y3OPT;80mK4WyV4aJZ#d`l#^BBX`LvKbCGJHmd@4*MNkt#9dCJ2<@6;AkF`oz; z=P1_sL`{{y6!ohZlgj&>_&N_##V0u=Lx@P)a?g`NZTkrpkG;{*gtWgkD>`*sxjacv zBx1mgB%0_Y{+?wRDV;%l*f0EQ9IAleh^y!e8%s7D>LQabd@2OBy!g>;N?ekJ@tKx_ zDU-qQb&`UoD1@Pbko@A~*B}ge0+2!6JJk;%Dz*3iMKE%LINX4sx?)=VIxGo!h+G z9BQ`%Nq@uaX<)(>3fVMcNVZ^c-sLg@3y-L}dkE`T!Cf(GvW!<}(19%m#wfiF&5VKb zQswbOjmf(^3!fw7=G&d}ACKom0s?}g{rE{gYF&-uQVRB!YH)4d{6DF|#0EYoWW_?J ze9|vt*1Qze9|04SLa1bON@^l-c?rGz-u(|Z=3CpbqY&4CW6NEVGmn2MvZCx zsUXt7TrL#*6@uO{3$aEC*aOsqqHBQk1z6><{nr<; zx@75xf!(;H>aCgc(8O>h39nCv(0lKC*8(4^Afnd`jL`;rSm|Q=z*vtELt^_Gx)%?l zj9|WoCkyQ5|7!HU&+GK>5f6xh!>5#s`+3i(M;2EY2ThNp0H1o`JnHXxxg7ZH?C>~H z)10H+eD_`Zhj-oukA`h^5T7!jqWLX!ekR333R~!kc;-OWwVvi^FkhNu*Z~9%Y`mfL z^*g?ejPgDIVpb6sR#ca0Z*<|0XP4K===+{4m&%?*Fj)i$GoEhiF53d1+k`H*LRBRD z?>o!32ibC?sX!UBYp&E*(rKvy=5LSgx`CT@+l)I$OGVUf*e_5jR+217 zS&&3S|A?ll6(nC+sL3~jaq^&R_4rf=1zXz4`F8PTxZsuFzl;MBo%HMCRa$DSbOI5- zQlLqo?qYXId7#pB*K6QQfY$(KX#qcMA@-EeTjfvZKkG`KxkzQ}xe2@YeMVo`R~MO# zx#X}c98SS}2Z1Wm(HjNn1Z59rS-(u7^lVqU&h;I7P7wjwFhvW+6i4d0lz5uPO#5#kUSRYAHjJs|80Qj*br<|3TOUmwp& z4;s-EPc`^=8g;3Y^C}z3&&M-8+u$5QOPiHht63KrmONk{L3IrpO48}tYo^(WqDzP_ zPWrxHykdvNBT=j)HJ1R&!K^vLy?vsJA4dXzM?1}glGg8ZP3NH=myn|rQrdVY(IX8U zR*>PG{M=PwT1^~!zWoe8+I}JML{U2-Tc)wSxZD@hQl(Q;hTS*+t(2J(yvuAP&`0bQP7$dpEKRh3is1l z2?*I*voFoYtWMMD{70w1WKlru7;w)4RS*0qCqX_M9S#ahjf7l`wC=WqV)#`a&X1Ck_^r;Kji>zg4qt=z`d}a2`2|fur6KWSt@s~^Bq5+N^ZPg z@duK!+f(@u|4q0p)$bx*4>tJ9Fe)CKIHV$`BsdAO5KwDe1BipnteD;S{CV}< z$FrvktqzulZwn7~kcVj;E=3)RTun?rbjO;D|MteMv+|1noV4OB?<}97<>EIP>+7$I z{qkP-Di!TKpTYCTR~cE15Uhl{%Ump4D^v}aGe>T0wY2}t7^jr7wex?s9{;A8WEdrCGA$tb+~&)26L{A9OBsqu>nlOh zEDPUoz|QkJSn*A>ff}yAX+9kbN>tiV0qUi|N`u7BjcSVziyB^fjyfj~%aC`&^LD6h z^KLrt)48`ZMhiogu&E4S{MXMAtFWu9DcOUQ(+*;a0u#Woo6$OMrQ-EQeb9Z!I=Wz2 z;-4JTg8hRmBRLb=k25Bggo_lNay|5XzVrTijD8hw*eflQV2B>w)%36^kZ_Px#@{)^ z=anwb&st?0d%8KFse>l7Dn_i{_7RJ;Nmg*nB0C> z=hQ}~b&dY+{MSZYZ5~Y&=ZnYfbfa(0T(U-``J2}P?R!VQUIiZacrA}eP=?W1otx*j za=Xo8W5{l3c^-&1aQRg;{fA?02KXd_JI)^VYcZIG*QjCJzjt{q8WR0ei!4KhRPlc- zs?E)0Wfc)3c;zb=GY9A5Mua>j8sKZ>rL1|<(aj77SWZBOzf#W(pIGHW(Upp!&`FJV zkx%j*yU@qLjJ9z2*rbCkqm^OgqJg(k2xf?Jwg!IaF-iKI@S$tdkZNZ!X-I%$NID#LeVnH0X)lTo@{}bBI}_hB zvm$vpS}sMYLxvwiRUlilur$mNr_4VORCCnn z;Dlq2V|f}NQYj=)p-Eqkr-Ox(;p`aF>G80A8`aN+EK2d^aljwmeRjl zxqV2RDOnyLYxy$u1CyoWfnwTcT3?F++IfLeWd}Mq7o&_Jet?GXKy2qA8^fajGbGze z4XcrhTGbWVeyk~kNl^|(5{p*HL8n7&kdX6KzZWn@H+Zk%st6t75Z(s$Ur!ii4X9%+ zUna{?#t)A!{2=cPGRATJ^>5F}YhxG$tLm_!q`ndO92_8ukAQ|0g}w~4rD*0YHh~|{;C5P2TgdV8EvN87V@DS|VjPHQ2VR7t0K_ zcU)~Gsf-<9z%`j%Na*yP-G0I0umfX)&4_JPLs;wmmnQa~`n>1c9`rP{QA#(s}p7K|xG=!@9kx_uU8UKq8Xv z9IEXe&);^9B3DK;nk10+1TWGtL=LHkZkw~eBTi4QHV3 z&+3n7_sZub!)+GXAH*7d867^0^}$4!CSs1>Ro}>X#`qFP2b(fS&I~KYdo$}DoP7od7ALMdP8F!kUf4gIx$p(PwG@*sS3;B^7{5(f1^IM?v92qlPIW16 z&;_wHPFcHxI+8GOiJrEpp)$NLJ&msC#X|8Z!H~sJI`mzuwAyb5yAUfy|6n z@`=bpEMI916g9k8PU2@#H=UsQIO?F6@KMp7D80ZPnKsXxhPC@|xRLW?Z2L(#>)&D& zmcN77klm2$>Al>8ys3ucW%WvJF?^1c6g&cJ-));3`8j+mn!#pDa~w=u_##Ai*{zT4 z47^?wT!HN zYX8nr$s9%js(A{UR%}5)cFPBp)Fi#W*UUssKKzUsb%i=L$$JFe>DzoFa}B4c5@O)L zUcJ)1fb&)+qAJ&a+MCI+H@EBTakfy_1QdMW4ZHLv;)9qV)aTtO6_UDa{2pLh?*~(R zkQNQ++xMxEIt->p9T1`1XgK{z8b9Ls58zut6v#naW0JsuaD}4;odBy6loZnpSHYe0 zk%tRbC~tPXEq3GWvsQDt{?%P`7dylEB>9X=mDq*9#q3(LIn|BclbWN=It2%a;`Md2 z)+eV0wEhKVwZs~atOXEz^{mJfukzNv;CC%M;PjtxHQ=Pa-Pn=mqUbdvdNu62E})%2 zI;i(P{G3ho8F^K;+xkxIJ4DYWXL>vWGXc)A?BtzPbB&Tf>1?vk4o1N*KWjhQ^9(-E!sPw*^~nK#mQVdD&1a5y%13^;0l)odj7~zw-&rJw5(&f-)(B09oo) zetzkt+~vDzQC(#8-SGB)X-5HTb`f7EZkQA@$LEWSA@pm&M40#r%-L3LDx3%4@tl6K zk1}<>56nBRixJwLwf=G^yO!SH6sdbnc4C_*;z2SKv-L%FEkQ&o8qyb40mo8p#Yj_h zzn!xZ9lSM&{KJiuR$}_y`xbEI^7Bq9?)o6`5$|PvGmvOkj-iF2#yF#1rzMxZJoWA0 z{&%A3KTbrfqSqa{{5xv4r^BBDW7KD9aPA26rr?vSliEe>JyXZ42hQ}aAKpF-anGCe z1!rl24}yM(7Z+uaUE`B;hv#s#`VeGv--LGqK7jolGl~mR+M$C4K>TUzw4(r<V-On!a{TR%Dscm>xgKY)f5Xg+s3DspAC z`P~GB0sFLuMDCtfZPVecARmkCe)C%iMhG8dzb9Q|I)}DVNbs-VHTeM|gwt%uOfd1b zj-B76ypGLh<5(pbOa)M=GnnylH#U!N<-lP&Rnq?p*0r>>%*@I%{q`*e=-dSI&}>GF z)=uY+ZzrBpK9tA)lDNu|1PpBy@sw+3Bwir$vFkrryZmqS2|2rbk#KpgCcGg*Z6^0s z{|UCMP5L$@4(xSF(5UfMB-6{1@aU+Mj8_QDxdCVL(92^%VALnaUV_d00cZQ;Y>mI( zDmeFmZzYq0R<#poQMW)be`qc!Uc5&wx37n*ld=K0NLvl5#s>+o!_WWBnvU=Li0vm} z#S8eq(K0v)o4SacZ7fPZa>e+~Q=Yvp)=UmYc>`drTu2#nLuBg07cgt5)r;)}FN8~- zqQMKzCHZRZj*x3(pA|frI?}<5`I;myixOX$foWFTN{emA)I$d9xa;%3{P8zpdX-E@MRQ;38dzF|*IU4C zon0RK>Gb4;Njlr*X~pV#b-6da?fsuSQx%$KQVK1S_VT%`!j^ZCMgNktiXIYDxOwN= zPR?dWvTER2)1UVl8J`}Kgo6(um2dGI3RcX&6XENgT_nouKYlF30es+thjZ+4mlN*y z&vG?yZ8QmH-Hl(fsgQsOW-0Zb4-XGta(6xK+<#2Ed({HwAz%s^LiXkHkYkXoRJ}^G zMhEFNhztZ8!hl@s2?CjbL^*LF$w4+Et#8`|g%SC|CCes}ETJvoR2s5ovN z!Hv7-9&c_e9pBg1q0P^_Q=egW3uOO?qhwsH?6BJj)u^KUC-zjsEowI>7NiV-= zlDqQy3SPLBq8%rP-%*@XF`dt7H!Q*^GdBa)F zJ#kNxWu2+qmJAdke(qCH-3A;fM`U;P^CSwdb?i!veq)q%nJp6CD;xmXB9Dc$Kpf zy3F-uh(^uzdGu7@uiqT+Qkq{O#VUw9_*aBsq7 zuJH(QvrMq7pd9D!ML9lgggJ%KJDr?Z7x+clQhSV!9ee4^d06?Y0n-zl5Lp(}Iw z<1^iHl~&!c1!K)K7FIYWF7WRQXIq3$n`Dc6*;*bDjQ&no@bZ`TKZh8Qty87%^-8wo zi?HH2{<75w*6^?_eqj#rFIGdr@$a~`e(V;WiW#iQt009yF(WruT=*Ry3U&B@GI`3VyZFz&@=WT35!cTeYIBTX02YN@ z&d8J;)GNheE!pg!$eOyzGgu=8`&Z11)5{+|^F@glW>F!jx5+Xw!QQCVOvij=+=qX7 zQ7zW02W zZ@M2^2wZ7}19g`tzAwD`ktqbjo2E(>`4bw$->g%2Vl)ZRpvKu+AqJBV@?^=HglBTy zr1Nejn6GC?M(V(yW3pl6wLQ_-)qU}}f zX%sbH6y%I?4ka>#nP8Sb6fyA4d~-c-J;k4;ykBnYUMj6+d>EVvaW8`egIZe*PI6;@ za}Zrvc9LEA<#sAo&C`fp;QWQBE$|_%^I5F&It7TL@)db8SD&5W6+q=t>OoYa z+U#IZBu>iROb?vuBVSfOtGeuu{d$)%HG4G9)-ydGqIa3z$Fy^o1LAw|PkUtAQYY?t z?*TLQxQlObDcA(~XcB~U`3f2%X_B&XO6p|cVzTTiJ;1R{I)G~-q?8;2OyNeA{i#kq zbRT(tVye~@{IoP|3XOUBv(-zwrK+NWCZY&7XOp$iw}gFhh%BZyW7yrmxi-9MY zZ^38^u({MYB-YQ8UDR}2XPbMS&Fj8zU-;j%9f;`T@C8HSH+#ZiIp@0%KA-=c!22w& zSF?pLuJ)m3PB}l>jgn}zNPx?(FUKNINAibN?ucXWy>PXDL$2z}u4sefn$F9t1u8G$ z%}x}PJZ58ml~%Gu%7F+@hkce_p+gfJzA+Q@R=T{qtQ;Mee)={XNuEQ7;8|x1&rM%o87YrO5smbBV zBAmnzPm;C*$yY6aTYDVMQ4uK!s0$VBYr;Mc$Z`L%T|u8o-3HHONqb%f)*Sl+o;6iJ z(>GQB<3r0t)xX|6)&GHaZPUae&I zODE^lLEnY9$W=ok2Ro)|9D$Y?n2NyqaNqk4TU#Anwv;odY)CA73}5lWd}6{NyS!9i zsmvId(X;%`TYe{G4Y-WGa6Y8AHxiYS*G3rCd2ZLJfk`^Z?nghQX20L?Wi@$PU4D3K z>m5%&U2}pdP*`kLxT%sH`CTZ1q(6AKD0FbJRpL(Pjx@Z~iGLH-33L`k-<`9QWiSKE z27!EQy_Rnu{Uh9JZpkq26<&`zVt4uE>=?y+GyucmtR2tkoHa%SIp8K}r)KyM{IZAI zDo!swES%doC~k-|&=A$+$!BGK#z$<%EMA&UU$Wulss>cOWwG*BdOh9Q`GcG|?#CCMldp z@9tI@d3j0$z_cP6x12SDZY12&_6IWOmT%w;M-1%>zHx5Mx+#nO^ClzsC7s77DFDR! zEMHCb-T1Hs4xn@ZGDHGGWO_QxpCfGZ#}t3ymec5v!PSy=oZ=jU%Co0pxwARB(l*C5 z^7QN?e8CdhLg}m~)2j{Gm(nTyb*|6o=N6+6IB5#-Nx);Qf%PAmkhm^CfT;qy;{O0! zF%-z7KngDGrLODEZm8IZ6MJ;#~i8a zFZNJhF;TDc_jq=MsTar`MFHTyp`XlvJSMPPk}WT*6c2bl_pPb&-Gsir9e03&spOel z3T@L^0H9!Iem)5m?cMq2=+As%HJpXfkqiFoSM%-$kKk-Ns!-vkJmlU^HGHxUODbJaCd1dMpo#4{g zCBo55`cm?kPQD^qz{_NM*JePw={B#t{Mm>&OZW|*^)(I|$Jt?K?n&u&2j#Ulu;n3u zrG=Mu1uWddObwNOaYSk`F=gHPa1LI6Rd2V>c4|dlG;Y3C@#fG5)~`8 zOWvTQ2$AyT)OX)}$^5l+=w)}{jRcT$e80j#F1-f;?){>+uJc*P0SE8}A&1|;#lI`K zPlg(jj34k~EURu6i$+V*2;q_A7Y#Sx&vks|v~_q7e0P6uD@Z1Az2My!sEYJE?7?oj>qKN`|B~sew||t+B7#s?x$7N-?^o&MxL^D{h%6|M#fuK3Qb7a`VCoHE-=H;F`v_;X>*OGKC=0n0^g8dtkBjIH$?}Ey=_AA&~6n%iI}co2taGWA}5=LA&wS|{K$}> z{tqNP#+MaAQbe%ushFV?ZOW&s_1YuC)xVAI!W$VOgJsrmwLl4=wY_O})@)7_bey z9F?y*bOk`n5_|rr&PSX-%OFuApvBJ6L3B7%=zzgIgTlNum)ByI@i04W9$Xr-fV})% zSikMo1Iap9`S#-2T%1oy1Pf~5J38qBcEJN2ka#TXb$4~D>+qx^-^b8UFZ<@?(cb&m zv7ee2EJDE`~X;1E^0}VMD7xV$u-b@Q;IOvie1atM(^wxbl0JOu`>hx?7 zuVb73n!_vEGyMdl1%w>r0t3K%f!gjX1;1s}^2JuRDTSz0F(G`ZPiPUAFgXJBaWXNX zV$K~~j`n2^(+c$olj83uU&7y<(C#=Tpi&oi-(n8HTI1m#-OLci8Gp@c{v^I7Y;Ldz zA%KnJ*hlW-1@`1bCMUOD%YM9Rw_bFKI;-8EkQ5fvT^J>DLWEK#S-Rp#MPJwwg)i|> zJ#u79#M9T7awPJQ8c}^Dz>|dey71ap#S!Eyb~$&yxT<7i zyk=2Y_op16ENTHE=(w8%>lt~eWYdO}?gtxIifGLr36Prv+LgXr`TW(+=(D$1jJ9NT z^!0C)0_>ANly_9nE8&2x%pb@hj&Sa4$VI=1)-Ie5A0+^5Oh;kuPLjP>a(*6(cLRqh zl!efnUIRvsW&>uQ{tX?^AU!AIM29xT?{?I>^wPM})q=NP(|o(AMn`%;yuD%g2{+5r z4@X&h6m@vEg2-aXCyu&Kp#xXVALPI6yRy6ToB6!Z!5TXtcc&}3Rc9;XuZyldS0c8{ zm&@XJeOVXd+*yfDXJEajhHhL#;nB} zNQhU}`HpQSz>_7qQU|s+U~v*-qG;~B>-BxFV!nk|&VS5AY5x33N!eFhEQy3&)FdE9 ze*5{23~9da9u;V2TJ6^!=0#sMo0p6{Pjjq!7|Ir^i2Z8B`9gAGqD_ZaTmEZWyI*%t z`kqB-S{=&uT`QMhcBsfFvHr|_`ZEbF1kvQ=_=17gp<@dX!pSusbHocywyL#_qCT=#079AWSl*#`Hjc~)`AXP3|%VN=I zj4RFSkWkVV49K&3A=#Q-tDu=AP|)jnEh(uvsH|x{A<{Z)TBe!l8!~ z-{Nfb`RLelrrUAG?6`e{tumN`H5VeLn7T_5_A`xTLLFyyMiD#gxLBR&u=U{?F!_nR zK0+?HB++*wpc6=EVkulcZ$0+9gAS-jV*V6E6O9gE`(dS+g*B8)4Yu0q&B?@L@IZ|> zp+ej*{1b&#`fuA`8YjJ;4FMxV_d75Daoqf6YU%RP4oJMo0NOq?E1TxV|2QaB;9lZW zDZPArSdb7Py<_;Ptuq zec&{csWJaq@2d1lo$1PvU2qjQgsEv!n~E<#bhitiT&^jOF5%MeoD6X!IlZEx1NzAn z_SWSDm!-4L*YV^Q*!JYN=}D++Cj`+gw``4K?jP~4^P$m2Cu5aR$$*sPaleJ7$w(@M zB{^jdj}6^-iKLj_JDS1Lp@7iN99Qa$|F%96Ads7uh3pFaQi9Yw-jn$4?SR4up^u83 z#TfvfYpo)QmNkmFqK^^*Fx0*2Mv%9NTBs}fjQ&|EIVQJzzFf!gqEojw#`FEDtK$Kz zn4}Q|=1Y*O46Am9(v@nb7+$-C6YPD}E_Zyx19zQ^3*XUEc8%)077ib}Wf(A)W7&Wm zWYYJ{^~KZwey1ziV8s7txloQJp_`(tj5WfpO=M|VvC`? zyk|!`nN*4BoB!C{0r6p=19lu?4NBZn`$WS(K8fP6J?$h{OLW;E0~FzD$R9_7SlFZ; zs>Tu`>xhh~G(P8HRCotaY#JI?v-+KGsjnZWZcqy(kQ(#;%NQO8gz$r(!y*p4jJs9i2#n zT6wID;iFk)Fy4=A(1k>u)d#5d04S?8X^92_o?X{Lakfrm&9?sQaZEVFpnrp)xUXvn z2RJojLFs#y3JHGUtX-W61pPgI@sJd&rX)-RcA*WSWaN;NRW-RlR`}B26ez#J_f2U6 zumMtMcoI?*`V+Q#obPqrP@blJ9#GjCP_|UCCskl0q}`{*V$l06ujmyWtR}br85HP@ zowZMrZE*M6>RM=-+H?JG*f6YO z%*)J!O~baEcvbvm@IVyW>WugGn=EF^NwJB%59o zQaqXRfQIjFuFCiEi802u&C7ayBJMv1OHZj12Fd->cGhMge5TN=p%D4RJ@xLf?a>nv zqB+c?M!xp-eyqpyl?X@y9pc&}`MZ+-F9-?9k}4bC#K7Im@a@*)LcY@zZLmUH*s(~U zFsC{i3-lp6NEKbK1znZq%;1?jHHGi7404uv^?ae6TR|9Rd&XrW2Oo5|3~obyd>!C*3fE$HRPqVikJ(N!`o;f zRv`qKF;gWZdR0*u=vmx7Ek7$&X{^e0!ckU|)Q41qL1etsouMwyO>PtVe3=sgD`o!n zW4DemT*`XogT6JlkZ3hcmk3ocaAM>PmvLPQks0*H&*gdl*1jf^r4gfbJW42ZF{Ql} zb6nm&F}aZO%>^?>&0f9+1Qo{c-^x$($6$dEEDx)%SdedYX7qJ(tXzBpEojGSSy_7k zs-o8atKBCWcIZP-%lZ1K>c$`eR#GS@#_a6QkMG96$1*t@5Yv< ziJLg|fWsIkDz}KL=eRzur8?t-Y!3rmJ8D?ifMsN*c^kp?!$kXutanq=(Z*A3d%T?i za)|Q~ozM<1adOBEijQ};ES6@ab}z|GH%WCZueHU#SpLX$NG-+}H|4ZF>Y7j_DAr>A zQh#tNq(#_YmJ9=AC~KAgjWQ=V|98rrc9#d@V%)h!LVejbN6j;|vF^~CPH)xhxaO+w zfKC!rEz4@cB1S$6+p!NS7e4cx;5%mc@AeD7`^iSvE7CKm$Z@}h^Ip_^&}G?7nJXXB zl>jvZ$gY-B645cK7g+lcaNC<6Co`6Rua9sm)5=ezlx6pkR=Ht#`<7+1#Z!}kfetKW zMw0Zr7I%T9=*3KOh3OLfL2dc#vSw{Rk7kx1G0?haK~;gN`~b-;mw188iXjLCL0a1zm9JSzGG#jd%VqedbPLg)>U18b&rZxom6Jx!?CpUPBlUMcmK1FDR1v1h-~-(59~co zz`M!mkTXbQ!15!LH(#ce)CExh!_dpU74!KKL3ju)`w8Kz`LYDIscPpPcjCldA9C^WHW7AUfx*RZ*imHXPm;#7$AWGXX~#k7_2rl(B%SuW`QPlNtr z^i^KGCgUFkV8v`qE1e1|bn@(GWq2BTYzhjB(YXEIG=**&NjBvH@kKjF4T~Gu@MuH= zYZy6wd9XI0yPP&hAXix1P{nmVwszJgyihb95uVzH7rLr!1V=HA^A$~)*!4E5AIztV&@LB3y+T_v1YMjm(rpP_XPbxV)V|pCXTyY124$bDSn;x% zmwDK5DQ!_v@!?$y%y6ZUg?Kh?o03f0J})Q^Oz~k_%7mprgb7s#IWpdoYEmv1g$5Ib zasn!@Zlm4>?{AMDap)_kBbKzRbEk*xuvjVqU!j0Kk32sXnG9!@oVr(;CiG*_H^fh* zDO@V41FX^eCLsj`gD_$hexX7UCVK0Q;QWOF`^v$GHQ$*p3SQ7`C!Y>8#N__MGQ!18 zumV7mp^&eVy83RkLz5Dqi1a##m&;Sbw->I=(6&!6IY-p8pT_hDSGK<=lG%5X^Wo|4 zUl;WE%3{$GtDb6eqxH!NvHHIV7q;VW}qAftN54eI>HM2k>x@9=&q*1OE&!TL* z;;h=dt$L&~*JXdmQre)&Gccus6aY2Z#N)}+JI8j5xqeU+r2ViFooMeotJGh4r=QGa zhV*D>4fGyn#_%ncK zk|2Qi?bn2AC4kXi9gHCXg}5DaJC3!u6@3o9sP6nN+mj&1i{x`sAE!mX#$C(6JmjF~)j zi>nMiZtl~LaK=`vz;{1imTzC&Nvs1K<#F3Azo(#i4d8)U23kP|Vmy^F#=mAua=0?yg{~kmF*cDbhNjUxaZ?42V;cTyX zqT{iMV7=jdFs8%Z7dr|XMwO?6Q!df>VPxUNy|Bj=o9s{gZ>E-?(_ledIvhGhs4rK2 zeCM;)0nTJoyqP7ziSaQ$I}|IxGu_E@BgSDESL_*gT*`+ny`CluXOlk=P@!r~%ZLic z0sTqUpcA2&3a$w%5cnyvqbJg8-@<7-wQ~T_;Qm4##~5NrU?*kde+EIpB2Q~MDY`bP z_TyLW{O22QkcV}bWuit3-;|!`9n!024ZKcO+61!(j}?s`Hd|b{+iE$&du1`F%~0Gc zKrS4UV(0`17gjol+8g!tcj4q`dQt}XbzxWEw+0*}DjfDx{CAt}S?jqFvEPGngTwm7 zTDv!JXaLyT<`x#Td5DAvyDh*D*m;o1SJ2yr!~#k8p(OOB?}M?P7SGawC6qcZbaAvGu?5 zE=YS5RzATiyP>c3pz8)^i0|+;w(!b8(WrgZsemDBxx3#YH)#=+Z(l2zK4h7;o;tq$ zDer~|WUGP#G;VcdnGRKv=wZ--egrVFCq-l#h?S@zBABNFvkeRk95m>dMn#~-*Wk<= z*mC|e({9cHa@jf+I&3`MIfnCY`eN(F)9FN%5l=|lLRtfQ=&`*~`Xp2A9(sGk1Y``C zYd!y6tbifg-jq!>W=vW)*DLVi`BNK!uWQ@G|K8&fDA}j4whqW{r5Y_FF4Y_ni{=N; z(HazrS-cTHTNerxv+2#VwG_)jyM-TDb!Kt5?`ge*3Y`)YAy8K72{?j;%ofgIMdIdN zDfhK|@vsCYdSL9B#wEr#qlXdyqf2;G{XYRt{_$YlEYs~7SSOuoGbOn=@m5Qxr=Lb9 z{ClC)nLp>23~&cVHfPg&%fHtI<>vBvM~Ut~29!G6=Y@#{|*(nnATNCzDQnTZ(3 zd0!8wMP6L!FvVhN#`0LH8Vw30U%peOdM~%h{I|MVaZEVj(tQ8F*PA_$xGG=!73DVRgiPH9UO&)2clWy!02mkjH=mx;&#awYZi2J*g^_$05# zoxrdrD~F3qE`KV=Z38Mw3dRJruC6W^;;w=X{<&?$ib9729LRo|u-q+;*G4kxHeAF3 zOayZI<}N;QYWyq%(eiM&kT#;#$msG ze-d*$q}zcbUPZ+?w+#0q^dGCL7fxAKMjx%;h6>_BhYQB~lo`=dD^KY;A7ENfsjjs^EAdT(z(h@!Id49zpXkev0@l91z?ZSJ zmEp;w*|s;q^If3Pg=LdmRgGg$hG)ZZnvQF1WjGe7^Rqq`1xHw~zvAtY)XF81(m9RR z(|J^F#bi?58f~q_QCh`bH#Z51j{EIg;=6Ck%!`^Gx#P6;L zlt)*+AX3x)vrL~SfB$p`pKSubu`zw>ju7oE{6O;M%MVjaJn*&c1z{MhC`;_O6Y397 z&)6=z7?24!1Ne9pEZ7&38Cvi#1>cV(LTG3_GKWq}>MD@seRNo^-w}U1nBDzO_QCDEl6;Ss73a*7 zD+rdE=22Ga=AVVT7EvP+hNn}c^0Ey7Ck6CWU(xj5mJBz>uoN3yLb+m#W50TW!f?U0 z+Y_yxTWja+?T;$f?B4ipXuWa?5s9>F)cwW-rb9Xj2EIS_Wja_Fx8^D!3;WF*^Z4yg z3_UESV7q&k4x5ZYFIq2k$E0HA((YeNuGB>(UTD!aGrSEt#$M*hLs&*WiTmVH?NxaB zDn(sJ2a-s@V1wv4i&Gg6m(Uf9|79-5W*Y(%-?>lFe+sV$@qg8fhNTZ1VF^QDLa?F3 zbr!#beV6FDLcA_9Fa_ewaAqGOx-}2sDjAk3{z~OKhLXABXwZuAwe8f(e{cPPEsWT- z9nHT`Z-w=r0pLkNtiBEdURKJb&AqF~^YOxPK})CfkD4~5IBM*SU+-3X-yr)W1w@6< zBb=Qw88$xag=d_s@aW$ZfsV99{ilDYZkN5tSs_c4nDZTHvk(6+HUa8@H1})jQmt8V z!Rgo-s^$2_0gY_@q*Z-M(yze$8oy)UO*hpxPe@RWr>2b&xTEoZ;3g?(FvqU~b<0~S z+~QfOmwK`A&K9z2n!!6B(I0$N;e9oocnUQ%{+eL>^qN_&;`XhEhyt#L-&Xe!Ih+p3 zZS|u;)&|(NRAFVx>#-pxz4Br`b#AU4@)1fqs4nNjX$g{citVu9#CufRzlrfygwY-) zx4P)Y^hqP&?|e6kcq(r-@CN&y*Xt5Dz14S()c#;fRK59Ilq15IMFpP1m$Hob6y|aE zxbLzhZvZVWZYmpeMfOhwJ<+s7mbo88f9aHI{dtf3@jzO5q;Ka#2xdbI4V8|?H73-{ z+C%6pu8A#9Hz*z1N_fFTe_pKYcaKTq^7>706;GrYr-+T{9WaYjMhp#4u zs=zirj+%DXD>IJZN;ZfDfA8|{fi zF@Z?OXfk8IL1R)%T&^+UVE4VRZZ{oFpIb$?>rNApcpT0$tC`d6ls#qm?#2n=k*tit3E8Hiq$3-afdrRf2mfmn=)Zp&jvg|4)EuA|FEHMeG7KNPx;`T6St%oKuTOWbX z?NG}3vk;(AGGA`6111j?wm1M@kMz8`GU-qi9mvX->$iu!XTjcsHv;D%u*p!3D5!3c zkTAio+CCC^`H5=JT?UPqdVZX-;*nBbJzIT*vWmOYvafG};Pw%!e_99_$-<4G9FL6# z>Z(^QWrh*kJU);j2liGAjHLRqp&ra!+gn$6>-e}hm4APwRj@;D`RdpcU`4xZ46eVt zgS%?nPj&J*#H=MZ=ItOV$*Qh=wq7TLD=+QmtR0VJbMt`TdLXs}rq2lwAvz(4^F#wM zcMW>2nnv8~i#!5DRbcSc7;vQ9NW z2S^LU6eN8GKmx!e`DTVgGAq~#UOW$FIa#I2-N!W^FfakuFNGg;Nde{a+k3#W(Y2xX z?V;)|N`8VDw;D-+%+5xwPMbR7lh0e);R4BU^qg>NI1TSNf{C6k!v*G-KQA4uE;~vX z!SKre8h#<|Dx-;CT@mN#gUH61mtyF;hMxOh(VxEdLoOdoe}mLj_8V$oO6nh94&I3ba8Q- z!i823=5w$4){^JPb;sLX=1}ab6_%Fr5nClJetgb#s##h(g_3eZ@NSA>^pbGzjY&+P zOYF6%jY3vYQ-S4tUYeLNN7l_3V0*nmuUn6^ifiz)q-bJ$@^ML@W=f;0&7^h`L#Gxv zPWArz-Xh}X<=%v(EyGKCr7g1o$FSC0@A?ouVTv!34>e5M03eey1gtg>5V!ErR~~!0 zS08Vy+Jx8JPeJ171AqC+Y045;+elsX+LkcwjJ_%iw;|hcShQcr89a<=QD{2kVC@d& zCYjPK$tqF+kr;MuxZG5odG!Twg0=zZ#)bsDpJG zNVh);{K8wC!?k_v61CHfwhet}t&N=TxT|kFWt?}~vnu}aw`l(G6Ax38 z98{R-4|7&rtC~lZ@lwBWqV+%_FC;LRS&kut43wwK-;!+f9zV)IshLGUYV>JyqrC?^ zczfN$bZ~I+-88_N#pMEr(yvT8^2r zAS?UMhlMG%@9wPf@2m&3RkPNxeny;q(>@0MO`Rk!`=Bh6+VSh3Z5hQFMg;<{-}Z<; z`8vLYqc~#Rw_fu=>-9gpI-Rxb+yC!ZcH9fyoh@;r_0(VbW>m8w_SvEY z@A9#P4mc5h%fIn>}6uC$d@5u2l!51Nl&* z_~$?3zixGP|8vM1Iy2a zCK+9!cd!WdZ)6@m$Mhv>v~-qX`Usg+mYI11f4YXQ$nyFMi=D%icoTH}o-qxZuRjoH zkI{yOAtqN8ewqUTD5v4`x7Tx3+6@xnCy(cp^+&t^Kq+NPB`)193EG-g8+>F@W~0DQ z@0hH2rd6$YGiT=V1wln+UKcbBa=M(m;tc+89yoWNb@l3-QnIy=qo|ro_WAMya2# zW8um@YZv%a>2_8L5CLfXpllB{FUdo!w#rmN(^E0yc?Q~d9v-cdB6MNs<29%d z{VKSGuP!LLs`ht@(R%iaDxc4uOZM)$&=YHxk2Sm0f{>TVSU}Wz60)>*N!i>N_F^4w zZj?3ZBb@~R>)dHzTdbECQxYu(kDCMiy_!I=w3WZLO!)3eB zC5da;lcZ%Z4BXfzs8S3jj_Pf!q8TWrmj07W4Yq^}U{IowOLfExdoWvnO$IzJS>9)x zsr5Fzn@wm1+KLC>00m6)!sc5)HOMO6FJoNpos(0|GC-uFKy!Aj;`7a9Hfp zkE3<52ZWhC+K=`1{9kU{fH82fc15+%qw`UHi-P62nI7}vQYeqilLzHhXLI-4ic6(G z17uVzUWWo*b7dyylh4H)Ie7HgRwxK4mY6Mj_`4#IJWYnDuC<2G+Qb-}n}^XvAoe0> zy5lk<%EZGKOYn^;o@{5hfH#3j)!Wv|epVy*EG*7*0ZKZa~;UN z>PO{UJ=3hXuQf?CM#%p$d=DzAh@&inyNv~nxfnbL#z7Y|vhH-wTZKWlf_zsCQaGu_z% zMFVLHtW7>_v-n9TeP=Sq(4CralH4OWJ;yT;Y@kx|E^MH5yy-(n49^mAKt4y^q<@;) zWA-0Me$Ug1W+_NXT(*&)zNPfD`py2o;BEHCLPQ2(uxq)MI?NnVYhX_dhTG~6XE$EegVxFOV0Z8Mu&XFEfORl#y`&y#!i+81@BkotEP8D5)@5OM|O9l zOs;~w>g94#Y8j|5U_=)BQja%ih8H4|GCX@^Pw>`9fk%PEsF-baTj$#Bzn)V4?Ly%a z{^kAMunm}>pA0P(;&vZ8FyMbj#wJ@xcz!MR=It zgT=PwLjMr_^yU#0spkV*`SUg1Y%Rtb?+K#I7hbaq_ zK5#R~tDF@aA709&MDlFdf7@Gj*q+XQV`yCQqR(_Em@Uuu>2%#A@|mxD z2{EHJL?s-o?eFxV4b7?Q)%#gn^_{4^np--I_hLqKAX&xGgA*z#%Os9p-+%6^OD;j#}d zkOB|q_es7=wRmT9B*DX zyi{+4^b$++3rb#KK0Hm1@?V@~J_4q$N**a@GMP6MwPf6Gc-2^nXg7JUQkHN#`yb}o zpk|!D-l#IQ=;5#=8y=_A8lFlNnNJnJyl6*U(lUWn*WBrf@BQkE*D^-a+bbk3H3L2; zmbLqUrczx(C1etg4mIr;`596FQ7*BWUEFQs^O$7%pEQ@SkF5CRrye{it`pw!V{rVkk#%HI0d!NfWO=U4nDq z8Nqn(7v7Gs5?yyHI#CsB3bAl>R=}J2nGukM4A5iJbgBEzob!T-%W9uy(7p-Qre8`E z=cjlLjXCNWiOsi@^6*05>U0}A^hlg3Ny!I$yg{rY2iI4zOz!7H8=`D`~RDz zTM{Wk(L1cA39(|GmR_V-%YKCq^=B9H!!uz4zV{G;hP&5{oUD$nnuR$eT1K26Qjp$j z7RzoUXUmX$spbdl0+kTVFcw6-0qR-ICv@hPXW(N0WmYbfz@aS;xTQ_Vdm@wVQL*iv z-REjLM;74ER*NO$6vj)2Dz*YONDTrmz@Oz0$;G(5D3S)0H;kmlm;rcY5t^Hyp| zzOdOqrV!F8#)`p(35e!+5uJ&hf=jQ=X>Nj-13RA<*F7bP*E=XP55c!b+Ic37Mx%6zCiMMhu7Ig~qu_Fn^P zKBvAhUdNT3;;*j@Prc{WZqxY(<>84&A@ZY07sz{#TUiq?HoVM?H-q?%k3)j(4y18j zZavrSX%7{h+tiUk*Q&T{>oR{F-I0#hIc(U^hWM;q-W@mJEg2d&{S*0dp+Bhk7+LZ9 z1GNW3HlJ7w8OVwxu(SJY{(c(+&PL(g zzjQ)<=;}V|Owy{&t}jMsY4AdOcM*a1`PaI`Oy(0T@Wp6d4PpzC>RGz(1>y}%gFnuT zgA8an8-|eB5P=Ta4Hg~>^E5BcTXT$y$24BBH!M#<<n+% zX`sJL`=(7|wt3J=APa+@&mE8wMngry!8<&S=Roxzar-%(Hr%!w6%M`tN?G^~S4-aw z$0EavE=n$x2RwWYU1i%SyPeqOVF#`D^TY6uY&ZeMAG%bZ!_POff17^iVY=p_8}aw` zi~WGyW$BH6Gng5?ZzL>U{KSYTqueuMAjiYPJ8ajuI$-Fx<-i)!U*|gAUKl5j)To;{soUoV|izoFe&`3fAy)c?CuQ z*Ka<>J164#zZk5i0wma3WNj4@pv5ghi}|S(E$f)Q!-83*wfDWE4|r(~ZprDAV#WT5 z%gFfu;Fp6E?S$KiJ??zd`_sK2u6J)l4_3N%U`-Gk)1M_2f`Y_ad|v#Dx?>eF1!s?$ zBllwl6@dciG;JeB3!0-*XZp~|(SH5<6@KhVS|>uBjpfIy35dwdjGW`*)VG>B<%{IU z@!e67^Yr$L2N)H3bJ$9=UX z!)c^c^R*^py)gcucDMJM5!^GxN?)RQVtign^pkQx?UNEOPqh3-(~c90)|UwK&&GIp ze@wQ9f1Mpw*m3gJdiCENMC>Z{CQ{W+JO^U1N-UCS_|*S-*U36Kkp7^+tjB*B8j9R=Z6hgUPz zX8i8@P%Y)O|Egj5HV;5?NdNBcG=I-v;we}-Z>{2ho?9D~_RGrPDroef)Bm`!`6M1U zc91vgJRib{*inHv@ay#QcR&+VsnL9vug_Cm_U3yfs3*(LWDG! zyF3Jac60O)40U)~C@2d@I3Bxo1Xu=rfnWpGEU7dpGP|MXnd5MC=+A|#8Y91R&|7oo zcR1U)V_{v#5BL5COb<&v$8B#O(gb3Jr_W9ctk1HxahKYOJ1T-N&-{&ALSPqNJ7#2H zJBJVK>qt7E(S+`s!8IP|#BD5n%-YQs78VH6>|MZ@CZW}RTcgaA$~q4ihEdl6_m2pM z{Zy0a%~@c^q`P+Yd4lf+wYFBHpVchpg^*hAp1u(UGgq;&hf8N`J{&vZ9>RC6n)m zdw?9;yd{YGPNA-f{BiaTa=*Z_x(R;WaR6Cvo4XR{eWBbVmt$tf?AI?TGZDGRRQiCkx#q$zy=rCp;|yHGd06p-af82*1);H;q%Aj{DwD-0bI@(NTRLfTQt(3+>v>|4?1?cQHvAXXebtJpazb1Yx??A)cy5< zO_e16&xBMd%mrAf#E)T>tHXbDhFo-z|H}m@=mL!?|67mebFg0+B{ynR6o6x~wfP=z zL^!GvUm!?>OxT(DJRTh{QM;px8PxrpT0{$YSI9`7t}&cPoCfpV0x95_KIPUc3?#Fq z)@6}XnCx?Rjt?;V0;jmongfDCZ3^FKzZI(eoXp=pVyoF9ca{~0zf?Bqk1BpCe!JAV zie$H!(&59?x52dPwxu>NnChC{xKn~x2}m$8Ritx9g;(PKyxdO(;jRWkOcuqA^*}Vi z-&R-oF-wS^*a(2K#w~uNl%}S%Zb186rwJzWk-87VRyo>`1@Y ze>=|bm}m|rHigo*{!J~*6>B-_f)?GUanYA-=d;J2y@_J@L=GGdfGg0@G&T;CYt5eR zHoJ_yhE2U{N^>>ebu|B^)tOejyZ!ROyQ|o~dG|9AL&+Z})2!4R9+_hOQqPxr3{b?Z zLNoy3;;mc~3o4^cyTk2Dnb}*xr-s@S{<9pqlVMeYc7ftOR=qdaw9`%37J-R z3S(DYFc=rB=j$Ud7y?~qzTStoUJbW>i7LEYAJv_F-+SVV7DC~;dhWFQ0{aYejD{2G z8f8Ei*G!DNmkluhpsD!bL)!Nx2ym|eT6a8W9|u{*K2!ZG0#hlY zKBE@SkZvYf{XWt@fu7ab1`1!IoxlxQ==Cy&qHyPZfKg8>0;8RQj%ZRxBWl6xS0Q&G z(wO4X6J`QB_guE{7#k#Dt zNiuvA8Wjg-uOzRVBv<|~`)_?|)R_^mcTwji;}JL&luF;c|JMjMf;ABNRQS*lzRx>0rU7eM8s-$hyn|w57yfQTV0yl{y*8_!b6CuL}CD z7m@$a=KR_fJqH1&(BrVuRqwJx@v>E&?JXTZC%Awn+0?D=)5(`=oR#t!RP%MtCpNdrnUbYTm<~xhg;=Oi*KNOU8ef~QIofzPK)|vwL zyQ`yGGz_*+&Qpzw4HKBBA^Vjifk?ym(I#fGtE&Cn)G%1R}0Jq@4658NZ zo=bLbWs2UAheJDpf~YZaQC(s=f++4Y>KAy;L-aDGEA4as$eEmI`P3j9Sh`E)<{$qN zCGaxQrjsKWqCjKM>gCk$xH(h(5$~329A8CPIyrMaj7I&4AoO**FA!sdLLSB5_eeIn z^O#Ao^8hZAqpZM6l;(4q$Y<8(3*>*AHKr{7GT~Bna(a}Ml8W_nq}2NmkF@~+wge;e zR#>H7@?4-%=V+rL02b$oU>JpGq>YXR_*!#=#3si8Jg?rtHvuPq)bmzD3jlz&1=WFt zfNpMJJbHB5P=I^!_(knUsCWkP{f3GGCu~XM#eE{QtaCA>ZDwTUk&)$wVvC1CCI1M3 zxx(&e6vUx`;M@r6v^M-+8AAz{*$OfsjI#(c_ylx6gGtma>veLTBKUR%6)ZX6@-njB z(qfMqztX~n&V`c-;D+UAoo}~PQq8##CVmodypMVK%|jkRzIIi_O@^$%c%vfHI-S3T z(3Gq6xi}#23k{3ozp&Zo;&mUAj`Qo%w-;^mCB`0WxJ+DNJM%4lJ47QgjDej;vDz}o zvj)~$*ePzmU&NgU5n6}6&S#&0J(q^<^}_#INwezv@CXilnq8yiT^c0HxEXnP8&*n+ z=QN3VQ-rObqH(n+`3!Y@4-+T%@*g(yY=DR-d_HQa;Uts!e-MAqX?baVe8#Gw?-jcK zF=pR>vcO`0MUX?sg2~CTo&Gl3P?TK}HUM;5!E?zxz%KM~w#dWb`i zi}3QFubNnH2z#d-UGZ4jiSp`l5yBe13!W%L)F+MR`WR`@w2SnghcYnOLcgbdbe;uVxH@RE20_3#yTK4+!6%wcR{>1lmpeA}dqw!0!q_x*WGIDvgrAhX}2 zJg|~br5_%5uGqiEU?E`=S{MnXgQsfkjCF^!va^#?RUTt{cw?*d4b`$L3f^KX3S3Ie zRqFNvO=j(OYtAyQD)ZTqq=pn<+sNI~WL6H2zJm)E;N}cC(pYC~*?@mvOk#?Qi*tmB zTXK8>9w&g|Wt3O2*=TZ&^(>ucBxCWS?N*}VDjB7+7@>Li-g0idHA;&f?k^+U;0w7z z^mV~jDCFmJGo^VF$hYL|+dIZ&k?QL0U`8Ha^>1%YiuL4lfrGNeSwOYgW})2zW7*@3 z@Mgx^gx)91hU`?9aJz-6qLfx|emi~Muopq-;sX=Uy@0tcqnCzm*R_LVXV^QE#T%mw=>%=Z#$uzyF935vDKQOmH4n1QDat|`2U=>5zX39BT|9V zW6fxjNc)Cy1`zqQ#meUUE1rOWrk|~MZ+;)r%aPV&S?8lo$Lnns`|{b+9K$+wiDul0SXUiGeFVZn zfUc3sN74ESI?m$+nyqfgnaO;mKBa8W&=BHim^74V{1PN5DbekM5MkbFL_}@7xdAzb ztFYXVB-X4dp}ZRNg%X%YmxatC162br|H`Ua;54P)8%tWkBEZ%Yv0G+|jy6@oUCMcs zT-Mzf?=@>(SYF~WoM7s>?k4YsOxEA_m>YvRgJO{irr z0}`7=axmyD%|aCkn(vhORtJs>uH8K)=gTJx{H$Y^<)g{pY?_sXyG>Y%MXQIk-si+E z?Zj5;_c+++JJAqru-j3fhn$e3Ycigq)gNQ(L_KU32 zOpqY^X?>blg?^`TD|ef1p4JFOxcyHP5i4705hzuY0y28`^DJ$-56>JYi_zH6pn8C( zAO8~GP%aRhgsB-{UPThqhsRs;iu;cbF%&8|iG(ho1WKC_cnn6ac%2dC$n7HYDjfwizz zQt~c%Hv6!6-=42|&NKGwe)J;`Arq>g-W)=<;WuQCH`Ie2y8?3(do+@1#;*kk2g$^@ zK@Dg*7~o{pEna(BVvVo*dtH^risw&1UZ==K0>w@9aZ|S$p{JfPCN?igh6@sb})zmR2(vLrsx+Zz@~Z;xc;m#A+S9b z&jV&zvCOL$d=*2)M){-wcE|E9`0bkotoZI72}S7@AGT6D$L2d8(c0wTO0nbAVnc(B zb7dkD`>ru@vKJTehuDE%V_OO7H#Behl1J%U2kTEm8sqiANA2|x{?{JDm2}Fl&8ymr zjbxR+`ShVVai=n`%giC8rcr#@Sl#GM7gBh_%XGbk4NjoKNQTs@CV!5*8 zCyv2yM*haS{VonC)XKo^@Qt9`{EQBBs!=Hu*D~p;G|?gfH)2OC@=@uMlQNqD?z%xTGiZ2GXik!dHzxXTRUR*?1u*=6ymBtZ6@Y%7{%7 zJU5^!(5XDjl6MQH=YtWnk65z#ThR{TAcc3X0Th`PmKVJ%gI{n@8NduDL*qu;Y+dkhFP;k zkzI+~bAsT&OyLQu^rhn!m*FV$B2IZ_q+z}A_5`fw)j?sY;_1znUx+k&tk5j&0b?{OUo$w%6AV#O& z93(e0RS#8Q6_J=sGwY_GH$-fqUGW`X+^*^V6#?|-;2VJPdYHZVI4)w344sRanb>vx zD+s$njgEk;daH$7ncxa^bq2Bgs~hP?u8AMIjq^9(3OOMb9+?q&?l9R3xSlk;c(YgG zmkq%T8s3hqJD|s~{z3LBHb){Z6hs#b_>8`EgJhgypCx~HZTAkxg9!IT)@ZymM~^|F zJ3N&i&(+{p>zGU~DLcWLhMgrS8C*>I-nX0GpRK0YRKN^6eapa+F_{cSYakjVWB#{2KtcF`m;mI~sjD^>*Q+a@IfRs% z!j;yxP%GJA%XBWT41Uw7ZjW_ExcBu9H2fz!mVE<%F%PH1e>t1~Wd1C4?fKR^8EYHZBPQmwi~z0Ph8>hz1@< zykeS7fh?e{r;*($tQ!^Z+BFpj@|SBXgbTFHoLZK;{+-0?yf}&B|vd4TC_ODDems> zTHM{;-Q9}2TXFaAx}SHxA27o(1IZ-W`;@hgMcLQLKW;aT@@NxdMBO|L2os327kcA9 zdK0GKyb{5;{GT^X4kt4_uEKSHE!P^o_OiZ00hl20WjC~?=L!A&`MONgx<2rmbhnd| zbf*=wbcb0fCQ{;>dF|(RlzZ^ljTfvA+h0qzzhKGR!W2psI+#E-s;|(Lwh6+7KN+~c z#bE&pBlj*QDJ{MX9N_5K*?3_l?L)P0%V;)vf;4Z?T&B_6cgz}DTk867&oMf`Xf(M3 zKI9cayF5fZHa^i_w|T%H*!akNsP#G{_%X0CSI0BpINvRCbeKPftXhG$eP->=C(OHc zDgQA%`CWc1lDUu3{dSI%|KF9aY52qx&RH(}%f-ukc1&zCa{zFvS$m%TWFplb^nPLO zk~mrlc)9hJ5`QK5g)hWK#)#aJKZG!p`R&Gtb+_^u$Ni!s7yy2+JDQ=u->h8ZC;XD4 zIk_X}m@%*DxLf$?%}${GzJ$-(a&n{6B@|}_eU}P|q^bG-0+|~!_oOS&{Cjd5ElJ!; z4SNv9Li4)G-WGIhzwivOrhniIAr4SJWOeMiZ+aTOc2lxi{OSn8B%pMVd88OpQ6b8S zr4ThuPLV}-H5_g*Bzovw-2u|v zXecg0Whx=4wJ#6ETV6IR-W$P0q$nFDIJd9Ls?+d95Yo$g!EAW?A-NM)j`~{L(ZbQ-mrckR(%v$@OZ7ec@+G~Oc%G9IH^&j z;?9|)rSz*+`nmCVLqU3EO^G!a3qMqg{0M26v6}f^ziIPo6b8kZq$WSsK8}@Wk3qfp z4(UuX6s^v(s4xnLu;4H{P-C{!8|1`@@A)%!F z1U?3O^Kit}_D8Ygn=(Kx^Kps#(Jk9H0F>L(^cZ>MQ^i0C=i8n2;l7%V)X|bt3QrU> zZ6JW_7f2Zo-3ge!IfVb%SypMPrGR;}*w$N(rN7aZ+fs&br$xD(xAyX<&0G^zFI&D+ z_KSd#jY^i3gl!1`9}5|VFjjeSReA4QD71*XhRHPrs-ZjN(U-PLpT4)*ki0_I7t0R_#`YwT-3gdoP__^icVM980kA3PKkCh5G>|*0SE6 z-@KCddADdnNC_7u^QZXIi}9Bzm%Xc@$FZ)rpPjFPQzCfPug$y1H1vvbXp%qgSi(GF z>Z>tgojN>4Rms2YwN$hp27aGyW&t8~QYk4x&}q(=ySklspD>g!_u}QR*Dt)1J>4JT z4xb_YjfI1&7j5Z`?Jdb0$;!bo5C1no9GAFeJ9qc!8YuU~QDsNgTW zB>-aV={NI4u>>U->@=IG*#N5VY|?1lryeKvS^9w15Qr~)m**}Q2;zSMOe;^)wVZ{D zRkNq{F-o-_%|b-`qEdsYHRKyN7F|J;90FG(-g+N@sq{O9l8pM#0;JW&a7Pp~1a&ly zj_OzQrJ{CAub13F`VVD`R_u*#T)L05$@KLHtRH*w%N$%Il67VowLCOc0l!LxWO%7~ znui2~IVzJxQ>J|X={PkSv!#Upg;X*x6)PEylSluGKZLXyap87SzYYiyn@A2-H4|@G z-y1~&$1CD^NLm072XwQz(iE6ao>}ah%)Py(4AFlfV!%?osYzJtint^O zA_L|3g>*M4TrE%H^VGJ zhHI|O5N{;gEyF&Y6W<|j{S^uhysZxOCIiuaQG;tY%aZ#M@cP0ln|tqHvz~~q$5nrw zG<;Q3pNH6d`28XzB}7w@O(?PEax?KdlJ$zv1UQe&wK`IH_>c5729Nsh-Qb))a2VK$ z>^gaa7lU#4?>m7Mvc1KPdnfL49hst4F=?p|O)(397Gx{@>4(tebUSc;V>%jiC=IXo z+Ov$NIxiVD(1R-MtK%!@ijH19ly&*Tj1$2O&Yf@eBChsEM_)fDON96w)*F)Q_hsIn znOI6lUxJliG$X-aQjQOZ};*%|C>*pOpRwt z0(uzHxuBt&<}E*@$G6Q7Pw>zH{Zv->jSVq;#U~|DLhYH1oeeY7T8$kLX-ow1mLKws z1y81J-Lo@>bj^z|>vhOG8yJKf*E0(b+oM+ovml-rA+p(%PhcbwI}=@af57uttY7gc z5AM*3Jkqe8^40F@|uaMI?8lJXnq*jw&} zNY(vikf1`CFpfuJZTS;xG*)bCzw~5pc?aBV{(-T zY}ZV-Y8Bw(6HB6^TNEo&Ey#_2JgM6Z$G`#X2-NFi_5n56)@r=|-;gt>&sPfbZB_L7Z8eGIBFnPb;w%qQ@k(}whogFA+p`81hC?U?L`$3yX z;u8<&L1wO||E`-$WiUoT>9-U%w5590IAc(bO+q4pY%S4ZEKKLn^e`w{_X-2hB(FxD z0RzBELi?$kD9N4GCaS4Ru(d*B@@Vd@!}9y0>EF;+9Q|s~F;(v0ZhpH9Kn5SCyg}o7 z?tyy}WzS7F-gP_KC4a)in z8C7ewBxm1V=#2|Y7@)vU^kTwd1x5YTZ{!{vZb`P=VC{f6xkGT^@V)oU*QK3}0Z1wWF@!F5r`!U!U%Ur4 z*Dr0q+9pfqiDTWNMTLid;fYd`)|w*Zk&rHVYQ1?o=})({A#(1>hX#~OnRG(^yC_BJ=ZzIXt<%j> z74ar!VUvhNX7doTIk8a{&+5)I-DLavxN5w?-?{>;148WmKbWRQr~bK{B~j$R@i9ve zz!`NZ<7wx9f=Q`Xafl>egbkcAMHWYt387;?`IhW$GWtM=o1sxcUt;N4Gwn7VTt*bi z9Sj#LHiJrl)Ajxgc^RAJWgr#y6iVcePxkY9(dL8i?V-LAjJ>in)bq+?(uOlibYDU0 za_{c?vVc1K@&N~F{*kItogt<;ZgHm0BQcd>aX|9n>Y0 zrPF6Yt7jSQz1`A&;@H*gxY!v;gE-{#mz^SOAQ|1*n3e;`c6x8KHu`SOsx#X+=BWi; zLO&cS6dJ%Jf4PPT{}tBx!h#+BE`$hv9&e|Ao965Bb{JGZ4?002bxc1DjiF_+UxZ0) z2e+HKpzJyAQT?SRb6ASh>;kgJUm9ugKRA?@3|oyQ+`4>hJOq!3l%%*yc%ccUF@`=tu= z@FsU12``ir6tXY`e|kR5oRhaO3$xMY!!^Q>Iz%@?n6+K*@D}ubPbS?-y7128nKFxt zU|T)YNBfcXeU_BF5Zy>)>fiVE}g-Oadc8PM8TX>wg+f4#wpZjSh<$C zY%w(G7&ZmnJzMmlqjve|JW5+KfzlWWHa1jAQlz1@u$eIqzV?%zB(#|>821@qXOlR$ z;bm)9#1+!pVtwKv%A6z`qOoWCf|ze+74M4y44UW8X7NaRZ8JWyIs~Je{*|7#Up;7A zOqnzrPN+yRBuX2RAf!O+hmeWj!N8_yimj^7IJx{gTzsDMdVZ)SZTsCeuZo5JgG^LB zR!D?`3KEK(9MJ2OB$O;U?2d+YVTXb2RNo);EflP(X-yPBKZH%}fJ zI3itBIeo#$*syBtmw|hQR3Xq|qih)5pup~5NwL*|Wch#ql9QI!#bMJbQ=mF)W*)O& zH5b)UW8Rdb0yks@y*4?FuA=`dw)=JWINaRvb6F!0z|qhvlEQSHcWgNP!cV|0YUX=n zA(|_9WQclD>dV@=2LG09Rrg{&AV&ky`Q_{v)K;4*Ejq+zX9cnsysBP|@DA$Mnh5JM zIYhfc%mG|NH>RJoiDV7}7*+9h$@W3b`*8%GQDF6A?Zz%OpQ3A0<71poUi%O-GoY3vvgmBzO8Wb=A`jXE2nc{JmNlop6&OlLI zv!5`bZh3@KWFVMlkLL@(8VT$2Qi-?E-@>M!?l4SrOGms|9-@g0XT7*6nqXCo!S;088 zTeZ0TbOIVO2XqcE@0XrxvDd*JsgMd>>pSWw-3aF~^;xZ>!9V&oXP`T)&=ORRACnyK zWGucX8Hp^FRCxbnv1iajFwVSx5uqKw%h4_Ut6_nVAgq=Oo}wQ^EJ%OMX^=}86V}GJ zUsI(Qo8V}?b)(mJ@xb20pF(?Hp!lZ@ z_bPLy*RvTgyi(J4Chods?CK4#YC$=sXUMxc{q>ifczT!Qttaua%48vxpi_%7Hb7(* zZ@XAVn*O}?<<#R^*?Z_+1U~pHEr`wmR(d;_Tz@K3pI^E9Dq`Yww(5cJlDBZyZPR0Vq5go;^OD!RiG6R&#NaN!L0X4twPHg2K zm>U<#(O4AFl_(OZsu;@SLZ*uV;KL!TilRXnqH@BYUfZ;>-Uf56Bk4kS{5G7zW!^7C zm6K4)1*@#>aFV0}!PR#S%(j^RP}S24F}MmzkG8_ImM!1#gVEBggG@XbnlSidc`=!<(c~ac~bO zdK&`QXWMy+j0a9p9?WWMkc_Jv=gT$zzgHV=uL5xmd^o>{=7Q*9GzmxB9f}D`F2SKi zL=4q*>3Dit7At@NsFZHaHW?93u0)5yK~WF#nEv%!PD23`mrB7%B3X=IO{f$AHjsSr zbUIrZ=zRqP^=~axFen80_8@xHCMW2c!9!AyL_}qgOu7A>fin7#^5+lLcXx2h8v;;g zPNdGKJ3iygS}lg6!9lv}WH$iBiU?n}>k&kdN6!JX35Ga2D)<#t*Or;X%P!P)@$UTV z?-N^w91uEW%9-ZSwoZu_B2kwZT2$Z{=)U>jiGzb9>CR6xG!&W}^5*_9dv=G1kG~%W zWO#1%_(w!U=`sIu6(e%}WhPGM^SNl*s`{&f1Ij-`s}C#9-p{dASYp!X%`ZX;WFT~g z-1wxc9H!0cKe+QN%th8sk+B0r(;)HJ0JPAfmYUR~eo!^#)KFbKFYQ^s(`U%b4l`PO zHrlh7$t3szX=ycj|JE>??q&x6O5LQwd~#td*g}rLO@IKihq~^4w!!N0I#gP8ueByA zL%<+TS*_xO5#&ST8mnJHmPm3eDcgJnmh0N)8otpL*Z=e$lKs=%KzI8kPFf_A=9gDa zpM>DMqQGlS+Vb1@9OpuL;dBuA46~nHmA_5eoC+7X|XO@)Egzv>QBC$gm@sD70)wUz~Gv8aB#XR|cdo9OmX z($?+$UuGvznlMW0;L``iHl{r3g3K>a zHe}B*l?2-OMXLN*q)Ld`Fs4krILEHV#V-UN<0vQMD$$2;#OW1}mQT*A6u*+ZX##A7Xe8jU$GqqM zb}U2%K~w_(BkG|wZ~bi5ltv{zSy;TNI%|*h$n?51*|1!_`BIg1uM;yDpV<}1 zOgsi9(i9{Tu%Hm`u(xBp62`)V&uJ~W_71u)F3h+S?$ax-)%FZ+6Q6nuZ3d3izUVL& zMq2WpY5N3nN|(MdoqT`^E11<1Z!pje@0-(}C+E?3-v`znr{Lxc#YAEev*0YXT= zwbYp-mlXrW5el3mQhyp_)JQ1Jx--SQf8i;Iu*COb;LFfa1tIeBiEKK1u2(FmGa|eY zXd~c0CMIPrFiG}IDqK0N7)pE{y3ZZskT&!rg90NN!Kp}@@+TKhb8(fil&^?|?6QCP z?TE|`!%WGL;mhxE`0yV=eonxQ^NwlSR zLYlyR6Zr9n5|3Uo^?O)u|BV zH{&E_tSzj;8xW}!^Kcb6OujdZnBwx-*)L&0ee3&!Fju^HUrl@D?>}Vs`-|PHA(B2s zQ0~`lqomT|LA+UT->o*E&KDCFMb;!zRMyK9b5B_9aFdhzu`}Jb&%lxpaQDC+TJnW| zbJOG0!OK1I#G0j+5!oJ$9f|$p+<7)6iOcsopzG!1@9rF5P7JTL(~ph3_R5d;Ng!4V zOZ6v1M+5^k^~!=9a$|3_aKzO}gE*)N{^~L>`V#))&G2<5Bw6bL!&wJsT}vD;_m*5C zUmCMYbL=F!E1l~Y%3WZg;7=OOtweFYyu1olZ=MtaF5}ZvkO2Vvv|>ZI`nY1{(>=gHkc_5@`F%TRsX40Tu_z|FZ8VlNZ0Oj zs{{sMJ2z9o;3BLo_)j=){7~~Ye%>7<9dDgg%p7h zj4Db7l13BBEg03183_r=S%z~e2*gsQg+jhy_f6w6 zN)iH@VaIENd>sHgWZfvHj$*G~(j;zng&k!I3))Ad}-i z6S|FhP0Sq^hKoRjs)gC^$@>~~Sm5p7y2g(z!_4a-6_Wxirm`JeBcU&6?A)J&L~U$N z$bwObcYrGe{Ce5KU*Z03M=r_w$x?=M7iO zmHN<%w5Dof0{|t2v%uo$Ufp1twA=x1Qh$(NMJ;UfQ2L?bER zOuA{cVD5PO^zP{4MI_j6n$+FZK(9Kg$2kf9Y0Uqz=a4aw9e&a*Z{{0lo0BYw8QP&| z>m~=J&isSd=A{2~(Va$Dw9Stw!yn!-P!Rf@XKpN?@LEE;Axe844XTi z;uEJ|KN~H#|MS6ZnR105w#ZQ_38&VaUJbeKgwg`pM^|J%Cr4>q)%!vbXqCU0Z*Ms> ziU&$|KZVtwPAesnG{T)dy!_}OQE+xcBdMMKQK0c(S-qvsy~{RMdZax_QZ_pLwePr33a=MqKbgQ`i=&u zjtu0o09Qo=qN-)bw?6d>1xLl|ZMkR+wh%d5@@u#p@p*I&i z_36(blho z1!@u?8vgE{UE--H|6!FrI6S<9&N?XkzUMmmyJ^iYcndIgEHlfmLkGl_V^x++@;^Gn`wGpMIfHt#lAreK*W(R3JXX8Y=h2USj zj0=`g4{%2sY0Rc%(1JVwiyR;xemQT8-h5l%G};}E)N*@XK41Ew#}R4%^(zpln!ijD zNw$@0QJKTVKPK|=$a{b?#V&wP3^}zpIKirjg{~<=JJqz|wEEk+%Xt0SKdrL!T3Lyk zt`y2>4Dbo!7;O!9dC;yRIK|E@Xe`bq!y*o#M_; z2%FA>z`wSb$IpuNeM_d?QRp|8*ktHw(QSBwf@}M6r1e&^*SVlgPf{J-3x8_u!CNx+ z0+MNTlmXNDB&$yx=PEPG)a2ESyqBNg^Npa9l~q*ryeLDoSLXH;iTF2beMnXZKC-iK z=&!>t5IiO`f6-iydA0p#zX~x;-AE3u^o2HT%D22^R$Wa5UlgrdDP!ULI>d}nfkJbA zoMyApX#@0!_fqHkZN~wPKd^z1h>qsq<(>oEPazsfsUFENo0BP(Kk3zVnbenABQmxMnXX$fQV#@4Vga7pqUBv z5k6{#?CG=mp--n>08960y5ns5dv^cJXIpA0J(~?U-wz1#&ypy}8@hGo^XR@GcA9=@ zx#xUdzw8WJD68;}_=+`o<{C&bdvlnes7G!{0O`++ad<3GA(ISLcS!1r9p{UH6bQHi zvYcs+Rgc1?)uG6b67WB4PH~ssZ&5(dJ3NK)1r2m1r_dK_m7W{IndF99q#v=Q`?VZR ziU&c{beGvxO2V)XMe6MzR&gdIh7Gb;GBPLh!JX6OaL@~(0bHeP+J=Qx)A*n)2CH~C z^nKx;_+8$g^2^^Qp)`!>uLURr$%OP9vWM*=%7ICOAz~;CGA|^*?hIGzI?0-5&pU%* z>!AYKAc15)v^L zF%4<*LbPF5SGEgPy7G+Dcu16*y@&1Ji!e`IO8nl>QX$G1f8b?T^dLs_!#~`#uzF;A zHAz^^GbA7$nc$0ys5?u{1P&r~=)Z4ktk&$bCN;A=7I&z6Tb<25G6vvPnmoEPv+zz2 zvfVu}ox6-p7sVHV>)+TbJI=+_3t~nM0eIvb;11Z_towXRzS5)AX7GP09;~@ zpYJ^6G@5+B7g=Vb2jX$ImSzVXz$;2FT;zS?jDsU+zUh2<+yZ8r_eGicWl0#iVv5rj z1tNdr6XNcNLo7nolp)KxWH{*x&>Bd>(VcjVLH#y@@b!@7Fbs%jy|YssvISQ^KfPbw zeE1+!cwOPbF1BCVT{9Fh$;7dB6VR%wtMKNK?jVRM5-e1i-xylEK`Z{d;`=y#pbPW+ z52)wDvw>0%0r%p>#OH@X4Fd(sLlxPBA&zi^MC_oFEles1Iz9~>HT{8Sb3us;_*WLJ zFN3?D__SOGxyK#CEUB||sudo?IuDgWLN5sw>2IxH*tIoDI^I}}=LBl-$QfW;)N;z8 zw3)~P&>(v&PaZ@YcDJbQvz~6-xYe8lS|0;-DHQdnpG=``o*H+TyIFaYJ{1xZKW2pwA-g?HP$> z@(pNdn~k>TFI&b{m;#_MvX8Ov^h5llAjs!V`L4~PBPVi@%PyhL)YRMBl!z-b1U;y^@qUwa zIG6Q?{GSfA?#6z}3b!}reve9{F#rl5CdvQCte)n~>B`Rsa6DKx6qkm9r;f*`<^U|_ z^R#~FYr*Q%bg)4Ge^%O4YY$>IT~98+2ZtplMu~tv*u$P&i9h5&p9uM}8vGgMeM*^R zLOfnPuV-lqPfQWHrOH2Z(?4L)Zl)t~$6ey5D#>QzRNm3B&JknRm#uWthF;cwwkJEz zXCJi6sh4Z}x@$h)!#J*$<{Du)6pbxWI^fD~9wH+{D^)$IOqynchL{M;`S(H%S*?_h zO%_E|;Ys!=bStsq&mjQTP!~13Pg#Wb4t`&CD%;}W_{^6{toC7DN&|1l@#WM zB*mQFQh^>=Rwc(kZ21B;7H+5(GGMVRahCDF*il(|6DB53DUZ+#nJ*GQusf@QhN*sk zqeF#TA<;A}Ah_q(o#s`pt8Q+VRQ$#m1iVN+;o#dFtZGef&=&8iezVe-M#FWfz2VIlR2w~$UnSD`n_X#D%C}6t>o^-Ef zh=kI#;SwBOTW+2ZL_mQ9mwt~48$w%~XgD?NVsksC)=5HlM*7tuL~g+l&{Kk+kMe*J zINbx_t*;L#1@~M9+EF6(mhgujJb{1Rhs4^MaH@Mvq2qE@V7XDBSz}DN&3mhoX~bgt zn^;y?8o*^R5^`H^jp@EH@JqwflIFr{-Rb-dsV9FnU3RjlD1jq@>G_6f2wUVaz~j`v zR>CEeVUxj#{2vd_Y-M-xeV6s7_Ow#OHRisJGZ!y_OkNp7P?VnT24f0|*J9OpW5tWH z?u`Z5Kfk01y2Ok`5&|AMJi|YK{@~@#M41c;$9!tkpcl(L1f}D|V%de9T!W+OV*X=B zzs``pp?5uncTJY0anJLok(>4kYs5VwBniCL%GlqTS9ZO-{gn+qYufasm6j$CNer$H zD=kJh@&Zm4Cp)`YK&J5$UKiVDtW$rU!0R};_qJ4^+D%(41f}<_OTDv-HWmUHG_3=J zaNu;Q&oHefcCu?4w4H#Lf`rs;ZJ}C(jh+2733fk!TCpH`A0@V~y1(FeZvP7+&MOyR zffAEby3>X*A>0%554``%t>yL!v+9w3cHU$*Pk1P`K_&G39w>a2^7#{Nurnk`Tzr71 z@^BUDeohfVS0`$k+Q{F=(~_t?1*7})gshxu=* z#{d422QW?~!|LN<^rM?KAtmZNc%)l3AvGgTcVjzhz4biVe*NUn?ICt7dX;~ncZPJM z96(9QsTRp=qTJ#Ldlppoi&4TPgd!LM;O#50^t6Ae+}uKg;QD6=KyvTO7OLIu%*B8H z1~{a5OF*O!YD+B0w?xaP^|OywYvsw<$x<@SR(6Kh1m>c+VIZb)x@P+S;^;lS-w!=@ ze{Sw=&B+T9&86cFMbsbR@_H(_s%rW}XsBgtSC>GMb{#~c{GBf`Z?C(+lsa^%b88^&PYyV|40B@;@{BB(@jx^VzMQ*&-H~9jGez3bqOy0 zySNhV{`Sqn^;d9uid(`r5)Oc%t*oD!7e~EB0O7-|6#eWWiwl{8(1z! zUBwDM1a+XbQtyvrt>mC#-c=tN0#Qm3%x7M`-r;_AE10T1tFl zpBK*x93a~&Zj}raKml=*Wl4xQmGsD}JSRCKU?$Ak3Qku+5m!GdsTk1nn?Oa4)K?^= zwf8_)2tOW_mPbFN86zP|r=xZQgijQdVxEjunWPR;LD?|VZUf}Kga zFQ{FjctOSe&LBBxY>bejILaBSL#^&YwZwlHdz>VXh~kB}iNVQ|ve^jb#-ge)jTom= zrY!kqfEHb+rLE~@kRWTlHz)`?!5Vi`Qm)uZr*#7z(hTW$BwMWV~0_n&0OY%s5eAL-y9&iA9=kD{B;8drf4kd_*Z?YC4TE?OR#)6%5O#_@@X zPb#J#ExDh^7$?WJC(OE#7VQ2*A*OXbrCDk<1dS3z&}&!!RPhmxir^XG$zGPFtJgo| zXnPzN^vXotywxXhwd4bqAc29fD`(ufO1Ceby;L-2+#_{%!`9%;Ph^|^_bx^n1`M>w ze@!`?F9UJ;d^?SW+tvpkJa>2iq*(x!6du0WOo)NFxMoC?1klmf?+(UXu-d9@P=x^& zUcCP9W%Rh%d(e;6_Tkt;5=i*y6SBKUCl7e1;;b!RqZc}bAB8&rL}BYc{k-dCPB5CU zM7wdMzuSUPb;4}u0dtuGO6ezwO9G3bK2)e*Sf3UZlc>eI{+x z8yt4vovq!=x_JXnv-_9Rrp&(oK-{I$@e$nY8Cc6U%o7P%|1~k%^5CB5(q7D{=uY6= ze_p=2n5t#EG9=x^m7od-TAMa!=cV>{EK4-hjOTq*q8ut$#nzL`8uio4v|1*>=0DDI zI}#GK7<%Xm>~iate~Csyh2zU{QMLCr~)CtYw_8wv@(e=cJQ+d!pfcdsgmD-f!e>LU(*+yTENbpfn6ci>5q#~B0Ll%FqriF!QOm^up zbf?{75;yg_6)yGK*ROST{b$?-^=n?MzZ2d_KAr^MHrFn9aCt{nG%y0TV~lVD(KU1w zRk3X;4QkhS7QNpVXEbkeP`zSiYS>dJXy$@Zwj(3bFJCJ}A;96e$1SJge^b(Zn=639 z`TCgKo@Tsy)_*$qa%u6W<*YZ21o#f9xNeiqE=fuhvnOU*UL^hD1^X%LcB`ZzXOD2N z%uh3EV~6q<|1F6OJUkkfTmDpb03$BlDtSJ`MKeNq_pFeBJmd^ANVaP7Pln4L4oaZQ ze9x}c5t#0-#*{;N%I78k1#+lI%HF&<<=)%yd|lS+pmm_foKf8^LMfY!AfHX@eY-;| zaNTr)e9?7LP=wndxy_JlghnaqcRZo6BV-sCm`jF4E7_PaG`4YXHC|dFIrrZk~mz=u5=hdzXt8xC+a|`odOz(zV}T@ z^}!<6NaZT{!*Rsp(nuo}UU>3zWjyFWno~lL9GAnNo4wvok(pSVsn zB{wL-l-53fh>Dm%vPut{F$i*SVL4I^1R^v|NX=(sn!53SYhzV!3*JDo7wguiDsSd0 z?+H}I~2R@sH(K@<8UJpUI(a=AHW((PUn^NV$z{paFEk??90QCFnv%vCu2oxN6<{fw&AprlTYH9HnULsT z+eEY7rdV12DzxZ%lr&Q~AzOkfot;41U`UXqyG$uzG8r~2JcF9L{ftrq_t0;0ZTdI6 zi*ak9j3B+n>J#M?XT|`&C?$o$?{XE%spFsoMbu?1BD5syiG;QDXq%;on!*0cjGw3I zqoE{4nRC6Tf)mE86!?ncd+4rJ-w1s#0*|~%>7m1xXvaQ_cPNHwBfa)`zd*}n@g(Bv zI&=Mq!57ktP_}D=Q=G@X{6;D4Yw2IGV@l!wLBs)Fp3*pPCYhJ>9m#;kzD_irZiJ-}C z$S!S@_%T>LeR{b!Y0`Xl&wBOr)7of=gHNg$w zVHtg*(O9XJ*KV?RU}4tfcJzj9s&Pc+`ta*GvQ*hIhPxTOK9kfIdE@|ARIA!w5KUEP zT`=O)ib2HS4>(eGtobXCWCv1(tRLGLkPJ$eSpvfs-mg`XlPkk%z<>j3nZi&gJV+&C z3(W(mrJoL!w>BsgVEU@)^zeH>AdFXfrssGNyt(!^Q<&nR$dQTUtFohnq}1nh=cqDTGI!RD86MQMP3gny0D?);_y6^6NB|jOi4l! zf1ZngiwG~>-8}@&J{rHj-CKX$cinTpb}vayPCE}K!G~(ngQ>h=_gV;ZcJWRTYD*<@ zp^S^}e|y|A>bf3g!jrlwbMbNHln=(UxTg`S;e(1pazTciZ(dm{X^oeDxE<+x?J{VF z79)(&fmT7dPokZ|3id}T{eN#cyX}K@tqwC+x3r!md06M?4GgOMJeV%4uuU| z$4xsGd(Aoz$bfEC!*StYwT^>^*L&+%n$v}H5efuoQf>TM&a#$w9qs8_I_lWYsX6xt zo12L*H#5;*2}RET$Ra3;z*^QHGk!NcO24A|!m$!m0MNgZh*si`sSW5J6ZvwVhwx(`js9s0@9=jXvSG~iqh(^5sAe55!6=FN+aPhU9 zQnOqZr)=)=S4|PS{Y(E2PfxR&xbBPut9u;jzqV-5AR_(Qc4W1g*P<>*N;u1A&KDl_ zk*2f5|Gdt+%)hv8qd)xmXFQs2EH3t`F9M67KxiPu#MHfZLr179i!T9L&qyqX@xBmW z{=2h_0eit*ji};kNfpN!KA{Lp<{vU{3>C3I48O7t*(vpO4t@GDt?KDTnW;2X=(bxY zfF+LYz`h#$irnxswN&3wD)xxtF`caN!t36l1{9uyeM$Y`*43T$+5~gchPdjUi%@mF z7dy|!LV^0}*>MuKEm8cP1p{G>)7K-n4qR;y_M!|Yf+8z{NFeU!bBi$-;IgYNoxf=# z{((kBKKj)s3inOG%QFM{-kaA`6nU`K2ylzrx<66C+lM7ckRb=4nHnPWp;?@Aw+_ZR zwmP`e-_+HW>vqLX6jeIg8@+i;kLdfUmlZs@DUhp<_T3Os0IR0v*lMF2ah9%UfTLUHB{n(qdg_SR(sg+woV|@ zDXrE4i-x+Jz#ovq{s?JZ4Xr@e8;gFB){fa__S$m5a8OxTA@DRdHpasz+|RY2ETBUI zR2hoK31UKR;+77$IHugGiamgz>}*ORD|`nH(KB_ zN%3q5@YLSdYnzc!P{WXb^kZ^u9F)joCDAICXSYt``YJ0>-V8)-{=#(IH+rwm^-arB zPy<3xDyXe|Px)25%=v2s}q!*6cat7Nk^P0UVb1A7cSh~iBz z@_3#DcC%?#JJaXuoP$Hbmzz9M7KfKh+{obIUBe6^k{@(6l@+mA0kQt>xGE^p28=RW z!C31o1(U7=Wx8XmZ~vxjp9?4G$mBWVcydb_7SlG869(S`)YRZmrlxHFJ8%Ar=K?aE zwu850re3w;aHZmScv>BQ=adJOFG3rJh)aY5qt44YzUB5aCa>c|FJDsE^~iDpViCMW zKeqyA6FWc@vxgXUJbIC3gA{Ge2Do)E-}a@{j1&Yyg8Y4OFzyc?g}3Js62Y9mYI48i z#AHf%0iT|xMgu7pO$B?@Aowhu_-q2SFA%@}x zKH5gW)Q(eIGqS`|LUel zDEa}pD~EmEzs;^JTIYXyz=(X!{o#uX0M$%cX~WH@A~3^vgw!+#m+(+SoeWolzpo@chUH^*cs5Kvi?v{U+w6tNx1v>dN%|*808wZX|1>a1VK*l z%|SJ?iLT7;6;olpo>8&yIYB|jzQ1-=;1b5ntcD;J(F)j5EVt`JlfF)W2eM*G^$#ww z6lcHDi>){U>DVBm+YcW5%dPguzMEe&3o|2OUZcdiZ-|-}UdQ}h!}CA_6FS@G2%ec3 zs6w(0Uy4x}Plf{#4QFzrHdNPZYHH@<;b|ODKL6ExrORJDqX;O#rv~L5-zib~HFF7j zFKhAhNQ@12U`G0?D578rOc-NU$ecg!;D+}4)HPb}kI%_VK#NQIb;D~Jv@KhSXpn!& z8ZBYn*tzC$pD-yLhTsfU| z521t6hNKqfDwY*fk@8>_&WPpkz3?Ehva)vxB^>8G4I zg|7Z)={(V#Y&p?XZ$f7%RwyQ;y5z6#QR$!tP3;~4B+stL@UE>9+DtuqsQ zxZa)?75q%69E>`5`mpS=V)p1;cC9Ant3;Ah6(gK;YQBaZ><){u^+dtex!PEJ+U@*R z@BLh~6>h0B^ z3Z`H;eC^}BJeUfu8nze~CC7uBH+;!9x%6>37@?49xkWuIuONW0cGKS@cJC;C&>q8P ziWVe?<@n|@5Y7UQN6;oi`aTa&jZu3~r!uQoDw!fT_w{L8kwC?n^=jk=WqqG98u|s* zX5019{-m(sSBb?HgXpJA+b!R(kZjFSS({IUHkSoTzl;W$b(;g*&YuYs>uQ+PgY=Eo zxef^5z1K+e54MEzFYNad)&56*$a){i+9@ro+^LT|EjC}ro_a8)LN6N{;(7b4%=57m z-u$n2tohOpNxjbaQy_c3hIo?6o@*yn>p_dFh2+am+qRW$LMH_JMxvI6+X2dciQsU( zrMn(Y8LR3pls=H0kpKGM_-8ouFNXQ7hYFb!i5UszLKet&C2yHCMv^gR|{m7U-<=|=iI+#YPTjmAxi0Xs|1yvk;?m&=XTTGH|Q&we3 z`64O*+yCR~E#snUxbJU7V(9KJ>24`$7#gG-q$H)gkxmIgy1To(VF(4Kd+6@`pX>fT zpXV*`YM42*_u6ZHSLca8smH9KO*XY;7`-qmEMqcFBI-f`ZHc6PKJH&F6EF2DX}Suu089Oj$eIF%qb)H-T9t) zDj`5@N|)YStW(p!l+>&Wdatp>MH0{X8f+_g^+!y``L>7!IMFtgq7>4fv*6mK$s|)U z#fP8yM6BO;y$u7MFyVeP9jn#0jyTdR(^GQp2!7_Mh<56`3uOap5p9(W4jrEE5_F{jX!&`acpHfC zx=_M>K{do}+$J<;s{D3>h$OED%=}Ca ziB|Mi_U8zu%v>&X2jO+Yoq)I5w@s3}HHE*{?Pue3Q8~56-&MiSy(9ZcMl}i7tC!Vq}|1zeB3g^N7hQrm(W@hJV`$E`7gDN(b)-X#O+ zP{V%6>yz_@R%T6h3wcoYo z1)K|%v7Z)@U_wzG8u5||Kdz$NEK#v=tER5q6NVQ-Di2&{bh67#tUmm;kU(GhY1sBf zwq)lboh^R4P&hqRF*4M@lbDFV)RjV)9PphLbRIWqM09Y&>Av$)E~Qnn{}~}sim#KI zW4X3RctB(KKD3a7sE8M|PNQg+?R&^bJoSOV*jdmNH&~mV264vR>&wBLSBY4Wt2cv0 zk|tiu>%9GcvkK@J8q+b1L@c4GUZpFZ8*^_myoFUF|I7Zbhd;*8(neR~+O^(=Lo3HD zxEXbpij;8mbAMOp{EOU{sOq3~7TexNP8SxLE(^M}rh~`VEYU6~I&h|#RH1{!3VCQt zIxO#(LiAlltkCrosOhx89+`!%Z}Ghm7S;%xNxvn)!jPs}RwdQ}c2cnPdv(S=d?@2Y z5`l4mh&bWK1Gb@!DrMm(v#)=M!b7nTYLx@g&Cf+J^ob=@X3*dJZkn`I$jG)H_ea|_ zW(Yr?(u z=0sOf`gWMgYA0%sljX0hX1%2)mrm0EN$uL3hlDeT{lHaYTELA)UwOTs8#omPy!j_F zP$NsEWsV`|TcY5>0hg%l8f$pp#*0l)d}*qsR=yv~9DiH2#$>JrZ%=estn8PEt$jj; zArU_i`XySHspPP|Q~KidrAQX2^AlEGG$!4ILi;5_@|w6(Ow>Q{ZFpEA1WFon8QG4A zKDY57j`}5I6L-Y(VQg5^(@ZQRs9>3JvBR;Go25)LrGC`n_DiCK)n_Wg2qQj;|3vAb z`2X^DI52O%LJPfhzxm{XG19TG=g{+NRCO*7B#)W{9+(|{&L=#&bzR%H>kz@ZYFgJ8HX2db_VR73&Ho4ze8Nn`7wo3U|AwiZM};gAnj(C=LG#=P^a8c` zUDATad7HGlpTBz{QaM{YNx<0W$Cz7)KO8TKMG1)nNp}@$ z@SEF@5U!d`J$n=JU2Lqm-Nz>uw$3fEk<+f5f$u|#fzud@V8F6hW`hNZ?XVW-KXUj2 z`6m%?U9bZ(vMEf+pO?)d=f>Oy7UrZv`DC6<9g<)U*O$DGRkpiz5B{t$>80%gJA;;N zz(>kt7=K8s2R0Hp;=owHeGoNxXT z3s%LpN1MA+?GCT3$SB9pWcf%2lJwt^4M^ti-i!@x8@fYWxkaX8D!x75i0n9(V40qs zBQ}*i@$O-rorfoB@f! z8968^SvnFb=>6wYpeE{~eoKGltc$vM$vn-3LjI^`^~AVYB_#;gD$7GuH?__x{s?;m z_X_^^ve-369B=Y(5Q08LyPwSs0iZ~Iwip7&poZGo-gNzzI-3{0U_Hc9?bB|?OT9C3 zP!xFkiTsD{LaqCYceB_7Exr^2v)g)zo3nHcyL>5#;;AXrCv$u^dbQH@su9I= zA~=|THh<*$x9NyzSaw9Mh_4x{B$I9w>kFt~GLne`#Dl*r@P+n6kN?C(l(+Nd> zzNvhG$^P*|IT^Md|6g#7#&&MXL%^|ZJeLWYc_gJc3~EWYS=M}M5z!r@6SzW z+28ILo7ZPYhrMEz0AgzX*}Hk%GF*V4&Z9K@A6;b-bKHaFO10XX!%42N3Jd16E1%`) zRt#@kWAK}l)wg%GnQb?U{tv5SQ~E}4H1`r)f0PxLj&07jyl&waK^C9bCKY=mTTa&kHf2;q-!kj`zVzk%8VVYgVIVRfkYE4PwfG_GU| z;Nn0kGq@?OM*inr5QC|+32PHV*^-(b1}}Pfq2dHh>rvFQspPfZ)SIy}#0u-fG$VeD zYFwm?GiPht!S=sO^9Q1TQ}O3###b@`En>oR0HtOJEzM|ff?Y7pmR&3-t?Q6!y64uH z&&UaRyQHdEWT}@M*2Oc()jO5NK?B=N3N$w`Zn7V$!yJ)MXwGB9Ua&q<3bT$8-gWfk z6&_CRlN?U&1t)g?ul__aiJ`duJ2m?SY{00G2rQDxs+oXz@R70CmRKU?pR1-6ze(-a zg&sGYjhT-@Bi$k4_Y)YMIZvl=_@*@C_vE0+b27T3awd9%3=36UJHaPA|Hl&lAa1~Z zU4aX7E(CKbnz#E1c)n@Zt+(ck4M}HcinGAkP%~og&uyVlsC48iBO^Y*dx$ZYC4h5d z#YrT!uIq*|rOCUSN?oxOr(-}DFjRPLF*>!uMDN3y`}$U#Dd!baIAS54&>!FJT~~6i zg_#VoC(xmlah?MQ`Z{TB8|;cSN@4UY$dV*ep4m8Ff-<|Llise6bP_G%^2qC$gIG(% z_5Lz*U%z>JXUJ3x@h)}|LOcR}gg(JUh_@u2VZ!E;FO$X_T;2fn0~HPY*%9id>a=%O ztC15*aeRVq^9TF+U*5X?j@Mf-#3G#P(t3Z8&)peXEDHQiJvU@t3)0D}qDQ04BFy1+ zSm9k_WwFIN%!TrX_b4k8qRd?xK=E1pH|CFSB7Pxh8+g&F5vm^|uVZlNZ9C%*q?eHs zuHGWEw6n->B?us6;ny3*(ZhYCynrV({&p$|&8vt4S{c3wobBnJCK0*+`{|QBKe!VV5D7oFCFUC@4pE1- zU@hL?j8>1)wbyJaMV~q|ie~A&DLAqEJz5?DZYn*mRYoMBP;Hh-2$`WYJU8AjO}L-9 zE=90<$*~Zlr0T=yH@JVXrpEz9p#Ro3=<;Rvh7+#r8YrqWAH#Qq-`Ig!9jjMgkkP`jI1 za67T{c7<~IO-a`9^4jC}bAQJ=pyu{dN&sEwyFA2bFv2SNvC@CiUwPOcO4$7p#a_3? z_Nr_AVtIjYhnW+Oj~}C&Qcs_S5hBbN%dG-Y1;}AdOidGkc6k7E0Yuuay$z=Yt`yg9 zsy!}#I0hgN6Au%|Q3Dw8!EbN~u146yYE?w4>CQluszXpwqRKv-G0czK6>-mW44@ym+%07uPl>zO0>#O&?OyC**wU%D|L5v>}- zi3;PFuWTO!NPZNUhi0qHDloQ-6eiQs6vR~ONf)e|trlyvZsbR|-U3*v+o%dbtD}FF z|ImZ!lW}+4ZqU#tq3!j@pT@gk3LlXAy6#p- zjDbRSPF|5P><9Yt99+nzAr3tw z`9TA7O}YcAZt>0{pPjWOOqoOIQ*80*;UwVY#B$Y@o4U#R{*lmo{UfrXw8Su-Yt!o( zl+{jvL%US`!S6dqyH{p3o;O5lzP!QwWvfvzO1Naz8lZ_3&*6IYr2yT*?M)Sim<(U3 z>P@Fz5@0-ELHLY?D5pgLtnzfb!nkJ{em3YVqX0S0$qCO=pZ;}ao7wo=`!hf^>em+4 z)SQd?RoKNAbT(f)bW+*$bG%8s>QHJQ##D<)98+LNR=0mtZnD`Ps(KhDOCAtYxzLGq zbGIAlQ_cH1MFFN4Gm-Mpk2v$K-pLzQ%XUVY#>@-m(Cc(%oOr0@=t7?{K7ZYV7;bn@ zMZ+jy`^cIPyV9K%t7_I$5^mY4-~EWs{qOV);r2em@GNFsoOX}x zt?EoqzDCV$Xf}z;?(WsY~o;W;ji|0j0CPYQ+vJO=$A>%i7kf^vA1x@{k<jqN?WP{muxV&DSz&#FiD~87X9z>UMs^ACFL}(qRtbgB*VDjOnt$HbLdTV4SgpSm z(>tQ#nf6Z5il(hEq|(?s>w+H2ir&`cocNv`v6Dau1}?rgTJW*gs|7{+6}Lz0h?!^# z%hXi-;}z}yR};VuHF^W@ENP5dypL9)?bG7;Akxmw&69yP^Ihx-P?BE&Zv$kKv_Gze z(dCVrl0Tk2l;^O+ZC8@i_QRjyr1K?W1Ch%K6#a1G@i7 z+AEDx-g$}yrQx3empCTa@^KRpXf7^-=v!F8&f81Z+kYQ5**S-{Q&;hQ@t3GG&~LG4mb<3Kjtl_$}D zhtf%NI-4?aMRuhONAI`rV8H30$uJ|9IJ$f3MtagA`{Zj9!nx_W?8G7xY;F%3x7ShT z)N2!2FM}Hyryao>S^uHT-+%S+L+p+F^+3T`Vu(tdispJ`a&S*V%DihmaDo{brby3mTY<{V<@DV`s|!7{Cg#lzCI=)2+s z=f6bsN0&Zhp2%0u%4K2C?j|P&w-|Yo|9bMvpJq{F0qcJzr7Rje^EkH?r)iX%mA$9B zk{){g9JYvlpn+H@z~DY-r;bOrq$eXQ)3$ZVe4d=U&Q5CF!E})v{wD>+{m%tXV~C4q z<|=DM^ODUo1YoXd#j0#5 z#LrwMfFvMvD&_urOPt8`r5}!@qRQ6?f|G)o7U95K3UWSz1qDa|MXi7VncVyQ-6huu z@j38LWw^wy{KQ1DD<87}GTCQXbD?;E^+lLjmMA1c^J1^cV8x{L6g2S}HfI$y z*gCGcWR{hh9Rrfu{^>Hkx6o{p2q}v@_X))WrjcMuN~QVDOy9{Oa*e`-`|S7xvwamJ zbJc8Fex-jmliYgeNzrqL6lZv5N*j2?aPTQ1g1fqb5?-8xjg{NOfsa~O>Vqzq1&N zyBRGQp)@q#6)!U1iD;u0>wN}0kUI*v4Z=A8&F#Y(i@&=?-RSV(w5Z@e5`^lRJ}U{x8; zc|P#*+E0`vrAJrjS*LKv@nnN;S@Usn9x%P@hPbi&5S{ssEVmt&S7hQ#sC|Tvuw1ZX z;hUyi?o=-o#|eB784K{j9wL;~)k@yYRku3a7}}@Jzk&hWi$C zDO_GZ_`51O6myb&vH%uC#e2tMY+J<+x&YwRU2>jCb6$?E+ICa*@BbSzWy!rl(+_My zlci#dHEsw{aTwXu)Lpb=WeDJ3Dpi(FxO&V9qMtD4P9`;q3@_JUU9RSjMQVT1XZuId zV;q~VPx5fvDJzN{2*u-$$nV&);;32i#QJs zLD8TY%=Z$hnAVpM0JU^oWK!e-4#!5iRM=Ogt-OHM@YiYo@8{*m*6~N3KZZh?2${4X z8dvxibq#9H?EXipevN$&@h7y1U$`>!%)CSh_GHh0@BCsG?g7I%|L}%aT)l;2Skm`s zh-gamLX8FW6xOPjuYP`0F>Y%8Zz(O9r2de&;D_3=AXs!25@h29e6}E#6a^`!UDNTX z^10A#NOX1A_e8CR1=s`~R4`K-OsVu)_v)1Zp?1^4=Y`zoK!>I6S446E>LKDOub8^% zx1l-JQS)B9fSIjxLt^c*n4fcrw9h0np`6*P!*=QAJPJ*>4h_`E=eb51fzO~aXBP_) z%j^QSknlSU%g1AjbhB~jk*c&N;C}|Gq*zcI{90*T9#T}<=KYoF^ZM|-`1WZ0Ka!Ak z&!cANa}oQtG`lxenvpl7?P7J&pZ^wYAXfTbV&-cTLpkz~VjYNPJ{p2)-;dyE_RfSW zh{(tk<1i*eJQa39_j>YWLO)$#bbc@K_8zl+-GUn1*AMVI=RanUKBr~?^q{?|U%D+0 zWHuS~E>L9;#TebMvK^B(9K)2hZ{~tw_74JFTwD@8>$0{=+%^fjfA+|QTG`MhmNFz17 z#KIx{LzgEi^S|kc;U<-p%wqtj$FybRpZw*cAA}_p3G^@-bC&lKbLf5_n5HJTRaA=& zC5$oYMPI0g%&Z6F_-3bEu;Sy>%Z9%G*);m66EL3sw9QN6zL)Z=p`v_H!-P4UR-7?L zRfh^G*;9*TGo_gni({o`m%k4~PSNTAAXWeEuTSDCFuk+Pt|Q*v&h`4)aDm?ajKwzL zMD;?Dpyi(X)RDIfZn4cXAIsH`U|W0H&(!pCu=umrni2e5$|dJIGf4}NRh9ln%Yrw- zM~N2dABvv4wL9mdv>pjMx<;H@JW&X1f`H{^!SHQWAq?th zfL_|5shp!}wwzbzuI$>N&+7}sc`4&Y&Tva1EFnqQ#s2AerVnPm-U)mvaULerJ($yZ z=C|U%sQn$Yr}O)({5N03OR1++3qff$r!_(7wNjf%X zLv<}Wi>X9@@Cl#12`-v|>Dx|4&M#_>dGD z6D7SI3`5ZhElb#T5L4KY`X(tjbZ3^n`6@4dZPM6xK=<*?f9AgtB3=S zK^~JIwEb7psIj;_CPb_O4*o_2qsYLdPzgA{kWOmcrV{xmhBMBaYTYo%U$}w`7KfHE zP{&SR;8aeqwXm=9cIL)>ytoLG2*HJY18p0jXH z)&qmNb=JW`TCkf!kuU<;yTuZZRQ!I=145XGL-#4ADUM-x3oz>6DvXDZe_1Miw`N58@B!%q{l2S9RA*s2kp%6W zj<5mjC!Ofwg<3bjB@#sO14`#5R>I<3G8rem6s1bS=b5C$<$PV`AP;HXsYpVg%Bx2p zLco>DucEu8^>32<@-Y+7qVu$W{vW<>QXAu!7KI22!oK_j+~Hi|Xmq9+B^zA7;9J6C z_J3}r6TvgM{ccznDg2?sh}kNdHXpB048Gl@*ooeJE=(e{PwdYRE&NS4e&@x<2pxoe zduU>*oOj~jt?Vl0Q91RDa$I%6kO6g4_TCAX6Mw8JbYeX!+>l;08i^IVMmA&5EeGRP zgB>fpvzy%+-%-YOgWh3l1F$D1Lnoq?feWjQtT;1=y8Ra=! zh^MchqWp2L$!C_Yg;OL(9yC4AS3SKIMz>tbh7B3+Ni(SC3o)_I!(}DTn-9=$WAFq( zh?ThACjMYx9#`{V_?Y1npz2c=!Ps-ixa=)(x80UAUx+|#M&!b(pJ1%1>Ll{82D)$h zufDRvV+il=@gV879+fv{{NpjNn>Tgv&o(mT#283$5VOc@7zMDNoXrja41=okBMTAY zDrK8^l(t)omp;ZMArx@cRW)wc-KUeN5YoRY>?hw2P}m1hs2ghu?IRBHvov>?7@p?x zRAltgnlt?oycW!Xrrb#t2sS*`QnGAJlQ<@-@l$s||AjH}_hf9RECQ)j@exCe3<3F1 z;JrHv6UgR3rBT;+Ziq;@CF!R2jawm)-orKgXHTB34^y*9x091~cN%8dNhbLs;h0PDd+SB(s83k}4}758 z_|ixA7K((Q8vsAlXFl$%D+{o8ku?`+4r=>1uONuO z>pS|{ii-7k`4t2y8#0p>eq$|>5O;BnF|hrZ#rA8Va(kS)hF0)QxRZl=;^}iy{;XWD zntWFL7E-qVmW}8+F!Bwt`zJEU*NV$^*9MAlzH^BlczJ+cuBTFj=jAl6n3gZ{mTnn) zthzlP*1R(5^Jh(O{tKxj%8{aGjD{`3^~W@+O}3E7gkzv;ed>0+qz|~HU->qYX49PU zS?@*G!H*cfOq37)Bc&+Q#UH4tr^Nn#pZy#eURh+r+E(2`A2_Fp&O-!?XOk5n- zoCD4XCkekjaTLbzH^n5{P*Z`*!}s^yXSY^FMG}iWWQ(Bh<>jQwhTy3DPquy%_hJGU z^oE+aO&Wz}M{2Ba8pGro`h-#*fO+Eq_XW@|PnW z!IgHGa$=%$qcF#ykWbMDNLJZXNh(C`1yt^xVPZ>^sMIpHOauL|FRpjWKTekiM!Okh zFtVoy%enuyo??GkQ0Cyuw+0U>7<{c%9_~HSooxOJaHGx_LnT%x62L#gadCk6aisr#&1c)@*4v47G)|w4IY$#o;~%t zKvS!qpQVrjaRfimKR!z>{=I~#gnEC}oAIyoajnf6S?bx2ZCIDT5{`d36$bt_1b`Si z_)QTLPR92 zR9}zhurGFYlXP`4LR$Wq=vel8wsyK%wMv<6M^fK0{}Kx(Km|XOi|<@5Eq13qk^2T7 zq_=JUWD5lxpmSdnZ+!ronAnkIjVupm9~%EkFAyKqs_xk%e$+%7pK>cMJr z+a$7b+7pCwwSNun;R=`%S?@&b3{FQx;`66Te(FxBzeeYzrVwd-;2c*-NZ|MSYBboZhAe5 zv_RJybrCHoiTT&BQ5b&vl8rJ;oi}KXPQIVaSGo?FeSMwPSz!M-T-5`<-suC$W8eK> zU(%02xv_cWE8moZ1A(0ItV2z+7Zy*?ZBtEGfAiu=$MNtVMEQ*HRL2VJxUXe(pEbh* zV6T_ug>2T3fODzS+^gns8^YN8-TilXCZ$XIh+pj?y#*MZPIs(1KC^PG@E#n0ERc_Oww|KeNU z9R86~lPZ|a1&HuH0H-Q)`zN<{jrq|+)qS_I(D83oMGpg&~0G8|nk1%7N4#Dq-trLlYloMch9?F)wFfl@UGn-)sjQ<9}LCpc z#cvopac(6mc`^;6m^a6?JdE*oMlrLsCG-fM*`2m-qm%pGzbmIS$>#?TK1gs@}sV<+_n7%fh_)QQ)&)FX>} zlKOT(ckM#rG3UI=k=o6>jM`39AliqNq_H13Jl~d)7SfE@WuLMF4rpUu4?Z~ctt3KsMfJ30>O?`SpQa+&-Y#o`=?5znkt2cPE+ez4rwAr7VUc-TI zA_kCJh!{=Z0vQS^#d}uTSL8(fhAnJ%R~gdwGm;9V;9kv2<`CG0s*H^ipt##r_xvvB zl{9NeH(w^C9vb{rF$hhPdfnjNNMoUyNy$nM{DOmyBN!8)3+{wYS34(Oko8) zI)Ds8TbtlsM|85qSbx8;g)VTa(PeiVTXO*SoT+|eim~<9KWI1C;ofKpa;m8&d(!Tk1qN6C-}wEa_fVnqNmoW)%T##2pB3-`Gv;5?j1X5`_5B7j+~K%V{# z$4m4ZX}(KZXSN-^wfWd(6zdVd1NM01$*c3-cN7bjTLNeoYPdUIaZoSGoGON>ZKL>c z971#3#+5nVaw1STczir?HYPS!ErsrG&4)d}WnNam?}`ZM@gr*d3^G(m(B^^7skc@Q z>(z+}cp$XBl+M0D6>1TiBxcpcYfO};SO*TV6Ifz4DBV5%?VMxKugvl;`GfWxbR&AO)k0Sv_imFN;Q z1oghR46oX?@in?-<+1={J>YFZze>S}6X%FY3?= zEw$fA9(Y!t($HavLz9d48ggD(C>};-b%Z?=W^axF%8zxGjf!He0KY70OHNbP8!7sk z`cMG;WQ+ek8=Ld17xb#yqbu6BrZcsETooahqj20Ml!6pX3V`;7d=`GbH-D~qy9!_N zKB{6UI`_>17+A@JpEacyj<8ym{{np2#%04vpFV1TDEI4 ze%N|M0e6)R@QTURa5=fS`UeO9tEP-rUhe;|GPT)$nGg3p>F2VBN%*^whCV2)IE_ti zo$&d2$bVh(zUOGfTZ9M{4t+4Gtu-#N%)euqm zJN*}dz(_EK>pR`}p~m=8Rtu!p-z;9XsCC|~6(h2s0^+=c;(aEo^_K1-Kb14H<$qS+ z)^@dN_;@(ohIaB%rcGb=-Uh=6j7AZ~p7~b*Z4Nk%%_>uO)+&288iY9{BycW#(?VP( zodwc20``vlVTVrbHI@o7`CX9%?<1rbhMJHy)A~5`hYG(nv(FV6l4~7wj zK0OKgzFA*~;820$n!3;MR}~8$9v6G2kB=)g&Z=v2dOvDj3PWsKmR%po%E8>-U-AA^ zh=3-)du&A;)oiJ97=1!?vX6tn<<9!gm=Td@ql_#O35hv$I*XU*pJayka?kd1pf_i0 zx8Xa(yu$$vE$^Q??vK>?n+k>ONS{BI@k$$QBAP{r652BG*)I*YyB*DRm5g0w$}uK$ z?VII3_017lk>c3|nxG6M0PdbagS7gE{aS&+Pjrn(OKKiOKeMwxKwOe~E8LX9F;0tJ z)lA7A&lmP|T=uo7aSDWR92;dQAhR4+{br~C2qR4ZfN}i<`@%%(ogSfXgQ>K3qH+A(e#zfcG1q{tnd97H(n7CY_KYD z8v2iiz1(cyxsjwG=yRk+tExrUO@QiV9?Cah@&^Of*Q9;XVroZV(ZB^Q;O-y9X`@%1 zpz&*34Cb6VZi=L@bYcayk7&0OYs9Z_qw^|aQ}m)2NaQ}pob}`4TRv?l=OT{s12PMX znOq7V`8~Z$@#eoaeTt&lkNXWhv-VH=C3aMJH-jkPoJk0`X&O5?iZ2BBO|ju$VarAm zUeDW8Py7O&*v+&Db~tA{3&;<{{LoDsZyY0G_yE<=X^qc+i{3vNAdfqbX!oFgYFGu> zsq<%dM~C<760e?oatTouPi?+W(fPTvc1b1Zx`~6F3_~w>>kxo~XXJmy9}ou2Bmf)l zi>^By8YYW$M*T@Yike1vtIIk!3;EiJoDi*1Dy4E#s6&ea4bor+ukGYodU`|8HBj=o zTV%_3_SL}YA}fdja|7U4;C;`P2^1zEp|$SONUr?hKG*%@|3ShMn?9XlKS|^!hzQz~fktDYWlphLj4;Y&;CTn~?~EHaoF!#HmqR z;wH|ueW-&;9+Ybv+)CL~3OUG4%F(VK2qZtR|Au!y zP8d^W&9j|%#gBPMf-ttw9;s!^U@KSLMEWz*T8Scm*4k@c6w?0kf zOKMpL3Kg#vkGGcls~&H$oYyBv($w@;tV(V^CQaxOYOaA>0Z%HE5>_HcO30rMt{7Pk z)efzw^3fyP#RX*&H?Cem%nB<7ZC=U5qlnI^v7%iQNPQ-L9Vm>&`9?wYyT$N;1d8#hy(?@9uKU zPJ2Z^W6ywzcX)r#SCDZ60D_RfN~ZLz9CKH@7>>xcGk{yU`gXBi7PEI#)0M~&!|~IU zWFml(gi;nkeCcvyH{z<5bfMGCKoCDI;QZm@*m_+kLu+gnUnh88(z zdLXL$$cs1DNV;0egx3Gj!C4oVUJ<4@@eZc)cb(JMmPDwAUSv~(lqi4a^X`h<-C`TG z+cAg_q!L^whhl`8UlCQ}E~-?sT*7&(H>#N;uDw9@j@D$Sc1!FN%s!r6pd4~;ze!?t zAp^I^>cY0UEZi;5X1q$iJ@_qgz@ zk?9~BIZ)v)FE?uxi9+D3TJKG_%IxFsaT8n60l~^Dlra)~BW>`1c{HWgPNOp_{drJ$ z{43k?t}o>HSB6Bi-qXNm6IAJRRv|3qj$v(Oie5d1vWmRgGWcr~bX-_nh~RJrRg%q5 z#kBXyy}4*)H^N*S=^amE70l<&bA(kF{Ry=4nE2z=R?Y*A!Z-Wo&znGjU#!dz?YEf; zBKt;z5)=rcZF)|+=@+}qzgHY{Tki<6UGRIZ8^j=X9{)R#@hAZ=^?+1bQ))iLcid|8 zj5?E4!}#E$7p#7yNbhPT(^QMm6&joPq+Ple-vb3Hf|@ORM<0^KmTAgrTHMptWSRt& zG5-Q03L=ZG3}%6s8BzB&Z<0U#!f1Gy8A(JuYNT6kC0Kj4KS_V}er|9+j6|$?T}Tss zE6}c5Z&l#=;7$YssVEB%tRj8ff&&GLJ6my7*C@*6C?aM4|C1K45V6#aHTt=8$+G_N z1vzL6Ll&u> z!{dho-7YM1VT21^aTW^VMaOf1s%q!AmpdG#N~#Gu=@x~*c4qiif&ldl;2vMcsXx3a zTY3WuS3nYpV`rlKiiy8z+^pq$70+bd@9TEzsqo)$3z938PsD2DF`oY*-tWtb9eTRR z_a9H98Ueq_=ND5kcTEQRlh6Ns3Z7RSu=J|}Tj4M-6KFhzQ#c;Rczo~MqUXh!C>>plJ-o^O}9fxuRbh9hO6 zi=Gzbxz@{R#0J-D;N&RCx?>F}WB($tVM0RZ>ptRyntF!5Z>_iOyF@2s79u5OZ{yHO zjfNw)7s`o7AHJ$XqyQS9Dg0ao&>Mj^vHaYI+D{yOGU|8S6rZ`-JC3=U9af`Y9=)VD zyi8Dl-WPyVFaX3j&+g=xehl!Low$=E4QdWI$uMe9@eDgr6P+?R8^Y9A=8p3AFQg1V zUhR&EqDo5GjE3cv*RZeOiMQKUG9dff>UMeaR%q80GwgkjR4A=Ud1odcT=m{7OQ^aP z>h*a+vnzZ%*j*ytCiTw}%PZF65Dc%0Q%Ae+a!=OIbVK>ra4TPt+I!>kAG19VZ4ixX^vk`oWs_(pl~gW(9#<|Qp$Si)LIf`PPPIx+qOESTR zPq(B2E<6+HBIRs&xqR@-S1Q)`Z>v8m{{A)hLX{!Efrk(n+)|#Uh1g3GauIOL3L}rYWU7wlE{(;R$MRAosLD2yh7f z17s8D*ikI4tOSMmCDm}RuaW_YwndEDU}81D^2RK6U#Yp+C}?@4zI^n_uT!9WnVq;6 zUuZvLU{)xbLyi(X$;ge`rnU;qxCh-!kl?EG=AGBjh;dk(jHA!l>3O?*Qx-z^y20p5 z%4Y(FfINlNRn0YwDNK1XmJ)3BZqyW zt#xzuJ@mo=Q7s5Mh;_w6VH6I?rO#8qGtnyB>w~sILr^O4Ap_gyVV`#1*rzGkE;vo` zF80Qi=-lsh=^XqqL{=ZKFT@*xVPRnbt>0ChJyju+dv2s`r-{Cvd-B{`U1Y?{Y=Cmq zH&lHfo3HxSrf!Xe*MKPYmhpcR*^s@3NvH2QN_%yRT8*JPIJQ`Vl8~E90#WrHUFqoi zGAv7kFXC?Zbtvw>m-CMLcjs};%&R!7vn!9LR7@fv^|ee_rQn%YrrScLTa}plUAmh7 zw^@qt+pm)n;EvTn&+5_68HF(=>5it<5qHt4x5o`=>+WVbTa+fMGGIZeU!9zkTXZ1$}@Y|i@Q+cU!1V_nM} zh??X3Y-_AG4dv$!Byi#bnq`CN34`U?Bx=BY$=S9!#S`JGLp)^!16ZbB3u>YKquH)l+IoEPb{|kzT4VsdMmU z-Df}kS5fNTA+mFZDBjzALlO_VMtlTdZ@{(*JnSSbb{L|*(#x>H&rD=8)Kr&~DhR$< zN2YT)%&|H*GTr|^X}Lh8cx0{*^V({vD6P*#5M@oItO`GsWJ2R2DgX(ODgoPq>S7KM*lrCS4rHx$$3(^c^@stzjx9to? zh9R9NhM7J~M83x_XWRcR^3j@O?HYXQ$#e}34W4x>Nm8FBXj0y(B|u(qC4W$oL z!hEWURclp(WNcP`HJ~2qAL+|Ak z7mhZitNl{Xo`6;QVwZh={P@`4muyaM_<*e1nr9d!HM&(PGgK|sK87!NQ`z7-+oU}c z=eu7NGl*m{+ZPXKy6$|=Y)q5s7pOX&pcjh-@BYm7f!|p9E&YV$)F-1M1l=oD!^=vb zPP7Sf5?)u$Wpt)M#iRE$iEr2#ER21P!r)D80msUmutal<(^=p5zQWnNePAn3@O)U1 zH7i%FB?3{7h_j(vL6h_YahQgTi;)xMNQdCRa5BX zlStEs>z^BT7e^B<6O1DID8p!xL|9TCQm=3vU$NXB1Cmt&Zn=-ect&=H(LVQcaf>0! zkK*`bZ<@bd>-t|<`M*Qju>cE!_ovvo=Ip3qWilQglLS65J1rv+7z%`zyuTkGi7(hZ z`i?5jwi=&U!(kEGl*&nWF?sn3%<&8_8&$)2gRF^|j9sGWh+qzD5;l~E2`Bo}7&668 ztR(9Nl&}nn_byERYTJTmr%Z@)Xn|PMnEH1s_!N#YS9hn9RCjv+L?u?8MOb<5yXV~) zC6MOyeRFa&y%+hh7#Y+__@R+`oAR(r_`jpUf0idlza#x)G2a+EKiV&TOJ136sh;FHQpy@ISMTNBp7v7O~`be{}bZVRS!I;_?z*Lp^0kO_wP8 zkvTmkiflYe$}>|-d0F$SLwWfH z`gXty?Sw9Ra61n`y)97_V-ns|^A7?f=-(t?nP=GE?c+z{ljl+7h5dSqfw4dd{Udjj zkk;lv?zZMx4dR^~lj@fTj>*8)w(#XBLw%sK$y@@cxGd8CL_^rGE4`t?s$A0!>~ThK zGm;oDGhPz3>R^#n>q#WS41YflZKYovL90dxX;k;8Z?P0p$~;7@i|SYkeeZ=LlPrG8@4poIee8 z%3pD{=HtxVDTI4RL~l8}FH>qzD-K6OHqhc6F?Bpj#d26Nl=KTy?*1Rp=5+71(!#h7)4v=yiHQ4E6}Wl`bcQ4mt( z+uQMrN9Px9uf6C1?Z0K^%72iuezd3P3Fd}=0!1>ID{}R5@NuAny`IL8s<^f{S!HvuCXw59*!FaHYxOt!9@*wA7W1$|% z^P+QjaOF%siLf+uZAukhP_kb`Mq@z_k~>-C;#@~NZdY;+Wl}$;5a6|J3_4e=P5|8i3u9PD*8YMr*@-oGSsU5yq zBlTL#&y?w%;Az%!+-GSVz@Q%26ku`a$WBXLh-rESVs;lT9m4qkrXq#MRF-~WzuIa% z6Y+fc<1SO2ggJq=l&jSSyC5Tt7f&WMjH4nPG{)tMS@V-d;y&YG^0szb0{7dh+hQHi zzgUi-FJS}PB2EBp8rxf;{S1VPSKIIZMUx2 zwmP=iv7PSNPRF)w+v(W0ZL4G3w(-~djeWF_>a<4HGuFDFd(L@HN+~9!X%T2u&J~|u zswQ%33y84``cTO<9tsL=S%#%YdQY;`N70}Hs8SkkDC(+3Vskqaw!~c+n zWIyryr{h$S8e-Y@{{HWJ-6Ju=EG^xgPiwuem*qw!a@4PORcr}VaP;ZA+S(l+K%r34 zK(3eNg6{Z)-j@T1&4#1_ev@W^V>dzh?JHbnq8Y)Sw)&8tPmFjTJ_|=kU7pq#H{oqB zR6F_~@V^VNbNz8C5Yp6$Klu9ffL&@pBBF27$Pcf$@FuNLO?aujM{nRAM);M^OP5zA z3qBHB1W2$2TGC(9l9D>_np0R9v z+Wz=`go&vRH2P7R9Ags_mMmZLUov~JMCOP2^vw8v&3vbqmAN{s9`e{L2zFfibJZp@ zq6T18u6Cwd)^uUc1+&1j%k)LqXW~z6g>6Casa4Bc^zIoM1>D72&Z*BkpKejE3uLv5UrGhHs{s3TL z+nEp!l$ZMS4nR8kj09nt@QoVx-xQClYU{?`saBJgD&L&({?lEI!-q7ei&T~xpI4^3n< z{VY)har#WHZjr&(QAE}F)WSg0gl?wiP<87o($?^E0heqiswOc}6CtZi$lB>QRAWOD zqxY$d*UJE*$+KZB3Z;}vqDD6QLgki`v{qayP7!nWHD7IGBY6L;S<{JYyS%2)ol4D~ z+SZp$W`i?r-h!xq{`w5`eyK;*;e_txdRu&~$Z?5-gK*mit7YFxvcEPe6lGV6BdO0p zdO&)-B|-PFnI9#Dj7+50RYT6vy52ixm|upCJa!-qTFl=}yZoc%%n5!2^f)Rp8*Za4 z4hAS3u?3Q7%!F{w=qAhMxlA+E5MoxDd#8H-$V+nIJ^s@sr!h657zZ6f(}fRW8ODNz z$S#59an+$r#EC^Jd-UD{(wj06Y)L*J%ikJVoMf&@|g6xF_!_ILV5z77%je0Se z6#A*7E)JhKt$W??danNTO$v|R?>sZE$z8OXy*eJ0lGKisdS8v$sVtWkQ%&0F9V;me z;LRu#P{DL`7I$Q?Wpaxxf#v+D9iKGy&^f;tH@%WV&&z=Y)MfN{;qGW5m{t00$vt10$ChabYs`t zBDHL~lbi536g5Lt)8ER_>+QoZK~8m zL`^RS^Vw?|Nu?29u5#>2Q{uj2Z&bJeN{P~M5WEa9!=BQtfT`>)Bu{rdFbFE^oy#@SjQKAs$J){(gYTi+w9a~_mo zGtt7)+J{pVY7vqmsw{_crhopnTc4fmO2-5%jj#EnRl^5;+E54FdGP3Yaa14yeYw$2 zMfP(IJEcpMq1Uo|_+f|6onmgZi<%8uHHwa zZ{Je%U-Reog?(@XIw3Kb=4OimHD(gJAC3Pl3CFj(JW-Mxcyb4G$`RI1h7*i&?D5t3 zsyF3L`+&mhc?h2EPKnQ1N$bhSJqT4jsJzPQz^Heg#RSi!6CIDwmv^eaLwRhGhC6LC zs#zC4*U^x4`IAG+ys7SBnCZPT$K)c;A7XYSz6WGr(Icfs&B#G9f)h{KvTEt#Nr|^n zkrb2Lbv+%k7@}~k@d(6!Vr}QcE8|XmB%^^&g&4Y6QZ?Ccr8SLMMYlDNj?JT+zJUv$ z7lj}0H&FP%&YWxD1-MXgkee(8gn^N{7;v~)&LgHEW#mqNCU5D~aC*Adb~qYO8g!ZF zu~f8F&Ws~M8ZO^IFN<|_%;ht~2Mjr8I*LrMIr?jg$1SwF9S3(_TH6`|J5kmJZhR0g zHYL!-$^3I74Gj$+-m}X&OIuDUrG=`AA^wNX(C2;NZXlY`qwzIiY$d7X}|_V_7&DWtrxChOKTt zE2mkZqRuK`+KgIV)ri68+QVU1$*M>0Zvkx9f|R#$$Y1>cf0$Snz%|OEbNi_d2W5;= z@c0deX9f&wQ7g)rO9#d2LRXhRBP2k3;AF{~igAtI@Rs`m^7At(rGOdGqIqiMDQd<-W5E~)J1CGc4 z9cZA-@FUjsivjraqKh$G4Pk}ksl8si%&b)S^hV+ER!AkpxpsK9oPFF8`s{DB>JpOv z!&TD+{`HR@hU#G3mo9aRtjx^Qj9+_?WKSv38bCi^nyzUZn z4)U{j+z0Tsdeu=AQbHuvE(@xJOt?@ZHyXny7<)2@ygg4g@3DagOf(wOJVR9z3pEdX znk)X8%U=7h$3@+UuIBsj&mWtwo$Fszl|Ri=aq?tq-G)QZrvvE)4h}0f)+(4jdk zO)qUH7HmI;Z9lI0Lw(tvVw30YjUqo15{y7mNs-$G(NU$t6(W>{BF)}6xr{7;A0ZAPB~WsXQ64&+gP+JflyuI zI1*9V!v=c);=jgZ_JjTdq3++8zWv8NFJcasVFhVJuMkcuIVYKVJJv-(yiSw9{e^So zB`HJrr+ass-L4m;L(%wWjzoh;;h^m*t)m;*dU_$&U2iPEmwR?oOt&OcOcw&6slA#d zsC(j#HDVNTsWIGjZw@`LjyA7-er~tk%l1=|NF@+ox;G6lbN?8)cbvt>6M-gNfXK^V z#U0R)adpWC{;pBq$ID*?Gu}%L=8Sa2CHB#hXRph>q2VhCnXAi4%T=*TcaROL0d z0(g9E`o9pT;gNP}VsxBE{l#gwZDe7Nf7;Q3M%rOEmAlwHdTButtNPg5>0ufT=Xjqn zzHF2T#0o1RojYN9=8F76-pPOw%T^qP=P71dMQvuCFxFbWE63WH^!@tzOEDHn9so_P7QiyNYAk44r4i7!s+wE=}2h;GYc-9_{^FF z9nbx6ZAq^x69rz-Yd-cd$rgLHCf2oh5J6ibNGq0-EJ=U*{MNmdWZW}q*&tJhHgJ5X zY&qBq!s3F{i`pLu6^NSC$E>Nz^2SF^E?sUwc;Cm&{Vn&{_0PA!*R|YGqv_4)tqYkF z?ma8!$hX~+XYm}VX3Q~G?(KDlT|&#Mioa&j$>CHS6a)K-i;-54X^M4wOa!)Y&g;G7 z8Q2Hy{j;GfAa_X=j`0HrR(@{RN<5c%>RsK?ZKy(bj8^v+Ryc2VT&Z$jUc^2vJ+x=| z<>z-)@ufZ-nAqTz^~_$T>Bi__bJZk1*J%H;z|&=LheWB-6ngG zo@t#Vfg8IcND*^dKKQvjXQopwysU;t9@(Wv%F)|{r~G&tZ#!mJ?gO}m8k8Exp^AW^X zBP6k;13Ml)sAQx&_bX45XoTrVx$qcF+Tf zkIzJcB#4GCviTG+nALXjkrmaV`HN7X?;+kWtY02H&XgL7{{dMjx9to^?VY7eH&(n$ z_LNSQi8l)Q2U+#es-A?n(<46r{B?CVQo*}HF*;=HamV)Ve~V#>lGuXAVNDsn>f7R< z-SNI}thTuPqcvE5ceqrx3hv?fya4;93trsUF$I_s9vNX$K_ z!woWU(^Z5yf_*LoxPGsE@Xb_*9RF%hkwC?xn&T~+w{CFV-rsnrGzGG}xuwArr81SN zF#Z(j;Ta_%H)V(#?*9_t5HZ1Mqn*tYg7nU0Ns=akVa`gLnxZ}~j{S8gfwaI;Wl5lD zNtr_h8jgknDMZ~H!yD=IKnERZM~=$MTgu5R4z7;!Vrp%){hD`qEhTB6GIirRKMe{H z5axjcWLlXggUHa)iYiwoB*8jJlYk04{CJ<%sd;(A5_rBJn!K$#w}_XS&mOhh!iixG ztd<lXhdjT{i`b79zd4Mvzde@@)^ z$KJr-qk!3J21@zT0{iLyar8Ae#8uV}n2zXM}iZwf>i^vLx1zbpOs)Ak2VOV z9bL%}v59qm=h6u2pU69)oL(E?N8`{L}fQMC}?5mAmu{y z2*((chH&IsCe}b$P=>Y_)UV5$PpxdssDOSkT0SM;RHlY%o&0 z44K-?uGwV(vbyKW!)I?qZ+zf0P(0`CUO1NgSwsqE#)e{#hBM4&$&97r1e3Ur#(Vp+ zkMH&8TfS|RJ5J@Da(|;Xx)38b0C1OCxqQ5n7Z@betCFfGTS^{z$+2%3eQ3|+Zt-Gu zX+CVd1CP*Kx%l|Kw2D#b*QcH{d82;%(otTubhaHxvreL#J#gbKdv7cM>{V_^bn|S~ z{PwAqBa(eQVD(mZ)pw%9qf_h19WrRv?DcpK-_5b~mT_&t4<28W{@DNo4qUy=VU2<5 z4P3znQp*Go`|axWbhP#^6#xF%nE9kr({V`0B2h`;rIifuYfJaO@VsFN(0L{e${j_J z9zL0{-HV{D7Bm~`4)qcII(aVrn*ihL=*i-=9hSQ&K}Eo^k6le5Q0@CbuHMH1VF|ZU zo^ziER=z3X-2lXIkw0ueML4VCNVX{l=lJAVsSt6s(SSfr+nXKe-xGlX0roSsJ@Kl` zT%Rzf%teje!Yuug{b#}P=~;zJeV?{{$CU*GP@f9n!dQ7S;^5v^1#FK#B>LVS zdjXwaxj98Z4u8Yq-eQdxhOOuNdYEvJ?lS1q+@HVV^wp)0ph0}6_!8E=MBIlS`}m6G zurFGOy%JUH=LyH|i%&@P<(_`9Z1&gv371iQe~aT;$!J={E^m01QxYT z7HYl;W1{x;OBbNi6cWU|W@JBBK(>K-7y>JE#;w2~U0)_LLHAl5DxDPC55V|RdU(a6`Ou!4u zng(FUXrfSrB<#NLh*D58acEQYTUS# zloCrveEl}Ru|N3)a#y~w_fB*<+hgx`3=g0P3(VI=Wg1S3&`yR7ONaJLr}5jZ(Aq&U zC`AXO$YHQDTN3};v<2hk+~Y49|Zb;NbxLjiYsE@BxuIY1NLaV*6VxJ%7U z%icZtpc4fukH)!FK?AVNR*ywh9HE{Cz&*1DveAkKDMR zIz&VjmdsiSvzs2Vccy;kEKkl>Fj5G|{X&84}+UwC~H-v)#ccNT8@+Fw&&ezPuA&WTsW z6Xv}4O}}h5r8ryz3btQJs#bNvIt8I3HgK)d(SjmCgOgQMJ_M!kk+ivpncNV-2;QQs z(~DO6O?CQq12VPIgBbeJ6Sjn7ZFopAB7BhLhx3s3n87ho$)+XiiHOoH=4w-lN`)wY znT0ZUF%coKeM-*9qP{gTAMG5QPwBYqf2|^lFGczE9&W_)QtmV}lLv{0e6$ zpMK#;SHLewE*xcPOj_6*9r(QzhnYgl(2-QReGF_%7KPQLSUPtqBWI6d|56TNJ_5); z7vv{n(J#;dz{O6R*aMizU=2-@^ArIW8a?u^<8`$vJ(Lob2 zthRj+H7))t32fg)v>~zsEFNc%nFNc-JQkksr_*7ObIPPG%wpmy^nY%5rLtF1GjyM@ z>`@65*STGS6p=(FCt*5O`P)?OuXGx?ToKhFzsMq2mi%OH$E0fVUH#tyCcibl` zB;n_%w;XyJR7p`U%=X+$e}l;*iZ=Zqfs7KHIjN_T&a0I?po#vwc>fUfyz}442z-=w zm;;}xgn7W7pltK6x8KwZL$Hi&aNwY!{Vbk)v#j0ULyTR<%bTv7suS<_zf+Plw15#W zo|{OcG_Jz1T4ANLFnTq;p-14WOI1S94;4hwte%ZB3RFI$$R`v`?&A2r7E`^?wdKyY z_Hxa!p?KRF<;4ux@>{$zYc=5=tJ9imWq_Z$2_SQvEH`uiP~euu=kWVQpj3sX8x7b( zNNIviXsd!lQ;rIt8c$el#i_u3g7njqN3)g^ARu2*Xm~|(&h2XE@>vGOVsKq&XI{M6D#Y0 zA}~#P$;$V0Vonh#six|-$kpU1ngHXYlKY%iEJ=5KwL++8aX@Ci!zZilj#x`qP!^V6 z5F%L2)U^IDA!M3ymJ&Laq__pxXu*FK3+TUH!(~1FiL~-n4l>uv6Ay3Y`t_;ooXc^?SU~_{8kM6jvD3!X2el^dFRm5K8A^0~ z0`QA>p_ss4Z?CE=$1d)Po_q>7l_x^kDGThZZ_U$0X*ls2!<*MK{%Vf`CEZ8@UPjKi zgvkT1bFJ+?ookO&f$!4Y9A>3_@|F5toXDjgQScV*x?gvxj_Z-WQIgbln5J|J=n2go z_*>ps_pzHZAy&8m6+Mai*FVM8?##gajjs`5?DoC$(!uF<_@EHb z_4B#wW{pH}?UWOYXC>Io3yjp0Z=^1%uB1+Y-H zD;{}-I4k>_slj9l{5Z=OWXA2tS=;?Ex$}Zjclhak`d<3My>D)hBvsF2HG(7Mj}u`j ze>MyNdoi1H@#FIx6cE_6?s@_JUtD9xRN$E_-y;i-q16wo=Vj>QLGGIkOV17ElecKq z40)%c2Pja4oTpPG2$ibxdglK@N35iaz?gZln2npO^m;1qQlbf7z%~7txhJ8FAW3@4 zwQN~`ByedY2?w3-(WeA5Jf2;z^5#!#eFh+bDc-x6>TZMq`{(0CV~rv3Ft0JWj6V?x zM6>t;4oN_yRI}CEBstclsEky}a)CmmJtnRpd;2ClF_}Rj3hI*eO3*@tt=IkEfuOMn z=2HGMR;I#fqhQ*wGv_;9Lg`4SZlk+@529!)Ru9DHfgCN1j09x6l}FB-`lZHXuUyzVa8*7l^i7WfJ(=q>#i=NI5>LASn^2 zVFC1V5x4y~wu@u(xol{?ingV&u@+YxNdalEG3XAIwII@WeFv8^jB@>o{qDo+c7wXK zNgZQXa(eTg<0XwSjAAw`;?wEk{uUBfg!Z?`JOo-nFp>x8cvZHf^}Y#*>TKDusrsqN zfTMg7akycg0ZE*Bj zol+K$EGyy%f2*9dJ4(GL;^mPNaJ{3UNmK=(Jbie}E~g|<>-4adNy4yFAy%tg?bR$8 zeZC;}{?J{>>q3WmR={@yR@o8W4f1d7ZXUe<$meZ`ax`N++~r#V^R$C{CW_&W;eO-n zi>EZ3olXf$o5nk6RfIbkSBk0Y(+D^&X3*|s3{>#0#(c6HY2=d_cq z+~IXjl!0A&@269ZJxyHIsKYOFSwzJoQAz*AggM;$dO@?P+f%fUCEK1v2^YSI@}VRS zk{HwopHM*=d2;vce39P*GOMiyv^{UOU-ViWm6Rw6f+?j}B*Huqfk^RNk79S9NGMHY z1ji@VJsC|it-;~WYPl+-ADeo`UGMLuU&K*tbQuAyT(a8S<1Ru9w!K88HeK?S$f%Lz zjBwIQL`|XyS1KypN=GK2VB%@n6Gzw71y>QkieoWB>p9`GUEZVu>R<_FoZiK#7( zR+9YcMTd|SDg<4-zmFn!{u%@7s&YL?&Sv1_Lb>Su+~}aD@JmT)^<-7jMv#W^CDR!> zHVj9_*h?lzB-p#BXp0HwklN^leq>LV3zg1;dBrH?7b}g)_bt}PuRk{@&wcNjITYqRkMd@_M< zXFu1Et?QeWYMrQ`S{qOKSoh62zHl{Os}rlu?r_ZA3&JY!#bgiGzscz$kvbd>-P=)i zd5FD;^twv0y&*$GXD&)UyJsq)JS2lep@S5$O@VC}m7wl#M(D-|tP3!*r?02uo-@RF2B|iZ@tf_WgYWp(|bQ z%nTi8G#pkNepS-m5jKS6=mz*ZmE;rB`GWsSDYaYgNj!A)#Ah!XKYbXxR!mgg>iSt2 zWg(?aH4t&3_u6~(VO4v#_4l72G zwtmjdn?y}j$fF2`h#m9y84)9~k%q59a0JkGv;7;mxcq>=BqRYaWf<@g zu=th_S=~J5%Bo`54$JQ_P5((2gB>8<{(Q2I^}XK8xh8Pi`$%b6zz`k{5Y~u8H6);c z4&P^vnQ7GU?F;7p#t@L|bZ6zZ_=7KrLjngPCAw-uI)JQTdsE{3TH;1H)*R<@X%BPA*WSLZ~6s=s;pDzda5u@e4t(?1{C@R)0n=#VO;^q*^XFUBQ-LRYg z{qa`wg~zb!9$&I+{#)MoO(@Rzl_@ffjJd(l(d&ei@aVrpUuZ1;(@v!BbYAATIc_6d z(p<%OpxQJ>e=5wweNkF7@fU9w7k%~- zB1dW8`}tZ|sEgwWfvdcWqcRM(5V9zA6^j3G1gaHGKhZ>H>!^laO#?+)!Tb-6=b)NC zU}VEnC&EYC+#!O5a>h|nYwp~1(shk)l9A!Y%N zTg~PbLqeXWTO1LCL_?WJI+zO(e|0R{9{Chfh3Qq;@`XvgFYrm_`OG5G|<%V z)X}ZO>Y1~rPA4=n*dxFwy?T{w)#6^Agsc6>3v+ero^-R#hM;HJg!(3!mPU#~#WK}f zdQPgTe3>o+VrG+yOUTHv(@wws=8uKkYD_YGa1)LA_Z>m0!UeCR`<%ml-!~XcEUb7< z;s9nK7^fALJeN+X@E$~L>H0nZYhzeO_YQTbaoD~{3?`5YR=Z~;JTR8^eRi|;3Wj8{ zK((T7cg~c#`|yvbH&ijz%6AvfDgLTVB*Y%mpt?kQa$Is0`*1ov>>eitBAAuJA6gYV zHRmm=Dj^AjqQ4|{!}>CzV{lQ-;Nim{!)8%%QevZ^38$U<+&|L>!78Ucj)bZ3>s0*; zPFzp$xg>kKL{p57K7WWUm26)!3GfWm8IHVMc|YHtWK(i-n~p)OQ1wBwJ6!VA9LP|X zs%>(R5X8B3{CAQ5SOWrx3?Dl*G{~d zhxMcK=)6Ny>giU!`rJErAQ*QZfliqkV83A7LqKHM{$RzhnlEKVmqRH#2>jrBA!Z5E z)h++jjZIAUc`iEr6m&umQ%u*Aw1y%kghn=yTpvQ$$^;KHFe{*@aWny%OhTWxd=6}f zOUJdn%RJ@>cH0Ao*L$2o#RWV=Ki`7IMPr}9+O-=)5hO@V7xawU<?wR&iMZm_T#zor6uW?I%R*UxRuWVRR6vQe3Qc~9{;f2xGae-M5B zFzunw`%%R3d|+(wVEvLLI#>RMM0r`^rHK_yWs&Wc4BXedrCk4LBSG`ngs>A#$i>pp zp!}f#*s|EjxRLp#-FQ&|042z-+|bWAPgKQB2*8)ke=AD~vu|V&0H^!y4+PPfgD^8K zV|-94V!Gf_U>I_W4wZn%ZVTz_fz)=&$8MWmX?{eR)`bB++759o4-$jqm!Atl3m{N$1=Rti!5k#{O_nAa7Cq`U3-TQDK|GwYQt~_^qGM9pyaF?n@r_^F2uMKqI zS+@e4{Q^_eqd86NZDOpCGY5Ly-UW{TTMxu1J-qX2N(Bs8e0V~IBq#Y0Gxb-=Kk9g^ z@2Zvx*6=UDy6uJvOmCQ-j9vaCg=z&RMJO$wnT8e6xr9)aT0zMPggLF!6D6@(QCDY5 zHGV7GDw2|25f-T83Y&(@h-{{i84GDYz|`~qHVC_8P_PYeU8XprLvdX{84_FgVA}`M zG52N*PEK`7(?{&@J>xG6z(38E`6UL7+0I~?14!7dHXRUK_`k`uT~_Hw>zX!l1SHiS zs4+djseieko>@<*qs)gbIp(hK`UMv#i2DA)U$yeHTX@GAPgxkxbU5N%{UF|(oh!98 z6J<+?L(t-=cYjy?vDp=x4hH2tn|3@phpZL1^baFO)iJX%^-pEND!!q;Nk|tIBJgRr z;yy(9RG6>x@Ny~e!q@G*{8Ql(oR%oTd0aP^$`0DR4xJOGtzlt=(*1nhC;YsoJw!7X zIg6akdlc)G(8I4t=Nb8;jnEvOwTT`5SZ8RERqq$CbGF)}fJ0cI>lc^(J9yqN>MGZK z1d#lN6T7J9qy=0hU5&)r9UH#C zo>ik=00Y3+GME8jo%~`yqT?d~YNtG+%v6-n&b@ONbbo(Z{m;4DdDHgO@IFD%otTAL z+w)VRr1b1tEyeePX;tY)2M~lzMVuPwTL;f!q@p#$GzXq{2mh0L*8du=rfQooM6|Zg zt5Q;{y755c$RB4H0?O*t*)f0$I|Z{UyP+bmuVmnc3xf&hQUxYVWfVEU!O|Nfv0;KZ4I)ixtP2&pSI8zT9l=65rTB!u5(dD(FI0ckIbnPk|D2Q&_PiXN5wgcoD6&d|p>m^= zK{@3wwVCZ3O*MT{Q+A;DaJw3~ZuALyiiH69C7NrO7(z)Z!Sqreo*!bE5ueg!BO`5k zFU#?HJhyC_nV3=xN9XBA2K5%aXq;qa3qmFZ?~4lTXK3m6A~1F$DA?{PXLV9R7m6Pa zOZ?qr$X_%vc>@35&AQ%+)cYXuS6;ASPf|=W*0A2wC7b3^nP`;ujaCuQYX@g;Z5E<1 zjDswz{#jjLAePO#W%VyRJx{gfp0?+X(e1H9S1kV_&KvNf>4(>q-VAMz?-!iwO}4-r z=?`zK$Azf4` z5PIUWRW1v~gh7-?s(eg~e8B=E=Wj3wMUo~Gcv4`0NEzT5dRYKajSjZ(gdFra8;-ErZ_p-W&!llrW4yz0R{cT0aB7Bh%B(6T}B% zJ0iVP6nQFHgW^dhSnO^tOa(%J_MDoo)|#Nw=bku0gF?CIfW`8S)^&B5HJXCVD$#T3 zxDh8F>js2T5Si89oY*{hUt6+?`cq*^%_k8-OYT9gN!Cv?HJb;{n3+(ErI6kllP^ffLJmRv}mtRIfEO0&$-| zXEhZ~aLj8Y(y>%L75$eGiOCfuPB?{5!uo}5K*$uSDKweQTO?|hNn;Fw1qik@oIMKSX{`hdoFaOdMhazOO`3WV z(%C*_qT6TVLrcppIz^9imQkhXfd~h--A4i^WH$j(D5rLUBg`W+*ERecu0G)OnU<6D zOrQ|;I4QbYBP1!Mp}CgDuwMnKVUTXd-g?x2p8oeQ&>tfJ>W3(jPt~vf(+CN^+TajD z%e#l*(IZQ?BO3hd5%<~Wxua62C8naL6ZLO#P&{KaP%`(ep;46-n5aYKuwI>fc>&+< zdiMO4!ztwWCsViNw|2$u_T0Rqrwv%e?9aQH!R ztRIb)#W06YV8H^?m2b3hSW0H}yJnz29_(RVMl`-3CNd7uvfd&K4kc(Bn>Zq~Or$za ztHo-)f^wO#AP9Zt$D%(OEnS{NchhYyUZ653o3XRbc)HSbY6C97^ism$e>%vg2sl7i zY!#1hdI54G4W5#&$VDAKoGRWp^^V82XJ=R7^F%A50IE7{-W+AH4J{s7M{O=KL2#j$ z{p382Qd`iWuV~}tET`D#Hrc5@j!06TMUZ$*OekGlo0Lq6i|}o5#Qpoa6Kh?nE_@h9 zE}piEcy_logkK8PihOSW){eRG4WXVH6KamOmjt3HMdg!|2wWrkmA?lQv(N%mGQ&uja6{=<`d^?SZJ))#tS)$w_`d+2NAxuCH>1hj&__=5Nk499>8&YWiB zY#}CQw4tt)Y-wB}6_vD@+!9qLg@}lXo+P>wK-H`!=_=@$E(KJJn~Kg^DK`_Kr9Y2Y z-{7asE6(W+?)`xLHVU%gKazgZT(-=X2cG^EFV4h;;;>a5*>;t2-gcG=S6Xl~O;E6z zQ=$xt2fgM`LTa={g()Luf~L(T{x40Kf*HXvQ=OjVWL_hq?_oWPT8cKRY?-q3kSjIQ zkzXkqb0h}e#KQy^h2}tAcmyMih)749tbEao{jU?Z&iI^Ld<*Y!UML|&3|e*96?YUf zP{*rS%$@)3eUtC|!mK^T^d?~~01l?_oK@v$BkB0V$M)r)0eI39QQ;rz>pKZTH-YW9 zCmo|{`MvYgz+Z}Rpx|7=QZN=M?xrxCnj?5VM>)V74=)lqL|rh|HK?`virn)qmPS_%|+CW9P+Ty_}I@@d(N%J9)xt)bX><=?Ed^|(AvQ*3F zt)Go`PNs8p3(gqf~Yi+bPIf(>id}fDl2Gasp_^8FPIz-02yqzPX(m<1{aT8 zo-_9^hLM>6Z22Ehw-gCCMZhUisHxu+BLhj3xH*>J)hN8PP#DHL*z(y|&yjc1&P|qn9!|GiakV zgG3b%Ada&=8J2K=c-=r9xC>>HIi;?F3%wLNK1SWIz%m+@el#e+ick}X0XUQkv0)8> zU>;Am-AKJj(TZTF7{DRaZ@BH01=##G^xcfd$zzC6Iec++Z;O7Eab#^!4sfho6cP?= z%5nFuRwpm(3oFyJ4@W{Gn}>T@Stiv1Krl-7Vz{89D%$9_EiHP#KQ2gbHas*})qi@& z*T3s|Uy1)Gc$5NqORFFOkdpW2VgRv6ol{Ik zuA6@BpgA)F0|lo$_`htek421z^F?Zkki-fsLgo( zpy$3hs*)0boAmMLYv2kSd;7S19Fe3*?cSNFE}P>7znW?+GP82s^mn`8xy$HWQfGtc z);SUFupc72P_F8%W0rHWUlNIY#OT{a+dp|}ra51_$^t!g?#}?5D^7<$*(1+{BvW)% z2!G3(C{9;0#a0V&*xKIuWm>;*mg}q8$2Kl_8yX_j@jolosDrhv)`scnkumv-Enxmq z4$p3K`H}_%xfrCM8~N{s#fQJqf>iFFq$QI^1~Ae% z3eJlNsHelm!z<`m_%9BqP(!Zmd+EHe2hbA6hd>t##{~g|2=0ycu)_Ff!RUWL+4@GK z`Y9j_R<-*Mq@ryJG*6Qxn=Ef_e*Am?N)ri1dhH$21l}@PrGU{FiXnZweuH0Qe1=nkph}-%s9h8)ujc z37)5}@=Yf?7+r-z^Cg$<{IOS4_wj7`W@h_oru8B}%Z!>SSi`1)8v4!yu-qZ)u*OG5n>%y=qxr06W3j>h~?S>%y+I}^!`00%lYC)4IG}G|4m^4ti z+?m+Vo($zw`a8qAYNq(7G5Kic9gG8iI=;9JYPbUawbzyF(vox(Hc~_A+Z19xckUk^ z3t3^M6FAM0XbN6q0)-zpoJa3K^!)AqNP12VFk@mEO+4dhVrsJ5 z;mY_Q$y4vOf^lBUf|aW+PyR^al>F6iF}iG5#h~B|)}j3otvk zm90O()j>QM^5X^R(GU3ynWKinA3TqVN&rdK+zcUSpyUnz`~Q<=M*+QMEWhQBa*;4Q zg<+zSUQ&F?hvE&-pL|~@zKxEiYkG?7m^zxJ)~Qn?WEJO-=*!@VEN1EOTD$ioD~414 z+8&)@b%W1m*Q@>Q>ARMMDONP=gz|KqauLf)b2m6NZR4IrGqyq%eiwX=OHv8i$(iF|ci2{iFPO*&;@RP&1>TjRm`$8t;-+TPBQL z>as=YvIJx_X<#VaP`=pRl9vq&c~&=SuD7fZ=uc$%$8z$2g# zFO2heWN>ItxF|*_$L^w>4B~TBlyxXSIxAz@ffdvy&sUq79fnX^%{B$|HuI$;l0|l4 zDD?^y|Deqp+o!fq0mHtHPa>1w|MblSBbPMQG^P4qC}vhq0dg-qLeLWLCk^^5vBYaar)_Yf5j46I1I4b z9teEDZ|_9NF!Y&_*CjL_V}@IXL(xLQWyMZ23vv-%r=~3S-RNiLWX$vFw~S%T=qwIK zwPNlE<)$73jr|%TCCf#62kO*g_feDR2hC)xc(J5Y$KkDgZ$Zg&NWotH6vxHvM|@?Wp(jzjNo+cK81vam2rsGMm5+ z{1OsK7*C%S^T`US=%!2poq>Ts({0_SYXQN6t=|9R=`4fdTA(D1d$8c{3C1o&C@@P!*!E2l ziZXMKyQn5?2lIP0e!2S0#B(OFLk5G$rySW-^oa_YO+*^QOF(L0{@N;T zM`=>b2GJln;QPGSvK8Jm<=1U9nkqe5Jj?Y^QzcvPouTE7gAi%5o{VQKSYrT|Obb0ddh;__t}cUNGp z&%>wgx->OByT~0pD_=unoosQS^xb&xx8Kw0^IGl;zHVCn@z;3{Y6VO+^;u&Bi4|Mr zV^AyZtoJ617xz z`Z&epN@Bx=h*K9du|-@})STFDSYez%aT&*it1X$xQB)ELLH3DwzAMiu%3XI>{zJGz zxHzpEO#$NcnkS?)k*nJQ=z-wpmzkc}n;$LbK;`~)`0F3a>v#r}M?orraC7n*&*zJg z$VHS^`wL5Qu~eQ?ptG2A(VQqZWBXs{+2@ivgSUC@K%AI(?r*zR^|lBU5ko5<9nb=l{JSRtMj(El zXPA^N6_7(uTKRT^ez1lm0p81Z`7>*QsLd^oNM6e z83TsEhaK%6xz=?{mkk2jW&)cd&F5$(E9w(_P2y)@tc2iiaRi4EI+!f{`ijEgE>^9r za`o0?4}pnV_7;3~<;6oVgs?EcYp;5Lf^Q0sG8wr9L5;^gyC4gwf(#R3Pp3edO;rv9 zrXS(sz*`S%*p~lH=lwNUc%=2L{RbHW0F?#6wJ~%N1Rutu@IfH~^9h#tf#(5DDM?<1 z{o-hXL;lb4Zy4k-%)Sp3ps1j+3)YU8toEPOe$OqqEL;E1--8)Gk3%f@=NhZ(G&707 zUr;NZbZ^zo%i2FzC~c#l2-HLRC0w&>mpJ>ScaZqki^YT_D7 zWgHw*QO&p_n45hFWt2?{VZ=37aJjZ6;qxiFgnoI#vV<%ck_k>x(;%}wKOaQvHJRG? z?rk(5Vc(=Io_S5jnStO9^*l|r9G*G`&&mUq_O1UD@uz<+a4^GZsF-{aC3gwAtQaPT zWV&**GNuYwo(MMyDQ?2ApH0bT>ZqY3@jv|aB=o9Zdvf-=Y?-cnP;ywp7B!4GsdwN- zcxYFbn6G{d8W@=)8i5TSfukofQh4fVZoK7xWV_R06e->V+#|KTO=_wjiY|UZk#z(BMY~`}S zcYsP-xQw@(`?90|aHQRfw2eYBgP4@*A>a}{E5tHUEy7JebawYJNt_Fg2kN3qaKYWs zs&}H+y+1GsAVUso`XfanB~xh|rVAf~-9rYfOskuFT0Qpdfw~|=gRiHYWCf-_^2rbo zlD`8>(ESihtW@wTG&XG z&ucdyYrj`H?zQ@zw2pqhC1Z4FhH?Z(N1>=X1NaC@QLmhp-Q|VsYbRUzJ2`$2cD}LXQ_5?(PBr@T0drj z8T@m?(YIcH%@dZZea7F017W2FCsHX)n%!IKk}|V56pb`QnAHl=q%m>ra&p+bF5&zE z+cxVf)^c9T=h?nvKxXCI>V3oL$c`ym69dfV2I)@rA0Fn3Zt4Sm=1FEkeq3+64byMC z2vW3Xiw2eFFWlJ~YF)0@jPUwBgJ$qNn$}(0thzqbcnR)Nn@;6{9+36am8l^{HQcPtqX|g&V3mR@LckMgl81Dgye3#{04HukrU1 zW2Hv)K{Yp2CB9*A>R}746d7tA+Yoe^JgjMv)lim|p@Ptqq&OzfL`nnbzVNOmJ-zFX zq{5=@-f*7z;hhU6@t{bsaMJ?Dr-`upcgp-3E1cG@% zeRQIz0<6M=q&|D@m+idP96r!j1=lD|*cBJ|45j`*ZT;{;A8-v_Fi0Q!POJ1gQLPwa zS%!3@tL18dLvDH3Z3uA+5(vrr5xl?~UKd1$mzrew>Z_iHK+gJYrBEYE9ND#rX1Q+F z24HM`VTyJIUhKs4>pN8o1Y~^)!JD=~ptunZY|8?IP^*n8yT>=j} z*YiK7LF2TC3=9pP3tCKVf1sE)+mpeZBOzZl_2q*&Aa@;UkGYN689fkqS;iqjmy`%VxSmwEUV8UF zg+K2wcV}m0;M0_reCKzMv0xx!gNE;SMTg;`1*%$yWEJL=6UEeVa7sB|3M3>j=uGU? zyRN!PEiSXNyAD#B3whJNeSv3W9e`%qHOF4s3d9ad-+ZJ;9$p44L%X)bf`p=^gpn2dP>{Yt9yx%>LxL^A%$r3y?}d9tX9U1hm-<9nHP4 z!t%N9Q>Qs_W@)@_Ivs=XArIL~Cf=mQ%WzhE?3wJ)D&+V5Hi!m%KB)k1VRJ zwONcYXs=JFOtO`6-X#~ee^v}|uEEJ`USV9g>ly*C5{FfZPbENJEc8bk^+ zgi2Nnn80!tpTVkosh2>+YS6XsQO^eq34!qqUIgu5@K+L)vIbsjPB$OvV76S@Pugx8 zJeno4cCkO-F9_kxzBiwI9_&1ls1P^&NP|ptbHxywK7wfLQh2NmZ@dosJhTtpJ10HV zG4YcmAQg$VzUBc@nJLWGJGkt^!ZV$l7ygvR zMd_AhAk(Q#PM|!yv{9lFC%N<}0R!NzZifT;NYXbR)xw{#+J>PJLLc$9S~G; zm&y+VUiXRX(d3aUjs6ymPmm#^G~dnzY8B4#_LkG-Ghd`CyMk(tK&zClv6@`j zEkww`ScQcWs^7|6wJt0~TSK1;!26hZukcE|Y z3pUm~JM6kmyrbU}f7ja}Y0<(2`Y#V41oe|w`m=lxRZ047`N|1LQb;y9XQuZRw^t$U zb3|0dqOy9BUJMFVBl6Ynhwe_#8Sl+OV9k`p3)4aV8Ho=O^f}rv{@=m-vUGAV^>?i? ze5L2H*?zMtL)rIO-Di)IG=Jlk02wEolUgP)6-pEF*faIbg(s~8^K9ZOi(v}UT&L3% z8pvHk#|sU2ZoN1V#5()^4P`E>`^F{u+hi~kr?vZ>#^@?@<$NyQFXiFElOQ?S+9oU} zy&tHu5k+U=;*v7L5y+rU-MU)ueOb@y_5H+c;LkWEmEABJ&KUmk%eY=Og>3db#!4WV zyZcD-d3)pycNnh;b@b7f;O70q;^`D|^&wJcO6Nfxl7+vzDc3=Vp%luv3nuZqHw8*~ zUW0P|cV|@6sCAbmsq7#@ND-7GpqzX~+ z&)>g)v-bklk>1B&r4WxXSWe2oMH5d(2dI;oobo1{jJl#bf5HF-%AR;^|)jp z%ErqZG+$T9on=DO+Mtv@<~7#b;ZtNx6PLwoGW`DNxBh(@w=%LVxdYr~x^DF{O;XW?xMdj4Q5ROy2oQ37dz=PH&NM$-b5tO0oFnpNm|8_jh^&_kUs z+9ju=BBfyKO!x}~88>f@6O3u9FB1|e=#ykm-RR9sN8(EF?N@=T;}hrmI4Dff%?Tgm ze24+5SdLG#s(m%SPxpf!z0ptqx^au}DzwnDhUG%GqTeEcZG1?@VqCNQCQv=qa&2}S zQw&|x5U%Q`7}c|WURPrper6fV!cxhuYd@PCs85y3xjocSYH^K&eyYH6a^MvKR<@%6 z6;E0kSxlNtMjBdLUH;~<@^ZT2k&*HxTlrv zgD3ruNYASj>V&Q+P@bhYUma&}dKOjfGY3&5*2lolFFL_P1ZMh}guzYtrdwoc(o?r< zev@iwoHu&0Jg6#OC}1QPQ_yI=nt8~~IMOyg`Y`_dJb8?znX%G0Ym9XRu^K~(f4Snu zizV)_N;;j94uX40V56}gt#6oXyyT=lTks~IbMjONr*2l!7B_@ac*Etn6)>B*=IaCj z`$sx##dk>@d7_RJb*h%ZI4gmV^%qb%_0BN|mBs_}`G(I&#y*)orkQ%aQ5o%AYI2#o zb~YY35t<4|D0-igyt0ckY=myW{z{FU{q5^5YCp1yoWk_*yrpDJF9bi5F(VCpvm`4D ztqGZ!EDyV)BDA;<=h$DcxK_UFR-Y@A)`h8D#}l%gldsY#TWaYb2+YmU1@*MO-t_lLs^qCqi8Tg2h}U&chSWjry1tS zB?E9^hq2lye&VCgw{ka6t5uLF@r5{9ZwnBAPZF^meG35NrA!TWka+tuL+21r)bOY=}5}Tq~jknnAHbZAd1Z*RgX4h=vXx^ zcEe@{jW%cmSw%5va*pPX=Ks0dwDK#=OeZc98h9NQ`}|Gz zAAUg-j6siMi9~?zHO8K%$R5<9MzYKlgH?J^6U~LJm1I@@5@W6<{#cfy_bs_k@mJ z(X*W7&^j0>{^Yshy*V*FMY!7J2mR5UbG(Wyh69QfOPC>sw%MTT%4hR_!SN5jH^~7& znj(?&oG*Zf=GZG|2A3z{qjFOSJTEHRDfX_I`;$_49r_*&+;6L?OqS3XrEyRgSP6w{s|4NJ-3TZoDn5`>#@#us-mL^*8`ws6n0e zzUAu1Q7a855T@EjxaaQIJ4azD9F@4^+wW9sVm=#r^2D;J9qcgja#w)l`>WZm{kWp? z`)d2gA`5`a5jiHi1zzSw>6xzm@%5om_=&yeajACxjB@4D_7$Qp$z~^A zbDI-?t%!^`kMiOg{4e&k=h3#$xK#~PpYf4?5pP#T&ZKJZ{+gq8%a1?z?HMd<%UKoR zqS@VOVF}U5$D+gN#&M`FP-RzLb}hM0>{o35){)A0S?3*aPA1yBbvH2 zu(`GcroE~ff~=lpK)l9F#n)6`0+K|4lQDx=wgSuvO}0Igc_g$|`mJ%GD7?yt+}I^T z0LKUP)`@l-N#ji{E@H(>?KYX;T1-Y3fM&5lm+#e{zRE-*UvaM{l7Nx9M0S_4p zHN|q7ND^<0eBS=wq_EvX-oud@87AAp#} z3&CzP9I4OQ(|1Al5E%r5`rSkO{=zkq<#J;C&AR1aZQXc>*618-)ygFvK*R+INs@El zEx>zR2*C1J@@;*6bGSak^WXiYcDI9QEn4ibilM%pqG}osJW#R6Q+$;5{oviCYPVdq zZTvDYqaJNWWKso~1+k#`lkf#>41Qj^vizbmxsf)JX%$?$Vtss>>-A;x4P5envVa#U ztwrCA5G-sHU68I)QN}(r)h0QOmZ(2Ye7KYXIi5E=vl*nD(?8 zBJHfZIqh`4)%CsO`tuZl9DGug>6~$q>;3t;k%a2duksrSTmuMI7&TPlH*@Lu_W)3f zTqFwAvGdUUJSNz{4HazYLEN z!bqJo(i1MW)Gia?O~Q8q=ex=hOBL3p@dl#XTC0%6G)vu7*;8krn*)HeglCvJ_9m8izX${N@h_wy&0Z1pezktTh6xAnn0g6p5o;HzaTUhMjy{<`t?P}TiP4+*Bd z{kwg;?r1fU#`xR!&ZEMr+H7C*_(m&={8Kf9e2`u>6w`}A{ZfxA7A$@e%dLhl9re2V zUlRwfxc4{XjPE~Jpa%2}=;2fBuK2#?!6tjKg?Q4I<-~8_`rz7-F+$ zcVpoc5v8p__62}aPvigVIAQWTyYq|Ry1(&{uRa*fOWWWLBMyz4&u{*-6U}^p>$i>j z9WZtF?JA>7&N&HHdTq?4Yr496X8X-A5M;Wd62lDIUGIO0dv_^x0aXs$NpJUdG2A0# zZ1So|VvI7Kyz{q_%^?8!lBpx2SiF<>F_?>Kf?lh*j~6fnyEUN5%2qEsEy&A*HvsZv zEuwqY+iJ;4j;qzNT$U;pHH@AHB8#YveA8knBQ-xz8u_0Iv+}}&a1{+jz)tuKtIB9v-z`(kD@8=(vtQ$Q9td=kqmuH9894r__}jv2 zq+qoQb!hV))tAKp3t!ILa>d6z?(2`~-PpIi4_!Od%+%eQjZ_XuDhieUv!55X!fRYg7b0DDvBj-P*gS_Kz~BgylgX8A5Rwt5Lsx}< zw1}jW3L@Jjt`Th?P-$7Md*+{34bfaSM$%xJr!RF`Bv=Zwi^&HeJ-#eflIaRNx)p?j zccAUx;PPwS5Q`|{%n7i?^OkH`If2rYX1fe)j`pKRs|NEC)OTfpXk^g2ep#rP6=yiV znsN%6D^B_H7tnnXFZ{}5{PeiO%gQaEGGtxsdkYoFDXHmt^33ynyniW5AWA21s2$24 zl1ch*J;rWI@7Nwale43rfcT>%nxkd0H|;4!AT z%M4F{K2?Ysx|=HnxytYyLub<|>%95Mm=aOR>J!<;hn2>oXV*j+s@R0q-kZ|37WXW) zo+oGlx3l2yECmZQtJ#49zfFgi+uX#X6{iR~xD~})=;BE&&56{1eI)8IPjuB#@;Pi zn(jRc2S1>7bCIB_^Gl|=B8*80C4v;2SFi)*eV(zFC1s78njRx64-Z_*xhMoHOj$*M zwW+BokFgYVu{tDV>7x%vp0H*@F4b59b|ZlWbVQKTeOCT!c_?ChC&{6jX3ALYW&7A0U!1&b4zgk*=D+W{NJi+`1N!jwTriP|BLEmE=hbP)QkR>}5j<$pjeAiapP<{GMy_ zepwu+Y^shX44?G6QSHyW`@2Z8*P&@rT;u$Dd(D{84p#FHyk8C!mH8auy!S<@=6J&^ zCD5vGeE)4?>;&llDI7s$m+E_nj!NMRrb-Bb4 z0N@8rZR+BZqgP9>}e!M%Ie+!xFSTao?g) zEsh{ss3i@X1piJO2T&pc*R$e7oXpGLTb{1L>oCnBUIrtYk#QWPD%;c)<@INMqNqf? za;gNgkZf2f)2-9jca$Qwk}5V&)-aZ;YC7^DPUq^t;Z~&S1{AyBbzct#2B2&bcQ2D_ z{a=1`9dOo~Pi4}@1mErmNTZPsF*4O@;2h4Ti^4TKwbAT*Dz$E171L>U_L&CofmHQ5 z-y%3lTx8-%d521S&w1aEwmBXrQ}#xkald&bjwIvkn!k&PrQxS6bJ$_jdL7C0cK8dQ z`JRyiZ*0?nS?Iptr17PbEIfLYKyRcJ2(UmxS_xeReJ)-T!}DUP&`(MJ8E`JpZd@*j zxqecp5y2(shNW>m9`Fn3b){Y+(r?IGeL+{VvPXw4J~eL=A&_4^iTwP%t&be+cizX2 z_T~5axZ-;2Y3zyuvHP$2#Ga~WlP>37DW>*4 z%wg^?130j1Fo5W$ocl@8SA}BjYH0V}Qy}nsK4^U!JZV(hT7Y}L6_RSn>+>QoLpPpM zx3n`%=(yKh>&sXlH5M&oik^@0eIE5BsZ*YK=K>B6IN%CRoVIRF13r=Rcu{$KabC7yc-A9M|r20F={?8^?S&ADSYzE{o-7sk^=Db3G0Y-4#- z^AU~oA!Jo-OF+_rC$5~jN6|n~Ng!F|K`lhDS_*JKtXY2(4E!8TC9A{FD~T6I<*Z;p zEW0BQV=F4*Uk`8!hgfDwi(jNw-NviV`?6dmoE35`dv04e48CoLJ`XTILyah9{kdQ1 zk;`97XwPrHHIvb7ks$NALxQ_$b;!VEqDD~6C~<2 zp|#T^o1UxeGbcp>$ORfT`S+2$+ix zad?#lE@0kndSA5%-kw%G`>%}pR#)+cAC<5ybulF`WX-wQzAaIimzDWcu#zmw#KXxA zdYOV(>r4k_A>WSekB;!*DuXMQ$RHS6$@#H)$U^YkL-AfV|2RtLHj)!RmY4MSA?OQf z3+EP){TX^DG6po}wPrh9Q@k1;TsmsYVhV?ixk3l)0CUKcl({)^z^kBLIeFi!&pj)4ahW0QVG_TgY135bD&`qmK(SfBz?Hgk-i}3I!fH-2n zvKQ8Wiyo8o^HrGLZq;V)d$65`lpV;*N}J&W z$1%(Ioi>mv6`J0gR*xFHhZkBqH-xs{UhjCFcVPHE{#l%cF;?j|h8fk4n8ynaCz?xF zGJ#&Zve1`w`T#t$j)4KyiF<}lXAXy=Xy&#Nb#W03^@ank)u*snRQl?O0Jf=&+#iH+ zqX0dW;RZKsW$ol9q5vj(4^a9)ySt}x+Lg>gwb-u>yrXG=aw@ax{rl_xaMr)dx3-dp zpy@UoJVFFjb5t!jP{eD|FhLg8Qb6+Y{YYg;!DuhN2L$5Me!yRln#A}R1`swF8 z2#Unh0+;mZJUrZdUAg;q%4G#EOpmwFu8F5SaZir03fU%;4UmFsR|fG00S8GVJG;+$ zFzH?z5HUNcZG*ywSuG%oF-O2^S(iqFZYBU5e<|NCc~mW1+@$xGFU=*90?mzsLd zlc}KW-=)&>Z(z^*QVl$sH<5EaPEIMVXMnb53DE#NQ|B6^UM=?iSFYu!M)zenpu>{K zPI*QvuMsM?2n#j(@@r9p+Mllhbh1sbKX$!{J7{kmg>UzT-y#qDeA5*ye1pga+7XU8 z=5?D`5FSTW8Z6{@Zho}=Ilx`$c-EbSXN(DC-3{h0r+N{fmb0B?U_5^X(scl6CJ;r; z_J&V4Cm0=}TwsYujy`HVgXwHcb!{FS%Tu%r+ftYk1(w-s^XegEr8|e1uq9z%Fi39A zXq%W6XdL)N<@={UoOI7)^CeuM=|oimYxeZUS}|t9p%r8L(-Xg4Kl(xr5Z$_u+-f>VZ2ue7~b^cK6dt(Qxwge393`|T(rF28AqKBH@jHr7q z>#WgNcN&PZ`K6r*kj}AwrboEct{LRx`H2UMk6~n^5q3cq3>K~`=E>G9mPFM?N-6F( z4A@wS#dDuzkJG3ULgYTKi6V0k`p73)!ix45F)@B%Be01VFecNFq3b{<0yeVD89y$t z(A@(IS73Bz*ZDG`_2L^b@Z5XB>GTkuPITz^L3d`EIV7E6`3Q@vNTYy1HmoJ{D~I~{ zb6K9$S^imF<;w1Ho|MzY2T=J#y_Ilu@e!=w$=z!JE$UxdprP13Jr4r{2OCi#Gx?Uy z_)?WO`p)-Czv~2=l#GaQci660T1K>VOWLkhjJd+Ogn+W*NwHX`M^D4;>+-7t>R;oP zem>3ES0o4rkx2JXbgzZk5GL&~CMLoP598`%1ldfoTtMaWD2qus{SBa;H!TPOLj(BX zx>R_|%zMmAo?X}>yDDBS>YK<)Gb{}2OwYrE0l=;sMR$XoFFE{+@b9p2Qt(m`2dtiC zopnLHve33CW$>ZH5+Sf;gkg8h`LFnv>E)0Ejz$06GEI_o)G{aVBlmiTq-JkDXJmYx zYh?UGx>Hs&138mgvNIL$Y@n6<>LSOfXiMHM-D z(THZ$z*^Ut2I>Kxk|tCP+n%p88_y4=!awyl?`hQ3^PoQ5T2x0sPJb(5Yhky6!V1nX z0V+BfXOJt{>O@6^@{|YJt}OFb{W~xNROn)KrghN3#;_vb3}(}LwFbXaJ)kJFlW0%d z5HjblSCrYTXr7n*Z@B>G3EwZhi~THwC@86Cbc#!;Eaa|fRSW{Ns;R|*H7IHTrSq!{ z-NOa$*08H%cLpHPBp(QMW~ajf2S-Q06Q<3(p1X^er(R{ja@CYHl~61lpe>A94)md$ z;U}Mb;vI&jZg$;3BW8%n`tp}7fNo;H)swAv82GpSa=ry9NXk@o_Vm^7|;U6EEHatlHEX~`-`R19hQvg8Sy7D=YH{JnQ*yIyz zG&D3}mMnhuY&%pJyPrff)g@z5WNRnOxd|CagooppU^PsTI1 z$@d3R*eak$#dI`qm%ZzblGO6$7vl6*8{|Ax0fN3x6j{Coq+ammH#)+a&RB8jIQF+- z@9#5K2-p%@7`T|?fyK%(=F!2|k-lKkr)Mi;&&|vW_?w^Ue!W#IN0LyqVq|6v*oSzR ziN1RbfW7ji39TT3q>yrSqYuI?9$HOZzZ~>JpC`ti=p+oG> zcevjwBE172@Rty48zG)7&zNiAS{%E2vq z5xTgSkhJshTET^Z^sEg>;1EN2mk8G;jD{I!Izp=s6GK=b=i#B2F<_AF`gQT_mcRKp zWNtlVZ*2#{lbo+*Rmk`6>=e`rGk$`vghI`k%+>D>L?FLUHGaTet~FL}T%(FJ2aaBV zn*pZY@vT(6x$3-jk%eqdOiSr|seIVD@m3$kyj~%C5rez{L-@ZMs829(!D7`q)^L6$ z5c37Sf6oy^3v6LS^Es$xQ|?z>QBVG=u#9i_@rCH)@DT+d1;;Fi9G+`%{dT(gt*${t zB`d+t7_k$O`;d`KQ$^i%c8gZ$|K_KZ#nS^N;Z(`xFhh@#gGvX<>QvP&*0Gq`Cx?Zj zjyGS?;x2j}LGgi4v%K829Hbraop##}9deGr!QB0wV5++D zcR$|2vnAFx9)VoxAqFL6NXzO;n!WE++_9vbI;ycb=iq@`-h7$PT3OUX`LsFNWlN?e zOI_)F<wusywtn=K?QNB)T`4?(BZkI`iWopr(2Zp08(i#Y zjMoV0ExI zAvpYeFrD4w@o%zw)*~|`EFZqZhQ(xJxWy?c>x*uhWLW6BUL|pLEzS}XI`?T&>Px=1EPkD^HvWFPMU)J$qY?peF801bMp~w)-Q4%_WjB2^jIjWK%8x*K)tHPs&Nze^*4# z{NJ8@9-@tRdY=AKa(@nhYFq{&rI3Kd^x8{sSSoXGI1w9GeYcRRUHO}V$CRf1dP{8L z*OU8NU>0e3I@*A)2v70rYW!@(p8=>Rz~>1VkOO_6zU#Ec-40M}JubK6ec^a$eY@Ri z__}-0-^CC@%I>F^Vh#Di0H!s%qR;WY)ph^tlLQF&)pOU8BjmBj!Z=!m1xi-a?T{S< zPvNGK_E#M^z@iKk3H9!2t{6-&xAw-)J|zA=b+?ICCJQjyV#Sf4?s<0UP&OXloe>KC zo_j?gB`UJ4+|RQkLm7fDCwnQd0*^}6X7iFG=*Z`|dthbFffGz7lJ6s01)7zF5Z*j` ziOH@9bKac2ZUFAO&2WFNTV;%CbNLGb-ZBydtj+p*1mg!>bXieDiv$Kp-i?<|g4eR1M&=;uwdm$0N--ebct`B01W&k0v2e9Fkh|u!}EDXAuwuvDmQC-x{Hbk*b zVr$9eQwhcIiJ>Sxnv*5OoUU^tm%Ap1UX_F`YNwRoE7q@rtyltE)FDYy}iAV zkUkX~?>qu$vQL2feLk9L=kFJN08b!zLQ9)LL~Q9}ACf2)EJdUqPm!rA@QoxKatcJF zmZ>7w1Q7ZPimzcEh<;sUF**g!K7uil`W`9*`Nq7>%OgT4Bnq;n89?y)*b*R)o|l|q zN858lp?;HWVuX*V@bamne|~xY;|*l zNsY4Q+FNrHTqg^`{7H%TD*7~AB7zIc=Xy9t0rsydQlEtL=N-V*(;rlSwfJHR+ zA-pk#a+&2L{ehGjj?@pTA2hreppxjUho(F`qGfA|f1#l&tOT(tkXi^;Zh2%)y!0pN z?tBW@NVeHRKc6XHiam?mhLRy~4iLbOodFX}y@7?%#O`Om6lpkZ1jfxAGX&&q;$m2E ztYz4fhFF$~C{a)LvP1l8!(GA}xf~>9@IJt38+x%y8l8_$XBTbMpv9!DM4;~zqSS20e!2`;b@7U@xg}QAWw#ALFZpK9(Cn_dVe|@FW&(W9F1 zcI4<{J0WE3?aC!|vbCdim_>^WZfOtKr@8xYk2C%Q;_*U3DoMZfhG~Y!VyR^@gFu%C zM=V7wVPOjf9zZPOm*cCj^|D=2$%M?JH1*T=X!76Jf84q}b0t07w$r{xorta7Ck$c2I#PBGOr$b~6RT@U%BIpwa zj5YRdQ4xqpN(Kp%E^bkbo?3!nsY0Ff3waW37U(c+UL6)fvrh-Ink=u8XGB;1WDI&@ zG7`3d2+B+bDhpd@UHk|F<36Br-60tlw$Qxrx7*;vQ8A)v9$ghV=;N+uP9gj$qc&}E zg>!N0in*r}tnZ<(99_)SIn>cmUNYK!RBiv6L422I;BT_)Kpt~rc3R}^j)6#}DZ}_24 z4VA++s~MqO<_e`8EB?$UiP`_=lSRAeF=m?49s=E%K_m%sFy!+~5;D_XcI&1bC>7VY zSySIo)B*X}Ia>s&P6Zjd=pzDM+x@`RTFa?@1C=Qd<>s*x+#A+G(!Y22zo$}3axYsk zOLBm3ZR<;2F`Rfi*YBNz2cT{=`jjDJ6xGG}QXp!4$CkFEV&?rM;FPxp{j}zKh<@Zk zi2c(-S1FIfGjq>W&Vo~lEtznnk`%5c?*h`c|r_FB`H|>r((AV zd3f`5$YQ`5kGlFrT=ZMMJVznxs7SH}zL-pd0QkKmlap`U62Qw;<0O~h^QrV4Qjjsz z!Rg)KY)74H&z^a--))i>$bSeT1G3TRD+Ngd$*9deSZ!<>ZVg{aw1(&_&j=!bg02$_ z-f6rXKU-SvEhow!tyz-4PE|>XX`%U0vvBrsC=AUvhVX2b!D|^d4Su9Cj4Ba&Nl*aC*otl*oIk%s}?e}8}2jhdmVl|t4$ET#fa@3dfIxi@2alr_L z9}Ko1x=&UV(PjDp=gnm9+e7ZvQmtR=S_VFz7!DRSe6Jiz^@b8Q2kMmr{BA7>PQRE; z5Ev5^DW$(1WLT{NL2}t77FO1Nz-a*y9UUF~ItMKXMXm+gv~+j(^wN*_b^2nGea7jm z`|k3vFrLjgE`5TjGbY~ey0Gg;@Jw{YHh6DYU3rFGP*70ixF#i~a=hI&E}P$@!EsAS z1~YzTn)SXoDKFV_{*srEsWDdmb?WkT+Ikhr z>=U@#*cjYbjIkoaKC|JFBK9?V2ZzI zWB^^2)fLy?n-{h+9jsx1VyjprFnFbShe0C_Cb;?K2u#3bb2a#F`7=#elLFF5rgrzs>GOE) zGg7VBQe{Muw7;yD8v(tkegL2~TmezSN(Dtlj21m0_YWCWD}xCvAQ|7k^PIM4;Mq96 zrx=F0doZdw0c*Z>wGG#gQYdT zwR8n3dtV&A34ycN36OHA^y}?N|73h@v2v;Lbmw!1Jb<3H3%IbJFG$~5b!(*;&zq1= zeC)*N1d^}=q=K(zgmbI)TTxXQ2kp#mek}Fm@Hp>Oz?1r%pTb+AIz&ezB92{LQ3}7V z-@VU*&FlyPz0yymNmGPels?TOQEH%R&onRChok{a1Vqp90GKFLWHg_%sd)dZX=5jN z4@W~~xqy#!A8Of{y944=5Ty{}EW;X&pJ=ANci|J(YfN=HS&%YC{xDeAa{dW;BE2W? zeItEKfSw@|S+bL<_K7Z=Hx)xDQb8bxU$3jKJ`N0Tv&_J)te}U+_Cf2*Okt31yPTi6 zZ;pSFuj&0uUsNw+=d<5Y6{10OP*hi@0)&mpUwhxyd%^H%8(`=ruMPOK;c6E$OGI*< znviK^)<3#@kdg8elEQ^+)=BPOU0@)s;o*1Hs>{tL7eNN9JcR5S|A=tZ{wh{rs$#fO zJX}M+RU5_uPk)}RcXif>o0Z!*)_@?q<@X)4&RBJ)G`>4VB#+x@V}?VP+Rrc_S9%Cbrm2?{*(xK3IP^Y`PO}{k zQLx|n$5Toxu{i(atm=IDdOh78o1YCzZ30LY432vD1yDxFJ)Z?W|85KWF;6p zF2oJ1%sefNBjX8rzF5*CAPDums-IY43{#*iv7xU)WlDvhS&i;tSS7h44IL^e85d|N z5RyQ8_beu^wSC#kFLPuza@j06-28G+wDG>^C*(yt$mY7~`AE-S-7zwpV`CVQ z-wVi4DS?t{#wghi!8l_6@nuH+w%1~2YGw5T5Y-HO$Tb2#x$lyu#>rr2y$jzzf6Eq$ zI2l?k&ETwapVy2B&mPx156|aFT9v@FNwX^`>hYF@hWVy4A?>MN>gHk33ay;tuE$jF zE5M5lX|5WCn__}fx)xKN#Iz*XcyOg=npNnO7EZd>zta1{h_vgouBA%Sh>mweN=#NX zw8#5{+hK18EmR0A#Ol>Rg6E{_X^|_rk&64F_Qe! z1*YmYm=OAPDnsMMX}In8IBVN7a-aH?uS#;i3GOzRoXIkG-Nx3%smO_y!=0EgBJp~k ztO?vs3gv7zhTlFzO+P$ve(`8KI?z6!_V_K=I44rgXNAMsM8Z$G#=$v#KT0(cPinrk z*T}yFi)a z*Gs`r6w5qq|K0g*?dr4lrzLvEpMgRGJ7_kHtPhr!*(^&GBCEa^jlU4mY1pr-r1;FH zG6f3yp+7iX_;%IYF*hTl-Gm{^NwT5BtXvFjy{2OOWVw15@S2shSVlXtYQTk0d-~Ru~KHz`eCVeHp+wvENsBYMDO0_OaiT4dX;h^Q2 zKme5Wo?4XuvR*6xFDn^DgjVevrd67^!W{5sx3 z>=2Efe~aARbOEl2CTX|)3ByR zPS!;WI#w#<`OUS;Kb;j?8zowE(cw64tKlN&vv{0?LfznL2raK*S6DhMkynho8GG-e zdu5WSeqY`2&k=lHclx`^I&DL*M@h*8_Q963X+nzJ{qFm8J16SuxoSpXJ@5#pZRAP) zuER{$KYV=GrezQbx$I5KyJKAA=2V$o)~uIwbac*%A$Gohe7d`$^}nPAEV);&9&c2E zSU|^$NLn@M7+M^7uW|nmNoN%hRok{vnxSjx?(XhRr5g$9eCd`B=|(`hK~hRUQjnBx zB!(VfM7rzWe!m`gpa;${d(X4)`?}UbdHIspmbLERQJ?Chg-0yse*1ju4tTdOqNhXS z24iq=kRx!Gyl2U89{VKjRdtBOu9N33^1W5Ou-RT{rG@py0z0^-(45}S}zmpsJ zjWNzRYjQ^VMlLF7w)D0lsl1GWANOk+dm8?EhFrDl_RO`2fB`v9frkY*L$^ z)=j*W4Sh

}4NJdcmKFOy|1sYMk1L-C6ii@;_|N)u}Et2JDx+4M*%rUt*~gkALK)tnUfeteFYB}_Wpl9 zPiaPFDIuneI`qp5S3p2)n8LBdP)_Ew!!u9Ds2#P$=T5GFcR&BubzM|55fi7CM=j%i zEc5-X97G3T!~i2L7wjD(>JqrOo3Y zd9g9c&$!8+wtTqS9dzP$YNw(f6(Y}wfZ5oNgp}QL@)U%4VbS~AbcD0|$YiS4-Zn#s z)^zw$Yu^Wa5reF*%vOwe;AL_7%;vyi>*)EP$;b83Ub!m=`BaKTh2^{x_t0%y6kbNS zf&{6nGdEbl|4)iWu0eixA0|Bf@q;PwhZC!3i@PINAC&xyy4azeCVWz9sw#ejRo4w# zvFWt?1;U=g!D062OxBohsE)3DZ925pAltM)pUViOB}QwPTSY&WTq`HR^udQ#JogXl z5q@xQ-YIdllC;wEwQh-JR3rHf#Cq`(CWyG}2OD@be>nFw&+0v z@Ora>|CqkZg=x3CZ4r0=ot#e!7p=N__Ecg^OQBmyOxi$H`Lcs-xRrzu&{Gj#*yI2D zPJttybO*hpj4}AUsrXQd?skS2N?&D|NQNmwWh1k6z=YX;WN-D5UJ(fKTY@t@bx$5s z8ZyCztBexfoWruQ)Ce(MHq|L)%UZwS5xA4VIvV;#-tkn3L=BpEvX@nu23Z+ohn17o z_!$6nlxb<<)Y_k(f0e!6cu-dXTfP6L|g##`PKWjvpE z!e3^8GdP|uP$xDptu-%su_8y%v&J_8<0g6Q`#%-#ydkeOq^>)Ev&)C_-gP~LG@N;dt<~y>uCZ~>}q}zzC=F+0Q)iGwL1=<(nh7{WWc}e`RJldda2H{riCH+Sn}90@@z}S9PH%h(Dt4!&&S{Zw z6@T#%S?v^VMSBG26f`WnX?K*OVCSe7jT0I4xv~%o|m3opCkIW_wx#OQ-L4ASqy@yhjU1a0}Q?6iFA0; zONoyI^@oFS5R8^c+;AjQM6kw=xF$hqv3Ok5B7;JBULRKoOg2NQRiYrYXz+vT9Fl2-xF&UJG`B82i|a{Y zsvp{ugAsPYE+7*u@>FF7SWF-}4m za`DRkOlTh6^2*rF{_h0eGp%*!WII|~0!u2a63WalOp;1*#_7yuKIl&dU{&2^4OVJcWr((7FsEYPXl1qcpKEj7$LI9?KX3Sb z)Xs;jr5Z6ADa}i#-M24-&tU-y{%3v-QxUfU(3qR{RVIIGbCe2NDXqqsg(`_;Q_&X? z@_f~L5DWCV;IUwr02nZ@*qX;Y486#i=}p)yLBpnqw4hoBdTr2`&iL+Qf0=JV#0uzIAlUU}8i3RHzZEEL{!F;{0Ngl3b zK2uX(G$w$>12n-=NJLz+i4ypNeqk%zw)lrMA1ibgnLBOGHloDm+z8d9K+-SOIN1g; z+#qqZw2aiVmn`JVXJR2Yz(cxt2k-Tip~DzzWn7~mnUO*az{SY?*OlB`60g?efkubm z0s|!NB$K&^T{2pLaOxV|!Uj4Y*_-+ZEh`4H7!pPo%tST()L6YO#}t`STcBbXdaFl^ z;x%q;mk$(!1(Q*Q3Rp$u77$E<2&l&fk;2$fOa{OkSVKZBfc-8}cn}`n-*JF&TiiBN z!nl9)t)l}1PUg=Zuo0l{z4+QT?4I9#!0;l6ivYED!MyN&p}`18_!_#7kR_?9)V?r> zYWU%fz`j0zg>zE$tmOp?HMuf$?J=;1<@buA@4J7d>p7`5(WEWtVYV9;$u;7vZAtaJ z<0~n57rl9tP_s~s3$8&#XOvOGS2Kdn5p?00#^ZjJ=z7rIe`14UQ&=@(dt6(x$ZT6W zk&3+aRC-NAe|iUeI0D*w0%bcLM={axn1KscFUuek@;*~{H@P(;Yr)!AVzSL?`&Z3c zjE0c6XcJPUqvUE!YYCtk?6_e_+P2)fpV2i@3jjg;7Y-qdcn?2D>WwQ zx{fZgAVR%FLk}3tJ`0xHBPTHaeQ+FDuDSyp2(z_)jM4=FJ^3AY>Ke0=@*3j z2s)N0paH4|$Yi6(`l{4B?DOIV*aJ5(ypr=S5I-iSr{lQ)Ba;%wAI9t2ib$IEJH0rD zy%v@w*xDB$7CmOu&z{~tI=lNlt+dOCi+uA!P*ho`MYJUKQM0vWh0j6x>avU^nn*@R z0SllOlKAI)M4UX zAfla*0(K;WC7P$w_HLW^l!tT8%L>BdswYapulQfXiFl&!0l8`rFfNnW1|N**uP{#$Y*ayJFB{nisZ{Z8BmYYKdQ^A@zT_ke(AC?^ z5mJ{qZ|Cr`eC|A7p*QnbcqfImW~!Lmmb9atG2A2%5z9~yX^kf&b)}^vRnSz^{neq# z!=WKd6e?%V9wc1{rfga0e*UbJ{7vOpI+A!K5@ss@FK4gLy2|i!O~=A#7j(uJ%DUWw zOUBy}wBu-m$KH86g+tT(lBGG!!I+G7JU1Op1FP!@gQ z3<)I@Arc;FduSnuQ}eU}tQddhCK=E#!4*A}MhVT>HMj03%CK*k|GFZq3(|?KvFjkN zqVc4S0{cQg24nQ~dH4iA(I0-f8OP_-@_t9c*aiSq;AfngO&St}*ZC)-0Y#gjY?nM3 z!hCeesBsE&!)rMXNXB@d?+l?m-QadVD2QuhA+2;#gw#AnAjNnc@&cqmW-A+absfGX z)nZb)^UvgPoZ&U?|Ew=y?*9fqwc!l{6)fVQ?+%>!ALZb0i*zQp;r+zGCt;JwGD-C- zs$ivO36II8g3^+`-*>`!CPgq$almmRP(z>mmoEN^-NMnT1uIw*?ew(wuUp=d?6B!# zwXy`WKaYw+YEkBL=afAFTzlk)bn`2B>X71pF4Xx zw$Z^>>H`kQ+R7Y(SqcSMn_3}>$sY*j^nklkR)FpmbG>)WB)`69m>Z{6hho66~bwdRg4aCWXv0%ltv_*^3?HgOJ zfbPB}9s7gj?t4?e>xHC_=iT2OpO5R`%>abuwh6kQM$v{dXZdBy|82nTtr{}{0E@Cc z`}aU0F0Nb?{rUE3r-su8+p^Wa_A`-Gbq!8uuh5hf zOsJ2bORKbl15^1d&fe2G=HOnGB+PU}Br(vtGXwbe%#@biS>@}Y$RL8?5ZWWN*0$Dc zF`cjk*9Xykw@B~5GQ++}lT3hyIJSkB3~kj}Jll#y2JXBrn*NFV1|*YHu4rf7o+1R5w1ZI9*02F?y`>z0iRqUr{9-w_U&} zqA$5-Ms6?L&%z_^EY09X)9Km%@^rcqcQ2gW%GwfGqV6$=hpK2!JpkJmYN}UkAg$xN zJB#zh!^GA#Z07P-*t#=;gs(>zk2FdeB)(_HLt3uM%OIuVo8BRNZAcB0{)EAJa*n0( zJ3?q;G9lcr_^7O~v1^w|U!fwtHLtN9ko9hqG6p)l=FYS@uMbu5Xq0o8ae zzGF9faVj4{!W4yAm6o{1vXL`LR|t{v>9&9Y&Mc&YR&8rlO4E2xAM4b>r1$3;CUrg+ zWvXnkH!zXdhZ%jHlJ++z`Tv;SQZ=;da;Snn*JzyA9Mwvs>bivg$J zuEHnFN@kJNBkj?Ng0e;c3^dJPu3Gk%)?0jrFA)zwg&`b!rN$oB)zex+^zKn4tdg@a z7kM?!hdQh82KJ5|Xv;x$t-)N|md}Vo^0uz-fc}Jf>!w!F?W|7@*h7Wj@rRa3)AZ)h zNwDnzi5Kwxo);hd<@nE;cz9&A!d?vC`oNYvGaZA_g2KD6 z#r~J=y|14(5(Vi1emk;Panz@?@>g^CuAaB(R@u0^8l!;+d&Bj{v^tl482zuq!uOBv zJMZ)OKp^3v2LZ7GEiAb~EveJpC+g#haPOH#z+~#tQP@CD=#tNSjlRw%Mx1(;-(fVP zB=?IwnC;<~p<$T&^56V^)3ewu31>>`p7a@=J4KLuvzCr#3nlC~ z|0c%*Zz(tPrnGrbq%v#FrwLt3>I1JZh7EVcAZU)hX$JWs;o>+D1SfJhAVdqNvh!iu zvcw+SfzT^JOAb{zJGJyL(#a)nX>;Im#D4_%!HmF*QKArt-OKA~7bALYnT45BWP6Ew zmDI4Pix}E~UBt~6iZlfNh=yRBpvR$vk4Dtbo2_0w86LD z0RM+0UN;9Kqs>;A@4m&NDb|BPB^z*WK`k9>Bl7Vi6*d4&dMRPdTCiF)YP)a~0ONg@ znLwc7g_*SvFDZn92zTOS#iuof+J&F4LtUojnB21dv_w^B7=!PLOvmdG-g~?M)7A51 zbGJ08GOCyBt>Tm3o9NIGVoUTcIK$Nhf=`tKOU^6+LjtgmbnO2 zNP%;Ixq6|P_Nu8Sh`FBIlWl~m%F0?Nvq+$f#QA*&H5Q+5Vr~xYD(fAUmX@{x*h4;l z#6fbto!AKn*VO8-u1@5@BfFzN#FcVz%NE{^pZA%hx9MlA@~aLOqXu8V7LU&AoweS+_J<-bz9=FEV*WPvbIg0fYQJZ{f2Ljt(+*rmsCZ(~Utzh1=-s|>9A5Pc% z0mGey|Gh*-b*01e2*0|%SI+0U{f{{OBDGXjS_(NWZhSjcY7zhfq|TIKc79EC){Ft)_I?Fs=+NqiTs16z78>9`%uRH_U7!c#i(~a7AT7|Ff|Q*d?(j+9Ry4O@40qQ ztqqSBXEKZ%>7;ZBcxQC<_l`e(={j$Hmo`0+TD`IcSqIJiFjVbZrewkBA9R(We}Mt| zSTuN+5^hX3Kw-p6=6gMcrQHesqs^@3qCx=5zxSeOs|;QiEH~Hv16tj}Z8(uAD8MOK z(kJwUu{wmO1jh{R4AYA0>iG*dEdkH{3Rhbv-#4!6-cynU1Eqs2XF5i}31kCmlW&G{u+tuB-%3xW~E7bRGi}>tu zw4N^7kic+^IiS_GE{_m-Dm&XCot3yRpla#k)fG*Ufd+MG^ugcBm%UN5D)%v=Z>5s$ zXUAQUWt4LMcw%F$czLLcm}@ECM_%ShVI$$}*V_kw9avzF=OGR-D>40xLsy5%lvSA- z?XBX!<8K&}_hoB%n!c|qL`d}I1tg;+2cA715cfX}q#y=4;{)~O=DEJ9`d<_O_4P{5 z)D9`f(1UuJg?%q$FRd98s`oh=Zj?BW=2AVbLY2oPMDc;cEBf1}=TTL;-IgEr6>)42 z92!p2TVm`pYy)$Lg+Sx~E^;}>H6g4Qes*ZjheC@grVXY^<_gV*@65gLq~*LubJqDQ zjjTv0?~a5zlmBHoo)gr!VTs^ppD(r#3u?H#<&Nq+bWpFrH> zV?_lqqj2}u=F?CAn}_P!rjCL0SOU%-O&MHEI2C5Oco&u7zm0uBjs#mVl?0e9OC|e; z-G7*X!n0|poJv6eOFD=DLUgmJe-Q4jAh4ZdKzN2nc0;P+PGNe+hsV6-o)KF zP+a?5S47^y!4h%Tr+?l&J}#bC+>fz`<8pWJ|B}a6AZuz7IhAG9v8Efk4%4MgvuoN| zHav+Ag77_@=PZ8ts-mO(EYHH#_l|nLZ0qRm zn#zA5EV)3TWKH{tD8g5c%z8`WgpgbkO)@6BO^xb|cxyw@TqjCObo=LNYp@%rU6q=y z*!eu2&fuwudkDUo)%;ah2uYBQW{G2EO3g%Jo(?blx5hE*_fg+_5hShBC@jx*CqMq_ zfB2`pYiqc6fboB0Qf^q}&5|wNR|v}+j1tV{nmARC_;RhCljj#tg;lLd&uei;Sk(qA z|4@f&&|I=45Rv=6t84Gq>P78&74ELRUDQ*hU|g%M9fQ&cX^pa?ZnO)0B75RrgWUK9 zBl&~soHWrL4UV{l~z1&Cmbe> zQt@bnm+sm^U1+Gy9hzSH4(Ky>sFNH;b#icr$`F#dpt%%;F=CN3CdZ_zq0soD$|3^OH!xvkQnC9ZHT#-|T1hjK<|`Qz zqD=+{&QX#HgQ($Z6J5+l4u3}~DcEvWFl{t~2$)z!QB23x`Vyl&S1W6#wZa_1DcSg& zVKD24J>qDcB*~UAN5p@}ZMyWswEUUUTfSR_Msx$MAZT9ij7RuVSFh(h?NN{#tpQV; zV?9{44{UyQ4^*pcXn9x+8akxAtwWoOj6=ngTe}|45$$&1;HTf zkP)QKq85^jb~u)+J4+%7w9I72MzCns{{DDxwuFPbX?u8>+Y2w`2A9=D$$d4#m=OUGtWI9MZ8rUwJCpQk!o z+Zy~&p=JFdJ(?Zhh9n)y5sz+Ic3qfHLuVC4esPk?R2xI^<2@+@f^;$@3=k5?S6mDvuoARG2aE9DZXAJc(p?WS>^@h}s*r z=k>VW<^%dwvY!GkNK<>9 zgr<4!z}_X?_Sx<1nQE*K~yqS(CI?3BD*_!qO)G2NcH6wJL60rNq zY)h`PU!29j^kDVZ$|>W0;!r?Ao9}W@YWRsaHyewi%vRgj0M{m>(4!${G_<`+LblM^ z1hg1>jw|cLCq1EvT3K3q5-YSZd5VcK^&f65p+GNi(hl17#vle30BZI`kPQ+;c&9CC zM!%g!L|->V^(~AtZnvCebkyzEE*k2`)$YN2%=zd47S9AB4W6SqiFbdLQ5a=0Nur{j zfuOL>V*%NzZiNJ1=v!X2-uA5-3Y)pk@AtUSv02-b99uiBM4dfA3Xjm!gr%%|N-(s7 zQL21jjwf#WVY)SB{HVSl(ZL-gh$3~Vclh#7h9ZfH#_s|HOV60XPGV?{Hv9|BEan-F zJlsUH!Wb>~LdPF~A`Gl6YjeFI_yB#T`}^fr-FA0M{pY^_P=v1sx<8ut!?#E--D`{U zQi{poLeNQ}*RYjl6Z=`H3nPRfTrYcT_OEYYkq|XJ-8UTQ-05Dv_s=8?t$N-kZkL;l zBg5{KJA=3-@!#UOrrk8~pbskT_H6OUg6Ty-rW!6B!jHiFkD2JZOMa&WB-H7LiRpUf zNUvYMAFk)Ex6-Lk-P6D`k_1Ak($KGHmgys>3QFpQg0`!qfcRuIb6w0HIMo6aev>qwNzzsRQ741Xv+hTySuw@m5nC6wCzMroE9EYkGR&E;9@oA znm-zdApUTn^|o$HPK0307O;5%bR4{4g}b@gzU@yxWHAsQpTPuD(~}@=Ka|?xPvIW@ z=ak*iD2a*c%3ZjJxL~RB0H%ny6nbJSe<~si{vQezuviHsJCTgd#SeI?#(f#uIvgTw zzRkdjF7@X0zw|65I|if4q?(g%n0 zdY99zrLOO(`^&e>>C5+gv$Nf3MYSTd;D;p{=TU;PLq8&i!%?=o)AqGcmOJYoIjGg^ zK5TY}rSw1V8kET)FbElb?*D5~EbDp4=-9VK7Ql4*C}CL8*ER`Suhe>Tr0M%{$v8&e zK`LSFp+0vAN{2e@Nm6$zOA`PIsw&I5yq=5ieSqq8x_&VxX}b+WAfNdBn@?Qw&+5tZ zp6V^qUq~XVVk9Gy&nP|kVlZ6adq>aleKPJm9&8*8K;N4q=p`c@L@OOtCuP5bR@HUp zr`b_fP=||VG{Ulk%cM74@zCaT$FpVTY8$iK+FFxt8AA*f z@H5ItB#$2vB)TSsUgO1PsEp5bnh-RsD{o(n!+eft>jH-YKOeEeKo4Ud>RCbL`)Ufi(~2%@Y~#t+mcK6-;byCc-?KH(R{!@65vUVoD8VL(*^Qkzw3 zeLp^&U#Ir&Fa--t0-h46Kx^TG1PCJ{wRE%$O)X*dA;pUkkm8av$t)RN`s1~5kXlZo zWLmyX$J4nyBNo$;69~9uYuz%P9uPVg)oy#ar)&{kjoQI_SRD?0spPInEF_X?`lO}w zC8uBl6+x+v+mj#9+0Fht%($9xaxdwptX}Wc_}Q5TP}u4@v+o)L2J1N+u58uQ)V1`r z47<;mfvXw`>ne-C@rLW~?9poxWi(peBsuhxr=dM9d7dUn zXnG%T+1>CJCA;h)f#WzU7Uu^GTL~RntRn{$&S9t2*{tL1)Z_D#a?aIv)FCXnF;eum z1r1a>dBPEGtsWi@A~jC|Jhl!TTEpBE&q;~Qhb!IZTaWm$s^77FRU*gLTwY??Watd%yZauND}?6+Ynq5U@nR2#b_{ph+!6tWvD<$Ne87bIhnAX%0j4S>7J99 z@ z#;BmQ1u+t|gWaKwR=ht_be&dzs!oi6rgyjztxzllYx{QTx${>n8UUifNEP8g)%ZN? zS4HI;B3Etvm)e}W!cj1~Xh6Y29**HS8KTXB0k;B(eE!84fQ!yao@M?FjI=RzI1W=H zOpU3OC4yyP{YhI*hV6>I>!x1;k1)&_t84i(GG3k(blYOsTmdh(HKQlg5HQhbF@V@+ z8hD%26dgZl(t-3t{KuPkT!9-yzpH8^)YQHIqHC;)sw=o7DcnaA?_`f_qPusT)J$(`XVlMHx zVB}8TukYt51Un@K%=Ty}FEw-uBRMt9<9j}V_`ht}JAKG;7#ay#3gJkp3<{x-aiwQa zc0Eu;5uF=(+@cVqp?C`s^Ccuk)Coo;%IK2C5^;MiW;Abhd4Hy^>j5qHxKg`*xv6$O zr8lm#ey{((h|H;h`K>9E*s~Ly*72~U^Mn-M-yj#1tSk$yCZ?39D%eroc3P&mWqO9i z577x?uB3c(_{aWsK}7*nl|pcan*W>Y^)3!=Yuu!7u<-&KaSYDQH9y>__NRNaZSBOFhxSjysHcLq zukD%t&hs!rz+@M9DpZzVWegBx@4ZWRb9RahcwvP)&k-q>9bK8TG7vhSsYRL- zX_APV8+_}|XmIE)^Z2wCDiYgiwC14Ap>IXeH;m;lN`}k%mTH_bmgT%MEIP4q#wzFO zGv+efeBS%NVJ44IDb}#OT_2;$;lO!X{L4qKPW8IW9&4%k)qzHIW(KNy(0wlDCUF~b zVu;d6G|Z#E52moT&rT{h;7;hf80wwUm*yuL$0ki;tfjOAFS}UBG|t@CAI-9nRme9u ztJXiOHaz-|(PoTh-O7^HxXC?Jmp#qlrAq7PFN^%Ja-ctOVuFst@7`=-1Gz`SE`Xq& z*mhT)1$ei`ytKk={_@N;h3}CPT+KUrx?YV^O;>LL&n+b^A}U!ay}km^dVv^D zMTY2035vhhEm+0-Y?bXW@L7ju&M<)q|B6s~N`gw)2Yv!W`Cq>XnDM!jGykq|qlo2K zmM`J*P>J)6EiW(QVD%$bzynkxE>dtKU4WUE0@j^ap3A&dS)~By|2CD5veY5_grnc4 z(@eSMnqL^z)6jsji=3mup1&$3!oQxwS*d|hY6g?p!jOhl zsQ(VRjVHDE6+4IIPKD%Np@fXd-zh`$9MEBb)&O<=>=2lHqjw&;~9KR3#yOKP{=e^>-YcTUS5$gh9INVo_p76tf(c*Hw`6@8ZrCncv z8-5s*2IfgG`qS_7Vi)DR{qeB4tmUuqSI!d!sVGPj6dMH+ddutM@u2_BKEoYy4bRI6 zD^6Ha0s%&6dpz33kkZ@!6T|L?`xPm(Hmo3|0|YRVCFn7(FYxKRDd2*VkJ(C%s;$%} zxQ>jp#C4oiNOT(Q-{|o+)7>$2c{^Cw>jVHJ2pg|L!owX^+XFoM zdEC!Rh-@sMBLJ909c3*MGi#0)e``H6J z^~1{``d@=9n)82ewNS#ouk%Qv1Wzr0wPl%H^SWNOB5s5fc-V4KN);Aqyso4&RX~F4 zIo;XmJu){Gb#&!RdRDL7*P5AAn?SLJfK67V z;@bS1?XYIRYe%`yIb|syfFD8vmruG&)hDC$kO>uIWNRAwunAHmT8?4uRJ4Gt5zsh* zN~ZlIIiJ%rzOb5iym7FxAuSHIlD?MbYK|&Qv@cORe7dYjmS54QUXLX!t?D$4)(o!h zbc;|7W6EeO5iJ}IjwJLR4$xDbl}F6R!bD|QD~43^Xe^5w1Z! z7EG{Te3~^Y;Im1l`)i)&jH|Ls1M^4CoMmkliMmXGzTQyRBHLp%66Y$dCOv5wjj)(p zK@lcc`-I^wz9}BeY*BMFYUy%k)__i?UcxJkRuDD8CR{;jB!SCKaN^!@++C{MxndY8 z|8B#IkcveEcAiO~6D4sti|Np4g~_P3ys1Njj+4)14SR)l5;@^&e1pz9Hj<(H>_J=8 z&Y>-;#)Ksn9wa?ZZHEJOy~gH9)4D)t+sn_DE_hO-r7*4+FZmM0L{m-v;MFHwYX*Ly zrx=doEG@H55A74A=!azWx?(nM9Nny)D8e~2o3md*4TRK74kjM6ka;svfy(y>_yE}( zW{}7gd{ZbGZ!~EctLCI97F=#KJGs0mj%im@0_>U`i{1%Usbl3 zc?nI|wB@3D%A(ArKxO*Rgg#hcfDX8$kG+>JpmJ&IZJmi#R>vih4p8=h_5>;&$k75L zj4G1%mzQF!In?1_`|W5JOBERvF^LW_FGp+H46p(Qw1Oj8JLhiw{Cg51 z<|1tJB47;K>T&{E4E~R$bAHRTd%Jk{G}*SBrkZTqy0cxAZBMqX$+m4j)nwZ>S?@L9 zJ{)vBE zSM2WVka9M*#%`wD1Wx1;JHGSvwnY7>5dH0J$X71kU7X*Fzp(ZF!#5l4Tfm{h*{5*| z0)z@J;G&n|Yr5~KVg+6?dftY@Zt8Ez5qm9*)GL2wxvw#~uD>~K`n`V9u_vVFD@Mbi zb(k(l#$46x@iE}M|L}6_d3?}zv+3E(>0w|Q6phoC=I3J=fk3+Vp`Ot`EsH6xgk<(y&ml@yB_s`es!YQ6a;-S0~fxs#K85G zPT;WPefVRXKmErGCI}pmv+niWl9J*6Te-X1!V_t?#s9~XCGI-J^Yn-jpOxOFtIin( zlYPU74o2@v;()om|B8RMEbbcP+1&7Tb_sv$>G8$wXjnidLe&a#^|I8WP9izVsb9;<8KK_t)pXRY=7 z^sSa;TdN!89XaA6o1yWMqLrycY|7LN^DwLw*HdDf`oq#pW-=`|OE-L$hoXB3qrw7h zwh$8c&V*RR>MotsLPIIc$IfD^<#;%W3n(aoH6TBbbxXhf@Z*qEN+B$%;yL_Kx?OBg zsrnx`?jud)A0g`IJXG|vbmEe@RvNI7KVuHh831`H+!nQ>q9SdbR9XW(un#@kWC6$c z&kt6SmbHT^j#Me;tq6_;b*N(~!Y?%AOan&Iyfa+M*jeK{2H5Qoo@g)p!)m_{90;JO zy*5YzOr5nMY${W;mW}qRrD*Abp|5Wa;qvDAF5%-q6Gu?A7M}~ks#7DVfel}7{Eb2a znRs_Fleyt`X<{FCi$YJ&EVSHO$`Vx=yx`Q3Z*VP3Q~mzznM#iXo$}k_-8Q^a9V<-Y z(Vxy(W+X@qz$SLCqbVvqHlI$Jq^#qysAki1CqJ8k-Tlb-uP6r#8~fxpvbFiragr%C z&foINB~h#mE`YCIs_?i{ClXb5QDBGO;b2!8YhUzHGi=*i+2q`@5!bY^7el9P2NiR+ z%&nOXBM=a;2}zhrL6qxuT>}#m(EvkTNPogLMRCHObsumRt=;xn+1!Dn2_1s@B zP^WIJNg(yWG$4EkZvBCOpWxKyKJ3Emo7I3u-d%kgjWKms}Ei{CfvUqLAE-;l8Q#XHL|XlZRpf5x?2B+Kn*} ziWo}3VVruo)$ z@~kNae9zkUI&*747s~Blp)PBQwJP(o`fxM^V~fZ%!yo&i8TI+Y|NquO?bW%!)w zWcA>tH4^JqBIOq7H%ETYoXlNMbQkF;P)Wmvx)$k2MS{aD!*VSiYvJ>rxLJ(a)ShCL z=c;qrWXyRqvmRp_-A^bj`d*A*2;N!gDems_(5`1K*l2a~6jNzFI{fYg9Ltv}bJF`f zV%0My@e*1i{z6Gx!WSb+c2JTGp|u2L;Ly%4UHg3;`32TOBhD9w2&(-jf-lGOjUAIb zEi;8H_d6>l#QW#U>y^RO^lLZz8}Cjq$NG93{)Qlj;C_}+pcaN`1RAAsvyIb!BeLHV z@mYD*YI#-0t-41`XM@^VhSrtrB1oko{U*w6xVcg^LW)8N0ty_3i`^fFyA*%RyC3}_ z_9)9~%c}$b3tFw5)wPK3dbd624cE*a;?~upTNw}A0n+07vgLxtnBc^tUR(&a_WS1} z?>ZfC#)D-+6{UC21)P|RZ_YLp0)|7S0~DT#s3L6j+Lv_RuXylEtsi2T*X7bhRn4A# z#A$}?)vAi7DQLO@$fT-_cotRu;*ELSsTBu3%uqJDp(2j=l&Y_HaPD;enE*c(bTR+(7O$jDWsK0t zr2XPv6yxw(G|&d}fK6cP?1gJko`KeP*Az*sLsw9B-_MOVG!BOI?RMAH;$q6`wtK9U z%XUbY<&CIBtO`!Y)Q10}HLuBAf5ONUj&$FlkGI6I@H+&WaGHQytOSp8gGvSug(NF4 z?Ud=h&8tX{R*E(8B}$1~LMt_jVodE#AWeehdaV-5*>mPABICAb65>wh=t{`U1n9~T z*x|ZfMsd|3Zi4WQkS`AapNaXAoP^*2zTb`cAGg?>x|_JR%A!I>4_cZ+ti66xGssGA zMzUaqv4Y^H{@Y&~S>JzZyTx0WQD5|>aZy`Zhm5h-Hye{kSK{Tn2z#4}vMEj$zv4Ux zqsupJZuFsJD>y2<98+=)i&_zRc9*b=_nBTc-&IbDW=Zm zW^v!c#f=!zRScL?(Q~V}^+JlaNQbdtFh`D?OPsOj^Dt7PrE+g9Boj)G3rNr)N(Eog zoFy4ZDK~i->iHu=Ka9FYWTYr4-DggRVT|`I#mX&*O z$pW`ZNE;~I*o!QAEG|`jlPXa_dNA2h1@mAD|0SixwZ`lD*PIwpmegwQNTNrSzw{su zrtIY|eYJ`K*=k@Gcx*w2)QEYvRbD9;9#H6*(Wg?abp6z(iD@Ti;WRtcj%q+ER`Gqb z_lX|qdF9LTzLgq`5~ml_f}VD%cWr;ymz%S6;qE*6nWFB76-6$i^6_*t@_c)hvuzyq zHL+1dm@x$+YXo1U5@Uej=+HX$Iz+)Y1AS!E(B+$fp&=<8svc9_K(R&e%M~aN*B``c zO=>g%0$LU4u{PXu1U}sShPR%ows!JgFH68Q!)J*)}klJ-WRG%;8%-ZG6s9n-Tx<`__HAXK(5Wo@`M73M#x*W>f10 zixakeUPDO`n_lXno_e;C;Pl3UAB;U0sPst!d!n~kxcf;kV&L>Gw84C4lY;=+UUDI6 z&VqsjN*S0&3p6RE&>TsD3=AybVI^;0EMUvjDRuWH8n4|(`u;Bj3=vi1xm`-So4Uu- zb+z}{P4^dObkl@w_Y!b@Kdjl8u3bRPp16uEZE?>clm!|26rlla4O*K%kGkjXNL7zm z+!1@NO1V?@NXC$1s z+d@L1508#Aty1b>YAB>C#PqPXzqHOKa-J3eQruV~^@^J8v9oy^2CnUqFb4u{+&BrQ zC@7CY5}yMe3{0c!*D}2Sl)3vI?jxouX8v_^_g5x=eJeQxT#TfUKc@s-8unyNhWGH>jA1r z6>RlU`w)|i!=KU_bRYr3eU*p}tp}?bJT>4@rnxh;gkY(aVxk2X=eb9!4pnSM--{UX zUxFrm7FyJZvDu-SQgXc;@Fj8+as$ybmCai7BPKg8Z^*~Xo=_gQD@y*KV90uqUamqZ zI|;!_Nt(k3VU@W8Guu^eI7D8F$t}5sI(n4&u_tIWO8vSpR;%klcVjWu{VEfvM1B$nX6P>?mn&|W%el^coKTH8 zG_i}x=5f8fiS;A!moE*vt41|^CHYbHiK0km%DN=LkbNz)J+sJbcyZXUrJCFZ@p9_e z{GOw3-03SX@SB}Rh!oE%xF(R06zZ@P)K_D(wp{&n?@xeuZV`iwDCk*uGc0O5tX8L+ z8gwaA3yPX;pZ$T>|L5~>sQ_Uk7+w6>MRy;Y@=n(z&j?^7c0VmE<@CNr>GzuFPQ!#K zgB0yqu*_#%cUjg2{LB9Lg%Xg-6`RvD$7f4tp3%Lt$yEL~D2o$Qhb^_bN}|v$wDpz4<0wA+kdJi$ZEN z623})a(Hw$0_{hX`SM4s!&3>55ETw{yl`*;8D((`jrR5QTB-Xk>{c}a*&?UgPnXTj zMqSI@zng^wNmPHC{PyD|T7le0kb7d&C}%;ItRnZ2nlP(m0Qd*sM%?}zk@&@Shi}TG z(?wLR*B(BgTs@;7>zHQuA0tXLOS_Va6?gvQd#}~O4Cl?VD&E$9&X{*b5&J9|%nI0Hr)~%S;svb*!KIa#FrMr(Li;=r^v-pilz}R;18!S ze0FKJ4riBy>+Qxl_}sP+e-f6Yw@G?fwZ9!BX>MvBU7!tb;8L)ffbx7eXTT(W_0lqA zGkp9X^lFfnw_%z_jC=xFSKeP} zE|@}$AIQkXRhJbNWmIZjomve6%D=j$N6*vN<*o}T5)3;{9V7HouIJ16M`EJWYzGQk zF7`go$U#-8BkI_iZn!tfVVPHLi9wG9;K_Bj{niWu&je%XQ7fG?5|ij+sEL2(Wt^6d z0xcFd?~$#FZpuYAV>I!lu@$Aju^RY>KkrJ} zrn=4Nkfki15jj9=E+OJcX+lRfPa82y0pm?+N1HstBSI~gmK|$h9l^vqOd*M@Le;@V zdE}8Ep6D?x9&fxGzM(WmN`3<=RE<6@kzjlf&LIJfji|5&GQwy+Uyycsn4xv0By2~I z{jZi_s8cVPiQ7X7iZAZ)xq`UO9}11i;$+?FNO#@il@LsnpQ8UiO1Q?{>1OIv5l4D! zl5^se#lAmm*#kHtWF;g}KP?3vn?z8y@i{%4_#4Vh{o(lM*kbHFm1{oLtfO1Ye7FT8 z1tUeJsl>!@&g8DVXGUl1m_PH)Ng=t%layr`HA9y_Ovfak0 zap_h)KLl(Swb62nk2r?JyB^azd-tLLM{3~Ff1N>@CfOC_!BkexNYJGI&3Uk$f2PIn z7=C}?mhM7ACdbR9gr{0mE*yz*@UKAvvBvv0^cBXBrjeMVQ4OqF{iQ{lZ?dT7PJ(oY zSxFm>k@zs{CjLFFB^C|LZ^&lBBh7OTBoFwl0b4&c5z~b7sp>0dj94~lCA4`Iize*9 z)r^%TZDYzW(Zp;F-v+mne?lc-k*e^CU_|t`RUU`&z5j^qsm9?B4*EW`;w86C`960184GUX>lmZQ+@6q=?dvOlnJfwLqtzL; zkf%b=V&Q#RQE*z;bt6SdY8F(j<;L6Ghjjw0{-OKhXSuE4G6zT}#K~^q+>so}T*VQj z0OL)?$Itq;%2PgmYJKPDv{Cs?r1X~wP-IG9{KeyI*73cEQ`JnwSnv(pp|x$6*9Hyl|Ax8u42jj$bh{pb05vOzjzsm>UX9Z+WfZCC zsro7NR`uiCZl&;=3gzyxA~nX`@;jM@q%i|Yj4%WzexioD`f=bkY&)y=ddl9?*#=sl zh4o(HC|<99kyYkePdBP6D{CFzFmF|ASh()6hRRxKJSQ3}jjI;|{sexrKn=bqsW70in1`4McDk@chVQ+QJp~r4_E|Z%tw!f zb6MVxoWnT4W|=ta*|~wT{JOwnI;eqx_7_XySnz-Fjq*Pi&7)ZW`)!z2XGFYX!(!ee z8(H8qG~qAx3bB?o+c^CuRwAI}J(|=SKha7X{5ihlCWZg5u)nssTf8RK_`-|>vlt^= zJ+rNCmc`#O&?!cW-_WB?AxC2Bqa@x*Slttfn{)yOhxGYhHanw4(&8n|FOACd7>q4l z7H|4B%y40^?xdMi*e&X-@ke%!hJlmrO#L~e{TkOY$$LG+8t6XzwAqQWW0igVqnpH^ zA#7kL3`^EjYuKF^xu6P@a#|z2>gzd?_bf}j58-Avin8U<@o%d|bIFA8Sf6vaue{e_ zHJ>Xd;#*~NQ~r-thNvSf2PXahRs}%A_h`V35AvYdZ5~m_k`@BwKj7vLP>=hn@D>Na zyUFj>8RNeOdUmb5>3iRZ>3JMr619I4C6VO$#$}43kZP`WqynXKwIvwC`-4(xpUxPD zBBih_&ERETZ%;R2o<}qK%lzJV73>J-T{bUxOHT_Yd!0IKl21dzWgk~7|Hh+0ZQYxe z1je}{=e#U%eZfupT;IK7g+qGmnls6;aT$;lPp?wbkZfqt39t1u+SQ+_zBPX26JGVk zGD?_E8`g}!mM!R>T|@%zZ!@FA6@!))0kL|>p)TxedI88EE+`pJOCn0Qv+rMj&TP0P zmg7WNL;TF9ATdUwf@3Zn@|0p6cSW-Ii7nUmOradz^Yc*b(|bk z>rMDGpVyPbXPDn)H=&m>yWmh-0Ywbv5X~{vXob2#^)8rArhg0e-bIvb0g|gmsWn>!{MMioMN+wbO`51V490+~BAY*1=-vCp(WDK+->}6P22nRS z^NUrS!Ru5<)iK>wM~tm+I!==J+h?BRvZp%_u;Aa-d=7@?*1r8)~K zk!%SF0qdPiIpH|?cz%~4Pee0nJ3^-o2CF>C#+lumb!=`kjze97U~RNjv5|BoIzvu! zN!qA*ZW`SbvVA2^EVm(v=Aj8GcHJi~WN`L=B)$-Q+B_V0%w(FxX@EV51=c533OiK9 zedCJ=Hcawvf!4k#SxAvKRPX|YBPV>K`gKn6NtiWxxdRP`@Gme7;cu=f)8_;cfs2c3 zFZdNYE#?A#7cIU)ThFKVPET>-&7dcf_$atNp>d*%f}-p%-|^mJE3yseY2NC92ZxRz-l-&K=7FmVYH)V<`nHqIP_m$9z;v3B%Qrp$ z0qi+(_F=%N<}uU@)uc~&2kJ{~TG2FCPLga6WEaGn122`y4#qp8s4D2eE? z63Rz}E6XTr&k`m#7O=c({{&MwMHk%r#l#HXhhC|K5WDDtHf?4@BvAgZG zZ@PfTMvo*c)95cj)SjyyL$LE-gxd{&TX45JvB(8%&tvhmTmgzjj0SCpyvow@@-qXC>4 zWL@(kfyYfD6p;e};QTNmqnR8&Ip9_MB?SH=mv?H=?`Bub_i2DwIZ9lVb)&qWB<+y% z$H)(#Y`Dm378t^?U$W+w5&xp9-VY7A&?L-GpgAhycb^4<>I@@4zs!~T?A*guy~T*9 zubE|wAab#6xvvf$ya)erL76k>9Hg7)?0o&${`$1U0n{qaqxpSaeeiX^EY>(~^ofW9 z-U$|Hu^{z`B!t?Yi?A(Tu*IHIL;vKU10XMV1Or~X0fDEfh%*AD3nokX?`eH+cM*{^ zG)~S}r6{1EP5MpHwqq|SsIX%u_eo!=Df?x_2S`g8aJ7!X8KEQoBSD%E+1y`42SfRd z8W4#y?BS!us2!%N^v-jWC*sDV{53u_#h)#-Iy409+=lvG7G0D8RSn3c^M2I@H-QeQ zL<1Xs%`53?9`2|>-_$vAGJ`_LElhyc!C+SdSu<+!4=0lsXx6y_>QAfP*RaRQx^G*; z*glgcft7(@g^KwMkSvoDhIJn%C0)7Pt=UMJk$(HDMwAXlGX-#|*UG_F74)BF-fgiF zdsMXq5Ff33U3I+$)x6vK-fQ@U5WYSH0hJeeY8~i}voMIzjKBSa{(%hB`#;tbVnRgO1`p+`mZM!nVFv|6{pb^$Ap{4@CDJrk)a%ZR<_X^ zOj)MS!oxq|mWfv;%!xVs896SEOb?(WVu^+r&UfP_h;|Nnh)bIM1dx~=|4JxazsSrK z)F(X4!{$O`1U!Pz&#u=XeCQ4|VjsFW+V}*yDdbQ}9nFCn+S|vCiZg1G29q*l>dDsc zq;g<|xGbKkDgUt($5-)yJi>~!qVSH`wxdFg!ad)wy)*zu-8;t|L?zr+0{ppJ;1|9v zPu;YDGVC}e1@?b5GBn~N!JtPe3Cd2{+s_P5PM25^4y#a*-`1NL6T~43&%g}1&?UiW zCmt2f!3A&EjSv~nOzYC*O@5gRn=PJHT4HXykGx|pSFx%~O_qG{O?$RXUmQ~QOl9bSDj()eFkRJ~|L znB++wmh8W7eez>}>};9O%q!outyaNrg}uK%0vV3w+HObE;{?^wYCI2YMH$-ndK*GM z&%bjUUD1B%E}(ZAbX5(`2l_0HXuZ`B-v8i-0L^Lbe?wJfjdH8+TGfA>{rM&IuS)@dYxY%l-EDb8R5|Do$2>5w2gQJ~ zIF6z!3GL~oVdna_qDB~P!Kx))mg<z)hEi0LlSiSF9HFfBAtUH*W9xm* zf@0chd>&0EHi}I8E148Z-M&?{XY~*0r3n@ElBJklRRTmErSmae$`C)XJ#LEb#Snh8ZDJw0H*ZP=1^YTpSF`m(}b>m9i@ zA$`Dh`>s9cztf5x!;sV!ISev?&SSgZM=w7QbM#1Q?Sp$-@R~9RdIeX@&yJHU;)^}~ zj{H+6X~@u4_qR%fGZH}2+q8diJTXn?EJH3qgBDet)i|oS)!6WLWO-wfpB&KD$^p_<4MZ23ODy04(l|=P`=N*`e8ZwuKo07$VsMne1R6x^aVPsPp zEzcub5HdqpJ;~`b8${UubCAfs&9-}huj8oI+Ppu0@Eg|$Or6^x=Dyc4LE^l!bVNeK zpfWmqU!QY8=2}j}S*S_~MJ#)_GhB@lvNI;{G}g}TlGP|8H{2p7r?fCO8hvj?Z4Zrd z<%7CKF>S8b`NCUQjZd`x$GW)%{g8ooe7z5(_`rFQLc1pdQ@8xtlzI4;cg)91R(fF-li5d?SM4*rzin5K+;@%Z@ZrkD}x|-2WB)p>! z#CIW{E2EZ;<0gcd{6eOQut6Ho8?J<3-;$a)Vw7sjBiGCP>+bN~L`y<*4kAJDq8=eQ zFA6FIY0+RuoI&(wq-k~F ze#SU{-`Q?jzDeGCa!j6ujqZ(RHNg;i>tm74AHP7A_C3Y}YpUI6lT$1Mg9J{^Ohgk_ zX!z^QDb5-zWq(yT_|-@l#aRk4I(Bb;+gYy_=kgm_hm2BJ0b7tY1GF%d&`jQoo{vU_ zRklaXUC;Op;`OlY$&zu^7pb(beZlIop~f(UhKn8}`PTZvj%uF=R&1VijNRQ7oi$8? za*W2~0#J(4YjhP5LgWaFT@2UCDhMc+!iJ2>g0#G>GP>P=igVjt*zTQs`LQ*+3t89&YIwAZ*zZD}Yj#vDsnaSH$XaNrGDi-Q7qK9Rl0nqfXbi zCrbF;uSVJ=kDGf?ogarvzEAt;ybsUJ-`3=BHVx^)6(d6HDY)DrPp7?(34Ov^Tl&CJ zg9uTnQ4@E<(>aIQ(k_2v>;Wq^gQthPFt?55&bW>ZLw%Kx)ulc7kG6cfm9z5ZV6}j} z-2_`~u+LFnmh(cWUVYL`-^+}0x0EJ;addNYGb@9M<^q$t)9&$NvGp;wQrxv@vxua|oO znL(05Sx_BAl#$Q?K6&0gX%I<5B**u~5}?rpg{u~pcovUYytFnh{RZA)##A#>3rQW9 zt&x51qskqTv3uhzK{m>>^1F|2$O3mO`YXQNV7-2;WA40Tk_#AWv`ci*Vkho*Qyd-# z$r?{URPvMgUvc}m9`WJ{iWn-D0}?FczlZz(${x>pZY$oVuilWqZny~`A|n3Ifb87h zDN|yWReRao`{SE~3f43PYG5I90C@Y?|MFl2K6i4PTrLod(A-iM&q)O|G!00o*3KBv zs6zmYmrwbsKAFbr zBIyMn&l3KJhhxB-;?G9R%3Msk3?}23_#`;{!0nPaN%}e})pxH#Qgd|<_l_-NF1IN1 zIH_Mz1$qAG!XZC?k^Q(;oBh^N+dJaQ;CQr2sIz4oe<-rFoT7E=OcNGVg5A7eXcxW) zU*!zbGXFLCgY#$m9;f(99zw2p_pbYbD4brfbO*K?ej^#pWGY$XcbD&+8_H$Ukd*6@ zufVzDcdPILAG_{BJTQl6{qFK`u`v?i&{{b(jxeySXK;{wH87SMA%QLV1@0`v%d~1p z6|;)w7oCKgqKhGzc2es+NtLj>qOv_%U%B+`!%7}no6`!xvw zVM`0*At>xa%;I#&XygM}?A{12TS4FvKOM4Db38(gnR|LG9nZCOL^UOH%<~5j@T@tS zxUBY}QBZjG9D$s%`iSvvs|aA?;w5tWCNG%~Oc4=Rzutdx@2iq5AhpXlzET|4XMj@v z*)DcMU{s#2Qz#c;uX{?`6@Y#%kp>kj+e9j`61w4>R z^cXw01T|ZJ5?ClYP!1ku8FOaU*3}6G^pAl|oE8E$$x7%c|2gd+w_KQ~LG^RNZFZ?j zJrZsXH;^;TUsk8Rl2%utw+E!bWbI421cIXmvVu3t;nBz(FuXrsPWTRV@!*1fDi zj^2?#9A`mN(wnTo4$a!@9eHwDapQQyE$d51lqGP-OtCcSa_o$|y1>1r^wj)qv(5FZ zd6(}g4Hl*wqnNRzgx69}pg^F7)-wBF?bGLzz(?#q^jZEb;mDV)Zmek^=0q|JrO9UP zzbP8-z-aa);rB`WO<+yjBV(EnB(X2HLSc2;e#T_ib+4|+eX%ix63mmt2&G@nb@XRoC@ubLvKVK-4Q1gZti)xAr80apuD=~7^ z{=`DwcIGW2Af}N1B@}RbVH0?ni+vjK`;_qheBCm~;0jhfeh&E=MYLcx(pMA3&$W`o0M0a#%2R?w1`3iA>~ExjFV)zA z1q{uN^=-i&M=i|Z+8XRWxF(@n^;vq-(Pe~CM+ET+nTtQZs%{{m1WE?)ujzCIfp=f8 z%qU_&f9~qPA;$23@ngZPq;^i8~ne-0(LO3Vl@IAGY1@~v8M!n9Uri*`TA_?Mzta?GV z*gkrt_K=kVg|r=j!Czh8ISlIH1o93I=MCSqxa|p>7@~IK3IPjuz8Byv#N?1>fqjsDpj2I>N!lgrQ6aFA{!oN=?%a0YC>=Qy> zjgbY&v2(?AI}zx2kA_t4UnB=rGSsNZhMuc6ybW(=!P@B@jrLCfIINqZ$Uh!u)NOa0 z`jlNeSekkP9IZTmcjQH=1K)5jOxM$x>H}(ol!5ieq@o+8xiGJ z-u-7X>4}$Lv^{x?t4vsT)Gp$EKI&VrxPU}$Y=W_RT6K`K`I2^{xnOl=;A$bYK@jA_ zsNQu1TVeh*W{`a^Sy1?cF>_a(l94igevTd{PJA|Ej2iNxN#^ocd>xnT!IaBgY~Je5 zq;z6$;_R(iWN1?yd8;bVic=Wc97n9bV^I(WLENYyY3-tSwka+vE9<|fC7RgZFi2;L3jTYvJ$1&F zAEsb!;JrU*^?roiI-&>AgFERHBB}H{gi-_{$l!wInEFqXN6$;>3boD6OW~F+AV#3( zV8bpiZwVv#V#eaaSeBX=FT?hLL;6fh6J&C~f$n|Ov2{TF9^^Ml5@{g;?~oAcwOe-R zpJaXc33au8!#mRb?D8=5%P>9>BeZ!b>Q$uR_kdBxZbN0$?OQB=-x1Nf8+VR2BZ5pq zi6koQFXEg@95g~X%$rj?4ygF`7yAyW<*G z08hjn03^ptpdo$v6(LkZVf$Vb*!yc~)f+ALHn-%dXsiKs*49D1567=3!E@(R=svy#SYAx_(2kDww1VbzzfzHBn`p_fhKb8yi zanGKaw{wON_{Zb_$(Yk_-2+1h$#JTG4r}c`J7^GGi8uvwj^5lpPxWttuKaSh-Z!=m z{#_>$fTiw+Wv@!MYuwm)QZQ4b76p4{(I2hB)&x+S+st_p0YHIkj8nVo># z3t28nw5drxxv^Qh?%|>N%ECpxQ^`aOo2e3gJH&pi#4hhpLJY4==9cXGfDeKY00`fJkeM1aH8n|+(bDZ5g+kzk zBkr@5s2gAQvXUq348NyvENSK^awyV1onLG* zolk>+KuT+!6FG*W6BNSh@xg*_1O9%f>;tS8ia-*5$^5O6sLYukIJwLykCOiW~b+{k2k-823o zqi{ArcQCDjzC!6|2d}yTAIn3Jh6b`A6BS%nHd!N$YfqXD-Q6)xF+Q&kb$}rcB`?|Z zPtI?;H#L-fdMIhW8DK#>ZqU2>0-9}(FE9IJU3D|ffhin6XtF7!^<4mP?6WSAFeHq} z>jSQUx93PW)EytjY0P$r;PP#M0FKz^6goyBL>rwO*Z~|NW@gGsx8Nsv>;po>1~$0S z!%4-x^chb7spTE{923OL4VxrJ)%YH8tn~N^pfyj5sjB_`3hAn&?UU0iEpBtFX(NXc z)>fUdJ-1L(vjP=*6r}xxnT>*)@UNHoFadql{$5+EPNJ%lRS&$-3`gC3@ zFy#V^Jg?l2DuHm_H+97WWzLj!gunGhwWk-GuG=wSBKy;<(vSm%~Hs4nu#@I}( zlhQ-6;#}cV*W7J^jZ&`sS9imr(H|H>XEa5GDhzIUnwuy&DL2=YQa$$ozt=Fo(MKSN z6+^@`Y{Drz#NvQPx?VEQJ2hI-2pudaHFbMRr+`g1a03(Gc&x!HC>72nFOkEej;W@l_+faQnBgowztFp*8IEb0FIQQ}msyDI z&}-SvC%J6$%_M>)HQJKWP#}@)^|C}!ATSk%pD40lFbC1O3+#N&F? z;(JCfI(;L+If7{4gL3?h)s|aN>A_1D#(32-EE^FqY66X(^e$$erxW}HB5XE^(n2Wz z)OQI&Zi){>tqBMU1#X>b*d3RiQWQu%GK=VNW% zXCK7rmJkw&ZNR(#Ebt*h6~tf3;H2_lc5pn6b_QLfH^@EORXn&efyDToBz(aTI$Z_B zh+18<-E@(89lkSBvx2s3a5PQUno2mKm<2z6UzmSq-z2DE4;7mVAE~P^=@rKmH*pNX z%e(*REAwqKENH!{P@=hBw)wl^;{`|UQ6Do)%PUpA%30_0V8eA{DaxKHRtFI^!Cq^m z+P4QG!_G`v<%(kyL+?zQd=yk_=SXAm+sft6y|65YU%04=_ppDLosci%yf51+t2fF> z@V^a`h{7Hv^hQrhhZgtJ#j0f3n8im}-nlmS-Qkn#(K3X{3N~N=7*0hwgVWgO)DQOh z&A>z)l=f2r&xtc8jU_Z5E6U7V^U@>dl<}^A)}WmhYXX_o$h_#!+{yL=a;alqCO)n} zdQ{wZv#@z*1fdDjMxz0_y6vA5ahh^6R62^fIRI+l@l1yX(ubr#I3{Z3DIK@dX`2_g z*zOn@nQl2gU#@EXMlQ{&)^*b8p}uNVfAkP%BC8vsA8uCGtYN%~#6Q1Z*>l5{qZ5E& zH*Z4_v7a9HwhGrSLRpmak*(mob@S5rmprQ~6VG(9=j>YQpjH8wn$Q@^H5N2nh{UcK z3TLu#h=GPbdVRVZp>~k7?!|yiIe+Y52F8F;y`JJiy&!Arzo@K24A;pY3c0t zVLV1zx>GNW{W31a{K{&2FtsV0Yri*HiM<4B^^9pHD0m->(5i?HI!nXC%C{W!o$ zKv6rxZ%c=&Y0S&p)z}fH&!_7vE3!u*TR?bOixkl4^mPctjg@1S&!43 zTig3^Castj>E7=rTo`RE3Z=!QZ zYlSfR|KpSa$~I(Hp|0A208&K|rT4Zma+nB!b#655MfHN_Ryh*g6r@Bz5v zPKs0G)J!)(Yl6td?QbYGGdyK^Z%ZJm0aBbu$%S6I>LkC?iuQ!6MLpx@Tck4t3EPE$ z_rK<+wiqi#TtwEkDoQjJ{(h#W#X>}~TX)>Fiid?0>T}7;(ZZhDY`<&pXFHp5ngGFC zzO;c-X!gVzNVsftxB>kKD^1qeVaSBLv-u(njEw97b}6Qf^H>N#SBxa#oMlt(QhjIV zIxN`po1vR)H-FP07D0d)0|N_grFX5XD;i6A5!K+*>b8E$+bo zaep{5e>zR|OOz0Jrm4f)FCIdaB9H=(dyJ4W8tlbDF-fE^VIsgbP*YnQF*#!H_s+4r z23N_|!NUz?oI-u*yb`tiX&rg74P9uqe3)xT*TG9Oh%rXT?RVL4-7*kr{UbP`@%6cm z&Mt@F9ml_9?&rDRlRc;FInHw#qO9oP^omx&1JVj7fO;YhQm~< z3A#ILG}FYWjP}f;XN`H}Gk1~`V8w|qAj1S@ozw~>4aWwpdeK4gxLxjt>fW9An8jP0 zqk*Vl1Qm^#D-HKqLvdibi>Q$*iVdgwhSqD9xnJa2|NdIHa>RXF2WM1NvtRL6FHTA_ zMHcI`;OrZPi`UA+Y&0`NRg%UPOY%To+Jzv1r#n8eX_=_`IIR)xndzwM9zVg(F?T-1 z7+|Hg6wC0q0xovL$#mpaxINxs5CbxGxhO`n(wT-H`)IUfbt@}Tr?6_=F5ZnnW&YL- zXJRzxoc7V6`)EcG1BA21&<|Yf$*F0_ zW%M?ptS-?+jRfmM{Dm+#t2Ls_v!-d*wW9)GoX!E7-+$P%I}LViIJ`?Byo=|*0cQa4 zX#%O1JD)mOtE6`A4i~uz#)*F|SaFh|DsMlI)up9;J>A`5p?8-5p1R!@O|QerHd?!w z>^M@$vzA}R`r3I4kQ`8PHP}p$m!fu`FI9q7BEOw~qLx&}B&A7G_M9FrP?fZ_DAjSG zBZtZgYI?{m7h#s|szPxwAfr`Q-bVyZfr?*pG&Io=B^cJ3_A(awQztBhO8LeU1bptX zRJoqPs}5c5g$!y@P!(TtP=G+uz$aw>UwQAxdCuDt85TY=$?Ou}AJ!R8;4ET|TLF?E zYg*`o{~rp4yzV1}6;XOpp;utA%YCrb7m~f&o3~r{&OIals&S4%0tH+~&9x8D+cw`H zcZP;~b2sM%ML5FMF;HTXDrc}Xd3wf4biTd7ynoy{5K(~nPucN77(M0-G5t!;sW#JIa z6GOhIOub@)_{?oS9;yvBRN~WWMidZr?LD;{KE)aslxqHS8H_qoh|uFa5gzI$65-X( z$8<^=_z!4)1VRWq5d>7l5o-%5kn-8&CyFiul-sck+xmnA> z_)7*+xj8xAwtErRb|MtW%}Q>5QR*%h?# zkRFFT-jnMB-cDaf4SfZ;onS27&qJw+1!Z-K$->;#TZ%h0wmIz#RH4OXWDU{~Bu#-k zfDd>X-Ibab5TSmn;mebVnagsZ zEN*e9XiJ-woMSm9Gw1G6pYr^4;gZYyFu&h)B@1{i3mD6Lt@}u8GZc~)It{B-rIU0+ zcZO1cEp`;&*u6nhHxsA8oF66&rEH*xic4fvdqRViglDB-!9s&;ra6|Eb^j5Jw}X3; zu5aY@gi(v1jBRSmLc(fFs*A=Kf{s)sG7>4%Db_o`pN-MQN9zgAtzU}YLMSEv1s?5> zv4Z$ST6_bZ5!vVxws6onPGQcCUQ>WjL>ktzHDt(Dx{#rxnR(wYn9n7}pnO9dZ%Nix z)VF@4vB3OGMt-U&`KaAUHQA|3i29!x9R^7-K@B{Oy<=wlB44*mJ5}vhd;&`b*SlQq zA((QwzfMO48uDOgGlS>^$+zem5?yWk=n?`FOy4-x!kS_?y}mkU$JKYb0S&K;GsRr>%st3#DRf@n|UhyIS-QHEiRUW z4-W9=x9J!DE?39qagT5#YQ!5;?G<%v&E~~qf zIi?%N6rb_3AK++oxbaBf^`VfV+L==-M6AV3SZD8I^%)-3I(|q|QrHz}+fc>sVhu|M zgHm&`DR0EjQ>a~zNQ+iEo9|th(rua=`L`xpycjVcSaxZ`@*ODYQ*%#?caaL(YpAVk z`pOAhhU9V?RsBtjYm^>G<|xD-AtWHq6_jpkpL&a6p#iYeCg9DXekNm(JBA~iTmhn9 z9u6gl$}q;m9|gxg|0R^$-UmWhzAnuFJ1fRc?*sPQU)aEo#=4ep+L_*)v{fw~olG=c zcss7Ls`j}sxFz{Yc#_E2ax|`7*HZM_)WFm@!uaD~;`KT2Z4?bkL{-TBj=D-dB@)(O zbtw8lfF7sV+4Z}|clI6?2;$nAu)7tdxsPOWSQ&6p2wDa79gPU?c)XF<)Z}T|Yvyeeiz{5l$h1&jpH|EeO`$O=J7u z+DrNsB@ioCN26(BI8Cxf^i!q3q48rb>K$*rSSc5Pefb!Jc8#qWA?hc))WY_Ba6_x0 zhI@W{r%c_a)!3sT&Pah`%tMh#Cgpm4YU>&O(fexd&NxLDSV%v^N*T2iJ@$D6bIp02 zVGR)b>T!G2;;t%VB$+Qm7lQqLKqkRC#C4+Ezg=$f-ObwEd-nl-!YE-<9t&#zEl6^Y z)&K&#s^Mbw^g>!bbvaKAq;CxF_xfC;^jBK)RNSG*<>lnq)MJu~F;`glOdyfiHb{fT zO_oycUFS?R^b>mN(~YGB5isF7{x{)a3e>NiHH5AJM^kUxs_F$R-2~zDxu5M8{ju_w zv8m@s(2bBUjinCzl@cx%VQ&Q5=oUtKg`X1s>W-{5Pz1Q^c4C;q7ilkAndBaq7paLI zvqd)-AdCq_rCqBAixLFK&dzM-**tG}Jwc+FJ(X6yPX}52FK10kU%R?DjO6Y(n8xTR zmAf7=%>Qr`78E*Ua!M=XqaPPP+0Hq1x<7^qOJzkj-GPQ0E(r}qFv|#{k0FJ77vW#G zE4{PHozR&jm4C~Z$z_&KOii&02~GFE@&i(zuSUH-_N5i9i>YD9aANxE73u?c(LwP_ z)Yn&5F$N+6Lwl{j_~^G!bmP*_Uh^CVvbgwO>0auh;VxiC`uuU)`yyuG`)rL>yG#V} z4ZTvR@WixMr{-5imhI$>L$9JNP57Ij^yurW?@x<2L9iP>ccm`_H`7AXf4DZbmWkfd zdtV;jIrCoj%4C}R)8ff1D~k>6or6(m&z8uX4PT^!6!J>}dnFv>CA%x~Z^#`SkXTmTyJxIg?!8`? zfRBfx=OSssniKMap%2;l0=?nKIOyge40GWIUoYs+Iz8ajMlP^E&3rVU{_$<|!_R)R zWh8jC-MVLdBZFcpk0(BNuNgCTco*fDH1m{dOrejBQ>%E@IK1lusR_p#rtTf`G(2Oh zvqGJNqj9p#vbrG!FY&_@5PZ|vh6$LkWnaUyAx4;?BY zNKyG$I`BCje|en1W3BJZHX_c2>geHx+&~EnYBqQjYKYqm1EN$k)bjo|V-Dc+lUlYT z8}UeVX%;-IS)`$4!h+G1)%Tmyr27D#{9oTFgJ%ETLoUD?A2;~{o0u1*s#bP6OYw7c0@(7+*gb3?(brTvIl<=f}MIjJMyq+8^ZU z@iL(|Yj;2b`(=Arpi2WsZf&*z{3})b2)vF3yZnueEDXX_f_u}?jyK@2z3y$2yn;R6k^WWtEINrq+{z?&Xky6{We_m0nYmn$UcJQR4Bj2+q zEJ-~nJ>Rs#uu^ft=eq44hgDY0@<6KKs4XP@Rui=n{m+AYm=};cEcnn~$`-=%nSqNY zN0#RPY3 zTJSpX|7H~#0zNnn*|yQf{XE&GO#@QejXga*!(BI1RPk$`!;97>6zX&;HVCqVI4%`J z*9P~fuOHac|G?(#)%z_XtKg3z<+?$8av1DK^|zM!5KzzEftWjMn#@jjt7K@H0ekn% z@KBNz>f)L&-?;!Z4jE0QB{wRP9xR5EyyrpGFwfP6lk|$X(**f6s?1?XUOonijRQl2 zT8dZSSE9}&XaEIcSC|RK4KL1^GTO@%Y^%RHmw=H)^w|s`M>08pj?t zxL4jTn}c0`SD^Yvd$Df+10dutI|()nwX|SX7nD`E9jL(qrzv$IroFTEtXVhU#;=d= z7ksp!%S(ex7r=*HcM1zQU}P@Dl-%#vcnAYto!)OVUZpu}IEe0#V97_2*JFF8E{|UbZNw1WEW62ezEWzn{rGqAQ^Wg1y z(>CmmYaQpr&L^UZmePQmJr|93%D4p^6>{*JpDNFc+&UUjn||O2dbaWwW>l!X`f&$Jgm`LFvWl#lTSDAziq2Ll z6vHnsG@1sL2F{DCsrK*qDaqa47~A|qzdhMRwO}cwzWk!`O<_$U_}n^aUB}IveYx{< zvU8TiJZ6wo?K8X`4ow8faCt0_;<)v}fW*)NQU+$%GLvW9ym_o8|K~$UbDD-?t5jmM z*d_==k!{o9fzr@EpAZkIuu*3BSeN(=auEgA+hSo1+?bpc-8vz_Vzx1*zi2p4g|s=M zAn*xW3W4#~^Uin3ceA0xLr_g+VOY9CSSHlb6NI7=%woiUUrC>3w@ zv;V?f{_k;p18+!Lrl_?=+}j61#xhf@Xa6#YR#z$-z)~ zuc3C^iKps4lOz^*W;N9HDSW<8_~H^u-E)!!M816__hJ3_8v(jC_W@cLAJU;pqk0=E zAk#T8f>j0TnhGo16wL)S)Nvt2Rzf~csY>#2TC0{Prera_G~3D0Qi_XLi)VgUj?rvl zVUixFlVw?Ok!F`U&H#lSQZks{8#Luj6KqW92o}2Cnm>oQ?Z7zWqi^=Tz?|yfAV?#M zS1V3kS+ox2#gk2y$NEE)rlMfNDN`4s6=OcOT8PFgGK^#oDvu`NP8PB8wO56%GxC2- zPYrxuP8XUEuO7UiZuu_5s9i6X9N#yLuArEvJ&jN2CC>Oj);zSV3S%9~3!CE}bBaEB zUSbph3p;p-t!lt}nX-sbE&Rkh%-sN9d4fTLFa>#{!ZP|3bm8+j28;;pzohh(pjcHn zrb-(Ys?F&AA!2?pn3hxRdu`6wA%Ib!g0@-BKHT6#%}@EZ^*VR+t$T9>erIM9A0+IV zpaP*>FjZ6q={V$5D7{6isS)*+WhGM(8;$WtYv>JTG%|^3CmHAA!LgZ0GC79%RyP@x zOtDN6Bb?HLoj=GKJnx%3R_n3opHkRwRr%vuV#nkPKn-`%;%U+$kIYJsYt|2zW4dT> z0Q=<4_Jq^l4y2zxZsj9a2^;thM`VX5H=h?aljv?_kLvaH+>*TvqZz|jcuCs^&#;ym zTn3oIV+G&P&zwoN#0#eqYZ>U0jk5xCr;xtDDBqw%l&CmseYb-hBEfS?^M9p4z5Pjac-!~zd@Oj;I-B6||ACFv1x2nS z3FuxTi2T!qo{NNba@saaOZ~VH`+w4GCttcrg_sU+?pKrrO#JZQ z*Zh=PIzbZ?Or6=6X2emvXfSXV2dxb#B}^bUcrQ^6U}XuSpZFkVS-cP9G>LNgUyr6V zns@1s5+^u6@8r{2R5__9FsK(<`Fd`IG82)2`3L>?)}624-%>&Bd)M2|f)Fv_1DyVj zVv9ayDQNXAymql9;{?u}Ccw^i=GdrOs(f+_Dv*B|A>wt9O32vU94grz`W z6Oz%@rdRiXvMNoudkd*Yq{tGJZIFo$fUGoZYI(*};$0pr?VC!(mVrd-Sb(~+VeA|O z%B3~byEV*KGqVy5YXz1HHpF0Qw?e(FcUTvKZ)>@V^nIueT1sX?R_Tvs;>>W;6T2@k ztLUGGmKmm|nhiw6!kpEc_O_orI&`NTcy~d5gExN*os3A-Qa3olPh+S_$n9%Ia#At~ z#pWPPvheliT=mQI7Daj$tJxzwF1B|c)(0$wUT7|QcPX(BR>}86GekaPKW7I#=r1fn zpcQRg6mOQ{wFJ&Y(@_7?MXQ;iB|%H0ANRapwroF~Av`$Hp)N_!%cDB2Q%|jTPmdXA zX~#2dsp>Gb)sXLI$b=NOcX8$-X(9{ncl375G-o=xgU%*IYFGND6q02(cRp1#hb0>h z*Mw`HPG5v6ai+I2=my`}{!lB{+(9900|4ehy7IVjlK2AmSce-tVwQuAhAqI`fc5Wg zvlUVq_M(ni1Cp|o7M$Roi6x9%YR}U>R?BJ&Gn304+HwS6e~>_@2WSfj7~u2&jIrIt zAE#2By&#{Mnq)h1P5i9DEQSsKkroFS zESL<(6J&{GJnXd_10(tQR8*bw!qpR2Je4m48lgSZacT&A(L ze=ZLcFOyS=jS|yak9kTD;L+nMJ{ zDBeYgcjh?t`)WhVj~`k!rn#Q3L?b1WUS%~jEp0HwZUlNqZ|bJWsxyo~&#DV=?1i)u zxiq~^KFvJ~XIJK(KcJ`oUF<2HpI@!1lSwn5D7HgkStb_V7f4J+?@+d}Q8C67?e`%H zT{&?n9|ASwc4~WR%4)EC&$}W$=a;rvu;Mtszj^_xfEoh6e(y7aDPGcVo5i9Y5x$P! z`K6P~I~1}GG0YVD`5ChyJIH6%>r@~z`@E+C4aMhmW;^?n;T`I#(4cZ_3QY4^K>ExO z17QiZRAUDg@stnyQ&Us(zXsd3o;!v#CId5j|MwH@5ewrTzW z;DVCFO%cB%iBRuq?p6n-T-<(Kn)OctH=ID^a3D$|K1XsKvSh_x_`S8BF&|e$L*qYq z{mfEm(l$A`RisQR=$eG2mAh?ZquZx_>D#tn-PJY(++RBy_iSFblT!cQ02>?Qcly<2 zJDrfX!1p()`y0Fe&#*fx;dQZXKmz65m$$6Y4dl`EelE>7{c|7ZWPCB29Uh9YizSrU ze8ev9!?rYqFXVYH)AM$XhrrTo zk|tcwftt96 zXfXxlx2uU$hpShYx|wr&NU3Gm=vfjo3?q5o_F`mP7j{ON#Um}&PVQ+VzYwO6Ytz@J zkDa_^M5zh4PK@u_8YPNK9$%YCBP-_R{Kk78p7aT6kGV8^D`6FH;+LNJYPWJZCQaev zl$D%zN{L-bZwax~&HL0>IW^1oibd5I3p?n|Dg1wg{vP~kKY&>gUd0$R-3m| z@PRok_(DIt;fszd;mX@&W*#*OoCHWI6dNJUp}Yw&hc)1#L*vKw4=OR}al_%D^2>cv z7{cBIt$wXO0kA9y)1-y5dhajuW+&i^uwzIRoI`|q8gUl3jwR#e6l3UK4Wx74Vi zJ<)~4vjrtTZVKGiu)GXd?o_pFG`a

)qB2OL^72I%WrdWH(thA>Xadin<{0x(~M9 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

}rmAVsr89cOH!l+6Ltg^W?)w}=E^knFTqnEq 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
N0X=u+s;0UtZymCux z9sr7^)nk!$1Xf<3fzB`Rya`SgLwrW<^ega6=9J-i@$>$^w`7z}gX=pL7s|16Sv5}H zu ztnBVBX?djV_1%24iTm+whZD}!N*=EnTRdjle0DJ@PDYXBG>U}liW-c`R-xPZn=fcG zCW6WBY+0PuOCiP!npg6FFHD~>>}1vxVcinl8{0Ng@a~3YVfX4kAHF9X2%4gM15nDS zh>G6{v2l%9*soy#=1!GCeL33lzzT~-E^9Q)ER)wY(H+^PjC^6YT38`#d;bzQ9^6qO zUTwa$%J^c=z5lday7Lb?2ufo~#F#ek+r&URpk0otSqr8~JJR^(+k3~g<{8Gnx=RQc zbBt1~2wNC{!?h8sxtQ3v3P8+n95ez&$#2yhc(k+i%?NC8RAbbjSCreDBq!|$gp^VB zIau|oEWXa5U;`=<%)2xFZ1JNN)Ug0-u=-}&5p$Iu+iowuPzrd>ek?=vDLSK&2DzQp zx5llp&L#EsUjyrhUm=uoGv_ps#b>OfAS+9jlH1#)wz0)}&B&ybXP0%B(M=_qJ+^bV zshN{cX)|nl0INVODZ5tXm%_KHUI(b1=vktLs0oa!c15#hD~Y1NhvyoJov8jBMz!<) z>%O9U*L+nt2*YXa%2j7LAk^P$eNQ`zzhntWL8@F&@`-63di&7thSGgmrL}V50HJr| z1Z#Iz@Se1f4&rGJEIxX2&A|M78{6nM^J0W$gJuu>n{ejlwoA`-;g|9tWt&m_qlx>( z9Ek)qTYt}V%#gI)=_Oar^CYoPX1lu^T-&5Q>AYI7%y@Y?d|H_vjDSK2w-PCX+T;Xf z{ouR`&yr>-e$+r^Xv`MAcN?%V~;XUEmwsbbM^6YG;ru%~?A^&*A3ov+Aea>px1a$l$dd z2de8elb1|(CeCtAEalYg#~@P1|G(RQUrfgHE|AX@qBM>+6cA9_d)ns z+C2Xm^^1PCo@U5ay;R4s(vz9*hV`>-vKSypfV48`Go)1E>LO)fPJk=YpcGf3gDa>P zT(PmeN$9?`oEhz;`~a#e%!ytUsq9-G^O|&O?L)zcCm20fOg9{VcrSw7fa;MLkCw3s zn>4~1WA%WP;q5^e^BUk(r#WK|Bn<_O^fa}#Dc0~QBs-XKKit=v>&pGx-cm)&BVz?0 zbDoo;UOFSi&K@oF{zk2n6jukxh}A7E6HuO~BeA`o(K#ePB8v&3#Tuv4q}|Jq2-kR%S8yvK@9{Z1c4M(zx2CpH!13(Z zmz=qZCK-u^9y{FG{gl_YO6|E>8Q;;~a8bTm*Cb|)-Q*M8N9xoQM zdSP-k5j)s|B;;fg?mXpu^Nk&yk4l?=Id%B(Z-$pwE`yG zxxcC&ee`ctm5{u8k3|GSJTrRUWfz9NltX^HNj z!tLKZ@0UkfAF#@)p3mGw(4MZ%nxg#7Yh@L;XEzp{w(YUR?p$$z)tjFxLnjt999DJ- zu${!|pou^!)%wmE)Fq4F_COy5BBpnQ7D@2#L$B;?zqJ8ABmvPinmr4+PKg5xS4xeR=H-D3cU^S@VWuAt`rmMdxVFz;!J zSKb9AZ0~1GD<}Ht%C;#FNWUT5k!C2v1ybq-tO`@!aA+(iQfGs#NH=15dZGzvI3-@bc8~8ARq`dQY!O+s~U5o88T2BQM4U8cBaB zNFt0~avOEzdBx)~P$jgSxeyzhWqCvMjgT0B*u7doTHvxG06_h+M^>_{u-~q=;z~_Q ziZ`bA+NY~0_NBBJHuc1=DYtF=)_&G4!(0DB#pS9L_M44OBA@mYxYxRw!b({Sq#~fY)8vE5E4y0?U_Y-D zYgb?wg9X%{0o_ZABZSU#%hdS5fkQ!!vM^N235IoRc}O0?!#o{i9;s$rWlf?}3`pO| z**qFmH)#^?F?~I|QwJgw{lyNJ)(DqvwyIkZduQ-TGI=LHS+-i?V_{7_u=X+)d4D2v zCc`0xUx)CsEGvl*&k>vwU}|^Npj9JgY_J3mLw?(TpiYskfo5&Yqrid`~b8zBjFu9A6OMhC$98^%6KyGU)# z3${}q$?f}-0{SXl1rbx>P1WY1Q_nCJw=0LzXpsG5nry%S*~yAiogT&kxHyj*U@oXj z&Ns)wd&~EkQ4=$3e$R-vdY|7ryjl>TH(b{+(^hH1e6pX$?lYD4Z;Ae&`sDvhIeu-s z&)T$|S|Yd4(fIrK_{oKNKtruWux7DIu|Kg2@v)Q}&UQI_oD#wqu2KdAT}z`60M#(| zn9l!>1IwM_Z@)SJ(qT>ql* z`i5*LsqXmZ4JyuGFPJweAcEIL7)M13kvC9o2Da9Y|3Ce4GU9)2#$~yQSPoJg9)+^v4{)01yE0nQnX2*-=zNG#xeU$)K% z=opa5iDM`dvHQ~$V6mjsNw`40*DS{gt~6W&Ob9aD1WFql7ZI@j^LpA;%MU#V94OR# zAk%V`2rUE|7tW_6MiT}~%z;o$QV{MGOuE^w7}_*xB~19V zLW%1P&>)Hx^fLxgoeB^nS>roO%mJsk#s%cmh+V|vAgbS{8dH&&&7TH<<5Rhc>|>6s z8Vclegzzwyj;`EhNFrrT8Ytr*e$_K2qdlL^0_zcf?BP|YHRK%*Lt+1cmObzmREpr( zr?|?lwqj&-SS_eQ=8fXOL+&^2fiCPT5H$8*>G<3`Y=<5;2axF4IH~j=unM@iSgWK2 zTjyg)k?4t3OMmUD%k_vjg}&DU&^_Ho=#Y*?>WGofFpnnKPT0LX5!E+glL%2at5pmoC!p(?cS%e4&7mJ3~N zUlq=S!p$Nx=(n%d0IF^TNn|j%QMiw8oHaZrUwHr5z1vt3-wpY6 zZF2UqeQ41ZsPl_l5E(lln)~7Or0CJq2l@}3eK%%drV$r zxu!-R`1#?~lhykrP2vjELT+-XpX#b};% zoQ+oSz6_nh?dDveS_{(e*GgmmQuQ(Q3tdiVWvqs?$mTIkwtY0tui1((yU{(Tg#Veu z6S`_Wqkzw#8(a?W2N(+%>%c7aapU@-D*Z*CDyXw~4jD~$M^?+PsWMb$Zl)3IkS|em z^t2r%W3BT%VrN*|FgI}1We=2L+mH(=(1T6gRr%&--dnzWQilZ@xlVQ{Yrk=XZVahbh5 zP1Ng)-e~Qp@e+woOp;e#JTS^v88G-!HDw+IS+Ifkh(tCrBV>a!dlU+?*E=M-GGb8f zpZ-T*x>PmP{JcGb(0Mj8Oqx8&;m^2 zsKbx;7~hMFK^6E*`N=jtEF&&{dMQnE7^TH=_!}J+ZgnzH^Q*mCfFqoR&9n4W+6B%_ zQIxBwIr2{TbsxBxTXP?@_jden@m8I0CcgpdBm+O`G$Isxk8VG#FR@nAO0#~eBSA^U z&F!O;TZPty=No;b+Zqi9hEEeEHJ16=DU_3=WAc-g$~7V-1EBuTu4ozm8Jbv610`kz zcNc9vgJ)e>v@0;8b88Bvj5(4g_2i3bEN@1lc;HXn(&UroRaF$CY}+2lY+EldOh!}v ziG~77_cpY;kWY-^dJ)g+Bg$#-ZZx)QdD1V;aauA;V(ue zGy%O!A5u|@&23DERZ1DR$fZ=sra-RzE+E>;Z545U9JT7@3xoLaH5UvZ3`Z#k$fR*D zA%4jyRiD9?j5eDv1xGP9t6HxE+5bRQzSwkH{*hBO`cHl36v_%{b<8x zBB;<%{)pXRW#4+0<5(ZegG+o}Rv9jszGsws>i5lr+Sf4G`XfQ-uWWEv7y?89*~94j zG)#mim;V(2g4LZAR`>hfC24F#DuviV(mLu`pYrmur;`20AO8&L<(hym<4TAUn(Qgl z$+%(36X#jqQ3bm9**bf|mg=0f!I3H?#JodA!7dCBVQ#k@S@`6_EVl(6vM zP3Dy65UVa%M-%<0ph%`I`$k7Zh;h+(>lET7CDv&tT!C1Mn)!JMv{Q);zc|xm0L47P z@gxoE+?^TD*z3#CKp;>)x4;-RqI=7)(t7uPI4w1kSYV+aC%=rs^Cf3|uZlu))Ew#l z>hETB?^^|EdnZV*9_aXR4g0SYdE!<7%>)@s@k3Wy5udr%a#Nlu|NN+~ZZ_2BbRHoqCmSp&~!*FHaptQs>jiEw| zH7Q@?JRUk_o)2XW?BnJTSCZN-Z_jVm%Cu&WIb~4tk!6OoA3L8o=~O}&Q9!* z#y$8Zov*jlZ@YU8^c8f}YOpCZ^TRRf%7RSGZFZslK1Rx}|M{W#fzuiXek0lH?vgal zR*hl1tSc^2aztoIi9rG?@RYSjHZEs)8xaz+i^=ggGO$l|bpkzL#1V*%pTA$e{1Ak; z+h<|*uaU<$Q_o&NrI{Za-m##lBF-jt91Y!Cu7yB*tPNRGRw2Hbc8KnD#$FJP=T+wyZ#fYt#Co|?&)HDq z9J*bqS!p(4@cKANEgc*yU8X#SH7kTTj^CnnAv+a;4bO=hFJL!>>u-}%ln7;9H}$~Z zQ;5x^n#-~XE3y@8ELKPmk6qt1x*UdxVsO1H)r7SBJUBUkbF(;bX}S#a>z_A_rOuvB zGYon$1@-R0Knt?b7O2gE+)kqky;nX3nT--~+~`5Ef6$(Xf#->S$-7I&Yz`dHBdd}$ z^xy>x@w(*622xe@c&BbO$6+AmbaAUv7HmFew*0?48Areu`%L?azfYxGrMh}R1VaD9 zmG|Ds>+fb|JqRrY-BHPw1Ljz=Jgr^>((BOi82!{}yHHQ{+qWW=v=)|Q^f+Z@@VVf)}WslIP54{MjPa=pKU$$ws6vK5FBEzPEG5U7t> zZ6B(uwVI&g(X0F6TB_#cHZKv1&Mi;stB6ps?-^_Eo1DGT0L|x{SB8Kb73n?j zQ1d#h{na%OhgFKWhh)YEJSD$<>&QYR3Glwzi@=H64}@!S5xbz4*>LBt>a*5-`>B?ZGo+ce$s$lRQ>_P@nA^ys`e30gQzd+zJRBE=I-2hHEnN>EN+Oahp zqOt8PDSOK&FuyTVF_&!Sy`LvJP=*N(|2wY*$CCz>n5?GjZ*SVZ-&)bfZQN@>0tE&itZp%_BjE-ChFj}t#a@i~k{EYL>H?HhAPuHfRb3V(XYsVh3 zr)iirqSv7iDBBGwo{Vw;dxjv>%zamfp~U5+5nY~_KgKqLDwa}ov*eLb@c^BDN(F11 zjQM&}tyb$_B&LB|Y`8QyCmJFil8$tV6j^rad`i@CW;W%c-ARdjt5w!@u&ELDduJ^W z&18B3cdnU3C2xF9+*IiuI z<7ZlV^sjurTn(RnTY3G&Jb&2(9oO$<%8@Kf^k+z138I$Bz)1d6MUSfMa{(ap+Wtnb zUX7iiFXVa?j26fiPy-SABh4Y+N2I`R4F#U zOa$NB97o@tH`yv+A%z?)fUA=8iD_?*>*J@ep_;vLHV&4}OGKb|Nze^N_|t{%F{}DyXSjDh6z6OqQ8&!@MSV-z$e*=so&*2| z&=l~BEz!%cBa0OW$=Gj+C2s7~F-Ux`(jD=fiy^Prs4dWYZ}szt`5i8e38~A+#SCv; z#eH_zzo(4L;FM}3-22r_y~l?PQh`_)R_+XjBh4ar=~Q-dZx0tGikfdqrW-9-H(6qv z2p|3#zS*l~UYi!fp2rw(Q6Zf<8sAgq>sH^?9QeXTG_AmfR!P5+CKadbE)^uQ)Hi!KX5OMZRQ*;eCrb%A zQBO|(Yp@1$^&T)UjT8J*Ba=bs|7ZZxV+z@r#D0&9Upyv8Mb*#vS?H(R>g!m$6iHmk zz=_WUvIl*)NzwcSn7wDk3vrxnp9S5UIhZ!8jm1WvL|(}8;&{t(kqLB#jOEtXyg%{1 z{zB$?to}ZPdtPBkTgJ528JuZ8YD)75p~iX<`(}ylEk4M*5sX5U=zjHwv%-7Q%pM&z zzvMX~A@VwLDM&n+B+~c)*obE#=sBwW{N3DZm?!^LaIK7ObkZ8SX*0jExb?mv`X^$V zur-vRoM*b?FG*oT@u(4p?_x=*?e$4q4hmY10`|ql#jV{X>h|t(>Pi@Mp~=iCb4k}` zI(_#m+61BK{X%92j?l4F5vpo?5svcRy(g)7c?N6ezsECtWO8NDA-$n)y?geI1F9Ci zOGZg8vP(XO963>{(z==OQqY~HA6{eu!|`@q#)Wq$D=B$uEW^vvc#3}|OK^f5w`$m$ zIBK?*j>zoQlX*M^(ANrbLD-5GsP8FR~Gb|O?Xl&WdT%hI#smE#$cxO zk`#m{$V34+WE)}fkB5`l3e9(*fHQ$8re$C3O_<$uz6|%P)%8_7(`lpMz&Y0il06+EnRpK}n)8{eM7+Ofh6;ZMkP|3X>v4R91Ke)stfGsp^ z<|M=%MNKQ;#g)9Fj@6AknCqH>D{IG1)CxO{ps$q+%5&Mq*BhSaJl!BJ&r(Jhb%F~b zV$EvFE%}5%!L3)iJ3l}>S1jt=1#>Q-#Kr>Ok;)0K679;e| z8AP(Y>tD6(wimb_YNmP`ry+}vk3)=S!{IqhwtI>+Nv3_hm7rqYZ~RH4qCdF^xr_Gd zw>O6D`eZme-yNVqyZ3LzDPN}SH#GFWI%7ukl2)$z9t(>fT;FmU{2vyZeN4L8%y>D3 zq*lI3c`R3}L@|{Wt3gzLV_lyFZ7_)XcLg6h$M=o~+VX{^Ou{Au{WvM%g0-GL5IG47 z!}o-ROWB>|U~V2^uBy&7{~?!wFJuF*O9OBGN}r$7wsPBkC8va0B5M64E^op3@@-(B zhlMY`Ngu9P)(vs2g@s6gD}ICz+?cEhl~(y0J2R^^_pLc)atd^#;J~l0cyExZ&;~rC^Sn?{$GIkj{atWIFtVFtS%O z6rAc*+&eI6oUe%`W72nRxr*$H(F(HzvJXPZS~%vBeO&YAJ0G^QT5MQGu28S?Nbz*O znat^Yqov%wiw6d(UCFTHab8>NYUqQA;i9+-R$iL+g#{ z6crW6>xG{J64GkfH~#$2+uBOHADMG|2_HM1ab=aq2@{%I_KZE^UZ%B3@KCoXUF0zH zgCeZ{Q1ZA@0f=o?Vhwc%48)$Ep03X;{yO2qgjzGw#+q$Vb@}HT7oFteiGkO9o;a8M z4$2!4AZ{i=vAcPuJ>2&`S1@dCa#k0a6ZWRrN6B#OQZjvQ@PFZs%R0NiiZN8|d#w1< zjUarUQGB_6PA`~go?Ls6&i>dp@IN@nr>n1X(sE54YJxr2Zndd_siUJbteapS^o=@_UqWbW^E+)UmQaTFH7%2$cZE!|z% zk9A=hTxY}o=*xi++r+a%XV>0uIe@+H9(_RWi+co4dwIJq?JyQPM3=gS+$Medp2Fg_ zOBzf^lw$5I;<2XMop!(TPn^%8{D#LRwt|#I0EV+U$ePNeSL?unuXxcJxJ_6 zuXyRd*Wk1z%NRKZPXFOEdUv!{X}b}Le4-~M{8IyUr(%&K-ywAi;W=f_HpG&F@CSuI zVi(=45*aSD4B!1>HNo9I9a4bEhQi|b@)Q7&ur~#gPo3A-#FG`g=i+vSd)Jdw+e(Q5rRhPC?4w*9YteA*fS>sNWGWzUhd!oLEJE?-fE4iC&m zN}Wh)l{c|R)Gvi#UGMH%qj{MaT<9|c5Sl-d61{C;-3YNo|0f*z2n);0X}BH&Rj35u z2jPl4Jl%7hg7wYDkG=w1EVuUA>;DW2&sP{CS}j`#@0nzOxb73xu=xzO?89)gm>1o3 z@5cH84RT!R40PLASWjZvv}|Y6+eJ_&k%pu=(Iu%H&?ixAuvtc3)+m$A9x+|=9op5{ z&S8|MvWxj2T5)AD6aO}QyKYC2^~)_#v=FOYk13$sHz}~LH##_vkjrcp&Ta>NZhgdc zrDyu2HBfH2#r6cpen~+h+|mN9ZE8>~|E=~k&Jp`0D2w-GW9!Oe?c#2lj{6H?QIR?L zJmn~;@7xu4ExbHGe3O6I`4;O|+N<@c;~^{j!pdGwK~wZVT;^=+59T;n43*1y*ubK= z5ErPdH#&){_CY5@`VQ&tj#oihW#jGnQbIP5g{WixcEI=|yG;~tSsPZOwwrJ>{9b;k zCi7*e#92q&SekW$Qrze)=tFubceN@E+gU?o(rOc9^efxMTdb#X1&K_$Y1f+vih*0e zb^54It>*$pwZ{RzJb$sfyS7;`GMHeArOC%RUAx=WS*q?lyUYncXq2#+pLXjtL zp3OC09ltgmoc1avgG*Gm!v-v*WLdTE(LhY40g?iqB(&TC0;RCI@GMcA9$y5ls81QX zN4jnLaOs}rY&xl@QCy>;9_C=UT#RL=rPBm-ev6GoIt2apoIk1B^k%+eKrR(k7P#bnosKVQS<^ldo0&X0*@*l)ZFi0#vqq=j zQNWmIPEWLYvlrn#$Q5HS2dkEU;k47z0x7`a7ihn4uP^-va)uAA(jo7DrvKTN1UUss zX#1(#+RW8*uM=(6K!rN}V~x$Gc!b9jdNWOLVPRQFxs-Jan^c5#(J#%uZNS-|C(MmF zoChv|eBdiq?gqLp1wCfN0^wy?(;NZL+@?o=f7zI}Buk@B2q3`-TT{^0;=}Db2 z!77hP+QX`HvSJTXHey}JEoX8jXrw$&1h1^q^Tz%4VUP>KqL53Yw)d5e^op4oH&~zp2GV2qPVi%NdD=#ZWo*g?^fA3-mx=J%0-`lP z^E_6VVOcGQs1i?go5~=}9)5OERI;D)E$cmCjObM_0EGo{Ux79=d0}c>5XLM{gu}!j zf13DObzC?+$Q?^kPE@N~yZZac`T%pQKQ3#W?8$5O8TnVbmBM`|6*PnCEA>saLjkNm zhY)o`fvFcDZZ(c<1!9v=C_`0t(>~g#!|p8#u}km569Ih?QYiE0!-?Hci|E;(3rYno zm7ttxE|HRCP60?PvZILW`OF6zL>h8mlKV6d+K)3Zf6B(hWZ1y7@(IjJecW5a@>;;3 z-^hJKCbO}fcE`yUlGR_aExYW=l!O&sXH`6%@|rZT3}@`)>wjSb=rorZBxFJj^g}ELQWYSzuC5v&gifA+6#kqrP34kRAiyV z3mQt_ml(@wio1IHYdx+5#WG!6V%#4D-TI1|V1|Sc@J-5SF#POGs>KXg0^ZA=<)6Lg7Xy1r0&Lj-N zIbw0*Jk2e-sAgrcy8zCug-J1pB@h^ng{Uv57&TQdLE<$Yce}qEj|$3Eny<(7?D~v% zIE&ZKG*r^fmin0Vy_mzC=@Gf4#*zstS~%L#STTMPO%O!46?{UY_Bmsx_IX6^oFHm; zJ7Aypy?dXV#)G8F_rj52-5{3bTrU~y2O>qi)|8S?azis#0&liOb7W3<7a%Oox=m@WCm=y6StNl$82WWpw zSN4^0R{ZshkodpqsjetOrNEtu zET1%c;p%|dNuA@0T(S6idU*p?x)|Dhy6;Ua$C=eXt}NvdM^9k*WMgg3U-y2;926*mILO({z*UY zuJ-ia4=@^bA(o5a!AvzHU^G4})a*NkqND?K8&GyIn_(>>RtoWzP6dd$;9Xo)ivc^u z>9CEpGVRm#Ti1z;3QFZq#m&vIH-hKyY{)z~T@vEJkdz?JGwB%HgnDst7Y-Xz2RaO% zwKs7mKDZ*cy8UT86{sG}SvS58N8-~HbK|L`UXI@%qgq;SUgh>pfK=$#sYq!QYe5jt0lkW2Q{3{q^IBnhm-9^tl^-g&9Y`-UB&`q`P>qE zJr%;mKO-aL8QrL-I*@TGnmty$I4&kVCV-OM4P7RRNA$4zbe4D1{@i`Xz)={+X<>4r zX4-|2FBZ2_TC-UhSo-;xkmc>F4-amsW=$NW;jy1P*M9Db+jAtRo@eu^84udXyUktM z!l9^*!sBJ8!)xBN+m@RwU~Dgvga}fge~36}T%AiR2kf$UMiPtT!fK7939%6iyLF8e z+X{5EIi#zm!-47-ke zI$Xt=0uB3CpNPraT67{jHgVs=I=_(SYn^;&&IsG5wfA_pZuXU`+snW^_K_@?`hn?o z@MSGs)3$Gb<{E4B_58D^lplww5VOdG$YhB-B%cWc{}%c*Xc==Nv55yck%knvOkSU3r%l5 zqZ{s3iSqr~ovAi=U3zdBn^pD-#)0ttz0&DbbD6U%XuggPX(#88x)z}glchf(oK1*R z`v?l zFHbb5p6CS0d%JgQsgl;SSPAC(e+qZb`ul%_)3Qr^j5RsX>S7Y8G?~LLwmiE^q??}x zExEEaG1*O&L7op!H*4|so83O7WYH496$d|QdEADoNhRjvtwejPv7BXEGZzu`DxTOS z!$q)h0oU#t90qndoc)lZrW+EO-a-~&B7H?pd(4|f@f9kpq(8g}hHRgt`i5cTdXO3|OhWP5yagR&_**W-)ywec_M z;U;?dz*KVLAmrB=J)gHXTP$Q|ICf?5AhrKA+WM$CgQ2VQwqUOkp_ubq2BO6 zl-#D7)o&&oOq}m3{hqA?Y%kxC-{w#pKJI&8dG6VrS>G1uZM{m7_o|X5->;S8yY6qC zzgL?)hgHOvAV54nOCc;><7o{^7wS<*H{6{~cq)I3-F&Lh?5SOb{&cZkrG0i^GcM1-{T42xOMX%5ZKRYtKE%ia`D%|89U}@N-w?O=V9@sXohB?)~$zb-MQIlBOj~R zBj3%SY2We@q7jIlM%ZVDo)~8b?t%Vmap!4V?{fw+~tw#Kq)Z-hr zsRU#JG|y*sG|xlAT8^tlr;e;HouK46>e=?rGQtdlrvTG4xh$ZnD)g1Re>H*u2XY1Y zo1V6X;?OjyRA^&?Eq|mS330f62Ksb_!-}|VK3RV1(l4oGB{+*j9JiDFv>^lTLtwKP zbnXNarI?ukgp~`l=e7Zkyw?!{;or&K=sva@?#G?cZb~3op6D+c+!7eq3jm%T3UXrf zA}SStGk;InFyl2;rky62*qDgfJvh&89&6eJt8z}e=jaedN(2dp@2C87EE^PUIQy*a zpLHPlst!){kwzn+6I1ZA;zS-NvTwD01(EB;0)g|)bci>Q;&&H+~{LYl7YIY z`m<$3%}uS?ckw{3=lLA_i(eF6B@bDWvao|;7iU|S=5D*c6$-!5cCU#qFln%LmP*Zb zvav~fIg^YYPvO`8tY5U84e&#nozBdzQUrc0#&|2Qr4pvc6%hk=P@a7|U0k0{0)-s4 zgYzsaoQG7tc46%ZSQnJ$Kho396DCAzB4`Kdiw1Yn`QV>hl(({Dxbi)|6Zwr)Q@8~= ziEw2EcCamIUG#<{tc5-VgJ;umc{w-xcp3c}715!mnRkSVIa}tcYbQ~E36J-h1n0NA zZg~uZe5oAUp{vsv=XGz}gI3+qM~|Qfs-$#X7A=U&Shl|xUa=uK(DY-&NySBZpRZKV z*dP8?#_hHvRmj^X{(%qaXn+1av>7gN%=+9CInYG=jhTM0v?i+R5|+&pcEQpEZHy>;|EOeFjL;he8NOn2ylm}a6=xIT2l_6Tgd=6D z*y!&*2^8&xguqg{EzeKb!fZsspDnU!<^99XzyB?l5Z-X0pt$k?xR&*SNa$E3o|2f& zEF11MHVcZ{=AFUh8!I$qeb=3^z%yxnI9DPT50kyolRqgJjJ>g#ONb*(@~!r`D*R5Q z+3P=0Hfs-kNmIyH$$d@#rh9eM(cGN5Yi%|j>fUx67?QX=ukl#Z-)y%bLk0#-t6)<; z(G@-29$$EpRC@;2WKj0qHvCe5ZQeI#&^x6+PyL?10erp|zV5&)xw0YKB3Oxk&1bH) z7Kg0!d`AGc7M@4-WUkBBN=e&AjErSOs@tqoHUKv&I>tye@c%_J59YsPqy(A?{eZJ z^(qT0fsAK(l~Qegk7RWMhvh4?iDvHB`+MR;`uR}Mt7oKt`0ICvDi3#l9k*t(+h&2Y zbCEe`HzQ(c8C4iSmtn}mb&=h4??~$JI(O7bCB=zXZ_nC9T7}j$8}MK}3{2}>8pOST z1P{i-2*!#`*(d1Q)aoJ}J5aH3JT`SJ9Ub=^LIUv%9KX;5kt4_j?Zq%l9)(jM*T zOxJH{T;2NZ4u!05Hw7EqN0h@X{~BP&r48RzI0FG{Y?nw*S|5op7JYr4M}q*GcIRUF zdQ#6WW(qWKKl=yL))(;Nj{m90&#=eS@j3reDI+m+zomA2s%NGWY0k=z#0+8Z@8h;ip`RS6B@0VZ<4;Y<$|MVFM&8=07V1n{GO`SN9B-sm>w@$}yN^dWZb>|S15 z$-ggy^k;Co4=iI8akzaf^=8YBU?*}PiNAJ}%X&BKSbGj*+h>Se`y)K+ueA8cC{mt} z-y#$JjLwebzAI+2b}=cp1DNOIf2aSv%zf|mc(+ppNA-F*pzS#C8;^!Gps@$6p<+?zRpXeNKY%@LSk$hN0{A^J<>OX4HK#2dr94(MoqE z*Nd7Ls6ZsSvOu(ifhPw(Lit!jZkWb6o`=wX#?y0=%kVQSU7r9(w28=t`}or{=dXpv zVv7;3-Fr*s=bUJunRH@cwNZuS)Dn*dk@VU6FYhLU{qCEIW^<)ivzuIjtZ*9)+%H`X z>Rz@?b=fU|j0zu4A9?*tYyIWqkY3o?5Z$1H5{_~aP1{&OZyB*rb*1MFYXeY)QtJG^ zyKTraEGLQ&<+baeEY_HZkJ6&W`%mW@-5S-hF5BrgqWBZ0l!@5UBGHs>HS=cCx<46u zlKrIXSsLSiLQ_^w*nDtzJl)$-I=v1Eov$+FeRe#9C*ZVTDj3&SapmH1H{?^Svp_x0dw2Ushu3U_q>9=9eumT|1j`ENWyNvgd~0_e%zk||>C7ls%h8NqOYg<+NWJ3o z;_b!mi8nY%JKpT>c-wP-qyrC-SE798w?Y2i6|d8XOYZD4bv#kbnVe`w8M3EOxVYrnf`3pa6}QPH&K)vOrF5-H8UH9hQymqF{LJ; zTt_MH`L@)p8!rrROhjc)^d$j?4YK^{6>^Ziwx=uF`YX@6qPQ%G!2O6NNPl|14y2L{$ph;)v~cwJpy$s+Y#$)E z`mjl+AWWZ1WV8DOi7KZ@KtP3^L)ZunLkFR8)d1sUvoUTPw%`>@1G=Dyubhx z6%Xpg8nZkBUTjf?ralh?>rXg!mV#$@I}6CA0!KWWFjG~hyQik7-QkQOSD_n_gR-7+ z-jg3$#gg-5)0ohw)C&QNOVs+O%HWx~Rtd7m&`p{T%JsN($IVCrBi%vYQA?-zknUnK z$tQ^G1lbX^S!0+gyrWPi;blG$g@!rL*)N0Q)k+C>-R)e5L5~x1D`&lcRJ&1le1nDj zs|vox!L9)&wWfUQ(*fwFelj)7et{d4tA#Z@Ft<^#H0714UTetAdY^D3_NUG?ARj4lOD~w_>p%dGJ`csmWI?4; z4r^k5OaUa@C?CQRB6gJ{?%-&mP{edEl>BXFf>#Me7oxuwVzb;`$(XI+0y(TAP~}Xo zHC-Dn@-!)~NJQ&4M-Dbe?whfmQBRCiOC4`CJ>(W&9%G@Vf-@@sxiWn0c-MNnOIbIW zj7Ls~_j5{~vp<2W(Q6C}3dR}ZLx)O*=>>PGv3Qd4)L8p3DY#Npm?3;jh{Wd*w{s5v zWafg@3WpI;!1JR$!RruQ(%WAfsHTjqn8i4P8qhs1oFw_}yU4_#7VbuIY0dV0t07{P z;E|CP{pTM?3jC}yi%?oVq(8aF*)`c{F4NuBH~c?3RJB{69ZL>UW~n#|P+ZcTH>VZ8CpfGO06GtucN7hT4>@*A;mkF^^itGs z^>$dK&9y$kx_I-bB-Ds{?2zqxbx|@se!Fct{mTmcY#G|YS|m4S^Ka`_TbbGC5csj> zsPQtusf9v~faSYIkPE!kQ1?_<@aFH|V{l}cY=lG(Q$UEvobv7N{PFVXv*yW%g%gQS zL_M2b8J##eIzLK@nXKwqlK3PLqWFjuS*A{JQM)DzeK3fOw=-o9IJoK$p8E%eJJYk6 zX)cv*|Wri&_3zE8xw?ol(A4<)#ogM?9k6L6_mf~uY;2E_7iJ_-%htXTUEL%cvfRdfFOqm9 z?M&m9-)VUs?G}{x^G8xNVglFA8Gd>nw`p3adpMr{=In^sY%XEc!2-@zRn@eH&*_=O zXLR^q$+3}>F)V5(%D`?`C(P{pP?}XQWMU5M_5;S|h>}aEX5MWe$fYCj*1pH!l{BFF zG^>j{hGS_SzH{A^{GaPw)N#Z(*P?8gF!XW*X zo*d+{K-m9XMq({SZ>UAZz0)$qqXpB5{ zCw|a!;t0nvE*T(YF=-AYJ$dSGLfm?RtqxY>(T-CnpDJj;qWJaX;imc7zD4EPfr@l- zWa+{h7ueo zO+4iSf7+S?nVXxIp7FZ~3TNn3!sG{=#MN07kG_ln)gV6XmxZ{x*iwPmTTOxD z$qTn0lZa-}e5y`hyqen>5b0SO)e~;JfTO%o9!15*3Xp@f(I^HCAw}_{CrUrL|GhD7~Tm6g-_9ChrOJGwD z`m>&zAF|dO>#1^r65<{RRzsbXa<7wGzlA<{F&Sa1=J)U4VZWmVfBF=pkwsgWJ8!5v zLwRQ%J{oea+T)8y`=X}Ip}ISF?f4Uh7AC|8F%-wBR|O<+%?jPXHLcg~q>Dlm0NA~S zErZ9Zg`UzIBnFiYjSscU7ODEt#fR3zi~O4_9;m9z0&g{9Fn2Bm;BA{9QO@yw!(-Mt zMJ}j124>8Y8f&rTN>H;~82yTQO>$_h3~m=uZdqBG*MHG_wY6ZomeT=$w!!S^hD^xu zM`l#L5_#Gff+Ui%e$))(jo%C-yw1OnRGj$CHx$2F9esxBl4uL@n-sZPGC~@2fb)mo z0$CGRs})%*U1p>E@f;p z>Dn#y4*@M=mij9yD-dmX6$WlxyURdRk-DIvaL<4ZwbhI1mnCwe4Ym8&@th>f7|tFO*aQFQ{+r9s}G?4@1}G){7Jv3u%E>unGB{dOVXcG0gVE zY9Pl!^YLXrL)x`J(-i(eYPi+>bS?v7TEul$J%}0J)V-|JU+_U**a=a@!Ap#7y_YwF z9Sx@GaBb=I+aJ0VIkp+n!#BqSa57{v(#MgekmHUB`Kp%%D_flXjVrBFQp&GmJF2@` zEhLs4%e}}SM%@T>$myrV+or|>D2@dmpMt?#1=0pZV4Dpco&vWCR#Y|e8vD&h*rlfC z_f1xCG#o=ea8cGy@5xAh9Ro{+R^43rP{P7am5iYB{nrUq%lS!*5}T_%p%SE#L9gaT zy$spkGzqrnE4Z1WgiImv1BAN93pG&`Gy88aJtB=Ql?&_G>T&h;BGijOSea z!-&u{@i)!f^e5exyylMfU8g?qqLR1q(>aJwfQYgAA{6We;U(ld zfL0U#2kfCyREk`P)lT-{_u7D7?&qZX!tA}V{3p+q+tw^0e#?pb-Br8j|hfl!9paYxb z(p$_W7bw|<%}g^l%ar2TRzxyW>1Pd2n}~A3TO_#^N5LrGY#MgJP{=ydc3snbNaKLWw#uztzSrW%O4S4IQGg=GS(fg(&SsgF>G;}DWZ;b+TqxoX2&mA8WjSjE*t~R^=Av9P42n_v; z-mIlyYT|ICIxcT)L}Bmv@Nohu+rW#}0{n(-NhPP!Rdgv_-)-%Ti&1o?+|Auv;7UE# zGAG=+amvQYwz8%#!)MT(&_bQ-xlm_6B>O}#uuT~CZLH&3pZM2q0nLb=n~+*;Lw3pY z(6dga9*vCg>F9_Ql()<4ymNB?q+bF6y-SVW#MflO)%qcKd>5x(Tt`*m@=8iMz2}Ei z&FpUD@qbC%SXc++&EJ$>PlJIkq7P?D6K@2`HOCy|oLq%qP?2?iI56>!S@7=9H^BMvc$%G93obM3P1D|_ zv>>A#u33$-2&+O_UTcVjp+9^yA$KR5<_jY5OCuJw4Q?)_J3WKOX#Y(LSaHrH$NT%Ka#TF>nn)u$Nroxx!QEg=PS_N&1~(y^cor9kEw;LnV3HAP;Py3^%$ zXWF?k-O#$y`K~Rt%36j%3dRV>91rvrUp}2I9*iu1R+xj|o1|U0_G`xLLS){?HSN|7 zk-dCa)}kUa2ivdw8Fi1icy+B|b!Kt}9((ion|&8Xr#>;W)JJ_TTrN|(F)Is#(uYD^ zF=r(gIHRsqa#$uWy15Xu&S5rNGzzeBgk>VCn#{>xeT+gc?&hG zJ$^iSSonrobKiS;7Cter$EIAi(&N4o5PH(8505?DR_ZzhAa~qpuG@FN$607KiNs#U z_LuMJuH4HKi!@hoPkg&j4wE?9$-P@<&qp?k{fep6usM);ZH2 z3EcTTc^pbs=DoE|y%S{Dag*?Zmftb{0hg8n|G5HK;x=k7z}B|Ta8_~uN&>)stKc!e z_>>O4#lIFgyQ9D8@E+OHGD`l>t?;55u<0|}{3wY33;DCz-uk5XnwZzt+#s|W-uE#h zD1(}Ml8M$MzlnlL8*#LnY1#d9tns;!f+41s%^q9v!2hG$C!EL(#bh~z8N&IB*rZUA z$khSj8fXGGL(FW+B%ncd0ggpDk~Y%=_l%G?-e7%{m!Tog&|=(`cowl%)RkznTW`Tu7SdgS;y`aunY%JJO7| z9FI#y`md@9*5ei(-?Y>2y{vle0rh+bj=?xPe`&A!7v|T#_NB`dKi$zUSO|ZJYW-M0 zAB*G?ERStoO{UwRnL9J*IGwAHL|{O?0;b61BPTFdK(lrsy8VZpkc&iVj)c;2Px|P3 z@)UoW=*$YlUK@S-Xdms5l4RgS5F-FCN{$UMR8?1v+EV-*`HK30UQTpJ)&Q{DT&Qvv zYL`uG0OEBN)l|{@hcaXoiMej7mTYSKJS{=N@I``Ki?D8NvM4i->(6G#dxCcC24+8Z zTz($==n2~P$bJRFJln-st*gnp$zJ=OwQTy2t*5RYanom-CjXVq_wnw14Q6j!V4Wk-O^-j zMS04>gj0_Hy!4(4a66vJDWMu~Q$rFh3}Xus$x4^xGkMlkA!8%XVE4rzUm}%;-W78kT#Lh#l|}ZNWKs!OhjAX#eUMQ=H|t|* zkx13(h%?@PqjAJQKkz4karW7#xR=ABjEsz=E<{38mIGoeS3#~gvN{?(Ds0+Z6FW$g%Uz__Sq8?Dcqe+LzFd2 zVOGVKv8?+j7s*MSdvzG?yNc0!OrZ$a#4jYRyluP<9Fi5$J!AnbbhSx$eIS4t6>&Jx z?wS_Td-}%%ebOBdta$HxS6P=MT)lOP2>4N?yR8SKu3WB!Z+Ly~x^^Xq{H4^i3i{BUB97pC$F&iaq=h<#q zOMpwWy`KjUTrgg&|8YM3>zfiuMRmDu`71iAU5)II3$q@vSS>-|y@kw|Aou%1`!W2p zpueZ5FsEbbzfK11Y`iuw*A(TLuBzjRfg4UY_8o?Iz`)ITs;s_cYPk&Dm_+Q3IA%sO z{-IB&z*O$ORHwA?8pmHPT+H8s{o&H8xo}xJoe<^;4$K82duwXOkcmz7q;P|D~xr z$6ZuZVh4i4vL%oTBXXt9G1k-F;H<|}3Ua4JUlFA2xm3h`{+4)yoI*h?0*T znDl#y&8O}CdxHvD{J`@4dWq}KXi5x!(>v09%<+bAk33EQPbVMM%GXZ9vWv6I4>z|A z9U%I3ahO9DTeMA{40Wu((~WOGaVrRzrlqD8jy{KLWTx^}kP77yHV2!clA?j^DoJN? z+b#!R6LA|q_eT$|)P4}Sa6fjvaXo#@P&rpHEv)>v@-AW#Nir|2nOS@7b=$;6I2Vzf zzh1PboW$`N*pTbjM(lI>_Y>#0k)QDUy?^;pdP^NRNtEy{gfIT~2p6HIC&1mu| zO4t)Zb9L(Fm5}D!hXJzn;}54`An;2Y0m1cQr0d&yB~KJH8{Dl55Rm7;(}kBV<1UVS z;k}i;*WbwP)gil;Dq9D(urc^KKVZT1%ywO90;c}s-u`1{T}wkz6d)qzg9U69_`DXHlA$gsZ90d9^(r$nhapf=wm1syg0r`z+ zy-;lq0q(BCJyr()Q67Wtir>TvzR(K^SD_u>Z0-7aCu{FW(tAT|_CM7%KVeqCqbt-} z;41O44ySZYfAmy7OmE||4L09Q_?3FVtrJzZ?jo#-7_{%>!ShMucjR+3L&sd-p5z)Q zN!c@oNj{|jBMvEZL>NK9?j?oEYtYnFE(QMcuBqVDdJu1(KJNJ8^7}>L($-IJgD!16 zJ=kcR2{bxAbQ7(%nidrUgfKA#&q_Vb{2a}tZahTpFeoDiHVNx8;dImJW%wBio}4k}TJ?%kjSXns$IA+x_wqk5x3_ za<61i|Cn&$WHiIyj~z%zWgU>Ge| z-i~D+r=%zoazwuCAv`zX)PSJm2fx?9mkeVw1ocIzopQH3{Pe~p$)EWv#p@N`A@MT1D-g$Q|i>h zla7fMMcRw^h{s6!bt$Ght~M1T&3&D|UefuViY*kOgG<_WX_vmV_nE67g(bFsiz*9o z*<_~$@-s1gTUtYro1H`L=dZ*-Q!T^ByO+P>A9fQW!_jn`z0C(ve!HRV z!g#c)x7P&nwPblvD)PUw3-Y}92KO}qg(!ZPCkLUNdSa;+`h-`1WuR4%NK@Oj` zzbPv^?b2aKfhWwB{pZ28$+p@=XU8+*%x^o2w|J z2uk`z#4Kqa+zDENzDTzcVd5259HB#6Dtt5wmi!zBLP@$$5?KZVjq`Q0LW4k2K8ulH zC3qCB){E8mwreTq;zB&=aZf{y_XjrWlQuixgoQ>&xOzKiU~aA$4(V0crSR(kqu}K* zidM55b+zgr#~Z7njbr!zo^Kb%kL5nwCkuh-BCn{413{eUN4JLyA4vC$F%BF2R`^j{ zx1Eld=sq1*5>U_LFf3R$mT}=hv|>P;{Gr4i7^&QLQJ>ER?!4xhv=x~gy=h*Ve=0hqk?Zfk+>#_fI5Eyw0*8E6iiO?g- z{Ch_C`cYulHwZlIym4tc_}2$%DV-ZB)qJChHml$K+?~2QGzS%as592q)3S6)i~9@j zmb{+-&aCwoNP)<4LL42ARNU3@H#5Ik0@!UV&3NvLxn@Atd~nwxH3u`j^%rq@Ejp^Re#E@uENguw{$lsms0f+j$)8@Gt){~r;v6jVAzB9> zco0x8SB$i~p3rNsF%w5eIJbh|rId-6Op)F z-AT+xQ$twxUiN2BVw+c(9c`$Th%LSDO%CdWyFLLW}S_Q|hrTjRmMP+M$ zTY<_QzO^G)uc^+$dzwn*@#o#dOs~Z`EJS5C)1uv9Y@NeOa1#0XO#Cb4!$vx z!sz8A+3tFID5;aZzW6cnk#MP&$H*#`N8$05-85RJHtwpAH=~2oi;l>+QafYe;v4Bo^i200R8mgH$(toZFSx)hb;nySgU zx7TBc%HY+b5mD+xv{fO9@LWDr&_P7(S6K7rJ|>ki3)hPF&VnjbQA?qa^wj&o>Qho; zSA2TR4c;269BO_zo6`Wg^omBYKk5Htx4i@yC$zqV-6V7*pn6b)I_h`vPPneFr4hPJ zcgiU2knI12Jp#D6@8hy|>K9%_0wKcEb$}fPFnFs&>EEu=+%@P!tbyd%cr+^&MXj*s z8`ac06`X=EjoVoJep$BMCF}xK!v^dTrfDjzm&5olu@$u*xRLpI+VfDRyVXTafN{A% zXh3!@sMBEkVVZkIIguom`L9EuwU>`+W1ent8KiFSuw_wX{nFmN*k-XXnyQ%$1hsER zyIt{RDQ~$!xZ=Oy<%G;*=zIzTQ6<-u;@{da^~(u}(|sugsc6TfE~FyylnJ z)BI4;m=%F8l>(R%TO<@h15r@;By+WH(~145gd$f*!N_w%y~=ng!BI>rdQ}xjG2A! zl>8HJKq(!RT8Y0BBShj*MHI*`B{I0PFD_$GV;*{7cbKW`YjIU}^X!D_<5(H$&VSxU zr;x&04Bd7=bdWh!i71sz`;i?^6v6$|Hwdgns4wqwlaucQXQmkUWW!P(0gtEX3ezxW zPL|14qvNI)j|WXmd_pCHo(J1U{(a?SJHe4^vnT~MHYQqQ^A={ojooBhcW>kLQafH* zJKc68I3{t;EmF76E_{(AJH5p+W`rZ?r-s|(fZI$z3`UEI{=+=Ou9Tt-=9r6c6IXd= zx&abTQCs8)Z=^Z$^bR!b$fCSg`nIaFKY;@#*;jc}jb{tuY*!~atO{&uBi(~+Cagy# zMJr*y16CNTW_>GG3?W19!4gVW_0%a&jWNvlI`$Yw3-n3IzI8uaP{nq`T_*!y}X~M%(s#ca!5DVOY zkA>M-zUKF2iq4qao<4U`4o=%~XfS4;A!vsy9jscfU-U(LV0X-6?ZR4Mr6nv#Afc4qr?enDY`CUTsQ%r{)<_AQJ*Wtv|E!#?7a z&<_0A4>4s1<4*QOmmyT2=vA)F0md6pn$Nulai#5Spy%QuI=rXc&!{X{$RvC-gfrx{W}1@*CR>e^Bi>crX|Z8IZHk( zM%fi<$1Gvf?+F%mC)N?PPBzwovv2x%YGT#1w8Dzt)2k2>Yxt zi&3eF_@*EO_?@@VZq}ziaiT3Sz(dJI_1Nc9AHMNpZ~3Q7Z?%rcp|$_u3a9J=?Lz2K zi`I%IYnq0?!HLot$SGHzFi^SjCseQr7ObeJMyMJc?I%q(s!-J(!}3=Bg@NyQLIJvE z@;ojcajti2ZD--`V zqE%&0&AkhhBG-y%wIQMdfEmE0>mL7E5PYyi8w}&`)O=f52X%& z`S!qH)1+(8cF@;yCOn^6?Jhn8`k3al)SMaXsJRjAY*Bt$ezJi9d=lo-`(^erg7_Gd z#4kP7waO+ih0c5MrX4rmh~JIXuH#^H0?`%? zh(fq1Y*DR|MyyQ|)m#;Y;TG39bufRr=e^X*Ugu>_lt|rfwcdxN?i%=`CjbBp%Eg%t zyBeRd@m8yy5hF$-RFqZ2p1R*{@~|s{-mIYt^34f_`hhl{?Rk1C}TD%JVLe<)4usPL(v~?HnJ->-wt+m+MRHsbCXg z5p2f)gS|cn!F(O$FWMR@52cm{v_2ZokpoYJ?2VijL$beH-qL9EDQIXtas>zw{CT9( zjXMzz1vGj3r;x9ciGq$z;hPMbr9GoiC5I0zF5D|sA#xBL+W!=~SL2t++pg29?|*S` z$XM0k(=RT#w=!Zy;9J?l%u0|=9N=WCS9a_03;^VIsCdkqB1x?oO!7GeFJ2| z<`K@YdBk;L+ANo82yFt2Q;o;r; z?HPWZI9ZuG&W4++2gsRPm{HQx%fL6z!QhS;35=}%=ai%RjbB5CQM1Sj?`qbBGtTZN zjsAgjR4eN~W#(>JONax`Xe`8d1P8resgIt{0FE-^%*nurJyWUgoq^J}aT5iSQphxR z%>B=greT*o#w}_}a`hZsc{H|*RDk7J%;;QwFD%>y>E0)XDyJ1f;>jiyth|tm#e@-9 zJjn$Q1#{TqbatxVQ;vAj?DbBq7|4I{^hH)yb_FA|5q(6$&0OgGmPDb_!drFE%VuuR zc)ay~(uG9Sajfh0K6dGP{YTo_> z_R{_M4Sb%_o*HfGU9_L&TTPJ^U;3GPI@^>4Bc>lRgCU~``;)K85K<9BuPHa%tQS(9 zEI+;%rvFT@Uqxjwz%3 zeJbZ>y9m?W=d2)9ojwNdp~_h@0=GwwAz5#@Q%{|;2EA!RO8=y)xit3oga2jRJXauV zj7nSfQ0Cvca-MiH92~m`FZmru^K{M==0R+~jj;2W^i0pf#ie1Ne{Bh2$38`a@g?8vy~ zrOIH4I!MXeIRs`8vw~7n5`ABq8wKQ?5*4&8jo{y{@6>G~Ol(35bsxFh>^dKcSo+ov4SP$9G9pUL+i>OP%YzdjMq4-03wIkd zt>-T-ir-Nb&tzWC2P-p=HT*B{X42C*t$(!GwWIB2_;UMH3l*x7p|!Z#i95b%a9YnH z@S&wqsp^NhvIqrVgmA3i^5aa9pG?=jSz!n4@Xh8<|Cyqk4Jv^$C}WO)l~O>GvW~M> zvx0T2m(|;Xy?jnT6HEM<%ELO(ER!3)2M`IDmV%pgn3~EAoSvB*ewihp7UbCNGm)lZ z&x6ZLROTHri$cDW|EM*6HONf8d|3(fY`kA>nR(id*7xcP8I)JTn} zsi^yt>6v`$=bH@g=^$_5U%DVwb`P4qRevRR^;tu`mRGy^S7sp34#)339+6$2>jRE` zMVvnmrOo~`T6N_Yt0pf5iW>JC<5vIXQ?YMPWbxrGYYm!yE?eJ|FFgE%~avBJ#~+ z@!UO>h#R`afpv2#^uuihCuwWsc1?QCpl!yniY;#w=*${OZ$^_j)^K+91uiSmyNd05 zj*rdTi#_JAC&?T8CU)JvnpvSdZj#Da5uG1H0r23a zdRxDb5x#RE#{dz;^p-ZJ)T_~rTIrUAU(aMmM(gvtbOPr;_D3ldZ9dgZsC02^sW2G| z;*rUFV5ji_zwQOah)GFtGvLYhMF@PsI_21ya@{L8^Hw4dj+Dq5QBHn@rIfFqKpx!u ziHY;%OuM(XewdayZ2?)k{~X~2fb_@hpUzM1`T%ahObqk1C?4vt)>Z(zmHtqo>>_E zlN$clm+Kz}{2-bcRjUs0JglJH(tJPSH|8@SpQ*Yh>>q*3)yCtBfN(9q*RBBSf)RPY zKeeFB4sH3xx+Oc=5}3zdM#?~Z67i9r_}ERkVJM3O+jtm{svh>@FLM_0hrh_g)@^%9 zl{F7Pe72bn`Hw(V^r=ig;v%8u=l0a(+2Higx%{$-k3tt$)8LgtQ~|yf){Jkz3T*b5 zo6+oueDapsovvjCg&rgU*P~&8l0PoXPCa9mi@ESj+I;fPVkTAO%EmLJ^((!JiCR0O zIn=#>YWXcrWKM*tp*g%yWsX|aKJW$}JAl^5jZkn#9{7&BAHAo${%1&;=(>5|QNw z-d?`6qem?<7mi$|zakBYWbMNU4_RxoHaMTeFE8*($`Do zs+=b0^;QTltA}*w8qc6z^Fd4DM2qH9 zfb(A}fhFEhT~>KgT`i`5cFrQ%Od>4^1k$+*liaxEp>rft z1bjCFKPyf)2@HMzeieM}A5pASY28j;y}ZKS_wN2+2?cY3R=tQ;U)IId-v=p@D~DXA zuNeV&g9oGpBQar|G;`X_NCmRCXa`9OH+fGY1@DZHu#GD(9sh45!WDW|o#Ne51-4-P zwhva1*2Qy2%9cH!#jWz<+>^fd`*~BX1AjD^AvUvOX72j*JmSmc_BQndZqEv*HI|hc z!QB^?t6a&((hJV7IgITbtvZggH2~SXy3W)trKms z3IK4zYR~p*9W<8ii%=Rvh4o^UJc0NdPh#LJNGVo4sWUG>4z2* ze?u5_sUuH^WQz@q{o8AQtK@5upZb-3gUJk!IJy>c5A}ptvw_ub2d}O~n03)8Lv)WdGPYjLIWxt(XSb8}5^oJZPP;@Q=NZ#LH{V zMK#00DJ};~s5pK=zCfwu=+F|>jkTr+YmeL4QtCxxvUCLhiWQE5jLPeYIFOSP@~Ohl z*iJhI+HU%pDIaIV3U{_Otb)8?yn4q!@LI3q&a5!w=`%ET>gH^1ry)7gLPV~1C< zw1!Az$i#3d_!dcp>lNoRNwlP0sAcwp_i?oC<)Sok!y~u0kgb+j=izN}YXWZ)1>8dk zU;l}M0SE469L}g;IYTn47xn724f+~*b?2F%qTU*ytzfV<4-561daLqFxv^YQt{IQ*2?+jb~+PGiq_75wjY6 zvZ?YnP$#OsCZMHtb0v@9Y|zkB$Iw|=(t>%|IckM;$h@lhcV+_m z5-WxubF4+eOZC7=XYZ_FFYW7@R?|t#^o=guc-;YPZ-zvpM#}MtMJ~G&{ z?6T;9lnVUkznGdB|gdhy`!-30|BY)08UlN}TPlDCihOhZ}o?s%z7f;BGIN$*2 zsr7oKUu+Zg;6fy%1gIv4_=e;l0qPy ztElL4osOg%?sBA-`E`P{!m|CvN7r8TiPPA`%i+1v;>-9Z`=^MA^bl2l?h6F*#@t!cY?%mO) zm(k$Y-~7Txly=vUWPSz0l>?h9?kKQpk+&@{?_1HPHbg2-P_;g^7L_1*TKQqf!#33* zB5dFjl#>gQiVGHVcax00RO$`l(GMM(w%F{`H0&vE1uo!MPF2Vtck8@wuPhMz4$J3@ z3?cf1mEbpEZI?LcfYXB66#7k~)F|X#rTW4UsAO^BQ!SgDK6RqT0=Rqm4Dqy!Z%;qU z@^eI4yrKB)o;|rWD7`bo`qB#Q{mT=w?RFdx)la7{C|%aHTQ8jOmPKxq{!~xoIdT*=N54KA;b%dJH%vryZEkf%_9Ck}+2eLGPmjG#U3}qYq$c~}P$*!HiAp5T^b7hkU`OZ}jV?{=Z3Ev;1CZ-;?FVA0P5dU+(Vm?z1 z!d_$hd#8Fv);4}Bt+Gq2y<$o&@f#H~R40#%%F`8P#5XpB^%-mv?R*3<2q7SVlVBmP zqSyOpSJfKj`Lb3qv&QpL(jbFPmGbgQ8Jh{z&+c_5`0=4cSuYB;oEkL$k566BInrwU z|GL~HYgrVP<})H3gkipQ%ltaaB4H6>V_w_XB5s#mb2s_(=iHj{t}3Be)qyrXJ7T8> zTa}y=turQCA-LOBKLP$)>*z#<)NGj`5X@2-bOe!yVRI>mPJ=X~j@ev1T=u9LbNJTk z_@Uc!F~Gs^agR>IhYaZj0**}A(iLf@YOjJ2Z};S>Vq{VwK6jkmT^!@fLgS-R#=e+V zV_U zC}z~*jb?cP1Fh`AG^M{`$zRBcdFmu3<|lQj^WkCHWr2oIau=nJidoo|X9Hx84}5!h z>uKm!C*#g4FN>vNODZ^~L68G8sca}s6fCHl#e<~bhN8}N{}u%7KOJ$K*3VJa!ZDgw z|2i2+ud57J&I;Qv=uT{vbor`=wH9TA&uie5Vjjrmdt zSpCtoj(r7mGMi{ zd$gKrbtJ`=P<>tK7?w#ifr!Q!c<9`sJ3bB^XxGyII+HT-O7%Y_PSkX^BDpOj;sv#e zK_~q3zTih3sy15d-d}#vf(0#hby^s-9BbiZ+pu#?yIM7)q2Vl5(EZQM>E_z&{IG8L z?dO5Sw>AIRe-b*k869ITGEGM&vYLxldIC=sGB97$@tJ! z;NyB8dS%mhJljP(Z1zdG1pGJ(%CN1Iro|F34Qxo48kN)=Qn)G|jcTgxx+HW77%^c+ z>%fN>r%YX0etL_oYALDg#^&5h%T-)fr*)Tb)8a_m(Po0#X_S`K>y3;73nyb>876ka zwv@wZKZe1Aa=0TA<9Sy?aULn zI?a{`=F172{qvoMR#Zs=bc_iVr;zAd(_G*(S}>P@AIvQbQF5PIf4C1xZqLKAO0n{| zT{-vg+P*}BB!?~=1^pCxAqbYe?DJ6G3ked{`c>%xuY7tXH+fgDsmyk%tIqPU+9tr* zj?3U}z6UOz99@6DzLQ`>EKyzO!xfzl5o<}1@QhRcnRno4RWl`3UiSO!X zJ8h4?xN!1NWuH3gtx>;YY4wGZo%_=NO8c+G{J-8}4~R0hmyNO^AzmA?pDS=mudZ!$ ztzXo?me@RMct@>ROlI6MnI$)!gt#y$<5gOHP|{@!_B(1WX{Aooc86pUr+t--qzzD2huR+cZHMI*)Jl)d?T6O zAzBM`b96OsHnuIte&s^4(m?2FvjXAal5Wp{L?XXA3{USc@sk4op%>eDfmJLOw2bl7 zVz@q$8&yA2ItLXh<(q{^!XdVwsvQm|H!`K{Q;}5C6XEq;heqBpQyT~#wg8Z#8B`hG z@-s`A8L*hA8$>Dn)(T0%rZ}0{g*yqhn7SBqtjDm37scLjzvPuMByZHRVJ& zym_Jl2DL0aE-yp<9j>WefErKW-2?)C`^<2o*(Y~o1p?)EZ?*|vFYvXz7LvBSzLkHp z!;N4Z$<|fQsn#CBHJOWbp1iE=VLSUHcfLLNt2ipcmB-{*JmXuM?fLylXuRX~j{r-r ztG^3R=epJkm%;?0>Eog6uPFaoi}EjV?vX>GBLt;MBDRvP2W4(eY`2Y2{=CVkozI`by{*2jc^M`AvO0a`-e?nG72* zuRPsF;?JC#!e$w7{1KlYUwjtW*z)P-+u@;hSpTX*Q~pMe?rIpT35eo6QybeO>KIl% zh0%8o!+2lg)_`yy64>GrYEAECG`J!|>PWqJtpJ!zinj7f6P;(8hLSq6FmS3GK(}}M z)A^TnTH1on(@R**tYU^Q*(8*4>bN_(ecZVA+BnCzLz(E^jrIP6#gNm-P%w*@KWj(8 z?!o$S^EW6o(~A%`EChoahJMDEj38?p6U)^Pass}A8HoGqm9flmJtqgT#j>Ofh!c+` ztJ9MPO6R&_QWZNHjVV5TD9KJb3gqLmTt5tCb;AL?18G8{1LRoR-`uYH3e9*K$J2Vj`Svxo#y}z`uZ&XO=YFVaJIrrijN4 zYj!Fu7T1w-a#amQ%IbRWdk+)&veNgm^8_)J-?GnMsy*9npHm;u+1yt3&ckl(-|D~n zpo-S@pfMdqAkyN%-z<&6J#6?>_n0}g6^*A>%(2ahsl}B^n%pu#&0kWp zS5Gzs2>9htGoR-iGJS4D=KZ*Cbni==K5GCUsV^3s{V9ABwG!+GPb**ktxR8?*6tkM zZm@CU|6R279{yT)d|s3pyn6}$njpKouMEg#I$td};vim=ds%}J3cng7U$~w8*u5}{iY-fTfK_jF%V?hVL00LRaF%Wwq)if zgW=zCMoEO}UPgNA55k`5^Hedj8`pQeyrg%%f@*52zY>3ej*gh}i}?2P3nPH^R+C&s ze-c~c%Srf+yBS$by8aY2eqT>m&{i%!IqY^;99V4g-uh9luWnYM58nb4X%x5ZM*IHk zFtR!isrqzyA(mUGg%q|I6Ux_v)Lk1~6f&@Jh}ZqLW(byZqo6!d;SrzA zqri!av!S&gfHuN+>o$~FV5988N+@y!(UKO97=%)%T3T(RdM82UD9b2&skSO#?@35H z6>Y@iyRWNyNS|rsBy8A-*Pu4Blj9@jwKgLMq>^{%U_dIdDQ8Tzrf@r=w_QAXn@g(A5*KJ;1)~q8va}Hi z?QnJ=djw%UWZpo!0H4+`sG2{`g9at>OBWA^#rp46-^q*ZNad>@&9i+3|33O* zvom+oVrfv0={FgKCYtERQ;XOnoY8zkn6@Zd@Jj7Lvv=cc#M|U=X17`azM>u=@Y~}$ zKhS0mhN;v={(wP7T*618!S5-kDbISvCv~Cr&wUQ*t+BVgHH4o}Hj3UEUT7<(KCDz& zuh5^WwDn%D=yuAV#5=!i(CQQpgFSuw>~n9k1^gTpOq^f&oT3&4w`)vB6#n%(pnS0Z z4IGlZ?k_mQ$2}l(q7;s6y%f*9}1Vmv#8q3?82hJFBNKtAfYTnpR`owH-EUQ6M3he%S5}hPmW77d= z$EsK=q&mIHOn7VXwyeI%V$YYK!dd``r@$CUB)}OY7nDK$jR(%yFxp$l!l0l&U`RLUE{86R5XD%ijnyc-zjUJ*RHAi1sE>5t zwxFROWVXWvyUU~V!@@(+A+c~1N3rQJ)^#oakLZb&pw0_2(+?aA#>{n=$^g?EGY_Tu zU!S%-V+1h)a*3sTl%?VDy*H)=wOAG4%8;Lp6*vWj&1M~13!f`KE)qNcEw{b`s*{Z{ zQY`?mMfap+v{a392idd{EA213_f1E z^G5@}J(63VZN){WceWF;p4uT3)dD2QhC#SUIKYAWiZ$s&jtYl&cK)pYeYe3FFh<5k zbOc!OfC|6zhs6^hhJTFU7hJ*k0T_K1S%0ZP182^(SQgZ8oX~;QBU>GqXj?+B%l?wu znS^RR^z)BRe9;kRxAjT=@b9f7VMD&GA*vHKBL;1wL;s9{Q<-t#Lo%)Ur2Va|X_d7r zTpvd~#TSBHB5rHjjLu|1DNx_`Q_DxUrTF3Jme6kF+hqKU__sn$cCfXTnuqia=m+kq zg0^&f)D^UFk>h%YnJn|_!na!4Y%0zTODRuneM?y{zk45lIsf}q!;ZCW)-yaRNm!~; zE&sXC;HUAciViXL`HUa2x{dO2$Ar3Eb}+06KMMQH+@*-Ar!wSNog}5VWW!G!nqOai`tS2y=A{Dj(j~w$&~#AG#Az zUK~_%u}No!`7Ldm}fwKfr$wWmg+z?x>gQrZ~2*;QmO!q3Xw-rPskly$fXo2fQ^hAb{4E*fR6 z{k^-Dciu$@temkRFB!jN<0!O3GLxCB1O{8+Mo7)@r9M)Hhn#Qcfx(a;nRm&|jy}Af=Ui_sb_6@VD|`z< z-)SBZ-`+d;%7w~SZ%Yd{nJ8lF`95T@MmlkKLR2v@glB+s*JnRnJ0nQr^T3wrvo30C zVP3L!Hew$e%IyDCKaHzi@0rkXZofA!sv`5@V9zw~FIy3%{h!FMJ70c73?sZAiGxK5 z|L1}Fm0j=?3emIPb&br2gkocyUO!ogn1+wu&j)5v1Z8#5HSWP|l%FgZKNLR|d5Q-RnLom#x95)E|dV@?&*8Fq<(rQMOj!_gJ zz3ws}CuoS&0kf=&HUVyzXskqgsM2Kb&laxb< zJ#fFZ`BxWJgYK!hkRqFiSE@0`tujJfN)g851wAU41Ldu?Hvy0bW5P{3l+e=#mQ4Te zbg3>!plWS3<-0y!39#(;J1Pc7kC1L~V7je1pS=YRGQ?ERR|4DPK@T*1TG-7*uiC{V zce{Qln;nk{qUdKvIxMcT_0h%$1hA{kPYI6&eLg1^{_>u`$V!U{$;7N6dRoo(Q~2L9 zFsG3>Q@+>p-NcWP+h#9zR6NKBv6^l1xfNPk#wzXNk`hNalNLmz05I5k?-m<{JYoVc zJ9|>|CxHL01UUv0uPCebuW>g&k!r9uFR?06TcwC{RY}B#Z_Pj`R;=PA)Mz*Ne*CHT zvXt$|e1CKgjLQ6@r^R(3=kYWYo>5cG-Cv}NZ`hSc{p&Tl`b#w zdBz@mlaHEx{nvBf9(n9P0tz*QUd{WdCk611d8x@`=>Z_E!LA?T=^XIewAdkb7r~j6 z_P})!9`7sYN4?!z40@q_Kq6DA;$JX-Y7SUxtmlCQ`YUcbbl@~({!l!E<-?GSjPbV) zFD0B)zbrDVk`hbh4pPFI5z%T90)rk5lipm@Dufut>pIC1jrGDDcaxI~GX|#HC!&h2 zA($Dc*CaN2EjCIbq=yR$At+3O^1x4!6wa^1aI7a!$Cp2Vn!uvvxcTsGr@_!<@nH6h zJn$NT;52J6^5OH}@x2E>5+U~L$>CBes6BbMG%HXO!|()&ifK3T;MT~Y1;op#CZ2%v z)lNAIr}F2QlaA$2^C%%1%JGfA)RYc_<_$e?(~5io6DkCwEwd#;prfhe5C{CQC8Y3E zMh3AvQ*pj#9;+zbSgWx8Da~A`3q~Y$&9CtT;rIT^`2Fr?+%c!WBZe*C7l;zolrk~V zA$M-gVqnf6CH#u=1W+(71Hun=?%5ojkz@?ey?7?i6;m2*1R&iy7Fj;XI<=NDOA*d> z-NwvRM%pq8?(>V-`PGY2#{Qk{S11Xz{T)_xMWyj0QC3yz3Do(a27*l7G( zi4c%V7;G&TCMCcB@`?6|Hmm4(d0H1{z|uu9tnfp$$aG=fWzpYN7s0-z%xZxAG(Y4Q zPUeT_(ep*C)^QE)aHS1yD3|Ptot`>@Fm5P}^pb`DPdh}XT_uY!30t1|1~ljvdn#;b z;cxsnumYt&Q82EQudiKh)*TsGV1q$gV<|WzA^}42$AVdHm;WDIXBidO+NAB15J+%$ z3-0b7+`Su@;M%xr60~u5Cs^YI8i!yZxNGC?8Z1b@J~QW?nQ!J@Yp>PvqyOyPRrOTe zb=?O4S}Je8DpmioP)tR}H}&fxc@|pR{Xha;sO!)iU&nF*1xC7i<1@aSW4PUkFJi#&Y+@x!{ z`F%W9q>l>>b9fHFVPs~K6U1{{c8{`q2oQH&_4wQE2;J?7ij7ZImESPt&&#p%#tTE< z_pj>WU#ew4MmJ5Wpl6+FKFg8PJzoA2M=w|ayvM;P`u=Mp_mrxtCK8gMRXP!Zn`L9> zE*L5VQ*}f)WW=^u%tFjJ9n?G(`3QqbIj+=eS4D>rWPz=kO~DG16x3Oc-XuW$U6rLI ztx<3N3ZgRB7+J(Q!7?E3ipyTlJ3i<5D{wJ3noiVPY}qC|b0sr8)4jJYii7lZG?I>} zhm2e__a6R})qd6m7DX+>I?#F%BwyAIm>^9M%DOkT+;R=;6JI{paQpRmNTMTQ3*Hdq}w+;UY=bh zisQehbu)Pymz8Fl9cMIKQq6-_KEZ9hrME4{zn2P7h5!vhztDY~>ewH;r}>}C33?VA zRT5VTIKsUVBA%+}$;>564|5;>Yk30rffU~R@f@AizXlfAI`3rsJyt0c`0bt0)36Hr zLZ38u2iJT-$)5S}Z~s{lyQRlLDe!pFy^xgdM2M47%N|caE@TLoK=2V&LmNU*sZi2Q z3wyPnOX*yDzm=hzGZ}Z#kso&K2p{dFo2P?@juv>|G!RH`s9|B@7KE;*j4Ukx za*WE*BZM&(D3!$q1M%_VQzYAWILLga$S9^)yv{qE%XBnGGW=X9 zl?5KnHBp2|`d9ivoQiRS#BK_mWh3`zp*$A$u05^4jOEeBp3e%oRY>~pd3O_uFw7rD0u|s-DJjut(bHSnz$>(smE7GgW!Los1Hs~XJaOIYO zt--t5H*j(`u!LV95j5*iYcVQvUS4*Z`bt8&Z_qTTqSt1Oguj;w-m&=R+!Z$=a!Y}K zO)hqe9^-R?-FP&EnY~6%6`Zmtbd37n=aqwC8U)*9`IY7cB`dCm)V*i892E|{dw}l)QBXY?(zgspTm5DXWp7Xo?X*t1X6wcFIW}Ib5DQFFBhOHo#=X4DM@|pILg8=P2fiNrVigVN)1XMmc9a{gGh>XuzRs5Uw9@s73tAXHxhEyFBF@ z0wRz2kJ7}60);1I^=2~4we?*|PsW%J{rxSfyIaG;ydwY*1-daE1PkA^gJL5t?$p&t zjB>te7=K$1tAW?C2E0|AJEv#Dq*Kv`LfC8<1Fb+BrqOh)jrutHLn~#3t5cZT+$501 zlA4mfYgH2|fBl2rbwS=j^k?+s3&qTP5k`G$)o+tUW;8~@V{`t#+)cyGEM^W(pE>sP z+aMoo9Qa?)efF7aTx8_V&@~3`iVEBbwi>`~#iwimD`lToVg5QmU6BdtnXPzLld_IR zvaFgx1cxSd-pv42-MO2mEehObQ;$7;AI}xTPkMx_F_3!s&RdkTmRn&+wFD znX>3-6a0_S&+I$rXRGlH+e>dLKTFUdWaeT@9d5OjFV>-1)4uLI9-x%{@7eJ75J64^ zg0DP<(iyg zZMbieiRlgdgvxSCm+fDxF)Dcf5zNm8HBE8A0$`LQlrRyxHvv1ka~(@D!a8SNiGtZ)D1QR~^Jkt-@{TaINuT~p%LG!Lv^PN(AU z{=MSjaoQ3OsVQ}!+6nvOQ!?2f62`yA5=~7TH-%2F!yEJMcTQxj_%mMep!)ZoF;erM zVgZY(^39*?CZ7_ls0X69Uife7oU`O_Il>n3yjlDuhwVmG+p2r@DeBGi(gP=rG0kkO zh^4S`qX(Mg_7OQ9J^A+V!V@S^Hs))pr}+CqzPR8~I@SKTSaC}^LUN4%TyC|!^Lxp* zO5caC8LN~s(nnMQ|M>nxHW@1f?c;Jy!ifqpEb8Ody*J!9O8_( z9)y9;D1>lyKU-z{T&BXCkry@^B=4l|h#*nGs?kjQHCqR@MdfkD@H|UB1*E7Q(E)G$ zLY451VdjyG??1~pZ&xof?tf$p7AO-6WZk;IYFxd`EYD93)6Wlx!?rLPh}1QavI4dW zvwmDEpW1CwnN?OCSoHp}c|jqD#l-Ogl6Xh`C&Kw7qWuOJ2sp*cTtg9gq^AK-I|;8~ zWzx;X7Y6i6{as}7m?A~cmLlA8e-Bj(VYauqo+ccGEW?d07L$K@~*uE^b+g3o%DWg`5&@^rv^m-KsohI%&p za8ApM8^Mq3fx&Q4WS<<+GgZ$!Q}^2(P5tW8$E$AvHHcxdmk`VPVY3ELh+{C5gsmTF zwcY;Go18mfz91;@eNdcx?(`LR|L+dr?ZczB$}g|xqGp$$n{hb+d!uyxaZE6Wa0e_% zg`}q^R@to>G0)z3Sha}7h_-mnE#iy&&|jB#>~?=^QGL#%IRJD5W6yy?-bEHiG0v0U z2F+}JF6#B{#7;s_)1E#dJ>Gt&4ErDDJ`*tx$?W-#&kaO|TjSP&x!}}EqdWPwyiV?q ziZs$M?enWUn#zO!a6E+^{%degG3@Oq>G?w7W#w8W=I@Ggy5g;mRg&DkYN`%t8x2HRKKgHNE8pd7@;N$jx+dhPE0{vQButdgL{T2 zf&FFetC<=`+|d-mv$_Q7&GCZv_E^r1*jex|%~Aa}qP9T<=@?Q}$k6x9WEU;OzKerg z>BPjmxJcq3x2F$2x2aQgG^PH!PV<$0>?o!hTKR=LZc`V=ayGv+5Ah&4vHca z4V5J{^Y@%|L-FlMm_OzSO+(Gh<7!m`FuBEwA zQ0(;t9dFN&58V6c{snb3wUc*|%TK=eKItD!<+E3g@g}Fi{fx%7*Gw%#1*(|K2Vc1U z>Z6GZE^qqf*HOnxt_kmFkEA%9)O0PzFwJy-81ZDoh8A%SJczpn$CC2m1PAXy4;yn) zE8uDUo89`vhb}!>Q4&syu1*1@0SCT8yVa?LxD5$;6)G(Wh(4FB7sG+Otg9|f0ICwH zg0w5(HWcQp(oYFR%wGllr=(JJ0PjU;5Ey<5BjLhl`6u(Mq%%353o4`cmv24SD^#;+ zTFta&qOLWej?hIno)^Zvp=5@T7yoJlICInK$@Ka^XRvULSu$F_YBnDwi@U&fFrA?b z25A8C!MZfkq-CV0PP@fL%zwtM7e>U9eW~;&C@U^H=2?l9TTeNsCO> z#BTDkvQSiKG<8hkvYon7&((8LMiSC*`(jBezGtHG4Y5bG)l}Hql-d=o50w@9CWqTw zAM@{SE~T4PfmRRGdfW`cjxNg0?f6ZCokhEzo#>r9Z-tG#reryf-i+;BB5A-BxVywI zwbgV8pl72IPDJ)50vJ!2;YKT%58I|62DY5d=HJXc?KFi@P?nxTzI!85IabHKr=BN* zf=k6Y;v5n__i-m{(#So-Rhcv+kiYW7*_q%l>8tMm{5jUSTWy_(hTXuCw4AiCYP06C z@@j6Nlen7psmO$r9wvFRSVoI4pqUKeBrP;_S4pbIac1#t5I~&q-?9zk|9P<@bMFvf<#{QMq zMV=)5mHr*WW~UIRx0JL&B54r*JwDMb@5JzHR zLmK=heBwpE)9=Ro{-0+j@&yVn)ZqXJF2`BD4gpX47t)65%qpKBUfF-txW6m>GlP|1 z<_j)GL6-F>kSq(CgEDD%YnV|1bBCGWY;|>RkJw1Xo z+SmH!?mJ-vC~Rd~&h!1>)}8|gx<5V|>I-e$Nj9qj4^bh@>A0dvR4j(_9l1p)>~t74 zukAJY)LTv|a|sI71~~hfJu>;BCo7+`&)T#RPbfP71U1^O1vEcA2f!4G>kPi}O@RK` z6$QP}p9JiX%*qro6X~+gyQx~?t)G|o7WMu$Obr#*SyMLbe#sH)P^aHRgsyoLsT|51`Xk%@5=NmGB53fHP- z{fEK5uf;YxIBDQ#br6%J#!MpZxJXG5(r>=8-qI^>(ImsjSgQK2i|?Pn+wsB#95Fs; zx`-3z$}|Y3^|YkyZT~pZO>F6= z2NZwtQqw?pniE0a)OdH}-Y~#Yc55pj)3PsdcT4VbbBf$@+0~xA-oh%y@Z;rnkP@zQ zVqhW7753^sT2WOK(G>))?vTh193P+CZ1sMdknF5kt$Rpr-kd64yxdN=o!K{f!d~?H z7jOQ+R1IkoZW|U0G3SHxF@cC6E2ljB&Q^gjQh^WfWyAi;CX~GTv42sro;4xxCEd0Q z5lh-vOvY`J*Yt&TE$`e3*}m*SvjJ2bOKRF3zP#jv6ieD5(>hx!{?nCLL~8Kq(u^O) zGC5loFZgZz?ff$LW%5LROf*Lu7NKcCA_Q>rKse*_*oR3?R0AGNc7(+>o5U~-S>m(7 zqT;ReHGy=jUa~ONiXj92w3vY*&McoBiCq;@ul48h^xVR@=umr{yG}jN!pah z0yQCn+XKbx<9%=SD>$jm@DQaIHOZv_^t~sM85zj=ugFsJqD*eIC)vj$IugJF&{PXg zS*%<~T!e=HEC%9x=%|drWc0N=n#a%u%^1zz*_5W!VTPt2cu97bQQ%c@1AJ3;n@5!_ zDKEz2oAxBX7_uq8?ndUAY&q6KP5Q|I7y68=V;qrT)vmH3)WXb8LsVL|DLW+-QrNr( zHgs;mrda)6TUMy_oSUY7rlM1=jm-@#QPqCM^FY>gpS&>pGCYjZGH|&yA$N*9QN^rr z8sv`q<;=adstRz*ZRIJ;fo6PBucODlFc5o_T+>p<;$H4|6a_el5J?8f@z+UNzKRRzUL=YWn_H z-(*74iTq2AlqlboPzRUU7ZioVqXw_s)?psY43+RvUe{Ifb`&`73?fcQklNC>fRvHL zw0MTk$G6r$u|8O2h05vl%K=^~Gu(IDIelc~mq7Q2u2w1ks17%BN8dxsi72-!Y%3)} zZPo?*5*@i^RjtsA&n6$w3E~DGS-l^q`bIvO2T;ObD{WMO6gro zfh5VT>eS|);LY6d09hAvb&r6^uqH?j7_6!s1JgSZp<}?05SR$XkKG#CV(!Q@j4PiA zi8~A;%ghT6(GFO|!`ME3(qd(;m9%1{9uFfaHt`~$=stgCQa#N|G4=kLs7O@vj41y{<2{*`SwOU zJ}#16E+o*u9K>TY@#XXq@+mQDx<#LL1UmItZgS~v8vI!8ldUYE9;zQrP;gSgu%UX@ zlfEPGr^QWTX;VD-^0o+gy*KH}Ak%1h=yuY*9>fTzmcZH2a7;&6bkZ;iQCs1c50F@! zs;x{zZsqy?h7CZ^mBDu|o7^+N)HJWaMd`wiXx_4|H0I$FxY?!}xqxBc@6&A8S$&4h zqM64{=&`d*gbrJs?GO%`$M;uG*|Pg9M@P&VrC}PXSSGcEOG`qLh#6`^moh3rfviql z!HoPM7_+j4mZ z?>;g4=<^^AYKd$;JJG<&71mzbe1VkFdLx@p)w|ofvW;IqZYKF>Xlg8|^)b!A2|~5q zaQyhyzlP$`bR1(CowTYLCUwPzP|30necoArXX1K6bEdXlfgH$Q&>S)GkEx7?_R^+Rx zn1qN^8#>EGO?6h?{kw;SoLAfM;SP4iRgl++VTg>?uM;Z33~pgOxP z%`VEb34qV{keyU5s>)@OO6(QP17)tT_C-^Y0*=jpgnY%#BME)z8*X8UhakJrLm;M(2RbTuQFyP9DBnW?vN79FiOa&~`hGYXB=IA#3_Mf6jz`(1ccLx-2is-x6f#6nrsvSAUGO<#t z-Z&Xo6>AiBr&Xe*Aqp89g5h5Js1R)4UrUP=4VTis=qUXfB7K^n{l%PCGV0>EFny7S z6?V9PW%!yag8{EYsez6?a^-{JPab9#NX~os8fVS7c6IR(bP?!QA4l0w>oQJWgrPjz zs?|D8V0rTH!q&|ktKpc{(lTGh#Zp8$I5cM?b1))r6;oOeC;ZHF-uN5#AN0NSlns;1 zcKs$-bm-X%)t+`?P)Hgnps`qUA7zVHzgqo;Kle7%E&J>ZzE!F)7h$~N&1i$_&CA${ zzR!iugUFQY(^Mzt15s zanmja=gBTZtH4yI&=&pm9-Ihb|d7T%;z;ZrFTz za$H;p4uMuN^=OvmM~S>$53Q^v`m1{)LM4B_bN;MaFn2Lkw`u}Af+DJKKsktG5g5Z@ zLWbP8tt(meeDp9?Rf=-0%uAd7T{Cm&AnPnF)!Z!B>Z77QRwc`qpOq-Za;)KpX$d_2 zRsNP`n=yWNwpoxurK&&U3RwBNdKq2SIII1kwN81VcTr+LQ9}nVvGMPtx2k&3Z#Ard7mKH(Dh zA>-Zsf!1m)Bayei!Orj?PVnZK*wws(xlhziu;=)xWoR?ek95|O&f76Wp1*FUS&oG z5RisHO+ozddXHWI>%1JUyFr^Z{ue$z1vRC=8D8;V?NVXjbAOOf@XaG`E#e4a#iO$G zs>xG$Ktf`7lxpRr{KtP2NZf{-ox@G^QATWN%B~CTVP77u3x7-e_-!}rlc>aMC+N{F zose>(3+sNoe2Y(gMNEPJBXP6wkC7V_+&o+FN%TR-z$Bb-Fs3Jxi=()qR1S!B?bCUw zlfkWL(f+^y6H~8D4x8S}2Q_!nqe%y*^%Uu)@-|PVLSjl@t2E%G8CENK*P69&|Agr3 zbkLRI4mO~3RSA}hYJ`d81rTw>`XgYj1-<>9?;B2P1QW}#T6iEp9WoByP4&56_0|Ar z($5d{b|@hP(U1!T;ez__WX;F5M^tt|)gNRTi}nhS(@?~RTAQ&P+&#RwF`N^=u&##F zjVFR=X8I9PdcVhjBoET!Pz`A)NQ06l3adJdR^?BY z?41&Y^?_AwZOiCB#N+t=!g#05kX+-crb@#xxZV3K@ZG4(YcunwFjRug)^xe;2)H2^ zF^P%4vnab@y982>Kf8f|GYKZ;Sx~S$0sBCXEGi&X!Z-#O>kjJkphY%SEfROKCJjp7 z78==BF%am;;Bv0{y-TcEp#WNY4SXQgY_ev0dH3H%$UmJm>?u>Vk1+ajwa6`Z>tl9E z)Z7*Rh?zdU2a%J@5IA&bLkDgcvDK5?bi7a*rCZNz#VzVN8T8mj;}DrePp^^{`j{7h z_CPnlU0)oh3#?i}vEjD29DWxM6P}4{nw;eoP#{nyr^+J}?lAPu@jMzjA{vS5ZM59w zvq5{{?yuMG%KS_$F|K1)vwG||5M4<%A3g=TCPpQc)FJDckI;@+|qPO4!9WXFhqPc&60P1c}_G}<2kQmv|mK>&o? zR(_%f30r+;6+vVfn-RM4z0;}!dR7%50aT(ynY!R3Mi=W+!U{WzfG#fTvw=`z^zEKU z%I|X_H2~xeJw3I@r6}w1s$IUcT9XhL+NhAbb&f(h8}k#DO82-bH2PqH2FKh0H8t6~ z`zy1dWuV~G*DiA^&x|c%eNEK%sHmKMGZ^yCNx_-(mQDWFF{1mc+Usm({JYp|O#NPVm!y z5$aT%{*2iC#$*U4z`@$?h%mm~$CUMD{X6!mU%`lY?(DK*y`_bytBnPmtP5vQ7MOVP zb1!?!7JS5oG&^H;4@IJsJ?9bq7t`w>Ng;JncTR7Ua)B>eh7O(`+nr`>RtZa5MOua{ zWI4II*FX$Ih&QdXr>JDa42;RG0GD`RECmN!T3VKGEH~D6^-HUZg_Ru7mj{NQRe=2M z2Bk#nZBu5(HNpcd6I68AvD+C*ImRkSo=-b(0NuT;@W*fQoox@@yTA=&j#xM zb}3SkXY8dTw~Td!4RhPag|yc~P@E6df>^nHO8tuL;T1aEFSH()5ih%;bEv$kMv8S~ zKL(ejssYNPU zeP0os5r>0PulaXCQk-N_5kD=dZPv$)x%|g51%tnr2;NB`)bo0Gq8R(;kk~VS`Z~a^ z;Z&y*zF=9v%D_V^q4tb|S{4Lu)h;azQbWN1*nk}^-b%$lJQ^jlo!a@Uvjd3`nh-uy|c zN-CQ?Kix=LyJ|>aJviQ-qa6=~A^cZg9%-CxrH)V!H!d7Yt&-z)h&ztJ9tevDoq6ya`F_ldvCr?XuzQfqB6im!66`Iip)idPN^ z{1nl19-BJxUk8hS-W+hqhTHUtTmvSV+pXlA+frk#Msz>i08(BR=}pTa4mx_A%_`<* zx7#H{G)ix6)eergEAlt1@7BIl5Kp4VL$2_TT@ORkb2#JA!k2f_^>T*JZ;IU`Fw}s& zOTyYvwMIvQH))f%nsNBCC%aDOb6qP1saC?kR`b-+mHFJZLYk%h2zj8fd#?&}&Q2a- zdmPYEP&o{OHm2b|vI<2O`%MvljARrC@BJXFlJG_~LsRBp=BLt4_f@bPvdz9gUI zbr<~X+=X7ZRn1z_3|MTO>Y7L=%f)&Jw_U2I-5Y6XMR7UD!sQ(Safl;nJ-0rE(di55 z#1Ot|tG^~Rw%LuEaaPrYu^*eyBMocYDW1ng`zrePYBW57sVFf*h!ZD1-zSnbYZo=0 zK20py3{q;I*t}wyubJ~$t~zpA&^kdegd5m?=*84P#LvCWZp(7eu_w7bo<`J}1x(1z z#6245T2Db9wyQq^GtM}Ms(0wStCLcn`}1S?A3wr$q_}+KcUlISSLipF~ zbIF@1RIJ|;x8n%k!S|j)$8`hq2Day1FGIF zYJNw0{pB^Y9u|HgdnX5L`_QPwI#aTuSJK#-bvk1AAZe0HX%2kj$7pZ!dH#hZG&4#y zJA^i$ZX}IL04FgCi_G>hnquMSxZJa!=fL)Q&>wP)RAE2^zOSUAqC!J&os4iQlM?PU zd(qjk@0lO=9Rb}^bU%OUN4ohYG^#K#PNot+cYt|TLbj+-jFS5_#WS|OT2Jy!QF1dT zlUd@1Wv0oi$v3TP;$8qe5^_3og~K5%D^4~|j7IZ;sDq_vm(fhIw+~YR_3K00-I9aS z?S-lf;|FV%gwWH)LZ0ov=x+Exi&*(xJS1#K^YXK+X0r|TZu@E~6X1`_w~Tu`^7X^~ z^>bq5l&$l+^>o$#=avg^VkPd|E!Cv4}*%z}$ttFtnGFVT`sw<`Az4Necg7=I(# z$7mxuZS(FkR!1Amk$4H!ug8%pOu$-JSj6Eb^h7hC7#Ir_b-pxh+1Tq5Jh|Vl7ZcF^ zg>dud79>QCu5#Oya__;MS@>ugpJ~<~j&eEhVUyHi26uC%b*rY`evFw<$xS*~QPbeh z&zjZCC0Oy_eu*kXA{e-9~p0-xTHt(9aiX6WpQpjuUX3ptzrG0tJwV5#URuLR&pX|eK|D3P3RlU2@voqOEr5v0}Xfpyo(*@l^u z7A?w8Riu>_xr5PDjM6?b*%7lJ-H#|DMcQb@YJdo{66_T8qvEVk##B4VW+u(u4EsCD zgMV=ybgTz)vf|=)-=nPm;T^uLY zpT|jid0CP9{p^8{Wx%?Eu5z_xOyvbhOP4idNMelgmY#fYmG+Tx5@)Djf6J*RuDHeAg zZ8Z2HwQBfhjTSo0d&h^#0LW}ptmFl(GHgcDYz~~O1W3k0=IR`GQFdBkx|LeQP4=_j zA?TzRBSqbpJE$D*9TPik%xs+U(mz^9e&8mButOH&nfui+B|DJc>F3Q%N)g671j)o< zsw&Y$>B@JP%yaeEkf-*SMMq8taHpPF->2{=e^u}%bPvvpZm00U!v9wJ@hm^s7bj;o zHc&y(OJi3Oq*<&@e=WO07?k@*WEtuN#sI#8b_-14cVaeaiVFXDeNs9>vh?)!CgWTamyx<;9vgl>jYzm^-)=g4;p*K zrpWs3vQJ$?67U`{9j`W3WR)x8c?C7TpP&{j0u(Wg60t>ruOd=xOM%>XO@Ri`UR7P= z*kg`vwEY|}VHNo(8xKe6c6n}CQx*FF;;f;-V?yfa^O!O;Z&n$3h0^%;gp;&6^mwfN}m*j%4dhl-=D z(l$UvA$=0>Se?@~Qevcy&zH>Rh?eKUejZ@MObVu=i&487TN<0;7Z9vDQmaNd7SkR> zzrgAU{xDifMwOkprdPk{o^(E#_!kD9E)S>k^!rPWO2T@&9dyhdqVTs`JVhv|_Y^Fz z{bZod()4BzF@MK~sGk|&^@524!#c+~gA{M;@m!AnZ@cZ1hQ$AW-1s|;$R$fF8kdFy zz~r9!Ps0Rnx78(-rUn6YOkrT@tAx+DpykNZB3dNSGGod6rnt@P{&KX!YV&$VS!TS3 zl!Fpo=&S5`O*@@W3~hD;j9J|?l`98CZJ$c0lx2kN4V5aR+BIRHp2}la;18JvpjAe` zP3_E;hPgHBOlC;~cKcgK*`C^W%pqOHmPR6uw%{gv-eR`hIr^%wRAC(j^)M18LQ4Yt z$C0U0b`?Ysxam9k+YBSODAZO4<3g!47&%l>V5Bp#%1XXCa#_nLMvmNhN5$%rSlm!0rk$g3 z)Wu^y12Z*zzgezh%DvsGQD@O`U$KET4RTT|uUq!-)e{AReRRkf5ezxJRsG#G=at$8A&imyye^ z#fc`y(BB^1Cy#uJ@5%@bCts$KssO10$VV@dren%upUT-EnUt-fwzEqWDu>6$q@8Gw zy6_}JmBb*)o?r2I!KzXqH^S4EM4DR*ggmm{mccp?iuClYlIU=VxJ!E2%Al{8c-%>F zmckCixRa!`Q-Gp6s~Kw$v|Lx{SnR)+eSKw?VFp0e*E@yIRB0iH!@OC%cKRxa~^eq-Q0g1wLdq zRlM9EV+M#Gx>qgLVV7E%?^WrSA3@Dd+t8&xhOj3d3NF9ara61Zr12|p^FCb)1`bae z=?|FJDQpuU^EthGeVmd(BtmZq(kb6P>*8;@b~)qdrn1a*Q|WIJ(rd6}Iw=S99Sdv( zb9BEMX^>&ko7|UhY6B!!{G-&L->wdyf{uPpT%36iZ zT@X?w9J`_6mL+oMCQu{0`&%`ENl*OmTb;pM_=}S*4|`C3X9 zZ~F}j+5t?Pm4>+bkLO*1dOW*NukrZ*O&gq6Lr_nL&FXmiA3H;$^52KAxIp0KAKKPPDMv${1H1GF9y2jnBI_-2A(BJQImbVNoqoy zVL4XhCaGRO&9JZ}$%eJ8tmHz-8%|Roa)+ksoxiAm1l?1?>&ox}<+PtyMJe{Xwj!z} z{=P+-6N6eKs%#%yAHTX&<$_jkt9=e0$~d<+83yEHN%^IIc20OZlTvd}RYPF>+^aDf zdS5-NhsUJ562t8EsiwNv4EduQc}LRwOR_$}YCAD>SAtmJ@;NrxhasD@)^$#gNSL#x zAk`|z_eb2p?GWUAg^F>|`og+e-;Q&cACu*I@NZ;s59gwkQsy$|xb1$oqhA^C^kaUT zsIw1NmNNB=S2Iov>x>#|KPCic`K^_E$};EHs)NMZXETC$_C?6NhQX2VnSbk@gy8Ix zd8^arz;lE@MUY17w1*6MY>@~;Bf^~-Yn`FM&$FTE;vnGEe_TBHo`VCka=s>ciz;AW zAt|fyi(Qe2pX-@rYGW7ku8!5( zLV7J8Tm)>-@}=LGH0)fu8aa&Hw9XCF-a?lA#rn zl^eE04-74d7x7Z*SRH`xqCMGIlp7tdZ*zZsgA`lqDcOnSz6%$7z~hIfJ~%$04JPCA zp*`-v_kL6G_eCG)!zx$HS(+i2-ClE1zJeC6eOjTXATS8$qNG(4kNu|X6FBN?irjuK zR8*JvgSFItM+I9+3Y|A?7@u=@1LkO`2QRi9LlzyPoH{pc#T1vh`-BFa5xH3BY?tC+ zyli@Lhq=jzsgD46$;dFMJx4%=$JO|(oB0VI)haKp$d%XDpR+b;)~~Mh0Fl&s`aL$q zSm!`qiemBKZ}?X3CJf&KzvMcbAD_E_l76Jtt_%3__n%t!14D?|<#LOgv0Ji&z{6;_ zIM`-x_0fI_7#bkwa;W-$tAf%hJ&`{QqrrRZ89xb;O;Tw00Og+|m8M@eZqQk=$T4U2qz9SjF|x)DEJ!tRQ8usNa6U`s5^$UVH~ZV=SDiu{Y^GR&CL@&MeW1dOs&6KD_VTf) z9*{DI08+ietiTH(uD4`VUXsX;oH=@ixfzS{g*Mcy;~H8y+wn%)+CvxQeVpd6v)J~d zi}#2-F+(LP_#5U#3-&Pvnht%d+ZZ8(x`LleVR%Zq?#^dMYxk!Ndj1!hcje8q<7ac32tA?I zZG70yEi)4q!7kBCY0BQXS9@DnY^=Dp6977cDqqb02s zn>N@1YRdh3wsV`#6bxYXL^F(b?(*RJ!(}TpWWZHFr12P;Iv+ZIe>K<38*`tH@W&6D zG(c9n!q6&rme|kDwgTqQvSwu-fr@=rC6lEyAG*pf#VTjyivB%|5?1GZO<-$OS@WxO z1r+>r$Ur5if9C472dksOu(uSVPIO#5S>jv)m6HpdImAM&3+)$Wy4v4Qr0r4;%`^ZT zh*zy&1m8x$E!`O?f{5T2)y=l^4iq`*4F>ggddP_j^yj5Mo%BONV707d1)eSW$j8m}P2d zIOwpU;x0Hzp4NqBi||WllgzDnN);64#1Tu?fVL)bs(t*2x-(kcaQ|LVj{b8_0!K=` zi|{@UkDegf$SqDzph>qk5_O$$-D>tm5yv@?+lt)b6*)&y>8it2@hA0i(vMf^xg!4i6noO6 z@i6LPi=$zXJizns0u{D-nt!E1Ei&0if7)1fz0<0&e#3OKlZV|<3)`lhP@Gcx>yEE1 z@@l)7kPq^yh5xg28AkpP@aTy!7 z)n|%9!S5^As;9=NGQn5(wu^)NTa$M?mHL*U--#ijwT@RdqZ~0iml`gW6?W2_~c6}iMw3W zB&`}cgI=jljOg)@ae!6HX1oGUJ+`u(kKDegbtsnYSE=lVWRV)MdYJFZlIx>1`F^v0 zrwc)2FnXnSMzC`}DqH&TKMt5n76sFZeWs)lM@zs-3F%$x^lAf^VV$I$Io=PG%;&sI z=&;fMTTDKAbLEs@IH)Kq>GE{_!9ZZ|#M2zX0vpmU_0tv<&@w%LAx6!=+A2xuuwqOc z^hyb&7vO(gRMv>KgDjKRvX}h%7seCJfn^ko44g$8soQ!ZFsQK7>`e`MDox4`7|#$- z+f+Zea;}A)-Ny?0u7%?&14D2s(Wp3uq&ynPj=YnWSphugIm?aoag~M$bFrd3Ezj#v zNLX1rpXb}xeUt{S6}n`_YKuM&r)fCcdiXt;$I9n zOthm^5}@A-daE(~n5!Jw$fAdT+rsNA(1_;K&-Mb2z* zdZTxpYD)Xf1Uuh0v zO-BW$)hcq=z59OSc_CpWz93OlM5SVckT_WelD`4j_&#l+5feb^lj%-1&+tpvBwfABWn1`WvcSwLIMKELwxBJnlTV)mbjp;^huB+i|*+_ZCry=W?hUnk6 z;T1+asiCDh3Zie>9DPx;*F}=~*esqQ^OfeI3C`!=>Apd?CP07~Zf2d_uCbm*wg-so zSsvS+59$2&@m%)hhsPf+hu`;F?0-w$iIzJ%x;l=4%|Ww2$iL|pYWI<3bl7!HuBzlJ zlxh!el(S!ZmQyI_`;?57+4m@)v3Lau14l2x-fJ!3%UijHV>IcZ029H?=G@Jjrox#i zG<}R2jxX5I&Hg7o2L8CUS1C^i_os5XCUUiKC`YWPO4p2{<4d6Mi$Dm$tcowkUI&v+ zy4g{XM>9rP>bFCIZ6&0UzuTt7C+HBpGc7H_~h1F9EokC~c?{oi`wY>(3TS{N2> z-jp!m`a_0~sQF4L4qYR@T-##_zor41k+iTfP1a^SyxpWaXvQdw!_T5xI$-^=ZKI+*Fu~{6=!zAE@LJk z)#!+X>yg>5jEro*pb>G-8{f*83w{rPh@DerW4zuG$?2fiME0KXf2AFwyB#c*9C1TY zipjfocyE>Xl~wpy*h7+Ovl4eo==hZ6NqJnOuqM6eo@?3{aL*W|+Zj=45tNnFu z7d~#O3LW{9u;_3l^zcy56%&nPKq(7gZlV5qW;)i)7CeHz73VTtK3k@6;?~&tMp`yo z2*Uo=08QOX`_OQ;SpKdRhdM>YyLh*h`CElyIU@f|xC9ICR(NoS;O_3hQ%C_t;qDgP-Q6v?ySv-1?q2)ed-hpB`Byyi{icjD z=9v4(V->~%?wu)30qG7|ZacHFWx>BoLowsdoQOoYdLMCtZo zqQMYG3V86k`X*M_IofHPo=0lnFzU@{dS zy(M(YCNblNvzMQX!n{)>Mp(-F;Q0HirPD3=^G2e(W5Cj>p7T$GGx zLySyz8bk{kib7D!3$o)xnpde*m}yas*J%j#JmoJ{gvX*&7F4Bv$4Vhq_Vna++qnGA zYB4PU-uF3(LCZ04kNl;o=55Y9>ez?esi~(zZA}UXWGuO0b>T$pxFa)Bo8oR(5gP_Q z$Lc6dj8Z2_dHMIOIik5ebg5*NvkEl2;|S_!ljR$j)H;U~F}Z}Na}Hv+k-xZYl}=N; zS-DVaNwrFPnC7_sMj(nrLboTi@=q1`c|6#`1^Pwc7c5mA_g+~875GI<(vW_jM>utm1bJQpfGSm za_!oxv*p>CK$sY77C0@eGF?XH1`CX#R-_F5ko%HlQ){?eW-Nw2&iOB0AccV50pujG ze?<`%oQnD-wt<@qRY~TT_#OYTWUBRAcjE(`q@L{CZYD^#_=+$2gPv<-JX;)i82cT_ zfuakA_$Fn})IPHowe1>FTj0pucE0i*Uc~?AC}9o9ARNsgr|v>5Y_W== z7gpsAJcy;sG#SA+8_#%i@TV}$Vy1``v(l?jU2e$+c@Kdq^l2uaxI35 zzfUg=hmK1sjy(`&uM7kr6HQ@60apuE0R;2&DxV{^2AtSb_?7ZK6hK{OY%p^CTi>Xx zhH=~ilcY>FlL+Vs8On&xWS*GxQPXK_!B*Pt4N-%7oe!Un&K=b^t0jtDs%AdKs7S}m7G&p}esZR@$_0cqpxTCwHlnPR1}mQf9rer1F7 z=z^%0>YQ9LE=ab^&M|Bx(Ta{w-z6SHH>8Z&I#SO{5Rj6oQN1c8HLl}kw+MTN@NVa} zfaXdIqSlNMRNpq(q+2aD!t3TGZpP1T-6@x(L|CX47eb1p)N`hp^aB+n6CsN{#zEyC%iOm$1yO$je~TL)xB6^ut7W=Z^%f`= zW+lW#5O4^KxPnznRCS2am=hJ!lh>uC!$^(med8E=t`b?9AG*+(kDKs*dRj5BC@)Nd zJ7Yd(G61uGp61^kbHeLVGt;Lt!#>>b$mrYEpEjureE?82#Wxrbv5^rpK1wd1@6EM7$!(ZgK<34QYpk@K7zKUbE>Va<>8u06nR z?6}Tw_>p97rH{A^qCzJ&55!=O?vtEjA5e@(!4D)2C{scrTIJfyVSHOadL~- zT{7Rbr`G;)l&{ZKml*VxyE-7;MPv;@$7>!7_qL~-)1Jm+k+VQVBHU*mKq`0tIPHhA zTBe!hkY2i4{|4#h3F-3n34_G@fhN!Ul_-nC2jo<%&Lzh*IviyXPsCzBalgA6XIU0Z z)BP=f?Nd=&)Aq7%0T+2>1}k%KRoxeDtek~H;rch((nSG?<@^Asw7*e$q!)koIuT6G2O zrV!0W2FGvgoI2KwWz2r6I$1cHA@ppj^D|8YwP7>#>Y(xeJlFFk-QpKnGD=FcNw=xf z->a^hYwC7EztwY)`KP>Y3b7>W@sbz*zRl1Q9mGY@fQE`2GwzF5#tSTmQ|ok>tg#G zcpQVi8=`XFecD8S?5ic9n=Ek%dZ}cn~eQZsP8?HXw067bE}cIZ!lR zcp3TB?b7E3zO4DVwzLc{X244+_`zTiOt|EI`{|Z2b9C8Z@go<%Fe97&ONR8>?O?3% zMwXKA=5pQntRB*5#Z8G#+CEhq5pTQakvj6#iWbL=%SP+jQIN^8A*Mr4Nt)as6PAuk;QsYT+^^zaPY09-|Q3k{#hn-%-juA)3C^Yq{E)dJotYai= zM^bE2CAGk?@Ac?~|*gkuueJGMQ_+h3P6v!-b%)|e4|m=Sn5mun=v?A_Qx6H|Q7PuD0FspoeY_kK z@aDr>OsaL5?Id}9DpBmA$b%q>RqD)j=ho>)p6(3CmAQMeDE31@7D=z}&D4^oexw}B z{+?xRZ(P{OhHQ%*aR9>BT5&e)PppbIw*8#dGL5F%E-|nG%sYOW4|_)sX#jqr0||=d zvOVt`blJ8DL-UZc%mX}D3?cP@53HC$qKOPd)Lapx@#ynx(B?RGj~K|pQxv8IoThm- z=)XlW6lfRvkd@e-3Wdt3D6$-^=#spWq8`nCR?~H$*-*i6D=_@hI-TcBM73UX=lnM{ zUMB%=CzT+HD2evMRnQ9MX?2LGcJBF2f3-KkXHEcwI~aG-lX={i0Q~OJ#n|28w_YiK zb5g%e85@kvgb$Aq18GfR(SRmZdr2B(J>{5xL;#6$SXhq{^Lh0#*0=G)45waR`2Z}f z)aSBD(!vG~t^_C=^&4QV@kTKuLVGv)(>s`G{j7l;y=zq9QQHZ2onbk0KZxPp-NsdO zd|PjVq_UVgYuhh3A7_$cJ>_ZyO`2YS{|NqHt;6$B}}1#FElr)h_o^LwzIZK z@tErQk^zlkjG2;?x^;5L9sea!8%JP<7z`-;ypd=VhhVF0d+qI0Rgk-yLiq5;x#P0a z`tr>Zf5}fz9(F?}ZY-8?)%08nF-Jx5VHevy+FDQ#K@Zmll;(cTMDFTn^Y~rq6UJ@; z-q+I$y67 zqp9`3a;kqvK@hhc7QL6QGXlm7^aFBsC4GrkN(hi4k5?Mzv(mZei6@&_1heY{yXi<) zO#$7y=eOyvanu(*H-cr_>}H>6HA!P}3kJ)CTZ8tRQ{YU0yn9Rl{M`N<=QfG_DJ6Mu zk?;->#h_L5UMwhw)%RXf>Mv;-4C%l>G&YL3AX9*(8G*;Opgd!CWzvwBcLu3sNr5$O zQTacl-~TyWeZ}hlHDREmL!WY#>Zt)?im+R@D}k=P5t5YzG-(VPwS?KLkAE>W-_R0! zu5fMa0c_S%)NM)_~64yK^5?2E7I4f+pr#=_VWUbJu)z>GH z14D~C7WW}>=wMJ$ARQ|rq5WK@V5q8z2DaSZ)CW1Xyn}%pE(yN8OZIYrsn#0tpVHM| z4Q)^UL18$Cmw!rHk-xS5#NM2Stw6Hl==hsWV-Hv_gj`?>xq21q;gst7@tpd8`TDk0 z^&0=KZHOsE=zT&0Rh}!qaATM_^8%48a|n9xUZH7v?_`Z-PIX=m^Mu|>qiLE;BXkz7 zPX#<(NR|3Aj5cPWqMo@-^S6aS$?cLQ`Dc*$8{6(HU5e?ZbXcbluj@H-j&DTD#`NkbN@^7# znhM73|2Gp7Jbo@V5c}>`|I=@!N z<`|O>G23tEs;#AI*+`OY^n0^ed?$gK&$JIZ9~yPWToi}~^%lT-6IZ0AQThDm8bRe5)pmAt%e_X0C%jr79Wl(s2x31G{M<4EGJ4W?4>Ew!R4w90Isuo*@Fku4&$% zOO~wFe(Ubvhyc^tq9V3h8Ddc-a`|~+^6uUUd_Z-@k1W+X##CmDBlWoxkY*)nu39K$ zP)cz!{?|jO2=V!dy`lZ$c;-nhIBNCAwvFT=-3f7&_gML8CI`X)qN23zfwuYSfm*>w zi9-@PqMS?55F_<7$<6qviSsp_b$q)$0I~WNg2dQ9#ncua(a>P?NEp39Ik~ZPJjQ>o zTy0jX=C{eH)j&Ab_7J*AAq~#PCXSU5A21!*?AUr&pjAwHv)qK@qf!0+#&6S2r*LWm z7_|hA3Gj`33TV-)m6}T)<{fg~9Z!tc^W#Mf&7M%~#2v6aPOj^%SJVBxsr_lua%4T^ zx;-Q&|CbM|_wgAR-RK0KfsQieAN=F!b5x+%B2 z%>b$JngvX}m9wv}j2N>Zb!bASPoL`jeQ{6x7;zzORH^L03`}2}5UEJFC845$m=;#g zMITWydhjZ&Ey1*Mc#$j8{fJ>~1@u!bc-XW*yIDVc=0QW_f5ts&JWcz_aNR;qQ7V^; z`tx|M{J1~{ODUHD&1&|IEIyT#4!o8S`V8K)Ty_GzZG%&j)pW5E&v*Nz+o7^K8;Kvm z!Y4N;vdc`!83h(=1o=VEIUjKmqtcvm1T$<6sv zZ}|Bl*Cg6be76ktH-bUTEB$d4V9+7yWTXJMw>jw2{?YJuvmi#kGko6h6G8MGs>MtJ z$cHM8B2`dNQc)=^1ZuYnwohA>H`VrFhDkM)*XG!ZRJ$A_`QD3?j~}GgZ%f$Ej&P6z zzj&@qNR+!=noLOKq2F{DHjHU~vj_(tFTz_HQ>9e-Z9ZPPL=s@3=d4RpPqAdvlUV%N z?2Y(%z|I#hvRvmK|k;poRe1P`UC?d=xonXUjIx*E!(AJ!S6Ve;qXr(08IXl2GBL3 zfOh(a{R=xoT;u!IY$bVqys?&hN-PPauD=y+O90Ef zI83`o;ffpJ96QbjU%Or8?lNEPEJjg7iB_A?8mmu#a<#qCjx7=uSIP4uc(Pk+X6R9Q zopY@a@}QciQd1Uz28=^}jwTwaKK1$!YEz~?D)6CoWsmXF^(u_<_KowA#R30|5huc#bI9;{;hBlYW{DJVClX~VKDeeE_$z14=$=A)Be;eT{W>0p8ZDNf0 zOGzdbL9>BzEDX_GfNt7URb%x#$8|lRZpgS$kR2|!&PX&tmqQ)TPC+&zRI&OP==be= z6Y4>=fQ3rgn^Y-EDe1;KtYTGoV)s`tk=><=8rc!?2k!adXb+qLoxG@VWDR_!;|_&= zyILwdt~uXTm%X{nw@;mT1FA0Cka(|%hk{e)zK_uZ%(-T}AhF;R4h$i0v0ZXV9iiS@ zT$9ZlqQ3XZx25a$mX8OEFn5GZxst}8dgV$rWJG}W{R$70Y0Epyi7YtJOzV@zbMd+R zdxPcoH5Th9i?#vL8Dh~CE|*a}Vp7SOqq6b!(~bu@hL629^5ONH@z(~d5raQ#t(T=d zwDY8rrwUyTc=tFb-f0Y@MHu}aOHmhCyr8D&e!hA1q8OzTh%HtQ78x+zzcWfi;lub3 zk13gfo}yK2E#bah7bN}lDp6tO(xoIh;J?fXE~YZlG(wYtisr`R^mUR0thMOSE4bHm z5F~0Yq{)w{rYEAAE;(&6*iE}Z(fD1g>Gb1#rE?V~beb008%u<^S$?uS<53}6{z!tG zH}m;yZU8mUSd561 z)^UrFrnzFw^3fMksO^>}T0|GuX%tYgUs^uewy|@sY5N&Q?gL_`uki4s?36&-1MpN_ z*m)&6bbu!WjZtL%3s=?(kC6j7tr-}{e|%$oSR+KDWK)(Syin#@XYPsmpyx(hyL&=i zo=%Q>3hHVi^ndD?)3%=onk$x6qDWFLYq{peE>%bEVrh0NPbmMuR;mRn=~t?JnSG-~ zQz5~CBT2?Gw!d`f-ikh}LTnxD5bmBooV?Hy|+>Tm+X{2iMP(DqwV6DpfiU zsj3vQQ4$Hqes{vy-Jch&>#o+RGk zr>(E8f{%MIKjj_`(^VOi+wjvk0iI;;zK4o2!LX$cGZI;#+2=ZjRhe|vA9R{^LR}B# z*$VgC>5;VF=F~J{IXsX(AIH9pSdJAz1K3?Nv}ISc1$Ij?(ucHkJKgq1l*98gCHanW z`Wg_VkjIh{xxL&2-w$|)z35Wp3Q9yM_#qY}*iw_n9N_&+CvHwq39jHj3?KGW zC{tF!RJ#Ue<-0A$6lvFv@hEn-`yb7wDHlTYcr6z)N*7-k|J#<(av~gA*t#14ciXWW zlKGu8*qjVD*MJ#}(h7*|(TGLV5`nTr3$(>A5 z>GQl@9epA${!`LXS7icUyM4FP2W%Mlo~Rp45C5>Sc>3c{q=3gGX!-E!+gph%PGlxj zUpN8pd-nIK_U}96XyDl-ZjsG#4!1Lp1>|BZ z+DF69Sy5-tpI5bLk7ZhadjtnEQ>iXoq#H{kSxJs0QybS~u8e~5MOT*} zx9ooFwqaMq<{H=NJ>Ddotv?oMRlP@#>9lDxrH=cpyB)ju&cImN8i;aog&{8ke8+lr zJzc1tT!k`aGAjB>2lXHvU!}Mq-)fNm49V=|o=;7)Y2|xiyv~l+~Fq!Po*n@2H*WLK^3Wr5Xdc6ubA=Bl{agjpCLZBHd zibzBV`nn87HM5UabdfQS@ZF`B{4{ukjBohdnvT6h3X85tFusQnF)3w+ z^;|1TSGp&E#xd%_Y+0n}`O#@l*x3#2a&a}iJQR{EwEa>z68D(UJAL*i>Nw@DCtgq$ zH^y{S@RJIynmBB}7yyP}hjL(BVDjZNR&3>2Ilf}Zx6`zMdk0`<%RYVSKmDE`*DH8V zJIh$x`eNgCLw{`j(Wh3S7Xs?nr)4q5l&+99dcBR^aD{wHq^WcVHl z8ZSN~H`XXi4YA57WZcg!KEHCnR8=4Ti8bAxXUL0BgfG(HWQ)vwAKQrfPJE>cVIOu@ z6xB6uFx3TTE3jHLKUg%+ag^}q1i5bKoI=@pYBc%Tf#cZ5#0Qdg`(2>ydC23=PLwn@T}FC#g*t;t@&qi{i_R@vAaHv9Uq3D?V=*YjH4F3rF&aUFngN zCu@~KVvBsHu6@3x+Tq!90w_o?4^vtMU*Q(TO+9{ufD<@(_^Pe{$ZY9=&~qLHX5^_z zT($jjN(x!q#Mrjd!pzs6$9g}cw0S;PNaH9MYm4DK2%ABK@s4M!ArvMPg}9YD1&Y0a zk=q5BZ1zRbPwleiUXnjpVt-HvabPXy8q>bjMUcY}Gu8FQT7BiDaLI>)ZWMd+pTcNY1P8oc9Vda&0bo zj`P#J;>{jZx~^lFiB!aWS|^0Li^VXObT=5SPX&heG_qSh4F2q_Gq&;_<9#K3(QFk? zjb9X?MV3c2lfu0^?!+_<<`bntJ_*kwUm=lTOZ2|>;AtxR2 z%{IPT=yBzz{IlH5(6{&jWU`q?NOrQ1`@s1(YT9pjti^#7$xe~9Z}>hp^)p2|3fiZg z|MZ&T*;6k2B>l66c(hSUp%vY)}5GN731T^1A7zV>PEahKA~-mcG>*PgmGa#Kv!=s}!ryh$Z%J zr%c?o_f7RfpL-?;egKUNA3Hu!5iYj}GPR*^;7JE=(o7DWrg7%FBdn3=NK%{`4&(( z@6ea`XlKesGP~p)V#|mLt=?-ZYfbb=6G*2}>=1qZ#b2iaNhMV3A_^z>ygC~}C=B=J zu>AJNdhQEk`$fB%I@8L`s+DN=&JHy z8L2Qa>;3R@HQX3O%KKo+-l8Q2Y8tjNafY-YospuY65NYJ(;o>k!fl5yNC4{RtVnSr zvmVJC;{?bjHWJBqxV%U1UteW!F!jR*@m={Y56}mo4!=-`z>H8$gc^S3 z<6W77yJ@{ESHFKMi4ieu6%p&pvvv-5hu&`me)}wi7S$9)m3ke+cZ|6u4wo()c|5j# zo)`ijen+V#DdcF1SrdBSt;5%*y)56BcabJO7;D^l^w#-33Y05RRa-72g01@k8PSWD zj)lR1>8uaBZumr~JeXsV_(8G7vjw#t@Z{c+L`Sok-_Tple};~~hhcyEuwoAwNn~LdDR*j2XzQZ}(9;Go&S?^} zih5ebc8jqn549v^|M2BeZ}Lbr6SxjBrwGrb?XaNElxveSw|B%D?n{Qb_8EyTRW$DO zCa)P8yKf|B-|lxS4is#ely!Mva^~-^jwmA-R307nbF2dQ0Fu&m>B;P76zEH$B#FVl zF{N+g)-kp=c5_o!-y`;&otPi~!sx+?Y3uxn#2BbUDoxP{s;+M@39moqOC16Izxx$$ zzN62(W~XB-s44i%u3O=nn%feA!G(igW?JTJjn zmxvE3nXAG88VNaX`}5SuDz?GDQUBbaTL11%f8%e4@F?4F(Q~}yV{=U0#y+dpe)1bK z8%nG)$()s>+L%`;dz%@hh6q8gENC{)UT~hsy%YjP^ycgNzM+yfDZiXY*y^A?1|>z7Z|fN$PJoO1TC{ZDI5(iYW!%M4z240 z_duKve?Y$O7T4?-pqFY6FO*qpIi3C)$v2VgIK5t#7HB|!HvMUpvq$%TLG0{iVzZoXHeuKVT_4_lqHXwIH zZGpUxUNdm#cMlCP!2@ca{wsdO)QZn~t#ke3tbC8xV(gihsT7j;gtDGlPFTLDL(&mO zoh}W!40YlxTI%VqN85K*hvPIquHyY)V?_-gUR8zQ{z~#* zX(A9ZmolW3>&Wow%dO#)WQIQV0eBL15Jm)&`p6NZCoz0QqU+gj2AaB8gJMk^oh_JN z^l1Q?l)|wHp^H8b-nozdCqr2zX2|c+JWBK8aqT((@ znjiE#kf{5QOe#%m!CzeJXMH4lo)6~z&XMNEL8Pp$W<**iv)*$pm!$BMMSpD6L*^ZK z2e;_DFfCuN`_k1LECBc%X3A^*d}znP66wCEc8hW}Mi(E8W}pUQ5{@}e659f+$ydz$ zNo>R%Iv!XjO~?iQs+rzEvkh`fC&sfC? zphdP=9`}ctIs>8#k+&aQx!ZLZR*JOh?BDJTCx75ElG29>x}9Ha)oXkh@TW@yy62tm zGMDvHNf;mcl^wt5-;ieX!5p*HGBD2uVnE;ZZn(}Vh8@Oc3zQWICE@~uXvy&x8|r-f zs!rDKRz!jm8=6`EQ{hm6)G#nHwI0@M9wAac?_c*+iIQP;QNVb?&un@?!KMalrYrOD z+VNxawAc`bQmDgCzkiuqD=Qw=c@~Y(Yr)TV)t_%y%O!MwXRlU3lcWI~&MY6|ZC9@; z;?kF<06-KS%zWQ^$Ck2T%CWvzVxes{Nsr8&Tq>IuxF#gfMq)7J2{C4DGS(ZmrbNn> z`mVoI@z&o*WPdVtTSqXaE$GB$(L+Avr}(O*6CLUm-ww{Bd0X!ChZp7quG`ysACiY* z>S*=&`jmgBBU1x&g<6jjx1k#1?RPyqG>3VD(IO15xXQuIv{OAYw(@6mf+bpY!Y(xj z{bS3F?>LwON4_n+4m`vB;NjuH&F(|k+U#d!fxtk=KsVObaY zMWW145y1!i<`SZkEFtAxOi44ru14px4JCQfg0EZ9{Z%p!bU#!M3^)?w()ps4BDFy! zCq&-+k!b{T%5T;y=ymeuO!#x3Bl=mZj@5}1F&0BIUwF>v3^CxA34d!ey;sv=0aAob zP^!*3?M4JSTdHOY9WMZn0!BYL2_IXqm;3a6D?6h0a%BE!Yg1gAcEvWEiV<5$+iQH= zF}nbMbnbTbeSV{Yj2(<3@8p=0kg^NNEOe+i?{nISi^cr+Wx?9hJVKER6iH5PhbWqG z$ztqokf{%~kQFRljb|9tw9gJn58{s8DukJ?KW|^Qf6aZPvxi1oQY{1JZ9=>3i|kGt zv;#Pe2PtBEyD$iCM8ti0MKWX+1f)y^d18;fB!AcZUU^XrL#v>V@7SUzZ-xtUa&Lgb znPUq^uWk%F^C9|D1hm&lrGF(JaX_)h2On*z88Q^OaV0eYpT`QA&{tn`pMB(@uTLAR z{q`8mH+za%S53BmQHB038*bv#eTgfbN^wtGDmu^TatC)eeTxh16wPvi4gduHNS1JD_MR)k`z4tTd*`hCFuUZDBS7Od}z z=BH;CHugCzUn+NyGiONX?qD&|AlIejrf2hZIYi*~iHOxF38kw%uo>GjNx8|2DipS` z{H3B#I4-E%liYsDW%ktmtm7l?k=uR`4&A`u*)!g6i3!UVFgN;G%S&Ta886rG_M{6h zu?`uDyc9|MQK9J;W3}PV*I*QpChr9}ej4fgtQJ0--=B75n671FSJ;%%JV2Hg>I+j@ z6gy|rGf?syhCIg@G)J!4zFr&J`x6ppmf zIiFC|bCdMG@DknAoV-zRpM2R(3-gU@x^x_&oi5fz67UwF)3>^E!{aQK*9(VP=75c< z*N4TW21d@V;gM}kxaBYt$sF-4{%KcX<AM{v+oI>B(vkrYpAVHN<>ew>W^ZK9@sTA;<~y(^6aq*i7wDWny?9H#k(5vCRd4E zL@bP2NFTGYZv5?BIy;tAN;ay1Om0q)onXFPfl*?@*=Up7ONYdG-n=em8YMjaVlWZt zulswmsd5C=!#{lb@`9r`$8**8F`Q6ybuS}@Rt&d zx060k*Hxp)nqO&v-k~tFh6V#M4>7jZ!Ox+8|i)W9OfV1z}>tix@D@=A|H8gMzhW6XH zfQ8^)`7-x7rM#8;4js1?B-yA6sQ`mwXEnSE!iQ5$b-%h{7Y-Hpnm{F$o%-5#y&4J6 z+eR{vdl=1kYXS9#NtSk}*Rz}1YPwynda~jH57$UXt|!gz>U8K6^nuG_62vaJ5dC*W zn!#le6)vhJkcfa=0YRW{R!Gnle0O@7a^(9IJH*!1uWzRMe8crjWcpSeeY<~Ar91d0 zS1Zss{92^kn5%zI^ZcP6w`+PISqjhSyO9KBbez`o_-;jUv`UqWFn76qy6Xed7y%CY(|HOiXoK$-u4!LDS0dBOf;r0DXSpEQG&WR*&ULRUNF2m7imP9T3)ffpd0^0;xO!m}l%(RzuQApOmVS9pG zIHAyk6r_}PYpHWdJw6g*Uz|Ps8+0=gq&nSszxArLd)Io7pmM z9g9x)CT%3fZB-9mVF?9ETX)Hb;~!up(#BJDk@^Jm5q>lxsM|eh-zm{j#uMkUA%KK}_vb~bc`ShI#TMHc z%B~+G4yJpAhITCXtHI-tw;X&aUEz_2*z2#{gP@MWdm>dNI@6 z>DoDDfmV4E{O`8agc8N>55S8#a18I-@Nk9~Hr)Sc8nz+tv5F1WzhOHhWQo8n?8|az zs<@;=4;3`=mj?sxW@wujVQjl`aO+Qr?a(Bn?=Bf(uiF4)f5!evF-3F?|2rm1>(~!Z zuxs?Cqo0kxn}-9%v(YsS8Xmn|Y4lYIsfmJjc46AKU%OYt6z=P75dQw|4EwSZSe|wi z;Bd_!Ba@QFPYzZWKU{Kz39PPYPPh&f)31nF9ZybAZfA8intI#3VEcPb#&B3wmei8> zraFxf{;nb6mD$x~@;=#LkIPx{XuijMr+f;y6j8DcZMN68ldjzBTt@Mu&S3gmSZx_54$$uo;{aotQ!7Y?8i8d1N+!{IJV?`? zf$@gzY%-+#-zTRNA_ck!yd$qkFg3}@0J{s)OkHWAGYI!m;7;mgyFjc!dnDpeulK)t5;A1(=wit{9>P`BO%~taw$|}yc zKckd+!^=tWYF1hmdh(OJA(e*iHgCU{s!0B*@Rq$hKuYnM|FR`^~ zV+b%(^b$FBe^xIys94Ibtjqd7VNe^e5L>)4c52%6+E&|GhDPl=+TH+z^+C~0O-&rz zck|yAbJyJ)ENHh!9ONJ3+pyP8#lprLjfdKgABd-rW@uGA{{UMF1(GbYsth`lGYvPV zaXk(4aDw7QgX!M?E7)d`+0q;k0!8u?8loUvf-Yiv>^!h3wF$I%;S)GmVWu zp0~yQsNspzV+gg|e3hdHpKam{Z(S0e!ro>|##ppWUdb^C+P5lMD0)6ghH=_Zi8=Q1 zxhZJJE2aOql?tZN*2_#!y?V(Y03|&o;@`NQCKDf3T`feytHDul<^{k^TB;aKJH_mYnQnbUH!$fruK?yf>$yHK;MG zWAE;F5zgbfqrds5q+Ep5RVM}+za<_$UHN5pxiwX(*ux97)qA|rhy1DOU^Va? zMQOTQ%$C^2dHZIh!FAqRz7J3yA^qt=u-I+98F`L%ik7tQMmKG9!7zAJg1~ zp#(DkW*TETs^tBP1n5tb?qI&sQxpKT;=bh2a;y1N??;2v9fof1a{4j`mVwd0&70*- zwB_9sx)(3=YX%;ddXfE7LxL<{_)F%HCEVU33Pm7Q;P5wv;Fc&CdrRitc-N`mz% zQgbQjxr6EFX?L5O^6)xgISKwGy+EOa8;H#^|o1OlhLdDn3&fL1Vh_V5Tpn#Ui67eNzAhqk(U8uUb$PqaS}>d&#}p73^E1xsHa^}?z4!u5Yd=XEvJ3;{FSh#!(M!};UGz#w24}_u6Ccs~k7yL-GdM<#4 zqZaw2l;&g*_l(6_Ox;Sa`EH6|v26=pSRBK3&FU}9#RX{1qq8@D)7puhR^-1Y0$>-%ikP0C-~t(aeZ?|j+GND-C}?1{Fsb&){!T zYDli}YuEU0az9gHIsH+S=(Wn^ z|IA)Wa`Qw+gbZm6OSN*m`A(&NBWUkqxC-Q*i6 z?1co5K;!rOVKo#tM@10t=~EC6{k1yOc{QfKviTPd|Fw1|CQ9B_#=Ybv>A61_13AJM z1wn!}y8N2_zrAXZbR?)2js}b+0>01)kNGiU`rz}V zCu+s+Q}V`sB|7?E4o+K8ukZ2PHZds_WNvHAaV2z*>7{;ZEcT(gk2%<@ij+p{n_51O z%(z7YrCv2Lo%0C|1?=#b#DmR%mwvrp3cO5X-tPmXSpWX7V>FO)&n%7Y&41VfNR`&( z?Y+Kb-0hOOTL}4T3a8 zF@ptDiG*Upc3PydX4bK={iJaGC_u^g`>GYpt_J4Y)-`=;ocGyPkGV6)ek>`|@XX0kq1Jew@>&pKI-TrDNJ*A?oijL~HZ?fjWGSB+he{9twxoa%Q z?OBxMoq6h68;|M)OkQ8;RN$N!sbZ!GXVf&mIc|(H)=~tV{6{eZ3$Bvx05qJ{dXt`S!c^K7{go1xY;^u{xBC-ZXJjVkQS|UsL{9fK zt!Fxodt3*;dJnrLagji7az7(^vUyYGPZS8_p1W-o z*|Wrepc5EMQO$$o!p2{ycwp9QDhw9`xH-XIRbo@yyB{z9(2G#?@L0|!eKNo@tJLiZ z&zI+7rjXCJi+`OBeCOo=1no!{t-?mkbn4BqrS4T`5Sfa342=-8(k8|`km=^qv#!^! zq3-M6sjLS0CJk;VAmdi9aoo1>3tk&9QYzbfWvRFxCD_zsA|JR#>We3!AUOFwD@L;` zN)_UkCvEZGuw5^8%FZZJWU3|ori-3lvl5r#*5c$Chkv5Pq{gEDe!-pd{Z$7r zD7f%`?M_Nh6HK~5nM<#Ppi&D-K_(Sker;Pn@fPhjr1+3%q8 zs`x&{qqeH1NKY^F7*!?}R^FQNC?H}u{8ol&$l0JWwmFx7I!nVa}^yL4%_C$*S4>HH#AH2SN z9$`w@-_E5;i(V4}q)HAavU!8=MsqwpCFafyt{(jbt7oIo(_(iy9nm7sgy zB*mWV@DmGTQzFgP-IC6`j$-PlpW=>bE4DrzGSZ2lA&ksgtnJ&(xN{82TbM13&RK)B zWBdYd|1-=G?eF#pg@JBr|WNaK}DUdtcAu6x1Hjc(J&#)ccn4r+e zP#q*07uB)E*TEuORG&)|H{nx-+*tQl9aF8%Lb&tcY}jOMwZsq~|1%Xki%RfhbPEP{ zUxs3|zH|0-VAM7v8mJb?JfiSy(7lZO3%d|KMne?_2h`(Tq$!Tkd&nHWz4jx$A#nJj zX*hqvoF&-b5|kaxiAF0awHQrr8hSHSiw}l2S0m?!419-6q@Lf8ndnZS7Ltb9F*sL} zh`_G%u+l$FVjgD`T*qX(&<6^rWGOC%IdMos`=A{2#iWavhE|0RB_4Sojr~2BWCvam z4YGT=o0{hQ$-F$9{8D0zZmCA>lr%78V=Xl~0qvxSspVd?9owT7&h+Lq5?`grZ3Dk~ znop^^;|eB0Sjl5mpfUd+#oOO9wR|ICesXtEAi!UW16xd6N}L78MSCxkLD{GCK(v7H zQFo|kX;T(aA{mf(Dks@T+&iQ1SD@g6>8EXgJ$+LOMfou}Cx%)SClAIZ4ErGwu`=Fd215$Y&o(RT9x5cSp%O}G8~|D~c5DliZP34x802BkrI8@+=lOcZaXb!jWPJon<$dE56?Z0~ zF%6uc^N3O53?G_w;4xAGkQ=$>Yu*4!%TrK2PKMA1Pa%o(@LyIf7 zHsPL4@=|ll8dtl#nO*?aw2!tzIVAjA2k?t14fg7uQgM~vw))+MW)+xQ1rSyq3dS35sQan-ux zgq8N*wP{^bOzbZ*!1aW4_Uoc&gGh*rfa?Hmh~jkoWdf}=&CN}95E#7qmQyAcYLD#K zWoe?NZCbT}&!z$P&uk|~_gUQ!k|>YmXH%iudA8>7tGEV_IoWf2j)hy?qyl5A><4K5 zj`vT3ylHm(IG?^;*@@&q8K7aETHD@#78zsPbDf^IwWt0coasL=1ts$H6^A9zChlJy z7}(q(MfTrIiSRWoT8--G5Cb;#0GiK@*n|Vc{k-F5+|>Ks|Rkgl;gta{9MJ!L!8D?(mJ;g#%hFLt2Ix}ESHC{L6XrSXCv!IQY{t!fi;~w6T)^Q-H~;&q z!f)qMf**c;%p6APThuts(OPGFaGC^M>R*XiapD);hA&j1FP&?~J?4~=GxgbskZbIW zF6-xFSUl;HD8apl8RYRh3Hk1C=ANXy+EzZ9ZxfVyc1mU9eFe$zzT((gXn81wIHtck z8mKSI0kpf#(w-(#=C&8vSb1Bo$kV&+yOAyWU*4~=8-7+-G{7F;>?V+bXZ_TJ7JX0M zjXakXn3-cPE8Z90Sk~kTJ$@(|A^j?<)H0GQ4eTN zLu9e`%Q?T5{6V}G^G^9xF+vI7yWXwRNrKkJ-%X=~+Z{0-G)Q=CYNTk+ScKAjAZxwc zvWR=bIyRsJs^F+nt{I8|t&g0z)I75GF;Dxl8P@c9_49T#+=np|vf9;XF{u+~2}HMC z{7u@q{AYTkNCoL?uYE?5Ww10P`?l-D2({u(lbC`N=uG|gp8~tT z|CO~4?$35}zP}`>)06I|(lA_Bj_)J*uK?w5t<1v#0cgeg$;YO+TkZaYCX`GT${1E* zESV{|*|r_<3tP>!Sev90dVF;f)Cy7B9`t)phNp+QXS}alzWj+a7w$*2eHWNz zjK1AgJ>&h*tRgT)@4JJYXfV`hGk;a%fopN6MPv^g=~v~DSZ)`TZUN~Uw~~m6Uw%Ye z-L+el)FtI|HVx}w)5M7$|Pgeie}-jWx!RX%DL!i0oCDPd*dfU6W$t( z{TdJf0}T#dSddx^>NPBVE6~ZgD~N*;NUQ;Tb9rBtlX^OF!(J9PRZdk1eSTR61-*~` zPLU8x9VGpc-PyZ9>NpbW+yN4^X5vY#>M%6g^5vM3SZIDo_@ZY+TXT4+v>4jMlP%Er zy;?pMnS;51If%l{y5*h~;`EXD`A0Y>MDM_+Wgn<3f2! zxDhd~E0he5RmotHX=9sfuz*hzxfeg%8=UAk&J$I+tu*&MzxwL~O>rZ8621H#o+{6+ zs6-@s>3;FhR^cK2Fj3FfVzyeSh)_n5i_5U;ZZ_i7sw|6b?cHlSCu+@ZMIE7tkkj3!xfy=8U&bE2 z&fUukq+Q-Rk}?i zlhI2!-7)fbu&X=UKVl+XnA4djBI4=G7t(;}+U{$-7$f2vKCH_bCn;Bj@0I6Wi=T7@ zWq3FN3pzp}0z)ad6aPS-ok{oBCd8;RVd9sd%FzAdNR zKauB`BSyyKldti~Y#N0g^pq;nUp4a#+~?ho2Sk?3zM5HDb#BL-yuX6wCo}x|Z>-1P z_q7|21Qxxx0LzW)Kwdz$Y6w1Z#6e2^m2B~L%u`osuy{}8B+b!o;k0qiSpk4_)4?Fs z1*eH>w)-G9TYm=)76c(ino$H|oIOwuH{gTOYb#g9!o)YaS!;qjg~(R*-Uw8IiX|se zA^YfaH1#Qso3i4lJTV3Ts45idF4F=8$$18QC3!JSRF}S8yB4PMIZWn(jRk8Pc;XS5 z9S*vMJ{n7&+7MCTKf@v;Ej+u8O^NG$1TsX3ZRX(5LlMTX*KkU%+ViGohM9Ne>o4w5 zpD2H&qO$b1)@ZOCu~1dWuy=yJNoZbO)L)6u?q1x3N|b%VVuo`0TdzrLSs$N8zO( z37%y@DK)!zdreXEIS11}dLCV)(lQirX)M3XhBLY4z0onpU%NA-M{=w&;gy_keyN76 zb^tOTrT(kfXDDnR<~k%P-jkJYG=>dh`3Ri*l);1ytdL<_SP|Y~{mB|8$&ZP7DWB2e#@yn@V4+S+DrG#&MjGI@|Zj5evB| zspfcz(S3ZFef#%2_bTmY1lEZ}nPp0?RtwIp7kRf3Yvfzff9x|{M#EFE$3|Rwm2ZGX zEl0ELnqnv6W-RLlY5?s!yVr5d8s-SHp$ zx1O(NYwd%vrUCZ`?4~-E)g?grwVMn+&s29ND6VB?jjz*QIbV2hnqQ?m{ z;+*V6`bMw5;*n<8(fMKv|L+>O#uvq>*xO{?_FD$pko$sda!phN3Pjp)V2Xls;#|^4 z>&)m?-_!Oy(#1~$>B0>Q=BqcmPT&8CW4=#vr*~Z0Xw$g1L$gYT$4ZG8`0Jx6Cb{;ryt|maW-7KY1nbi2n5>$RhVjN{bJ}$Ctd{ zG{Awf1VX>#g;$qItNU$PBOP7-OTzhE>pSNoKNALU46ev->lZ`4{F@FKL7G-N?5Jbr zDxS>I`0%+n4L6(2B=(_vSAU>0Xm`#s+>@3TH~Ne^&9yj2d0%X^Y0BAk&V*UCLP8E? z#i;)$(aX<=32Ej1JKV714=~29M;@T2*|$8>S##&$z9wgtE|Ne9`DzPgRvj5_Py=?4 zYVS4Cyco>YCG9wPBcSPcT$cf08%TU5#0xjBnS}Vb{lK*$w`5@CnSw;Y+pKTN$CVOj z6WAXP2Oskv__mdSep=n>;o2r929jEeDJVsfglDr@W!5QRM(!X!gE^>S#Cn`RIP~wv zWxG)@2@)Z?l4^o-{D-8MVa2vuLuIcnEO)i<_xHZ%L5(ZBPSbX|*^e za}e8{{a43>RfzN27FH`*5{MtLIe=7> z`XG*ro1;WXG0)3-4Xh92C*#2F;S&!p85Swx->H0JfkL6%-CDSU+KroI>hi|zcUPFW zP|eziwy47B6rp@Z@z(2fuZvppXV^nFK3TIkJso@wP1(XXa`zJLpH(fskwR71;vR4C z4!J6aF`u=~_2ub2pVgC9b(ya%Y36g2bXQF-!Lfm22VZ%0%8bI(@#Gz+=EDa%WhTMu z1%5GizT!1FrW+{z_;=F*ZP)xB{d!vEdNk3y6P?VS*V6viG}2dm_^=p?$FxFk)_W7> zXSx?d8DmuE>T+Gs_C~^6FrgxYr*p5JWTWk7zFi{wJ}hn*F4t!Vbgt_fe}t^E{T_|v z{jPfN;d0bXp~W`RYPwP4VGF7Fqg&5I&~%ftV3~2tgDDd~CMs@|D2=+{AEXPP6lW$5 zCz>$kXQa~0!{rMar8?aGX_6G(j8o5-KM*F)w|y=*ETn2Y2>6Eq;U`kwy5geeO+N2A zrJ?mjBAub&+usE3L3y)C2cji=U0BMYqce#CgO}cMT_h!MMc4U!$NKjq;u~Vz~6Sfnn2NR{ba-oP>6ay%xLC*io z_WHw0INR^t9@9LTmdhe7G{A)J?3qr5(Y{(R*`$Nfr|=~esw3)wPd30nxG(lc&N0sk zD6VtJbwHciG>F<1@z~JAQ5UVTJ|9$~DCRQXwB>9aP`p&kpg{4eV;D6fN|&{EjA$7}q=!_iB))w~C<8R86y6#8p~@+;rp0ZL0R!2K8#JywjIvFdZ^ zulpT<{C}x}J1}m5C}N9^`K4H%6LH(EiOt9*$TqQ6Dl~jzI0Fs*-hL@be-Q<&GrmBG zR>xi^PC6C+_?bm=wGYWAJxR^lK7Mp*G+^1tovB{^nwpim;8^lianxel-f(;L)(G^3GyOR=p!ybY@+SWc&q zlAUVp4s%H?DPkqId(~K(&or5ObFDIe`1@X^TvBYXoo;FLW+>jfxM!Dgc&hu%r*Gif z?Sc5n?RdQNZ-07?TDwBW8XhSBWV(VSX4{(} z%X^2&ezAr~4)cv3S2O#(`*i11;>#O_x!1ldv_0Mbj;YHmh}CMMU7i|k9$3#)-2P0O z-~Ukk616Xd``z2e)9HWEO53n+uhGVo#A|w|PjbW9bN=J$d*N>gr{%66pQ_wuTwYKr ze%X2TVcB~#cg!ER%!kb=Z@qHqzxHN8jj$iI9(#=Ajpn6O_HRxjv`0#P)r|yxbGf+; z@fvUhA+WaGfF3o`ZGwz|vj&ko(*TuBDdYV9h5fpK&R*@XZ>wWv5DR>6&`5{F(C^ZU z9~^AiL9EfV;R2<2OZbnuinfm>Gur$PXIPuXW{{frI;DJO*t1J+!}{MbbB;e|U+q?T z^}sTAS`}p(6Wivu&c<>NQciZfg$6};?K1@5{`0Q?+@xQhbCaevPvm0D#Ov&kO=6cT z$$g_klBKxHV}SOV|7{Cl(={`fa(zXIg!|f6^taFWDd+>P+@R*WdgeDeWn^9F{7$PV z!9hx=7lxf#G@KlKNt>HtZm+rrjn4j$w1q#D{R{*UvwP``T*xAr3{rJ>4~aG%aW1;D z5&*kEg+=XtRb&&Ta?f0Xo(>U0Yd9R+eFfVib_$B2_bxr1~<@5rT{=T1a@1@W_XIqCu0mcUTt2yLI{V;Q*7blFviM3b@D>h3lD5 zEZF9IbTUd`U_qx4&81T6rtD}SA(hU7Kzw*2&=!5UphS>q4GHK5#VGvMDiDo|XFD%q z<(LzEjHW#ijT}Dzd0`gg2BTQkpZ_8dYA~80cC(*%9sBa_thX;1yh`v+MAZ3nsZLK9 z8$J)Tcrzo^^ycPX2sfH>%vmC?Ux@Ci!G-9FR4(-syLv_*QO_5HG{cPgoZPBZ-~?Rs z^y@4}(Ytbt-p?AKD^&|qc2h+$K8fs! zcpc_DzKeefm>ta6|1~fd-j>Xx*h#GY;f%)mcX@h6_en9Fd|-iR(B~#l+PU60!&Z8* zD`X&j-aR?jT<3m&mN2zA_rvZJ30Rl`#{WucF`Lf>>@oIkK(Vz6Z>ovu_J8R1og`23 z?d=ns`QT^imAs+0H|0dlrw8I&%>fVXUFO^;b7YD%8j!waOU_>P2YS_RM6|E${~f`D z7Z7K5A3urLcCW0zE#+YT+h&|u%58V{fkaiT zcJ5uNs}*=Z4#!(#J5HIcileK8GojwB<@^kEz*M!EUA30x=!`Z>^g54Z>n|?|BJ+RzB@wqLBJIBt4{%$EtdW zV7sCa(Ov_6i@6kn(+4XbEP=g8-ui)n1zeDeK0Z*vgw(`v1q)a3yOHpc?-MLNmj zakyDX`?vGU-JoL|c}sUaKqr^y;O$qt`#z*1^q96wvDsRO-SlG@Mqsh_ht1AghGs@K z2856!gBSrxGIxkA&4(+raIm}Wi}+w+(f`t&@qKRZGiU_9i_k>*ncIHwKmHW_EGeR` zKJg0m0wQ_}CzRV}Ez=B$EmGXpm)RW?faXD2voxOn01LQEQ{nC7;?hDM#X)aq(>p|Ecdf;qs$;Nt1;2v#kY%`) zkpK8p@_={!cOw>C?n5JiLn)3&jUUEO``?eM+2@e77sI;2@_4j+tn8R1l$j+#NHsS< zT%?Dm%a&M~i>Ww>=S?9he}y30RzHzT`C%hi1tCi<-pwhaxwIv^u;ni1gaklcek5(+ zThID@?uT2ete<#*Y)OqMl9TmU*IWzOhnd14QBA1vih|!xQ->5}Q`V(%lr;Q~MFhvE zi;-;8VDx-KzMnBGe0CI~#SAuQCplCcYm2>syeiykImC<0;jBlNJ4QvfqZdZXS665( zAEZr7F$TFP0E*ZisvSVHd!yw_hWc_Y(!-AnP)#yZ9+Ugt(I}fLBJ9`eJ5vHZes72`*C}lRA2pnV;Ly+JSx4LJiBDyQ0i4Twlf^ zFTYeC_T>9PahzOtkc47GZlf-dvKqHkPknCDu2LPR5Wry3;}b(^Z9}N?KkxpI605ta zilcHkY1m=umQPaiI#TZxo_1^Nnkc*y2^QHX+WUH*o||7iy<7W!s=bs~BDAaaIs1j8 zbvES3fZL-Wd-&elGpFMZGyB3hhj(zfn2XJoK_$k{<2=RXTF>scTlmiWI3fPS@ja|X zsDm#q7r|rL_LrIX!?=DiYO$LxIK#n^|7fB9&vq2Y`MX7XF1<#A$f@$KqR(AsD^X5- z-Urxo|C=GbCU?Oke5I|3Zxj#SBF~94*+m>UmNo7l0 z3@qlYv&}Xt+Frb*>{{eDK;fxb=Z90-hZB1==k`0gdNm#(ve(WNIgxx9b53ziBGYXP ztu_;OjDCN%3scU<=(tSki7~1-fBGZqn&+PVk!FMa)C}Nbpc1819Oxic!tb9Fp zJoxOjJN9`2=Ph#Zhvjfl9J8`%8t`*%TkylE^TE>o;}+8BoyniOnCQ;)V$;=KOhN7v zeqdXm%+sCx)!MvpZo|{WkLL8HR+s<&oZ04}1edYgx^i1b*^+-({qe@zt2N#~GxhO@ zlWdG{7bYES7AyG|X)ZWlJIxb_4^g>pB)8qR&t*4%wkp+K#ynMCa9`@?Ri-i8JB~Q) zXhk@8&TRhtFyG*iQY}%y-eTMMUhmv`0!lZHvoZRxUwgh*T5)(BC>{INmF;L@Rk203 z_JI#Qg0eMRf@aFZD;#V-hGF`N`@A;TznjPL-hanjOyxR{at|{_ChgCjQze`LF&5K7|d! z0k221=rw=j>&2L9qE9?8!HH1X+iznT#89sE+}YI&+9PA;ZTId^w1EStQ0OWXWI?QkjMORx@iP)8YdK;`f8v`@4x%gwq z%d6#&B3UZtc|@I5UVsyw32s3W^7^Q_FO3CXj-o`0LBS)nLDY8csQ!OAaoZ+z4hFx1 zXSG(r$N$2nZOVZK-NT)R0HQwlB~7&C00*~Ce&C=&avO_xM|REAgpkBRk zUqGCwi%r>z_Po$4c(rw$JXly{8x#&qGE{R{16JDQyXjQ!TlkH>hvZ-a3ut0J%IRP`tV~}?CLvg2C^rhFCx_(yjcqW1I6KxU7>)7?xt+jqMwd< z5(8ARo-yZ7)Xwcu9IVxjF;M9aPt=r&@vi7_5zvj?0!XS1z z7nNtSJE&<^rj=iz7SfmhtV(;{GRz4m1j~MexI!-X9!y{}>$xOVeEg|EYu05g*Mx0KZ=@^MHh87I6ns6?>iRH71W&0P zYrc;stama-QZWIZka)9GiCFzQKAd$3JI?Wtl3Gzv$r8P%&8hW0`+kV)ZTnO?V{o&VZ)Ia*pGr`)02Kz zc53}tFLm?J%c*jAY&xi};jkPR+ayTb?MC*RyXO5I1Iv;hNuKo0FJq_2{ziYE+gVz# zPD%TBckPSH_MlFO7$x*hqSwy`Lrwjbvn;5dxZ%t@FQcCc?3t~Nq|PKbvQ50?b}tS= zeVxm~Y+U^tZW{2Buy(>jD=oRWy&e1@-X+y!FOq@+$EQ^^eYD=^e16#7xLM+IF@KnM zgYy5Q{1&CF1<^M+ke|46*Ch&;HFu1VoQ)A~+wv=RQVcj^TD)1icj{3^?!u-K{DF$o z(u!&CjCWrU$@t@J-l&0OE)FfMprB5n=_9V6+V|4pf8`Td0N%#gB1M7HAPY`p;^NYd zA`mj@=Dnt@;|_NYcsa7$5Ih$AZxS)mbI}uS{vP#&141nU5o7&g{{|JsbHMXm`2$8arvAQ`T{c-LR)Rm(pX!kWhx>Q+T zDteR1`=8Ggl1atVXm~qsCIF>?2FfC(z2EDn-8Co~ zFN;JF@e5^N-zASWE>QMOq?A0{4hs#2ya*;r3eRWpXJyE~toX*^=}*H!e<%7faDxgo zrXfzj8?}4niw~;jNbE>LC0%os`8jc39od$Q+R|Rr#HkD_D~04CVlCrT9dniGSmwPG?dfdkC6j7+Ig?WlHmO>c;E0=H{$c`a0f+?Qtpr+Bdm4Lh zfKhDfMGto-AfRtY6Skz9p!8O0B{{U`18p=8*cr zb0x;6M1o3G*#s@m%@_B^s;@5k;zUlvEy;ow>gM|A7s)MLNs!NVkuJ4;y{^*@%kOzJ zbiO^6EpH3oA(bOi3&9M*vs7xpKEV&UnRKcK=l1F@YOC_hl=4#eEF!k##8P5^YB7p0Uh#GCbg9x+JZC{GEPeBlTq$zc%7V71 zy|dpdHXU!&^h_KOos&=ZD?I42LtWowy*|lZ7XX0r#u;N)i9%y2(uZI<?zesJmoQYB29fvgl=mJkSX1F&9JI)BWBR}kOS;BG|ktd@N>X#}~d57TFLpO^_5>MNg zqy@Ok;q$w$_s;b743U|~^Fa-?CyQW}Arip&4mGpiyR@8>PrLWz`EM_2q3sYhvmhQJ zskr`md(pYjjyb{g)i-2qz0|QF8%&2ZQT`X(UDv>4>)}UI_+m)X`o{3gv5(bZJ)TB z0kp-kS;pJcDPgd0BEW*Ip0g+ll%_^{5xs#w&!cMue{t++u1vzoF(=%zagC!#si%%& zJLe9j#ci$SML64xHDxA63$Jx!ef!|&7*!%YC2$hwBknqMHTTfES!l40~JIDO&=t^U9>B1{u0abyVnZ=uH%`~E>|J>HnTuW9! z3<~J`<4xwQdk~+Td7Q0&vBVN8nMDfJKwxdxTv9nq9_X72ic(Blps*v}cPv2JF z0&K3OEJ|5EKhc*7dxzQ&;kp1HC2;I0!JxWYzpNUKiX#pI<~gx@_8il3bZmW!KAm_( z*VdGqZ;*uI>ONsHG^SZXSGg7fH55Y(7K)3;)PG?Cip@ANVf}tOX8&^LyRxRjX2(u; zfQ!<10)9^MhOk%(^FOxiPAR#Y*#ISev4-;NC*J z(9jFqf`;%;07rbPi^P`VX5pDChqHb`+U5abn%-0NUC35^@6(qYg`+b5CRt>wWn~e+ zDF0`lDLLjWeo>g~k-2n5hS9scg6~T^mygk5Bg14?Xa_!P;l?-Tp(pA| zUMk0DBLs2k^%q%Bx+7cj5v=8Mec-DTwqsCTag9|?PGoD}xPme?{!cu+>~QA>evd(c zmogR8b*jE5X5K>SR|CuqIA0Je%P2R0OHu1-YKQrO19NK_Q`_O_X&eW!j0My}0cK`q z>)5Hl2GwjghA2-b=C8dQRxl6TIKi8>cq~7)9^60ou#*~Xw76#}DSaHA|Fo&{3$Ms7 z_O7u?A@+^;3!6P#noQ~FxLZV;7k}#IzZ<0igN4v=!wczMA-;rsba4nqpf&8=dsV%98Yw+)v?WOR5d9*0RiPrlz=z@Y{sixZ)e zLH`c?Gqf*Xlnq|X_g4iO_2i@akt!Of;|xp;HNtV&S|eTvfV#3Mhese09+X|bU6_sX zp|YHVUcZ1pd^<7!vN~r!{~G*;YFu}!bm%t6IcL2Gnz4iFaqCk5oUD>*#N5@&o(->& zBCg=s^Poy>^f-MQwX2-eYyzMP;XJmg z10G)CnMJaCfyKQqx&+YX5X+rZm3bFGbt}%KRkUF-0cW@A2f;dNtB>0c#WH%86hOu>gYZa0lyisH)gy6n!S>ofm@DXZDcMpdhhloNvsNO9`0e-K~XY3jVe6 z-0G*Nd?w#U(V57i;F45JD}S?=C<0mSQ@|CzJ@8PjFy}(4KPlYR&MCxzH%Yc2NJOp| z8L~ri7y)h?L;UVgepn$P^)I?9L(P|C6uz!>^ zaRL}##6bwS@#UO!PP;nM=a3N~@bgRy0&Vb2P6Bi$@40L{~bfC=o2q5$>K}$!^ zK$lF$O6K&?Er6!KbQi+HRb7P8@zu!jr6#vW9JECgx>kEaK8Q(IcSU+;-u4D@Z#P_lwd|==KOY84OmbCom)fLHIbh zY|BL~$bre4j61Ge(MM68OcT?)#|0i^A|Pcc^7VIYYNwVTQN7mTyKE-;Z8&_s=*9yg z^3L4KDynv4a_Bl51*E=w6^@Y0P6dA28PcPb7Ax%F=PG{|?jyfIn zt-lp=<3bj2rtH^g>qI7`8v*waOavyKXDYXy)}~~r6tF~yQHQCZL;lip`pXLj??qy1myH@cIFcPWYcZQ~L0^ki}2fwsYBE${teTGMbtm8g{Z|;qWZ*eVQ06n_O@L zBSFpEH6qozB)^2&d}Re60l->aU77E8v08~`{?RYW5H=(4(fG*%dCruCxS;P=UHPnl znJuFZ3(x0su|yUya~N|bJ#U~Wbo5BRPUQJO6p?+&K+L|^-Q?Je91#D6<6(c&5I0Cd z(~fFJ_nk^BlEc0vAoryvEiJWC3G``hFf<$tsH{!^>QLd}__JWUz(RN{(7gb2ZIN0G)=R)z|V zw6)5~U-M60n7wI~CpaI84dSJOZy-72wJWjEXF%|qV>WBFvKSI>d+MY=z;7%&!F!EQ zPhEN_bL^m-1L}G~n_zyVZ${l!^KSvfedLdD+_Rcz3b`V-vTh%xz%e* zZ&b-s_@cFs^42t}3dw2BTQ!=;d^5+eWs)pxpQx8$oz2jgD+_fD?`?yPXw^`T;mV@Z z<+T>2W)2?>$5>6@8yAZeYZd&gqbpMolI)h71-OJcBtPkqVzbQ}Q4LTV6-#)gWkS$v zX(_wH{@4-#?^!3Nr2wF|u4UWbIb$K1p(CjzUw}-YI_F4*NLzf^3gj|4z%iiIt4w1P!p?_+tZ#zB;juJB&Qwy~fx|R626&lwVQTK{JqX>QJt) zndc&W-E1@*rJ)2M0NOqgFSG;6z0^BW|AKv170iHgV+Ez97C2>k{ZL`c=;@w)EkIsv zSv(NSf##?PDlprU5YlwfI#@#D^2Z_?_oEe?SD%HUzj%)#IlVdLUvqx8?V4m#nNS-$ zsnO*+pbP6Xt9 z?44b^rmAWrXloO%3WB8tCv^?zTz@NTyC&qYO%?iAE3{27+NPA4a>0|FUnT5;SCuxM zd|U^0WHTv*sd8i27iEjmjGsn7f8{deS^0M585iwsi1;mC(5|pTp4{aN`2Rt7@kih4 zjTr!54M+wOCx!%3CfrTh5ots;u_UA@f*2#AX6-Mk#LpnM$;cDAl@pEc4d zP-h11`q5E^2^}9cO6Gk<$);LVd1R*0P`TUYmBMKp#>185VM?H>b%%-m!mhugn1-7i zf{>$j{sa?K2z( zci5LBL%nS~hf3JsR;CH>lAu7zuUJ1q_i31Jxme2&8j`q0-2Pq{|wiRrsqd8}# zuI5Clgla|h2Q-&W)!LZ=G3$mrIGNKh=sk+=F(UgA3bxQ6h6?mEe5-R?6m`uyAdfGr z(!7+hrz<$(D$B3m&>^0KK3wFLydzL!n4n`lQTLzOT_C;tPl(?F43A zEYZTs>GFq_LSrr9*LkDKEzkEN@kRyW{`HR5_|NsI=3xW$wN=`MZN5-~4)Rk$4^Q*C zDmADNr%;6=Cfp_jxsC9{i&@+bbqYfBTPszr=L?mnne2u|@1IK6hV!7PJk>OwCnci% z6mSgqq_r)KNq&LHyQ7w6>f#7Ph6=tJc6feTd=G$Vj3yb?ON17k40jvQfV~}lhGyYQ zSZ_#T?Nt4qT1C=fDt(g0IF6Y%Cov1==a)HR4=<7f(T}aSy$FsCf~U1v1Ol^FuGXVWx{>BsNrG@J$<`8Y#_r_%sT%`JicWAzNtWN>saGh5 zG^iUa!MLl}Oaj zSlp}AcqjTNA0+R4?TY)D#@afe7V1e$&cn5zb4|JregXgYh3AlS8N$C`%a;up3-<`% zmz*hf@8ZgnFDTg+eT}1;EW*SNu7d`XnM*!rb@VH^%<7m}lg-f#-gwiUuiaLdL5fz0 z)xftI+8njPXSmB1{f`wOs4w?I9XFTKw#^qPL`u1^Obu0(upL=~fCI&VEO3w?AQ-u` zUMZxZ$vgXa$1@{YJ}KgYggRMIilT=#IG=pPFZcDxm&ykCs2j)Z?Kig2oNV78O*MFW zZAJ^hMHP1a|sI4)W%E~peQYsO%hffVb^ZWwbjQ#|f>7s8Fs3Xz=1@Q1K z!9uRwp}ggK6HQL5i0i0U4CTczh(OJIaSF(cuc~kXjZKPsau~zbXevjzS$O`&X zKNVHB?wx1$(S}uLp(JRps#8pub=@VD2YmOO*yxvrai4Ubz?$EsL1T{AwP~vIUmMpQ z1;(p)<5lx_#RDGdAaET0MM9HTy&1ai;6%_EUZ5%%V$z$$)N75rWnCBK2vA@a*KC1% zuJM=#O4Kt#CaY^T9)NTEz82Voa|8>^?RbRDN+%*H1*mJ(H+~)Entx2Ha|=xSa>ctN zKJm8uJsQdH=TaX=A8JYyCFGi_hbtf@^KPN7F6B z-aE-+*=YunT-l`~(s^3$hPp|S&EexeFcnf^SFc|F)<~miIao|LA%f2aQ0nYoiu~RQ z)qJ0gx?T8Smh%5+kQ9uM;I{=G_=#~4ZptP~WsIXoN|`f%qyax)d7D7Zu27!8&veJ( zEfX$Bz5*pX`g9=Ft@qU0oKh{b6!-RRzti?%G&R z^iti{0x!<|PaO81=CcQ9V*W3lFx-%*(FI6VKi?0oq#&>7Vq-L$L)g<28Zv1ShE}@% z_}oI8P=F-}{+R(a^W;-shP&)gcxOF-Zb{sSeTrb-ciT;hY~cX{WXuRMSx~Imd^? z%&_l7-CR2)xmjpFyL{t%xmO5cNv0>3j^Uk^xsA&&9Q-sX z=+NLK#sdoKk%9|*>i?2-Z`520o+GT7>^9R_d4ZAi{yM}In z!N9H_Z`6i?2niFGssLBUh4t2ps@fhT;_sHVL!_}CG{5@V&bQ#sgV1W+QAv z7~^9HD-N?J_-~lcU#+sD&7CjovLro_RI0a^Les(@ybA#lj#`UIKnoN;4WS04J39Ib z3EUyFF9uevBq^XTKHyCtUZuNls%~HK$0aSyEq{wTwXNnqs3KYWI+pInS-FRYrS^7S zF(F&j1t4a3)7m6Rjf(~orUkzdpmdyhyX*o-fl!~Sn9I1)LV*eCYm&ITaLtr|b&$Y> z+@a>IB(K*SJxnz59ue*3WWy1LNpW3FRdo6gtJu*5H{$eoE6GJPcMc@CMp{6@dF*Lq zdWbHv0jR9nJKnDH29X-xpek!*E7zTa)zA-1l0hStUFJ~*j)`l&1>}2c>FiqW zuB~nCo@*QA!A4_9S0V8D!AGJzE;HA zR3tBc9rAKd{8f>|35~||)yq=M4sy`+Ka9p9t+E9&?x8Dbx|3mFk&{l_t;=(zt+O@j zEm3o^m}jq^KU}&Ei5=z)d31F#_>~!4VqJeAvh#fqmc~rf6AMU5K&k|R9|&3!$@xgi z3%?1|hu!~VG$qv0$OMQ5Ln0JM@*NR>4O>)1x?zpo8b?$K1QdMXvglQnGot)fd;hUTzs%SG!XzDkarM@sBIf!mt8B~^#MD*gIDv$YT z^z7cWrlvnE%@YAmxy~ZV*c2TFQ{q#uUh3*-BeLPekiR?Ky zzYcIUbaE^T)= zq-B65G4!5tQh{Q-j&moY@glNrDB(og2)xEj&Jz!yfSC7OIv4^;K{CoVPM-AavtO)) z8}X;#YosC-oS>YjqO|E@Lqt&H2AKc#DZYC~fUsd(%?XuDz++ zdyiOYt0;=vwfEj5F@m&J)QnAp*dj<`6N%)P>wbRs>v_Ka<szSkBc(4_4Ja9yRDML|jV!6rbiV9Q^8zV93;IUw2_Te^D)amCiIv_vJ%| ze}UO?tr;omSN#(QPxUOb943$9PlT~8N^?xP{VG$FZzz{I7+}R3*ZjY&aUyTTa%Fwr zy2Rx$cNGo5rfTfQ>-`ywQws!X=3HG)V_T`a2EqtD4bXSX0 z>!Rq0(}iaWmuHx!0yljDXD)`tX>|p~5flbD2=S*Xw2#v_PH>rH4Ppv32BW=NBYL!J zqT+Kdxh|fmUscQAq9x-WX(a^!r|vx}c-)8Y`nz$)k$z|N(O^#lE!0naTEppn#-`Ih z$vU6wI1gBLN{{3XjALWUPRvICQ$d^eYJ9~FYnT6dyekoDR2KaB5PYtoy3lG}=6?4`iCf5|_4&8k&5aMu92Jxt zudjZ`AQ69?7jqa?GLpHhX=G&|6mL*6_1~{QeGlK&U?QADvG2uLgQ;qrBebMM?0JUX z1qK*;%XaAZM*sDM(}m^*)A2r=>+TrvYok$S5#3M4 zWrmeb*BfK>s*0oNP}cF6_2Ex$DZIREl}|Qgp8AMM)O_S=&bp~N9l zwOG!D+dVeaiZluBMl&hCQ_7Pmx09`2DNozfk|oJib~(qZCU_%1l9Y4_>+5q5#$cb; z?|bfEHF;5^p>0?_^~8t~mk<}g`0I9*9$i}g?Ejt=)q2K$@lJXGMW>_b7ETMHKq;Sl za(w!d&1Z4;_M($+$=XJaO660jIP~Qk+J_*3;e%7%!IzM?n;iE44( zQGfPGd2&U1x!d{~y0(4L>Gk;H?UY4sJnE5`{t-J5=?;K++r%0^BM@xpA#hiRVpZyJaHFEE8^ zdAIZfNBNs~Ra$yT9LR_JzDReuJv~ECB^5O7x6z}!nj6Jb-&Ev<7Bb0U+r`%E7iw+7 z58pu?ud|1{3pyUczxq6!G;feg^K~okkJ9*3PG$9t3(!cpj7RsDT~k#C%|7_{>`C9J zh4e)3x7)PsRkJi2RMf>%xaY+ov6K0{@vsI3EXstl5U;7^S$;z!kGZ4ki-XrxRR8Dx z)=Kpl_Wg5M-UYaTkk9Q2F^FyKTVm}F62X(6--*%34w>gu)4oG@#Ss`7TcN+7>9w)1 z*FcZ9{aU!4;X>O%YLvAvqO*>{vi*m#abeYVT&!UM4aeovSBNQs;M6!uH}&Q(4j3BJ zz-^a|#to;OW^vA(Yh^3k>ieXi$#Vc|RfK?YO&-A$E=HHh=&)J3Ge{A4T7M8XMLG2D zd5YnHHzIyq-W&NIyS&VpxZrWt`}|f=pAm}Y&y-iUAiMaGlSq251C#!A@kOdcnQK=0 zc+!`5?3S!N^l+>U<+@_;`WZ6m5&=@a>yLHk2oL?$s{kkfDw`PvxG}eT?@YSpayaHUxeipyu zpyVkeC(SYZT(6pq*HEcV4f!X!z^Qi;d^Iujha(F4^(i?Ys~-G9m@iNYAH!AxwFf%q zjrr&f{@h9j{;oC9H8uIb)P|W>GaE&$eZOVh7nh{^%w69xD^k_zo@(DLc6lxy8Xxe6 zOl84WG#X8Znoi!ZyY<*rT&XX5G`Y?8o^M1Rm0jQRJiPo`u|?2}o%_#X0SQS8k3$Q9 z54Y}NlRTJ=J3NH#flMK==GrZ{c<_7VkU;Rxch#4xDuuDqE38xxo6;o6eiQx{V|Os+ z9iq3)JPW8He%vxa=;#*Mc1%JJc&$#-dZ4_{;(I~c)Ft63v!(x109Hazx`Eq6XZUN{ zb+w~0k<}{CL?^}H57!FW-*l>!Jc)pHR~nUYf@`fmK^1}-9xs8Tm_V;mm39Br|6XvS zz)e2$NKlrP)iMP+_+)?om#(RMiD%9xbytx#3N(N~F;DzY_9|V&f4-AwRDEuU1^Lw(W>aU3MnnY;tWc#N7h)!9srFN!yXe?>*he<0H-L%3E6J`In(60ob zO3*d&P2JQEjXkJn;;Ri8GoEXcZXQn)59zKv%0tRJbsQBMByfJX&(+iRRnsDHAo=8! zF8lz~3H)cS=rY$@;~zT_?yDc1tRvnt{QN_;YF=D8o#8KJJ)r_Z2+9w4=Ot))zlU_k zPv6vt3_eOm=rtH8li}B6D1bSvf;~3%b%r-8Hjq zYDj|SGqmN7wN#dAqKn;Rnpw-(tpZL5xhcm8Z>GcVe!hqm%$PLQU#?whtQt3bLCdI- z@>Pi*{t#g-pO9jPeq~pHRUvX24w{CrPULEra{uNA<*_G0Gwa{zN#RQEG{kV|@Vwef zw30_f4}~$^Cy;D*F1!H24KS!&SQf%4a30a@YyLSRZq^Hk@s24|c9sI#nTfN#j4Jqz!D+#r^Nc7F<2rt$&#=NLLGEp4&Qf5NyYlSC)ib-*2N-IoNPI7}h zsd0^e5LaqDN5gxBe|z+7sfoJ|r+JBRDI#3zF$>3mfm3-VVyxE?`y-X@FzXO4#G}(C zWxJx`>ZwrnrRA?^B~%zvy?arin^vvU?ww(Owf=T2`N<0ge}#Z0+{oHcaMk#7iOOZd z|A6U2UzovXl3PL^gN4klxFbHx@ll<~_^YC>(fqccI7BhYU;hO$Gk9^NjxP>a-IseZ za4LT_XRcwOUm&Nfoqa~M%Ccj3Z!s(Wc^fiL(kA?ILBs_Qr*7Wo&c6fNCm+E%bn6uj ziUXgc$j@qwwHJeyBP%WHZbqD=oi?^`Z}_RSS>}?8XnXJPHL@n+0>loNpcYn#6MV(| zT(5adqHk<4a8eGTs1CT=>ZOPni;8Udpbv`;50k%eYRI;@PQO~xS$em=QnEiV;8lXQ z9e7crqipDcq)X4nMGl2xA~ixW805mAC0HYv;AW6~0Fj zo`ll}1ND^Yl9udpx7Qa}LZDJv;!;!iDB}o_$oVGFGxEXxB8_-({Dsw6eFlbg zNy-}6T1N7FExV`eb=xot8C^zPpvF&u-O?6{$p73QH5R2{H<_2}kBnTx7r1|ON{o=H z3!jMCzHETPB2U%U7Y)DK4A8wD=iQS{QjkSML=PlYsximHmpGGbi@r-l!DPi6dMkZL;@6L$<-X0f#TP>+N=8!bt1&4xzm1<{T88ob3pzOD z6Y30VTF4bi7<#}V36nZ_v>1x0+YY)wn>GgDk&&$a#C2K~UH!PX(s#J!rDH@Qt~@M0 z9U)OX@HFXpjiWquDDlp>r{quH)2aXb5vADBS=1lJw|lf#lCy%b$+q)70rEWz!Q4s@ zQc|`4Zisf|)%G*+!79(#G+yoai(Iot>&VFR*%u!8I2BC*+TIVD-73-;z4^C#>19Ua zX1cGTx+|}ScD!$AEoVBu)V=;)<%>Y~<-2@N55e_TtEcfJH&PGY-)!EIP^Gx>lLXKAIl-P1n= z&m;!tX)qgj%ai`nX{W~rCy;E)MOda2`4Rc)@?sS}5FNkKwXE>u4yt8t|9sg(7~2rw z4Mwe93fql$skklr&sqH-F8NQyBr?kOo^fGnlyd^NLpOwfoDIXy4-q`pc%yFfKUV(+ zR^S>^E9@G|wHt%S3`aVH{{3xx?Sw|2E>AGD^5dduMq`+-zTY_6~FL2p}qxy##a z^dk&hu?D@}P*pBSJEg6mwV7jYry-)J7xjV`Hp#PYn!nNV?5bwwT|Qp(Cx1%|r?Fq+ zQ@)BAeVI@8tkP5z^FrrFeyLge7Rp)ZS2}q=gykkk$V!@%;aEYNAEHj*2lYF%KptpP zA4}=caXhFhy$4`r}j zd?|lSE9=1Pm~g~;X{zooNy`1q5ghdBx*+WjZl595N6!a-(&M^gX86c`9rV`x?4>ob z5?Tp7O((TX-q^=;YX@AEX}gd-%~Z3YxTf-7)#9t1 z|N78dFOsR{2;04XmpWN&3YMSRBEHl`HdEW&Q5A593&*O@WTvTm7QPasQr#S?oGX#c zE(m<^`y|^IFIiwqGLU3r9;5vyLrQJ~|BI`Sp?a|#{9CI@k;iHxyj$Tixf@2RoN4FS zQjmHwagQ&mk;7kH_c+Bo6Z48=q+`IRVA~F$=9epFHuP1KE!E|{x4pEXUcI6C@OKr_ zSI1h^Z{h1uwN>{+t|>)K%5oe?zb6euTL9VdheQH{oEr+%D?~R!~f~98hoaZ zE@^Xz9Is+5d= z%HkB+_8$ZAo+p$EbgWq*AfuuUL~#~FgW9-@vccLJ?WP%N#{?^&?n8g;$cOCC#e<#_ z_5W!V18Zk*QyU^-hA`jZewB3TD8~!NMQ6w-{>o|SiNIb zacAoL=d|%wZei`emhaME+~X+JLp%ZVq)uSL?RM5EoqoZ7pJ9%DtN~9l z!%oLrX1@=eIjA3Kb}{{?w4a=;1{)@SQU^A8)V`yTCbd&fm{8=eC(x1pL~*|N4HkC| zT5qi_MwxBh@osMTQdkit>%%qVBx7C8EI$;#0jXH~ihpjt;W^a>pfYSQ*Djr&AZ?Q} zh8x}-m1{4O65bztB_vBa-Oo0BDeQQnGu`xi-uyY0Cdn$H^B&_`0SCEKV*69ty?-~w zmYQ%r?&Nj<(2c)66UG3q_=TjxO~g;khTn98{DDc zvyfia`F%UU?7mau z8!Av}O0cS*KY)h{5?dzB5Pc_FAx88h4^lH+K}Sy-;QlYdQUTxI-4+<@qCJYSioa|2 zb4`*}ZR%QQNkrtulQ6tPJ0W&e9~-MdP<#8jJhq`CEI}d^m$0rY#loi6^P-POk8$dw z!&^O<1)7!zgGnpno=Y!7v0lyw6F(0Fq+bRx&R6Kr8I#YSGFp0z`npZ4)zo8r$P0Px zq~rDd{rM!}wLvFuXd+G76O|@TMJOFpV;_A42So1~xfe28&gY>y39(Brpi zGGtF<_?nJr-OL~F@-bizTX}vCAj$DtcUa!`FE1H0Wu{RI3_II2(W`R}aJO!{4ejw4 zs*YajKr46!5LLKo{vW^Dl~_#*T3tV_SxdEMPv-p)Jx-t?=D#-Uh0LAEI>6$O58t(J zPP`kUr9@TtTaI<-IJW1H9azS@7K}EZQc_`48hzsMR9N|$iCKBs9xq<2!f0ZVy13of z$hPc#P-Z+i>dsGya_sVCd85LMz=4Qj2`3Ff?S5?T%HYea;#v;m(m}Y|as@k=B+SD0&{)a`p0`B5O7p2+=-lk>}N`iXYKK zeQ7&+oqBtYRsKFE(W{)|Vq(3gmXZ9(h)G~&Mi{q7BH+{-dbr+;RNGC&J$1Hpk*#m7 zF4759;Rj;$roEc!YmMvln&u{+fFrm)<+_Dfp31Vo6eO5Umb~*IHk#>vVzw#P_BH-3 z-YQ~>m$asad6}|cea`OBMN zhq=qZm*>N?^P@E9qY+YwR6)-7NL;#l*)2j@Q(Rxjbq91l;$)z0X2)PN#VFVBP)e{m z_Oug}H*YKRqGA!T###qAr}cJNrX%*$Xi}twePq(L?OTz{9M5gIl$dS=?iXt%X50;dUNGuCnZzbQ1OqM$grpXAr&t2!f26~ z=LW5#iG^7%Yq4e0Pv-x;Zuz&-7EL?7&?d_0kG@-@b5Bmc4X1V`}B z%md+~k=c}tYmpl*ev~vYm!GoE5j-f8&}mtsxAHCF3yNeCc9@}`!;EV(&fD<0iye6D zOI_!MCTvLcD6VJrc|ARzf4e|;T_I7Hm8-}~m1s@9Eb(qrt*n_|Q?tgP=DtL|RpeJe zpPl-^*{X`qj#{Kykn?;kiv(L-Uf}h*TK?7s>#IR^!))RA341M)B)k))1?Lj2WXDUSJ_=y|w3}It0x_P@><8kTNuf@;qe*Qea$xHXBr)K`$BfX{|mDg9xxC`IY^GJl? zx*y*D@+w4E0wTJcD=M1vv6A|#(Duj zMU42^gaJcK$K_G$QqARs0@J;(eJ~_B{^k%@%bqDb@MqcWXn8nhxMj;>*((M_3X@;L zJXVCnc|3{}&xfCf8+REGBT2Xm`2o?A^SpiB?SjX+7?h^-c@;@#>CG;~75=vRU&_r` zi~FNX%d#()A|ZaTJ8DkHC}4`V1e~2!e&ahcDXJt@!=wgY`*@<-*bi=GVqbD^7M5cT zwdo=EvO4P3Ni(*{fAyIqcHn6SHSBLk{FG#^Y2#B(J0USO4Arhfzq_t?%wRPl#GN9x1hh!et&_1~V8s@`pTIik7rW1J<%%4Y%$=8y0~sNK`FC`w^Dj$w`=kZ| z-SYT(RUsN}6@;1ahoh=5HxT(%a|vX3T@c3ItUo}$Er7PmHMCRvWnT=o&kuO;s8>Ig z5!dz<8SKmu!mB_8N+{&w*!@ko&7<=*1Lu9GoCJcKYu6T`tIJOmcG;g9*J7%Ox#(k* z$;9NLCH0p_0|!}lI%9xL%cC?Fa@aXTm-|Y^yDz%&h48lfK$~?_UBDs+!s;Ikr#pcm zlllndmnIZQQh{=w8KKT_Bpttm6PG>b@k) zR-vd5o7NC7umalO^fwVD=ccyob3mM?6Cn;I;>JS+PVGS&ptn}y`9_7`cFcWk8xxy2 z`2xRRHh!neV?qNWbibPQyL(!1)*=~=;94(FmQBn!Ez^y+`Rl$LJ^)v@#W>QjNg)E9 z>O3Tm-p|Y$4v}PsPFf4#Jypnh3ybmxwRwv>G`=8Qm5?ZJiz0gFZe$sf@eCf~zInhV z$T!TQ@gSsz7+zyW=C!bUjacn?F%I&7=DbTXUZ|rk0?kbo?A07MRJ_v`Z8Q;3em_IX ze7~9AzqwG;;CgeOQ4;El$`cLS9zSHR>+a?A8^i%K7w%flh+mr$fHfZe;;0n*d&=k0(9MfO*@j z#{O)yTbH`f`Ce!$AgQcvHYWjjF-Xk-G0)fh0=sf$h2hw6KwM!0TjQR)X|(4D|7eCt zT{4#P8p1dPYlNDJely9fs9>byf218yL(Rf)?nIHNt@4@u0S9Mekc}OYZ&QPA7lx4v zci}k^{aIeX`*B{@rSJ|#Uzpz&o$MTs=kR}KXsm66&_2iCHsawl3 z#1-E!8!c70Rf)3x7q)?`HsZ$edC&A$tq7PbRLZH3KVw+1LaQ#FZ70{wSCm*+46&gH z2F7#tak=^LioG*8MHaY`=i**zJy6}-fQ>>AwZ7$sl@r$%sq$O9v8>S z7JRWY>0COswG|7jLZM*Qj(Aw#a z2Bx7Fm#EU_;~zN~7c{Hw!m`LL^0@gI$|9Cvqe6Da?C z(-SfpXx7@!1tbpRH+QY;oY0@rJpw>oz5{u_+o4DkmZeeXh0g^`x1!ZaPwin!c+0FH zVXH&+ochX@{HrR?RkvSWR=Yn6-MLz>^x#7Xr>Z9%f?L%+pZKK_-fSmX5KI7u?(an# zzi*god|wo9y*l`a)sddHSw6kVLDzpgqTwz~UYBcS3f$$vyw1e>iY4H$EX&;OBg4n6 zdbzK2VmsUbUUS?3(hPF)(V?l1B_&`cpv3B(rCYw@n2R zxhIB~kQ^i_{RO*OS5F?xfZvHc;SD9~FX80Kg78Ht$cH5^=F8-MSRAVyB@&4~TWyL* zLBCpbm{v1R!kif{Omy6HYq;`zD{9U~Pb}{)&=oZx7za-NGxZlZrm;w)?^#*>GwVU<7$j9WsCjMPJBwnKN zGP6&vuE9sdhkoc+n>y{JhDGCJ2nrJ7-`UzWorn&+-<3BW(Oh7;Tki{ z^=6}KE=ik`P;$66@Mq3Z>cfb%suonKzMF)DQRhy_@rBz_f?eX^Si+z95)(8}dg; z*(~dqYB1x_!fFM-Xm<1M7$ZK+D-(w-)y9yWZq4kuxPNDUUac~L7~tG$K@Cq2UFCZg zs7+=v0iHlR^9SeVNTp?sykM~LHxmB<5X@>W0TI9E zjJaa9@VdE7+__3%s@%9iFqOH+-o?)%ZrlI_eNgvQDs&NF!~Zl0zFZ5|;RG;O!5? zt%!zEE2l8YYfQMY9gP}?UP&N7Oy#%Jl`D8QjPY42K_@BIQpq2@Vh%CFz}@*=ZmH#CW6sHyOU?jbguKb`w<^KdFD+w$ zg@FT0w;h7o!l&lI;Oby)gx&2-ilk`&!0w7Ty#C@Y3{maJ++OH8-gm>Xtbw8pMZZrQRc&k`yoR=Y_)s&H|AB!HNu2@DXf)r}@c<3>1IVGs)Th?1 z;i?IY=^ZVojSHp*m~O=B6cOF5X@J9OT$pRyfr`J?%u<^g@oDzH$M__vJgWuDZBAY{ z2g%d6m>Sp#_esG%v!bTx4^P>m?+HmxwUtUz(F+ZA z;i-zQZ)vl>4eq+T7`z0kqTcpQxLRjF{_`~e zJsdO)M-c^E7zdVTD3t{0)V!&1A%(d5O;j`_Y9dSVa>CO4_?Aea6kEcaZ*Ln=CQ_~T zJF0ldIuv6>ql*xP?4?A~7~}3;*}ira}$Eo^@U_(Tq-=_$$_K!VSXSw^Kfv)i=&< zI)&jF!nHFcgO3~11SINyDm4{s;=i{$AIRi3uT|d=WGPu;rbWwuu&WG+pT4Q z5wF!uZSx$Wg+#iQ8DK#^LI!P~(USybkoCtWGs9QRAB0u6eb$2Dnu0i&08ZF;RH8_` z5uYcny0pP3d>1qa^U}F=ISoZv_+ECOm1X}j^LW?1@DaIagBx45I%?kB@0T#KdLC)a zoZJ^rzg1!a8|DFaiXpHU&HUD4kjMGenQS~$j6gU`JbWZlT-iuP*370m<3Z$2)KP)d zi_k9LHsYR>;%NGuO!iA|qLiG6-{w}QZwut4< zu;9(SD#jPC*0=VX8P}k9b~Ngo`P}w`5Ov@otPny#Xwh}pz42Exz<#Kt17FT`xX+ff z(NrZW;&D+s@pYwnf~D^Tz-_iV>+5x1ue{K#xH>FY0t=Za^U^~~ME2r2X) zIg0s#A?xzZ+-JlcwT{bnoc-GXXU{wnuUr%d9-WKSGM~<=?_U504!PiG8X}Ty@{b_R zziJoekz){SHjhF1#wo&cmsQa`kyk)1#CQnw6kkNMX-6g$^<%>EM_e=`U62NkT3hv5 zIQbgMS%RTUup(pfJ(aBx1Ck5c``@_4L$kn@ z6(vv7IfG9Z^~F94=m{v)pCvKgEO>%+vB*F2pHKa=NP5@`1V@P8$^??)o8Wx~pws!aVnB1S zmd~E7dk6Z6mw23noP%u;y6263bmErTh6yC@-zhl?gQ0CwL8aE(V~S^IaKJ#ONohQ@rm)jJ*79@(RkRNX-| z7g0*K$G2_7tc#mQh~-Bfz3#AP^!?$*{E)GNnasNW`+s?lP@BgP$IT0Zqr+llGJ~{h zFpHH`i~CPr61rY&z>Utf>4pEyjFEuyJ5Y#C&5b(Ahy4v%LSZ|9Yvlqht%=Q6hx=V< z28FH^z22LSW2O0)fhT2nY!Ea#RYy)-jg>SQwo%D8?DHc$97IY^arjZ4PvQh=JOI~} z0m~glXQCn`6{ zGm&&*BI<#xb^KB5vzXqWy=%t!5C5zchGqgpb^-ULm#ABqwH}_hJk^1h&q}qw*aM9^ z=4@^EcOU>UPn*3D)+~Wj+R~d9T$|0i^&=W~#)CD1p$>wi^$z?cD{PDl>hJF;VckIb z*TN1`Q`@D#K9s^A;r}7Jp~;*jcP@SP+Abd5$^dWl@hlhIaqG%BsTFb53Iq&};m6hP z3)nzku$z22DTn1|$$CM%@qw0(Jucni=EnvxVJ}$~j>+j~mcTU=QCwn8yh7_YxNC*` z{=(T-ht?6?cQWiIQXRU4nYlFta=0WxL2p zHavK~KL=pCaK(+tPKhs$Orzx$##Np5-0Sn3HVj6vgQ+41%qaXKpRSW*spR}NVVpH~0g^b{OcFLCcG%&QLv5Bx#uIF>y_ z2X_L2uHQ7|Mg8?u8x`XhJ_+L!} zTlEm!$Z#NnBgYG@;@NSOxaf;`iguL?p8sCNAn({m&8i@0Wp!=nyQz(h*Orj!4>eXd zq7^QAumkmpaP+stK)(UpZw~(K(np%Lak^wa%s<=YKy-6^h0n?Q4Je;US{IlD)N4M~ z5qnGn&E{s^m1|mmhn&oI)?gkK_njEKSqjhkZLfU7FQ4@Y#XP+ri}2yB6bkxQ4Zq_OoTFH#(X#lV^~q#4z?KG_Z zUq${u&kEjls1LP8dYGis$ye1Nryv`4(N1mcQ)cOhIRPAnE@xJ?lxJ$cKM8zWGs%pa zXSo8uA9wQjb)Bo97OK67&F@zOFtcS$PSoadqNyq%$SM7~@=^7wrZ0Jsqr)@MM*1H= z^?+Bid5y;PJu3}x_X^C>$}|sJ@V664Of94weqr>bZPp5~nH%yu>1e(rX=}u$Aj?na z!moTZEA=?AY*L&XQ71M-Au;tVmPtcZy4M9o4k7$O!n1kj;-VX_) z6EOY0TMt!OmfHGZ>ARHf&|u~k62d&|iz zgPgNBOSYVJrZqq%B9zo2je-Hy-Nu|4uJOGvCF7P@|HjZLhzTJt(*eP=t<#yu;%YX= zIjHVg#!p$KO$mCa`;l37on7^r_-sa(ZNuD_Ux9*1&9|ph%u{fny5m@WI+JGyha!2? z%q(E9oq`Kys}Q$_esJG9gNAEaH?Cg5kM4Q>?TVtBGF4YN#|CXx>V}EMqhKROtN<_0 z?yPjF~#yAZKEG~h&m8UP*;g6;o=}G>XMum0mvN*^abshOD9flwD`t}hys)9_KaV()*DhQ9vq_CaTs({C+ ziUn71x9H7_Ig8e2@g6g`8KWb})Y#wZn%WeVsfvxyupXgszw$Ec-NBn)WM|_A{|Y%) z!)yN=Kx7V1=6zCa`;4Z(&17od*YjbE%Im9HZWa66g-e?Q6*w_6we zcQFid_NEt|yntTW<$UCaVy6erZthhLLF$3w6Q}rJ6E;I-P?B=}#niG0`ja}oziGe` zBR)G)5V7A&#C&P-{Y?-2K9wZTV^R?6Njk0(^}PU{ZMJ1vW}tzW0T*;5>K+HgW5L{1 zALY)LF;_m+V_EmS$I_L`yTSg@ijs%aOzq_Y^ z@YCQ;Y?cT>BjRvO9-imnm^dvagzf?Jy1S^Cq;;5<`XKqLe5OmuXd0=E{V{c9d8h! zBmvEkP(N7s87dQcVI;BO++EwY#mFG;@4O{w`Xeb~$3S`;cwY-dDeY=~W*0jEE6FbS zUk!qPeNhy}s7DGa#&mQ+`2hoUDathX_xJHDMO6WyVxJSom-VJLAZDk9J$b%` zLt`@+_XtAERLd6QdW-Yyv1Rb|Yc#-Jf8BJ~40=GaBy4((9Yt-mY?l6468+D!f-hNE z$`eNPh)p$+EJ9GDTCftDa<7Bmwe4sy+%^U?oSZ~&<7dQo-H2y^18h+f*I;F3H7XqE z@X$Q_%&-RFf7+TGKE~>IuBMo;OnH+`&X0lSY*GgeSVz+aX&h#A;STRTPIINRAl?xS z`3oMInOkW%*33(5i0+s)ZjYJV!iw@+zR(}T??z>b0`=|(|B8kKTLMJv^AZdg#M%#X z>({O{&t|)ATH!*}B7nb);I4Ig46WXQaqNq=1kb_wd)7bflH>)woZXMQ30*RvD8Hi^ zO+j7Q;tl-%EyW)LETR0VED=)j-QAic_M3aK7tf4_3$I2VCQ5b-m#8HU{kg?56204y z$uA0SPARK%Ve)8m43El zH8WBmTj8#;TVv?AlpwkBajsji4H;sA1$yiACd?7-Sf%+{$&+UyUh`jxYe*OT)MCDt zc^CV-TEd{N4pCjOXKga~a9Gp;=c>A4F8XSC|3jU)XG_CDKZCHncLaVtwFTbKB+fFK zIh+{bwWZZna*&Jsw(Nj&CuZnw;oqFQOW!HDDi5=TyUC(=xU@|RaKn+D znrbd!X4}_9(PMAv_$|ko@$ z$RqKCsdhqC zIvp>n|5S>5saI88Vm$ro5~Z!p7dTo%BbOq4jjp2ky>Up!vHid$&DhUh*IMkyN&x3V z(6M4f!`}kdAIYICAus(L$6RW6698m#m*|{Ls1>K;sk5-HzsryM8cN>p04!0Gr)|Nx zX+$`wKs4ld+r4Ly(}Bv;qWf_Eg43Fhpfhq_6I}bdE<4z_aHh(Y+BF!XWJaw!ZyzK`Tc= z{uaymsaB4RJg|MOf8>XvV&pCA5x&51vmOElw|N?h9a2lW@XrvVLo#zLP;=6S)`J3V zS_|(nOFeTUuC(`uy2nhrb$6WJDi}(06LOKO5b9;zo!|NHRqFP$P_E#1fdJR4=tora zi(v5bEyc{`%ag-H!c*{KDKTU|GikI6O7I(lZe;I~);w;E|DPE9IQh|*t$A%$)@c?* zU)tlXOJFf{X#D zu7+;6arE#`0>QImJtH?{3oX5V2K8|FduL6WG})L?D|f(lWo>5kCs;`LMkfvZ3B`>p z(JU4;t*fG9Y>29f3dfDiUAWyN(i|?24BvHt`{#-Ko-EO9{(tPfcUV*D_CM+zM{q`z z@pupc1xH622}MDgG?hU{QJE1*NN6gM2%(2gAUYOiKtRRNi>QDQl0ZTTHBpfok|2^~q+_TJg=TJL(-yUJ&+{RXAY!c+TRQ1rCi zbgN6HR)um$QoMLWPaF{sg7zx^_PFD*56!WvN|1&gW{Yq_^p6%ROo>GNu~Mm~Jr-IM z7QMO17opmlEt=gDuQTQ8n5({(!>gvJJpwVOpl*`FkkBzuj>MZlTk3HN=+KvJg!4zs z$gC@Vu3B}E_p-arxaqo$xArX$SyqY@Oi*?4hWygT{N(#JpN>PCVqaS$hVI>mwv&H~ zQ%Tu>+&cNSIiKbFG#teTTumio3BQ2vmUGUuW1QKdz;k)_$V?>4-xx@hRZD*nN2t=^ z91G%ppPk1shk&%>dm{w3(16Z4^!iiz(U`$iUjrAv2Z3k#y2KmCqbQhLyew_a%vk!z z9%W=!s=%+}M@83&fa}H^2;<2YNrC-h9=tItq@~zcPj7N_Z6Se5Kd$JCzI};cbdK5= z9cci=)D@dWqgfjrId%d9e6=_&ytj8C-9)8VBAF~0dl{cpI<7mhcKO7clO zmq<=sM>#{gdUWW4{JtGhYKX+6ew-@4Zlxz`V1U0ce@ucD9-;z!|Nu-_=a(RAg#dKe(Qzdn&X)%I_d6Cr8Y4I)TL3hCD7VkJi}vxL|rW(px=_kB!U> zn&j5i z)~+Yco?}mxDHp@NoyWSGBb3f&7$d-{5i7Z-2Ekt4n;~MrDPUC#ultSU980o)*a}uQ zJSol|I4tc~8zEV@o>=BJt6NeHvRLmiT&SvD)_#DX<^((WN+qTBW!xu+YA=?X zeO6a8^^G@G3zprnxi?mZgwm-zhb$)DxNfvs7f&2nxVkz%EM#x0t$UBRIzBa=F16_n zEU!z>7_VtCkNW{uO7~OM*8FOdnGVD{PNz}^Hkle=1HwP*J_#b=^j)tXyWFRXHKX6dP!NbHz%!vh z6ItrTbZ_sgMBUK&hjYANjQrtD{Q~DCnw1Lt{Fxi%-Eak<{`#^d(339!ip={CiWDhQ z!F|3fUd0~sHJa#&5SzSFOggIxk{joc7mu8P{RKh|C1AMxu`S4o^;IMM@e zBuHkdqI|9Uf1&4#+hhX?__GGbd*4bhwD^m*(d&Pn$M4(3{DUV0kUHRT&O z2(yX8Woqk$UrugyO~v`raurV4VCI0`%3dQ)&+oc#Fr?r?TFryRl zdtv&90}<8+4j6KSWh9CjZ}{fza8Zg_EtAckL1Ak{38E~Q9jDlx6v)ih0OHAz~{ z$X>tJ62gT-eeOorAJ9ppX~7|V*tbj#PD3fUS|vm2Hy2@%fn)QO)orJd%~yHe9l<(2(-JgbJG(0n{nGJi_Fphy2G5i>&z@5mTPwLL5; z)V%AB+uai!96H8Y6Ef52Yd%xX&SQ6(3olZR8wi+0EO>~x`%SPt>BINOQQW`O$HuCs z+q*8Bg|1IM>#QrG(Eno}ApU<{#RYs!hB2emJjl zK+=45eV%WJ7mpLvFlSI|S())JQr6-5`NTZkmmpV*`55N=v|8r=Ond^d6NJ5*W2QH_ zF-#>(k<0AJeXHkLCer0f+V0@sy}#=Hi>o2^LOTON3!p+{fiOFD4?Q%xNAxVkC$%5J zWOX@iCQrS*P`K}KdPMLoH~D^OdqjJb)=H{ z)MGax4-1R>tyYVl@7kj{_E0VRX-D*?XnkT-jsNFyd3J$$=r4c|-%)d`LyN@2EwM}* zo-jw7?H2g-4Sil8+Ihs2+2)ux&~@FdcccNIDdzSb#o=&umWNbiV3qGObp(_!Kn zs7;@4ncj?rjK)})niKmZ9+gY8y$c1R=%f)$n3IgWO6H(+iPw!7j3U29xa^azG@^z~ z2Czuqnlr=!4E<`jd!W+4&>UZ4Qwn{7gI+TkZ0W2-F+Sy3{Xpn3(n)a+3D>*JgZObW z^dBHN+{l-eHD0UA{5zBYw*^Mhb><#}feLirHH$Uh*;R3(-pd<|d$|wDOzXtvx$ktE zL|Fi+m|eA%-p};ss;$v6Rd|H;5!98+ETFu2KvZ5|-2V?lTInVxSTz<%0?Z%0UHf}o z%s7CEloTIXwv3PZmq4Rz=iO}~n;V4ZWw~Tc4GmXHt*w8u8AmJ#F)!q%S(k|6jtMJm zF)eI~d0^+W$s=vp)#nj+p*R-q0g4b$(L>3$W$j=n5X%_12 zy~b(xZqhi{yc9JF3Y@4OOzL;pNIx7r%akmH8zPuzUhBe}-pS1ry@3gtA7EN~Dmh24 zyH*^1P+ct|P;1Y~9$CqL0`p{Q`WS)AU70o2+SkW&9rci#&rQ$yg!tA9bDcugc2+KJ zdZzW-u_3f|NwIk}TARL_FQ;sJOecDh1!P_ZuTx6<&n|VeM0>10@eCjNMs~D9?MRM% zjc^Dp2K>QE`li(^O~C34X7@{iV;_@0-?-)q^5&ug&)g-Mez=-tpp|I8dbgd|YdUbH z*82~T7t<@g_hfM?oaX-#=wa88F)Ci0wNt&A7kuguCo9WtHMXgq3W0nbC-Cm3RlXS1 zajH4JQ+8id8r{rL-ooIxWz1fN2gD`oeO-+Ec{eka1eFxGXjF*#vV=XVolXbMgnlSXd`Q~4VqfZ7m&BYA@C(n2} ztym`bF!|0nGb6=nkK&R}-gEFo@gW76XM&P5f@80OlzKD}%Ogf4wUxsUb%0k9Wj~v3 zD3w2CaMlsCVxm+z3zpa(Ma#S+6M&>6ah|bQV?zkPl8aNfd-yu`D7R_2E}QzE?6K2D z-5_BMNVR<~U5lDSjq%EX{quL$`ceUTGUC9(RgH_j^|YSYkV;2k+R785?6!Di%QyIv zZB_>&!c>jMY$m51pZ{ecjRpc>&2T?7W?(6w>d{Z(F(NG%a!qyJBD~^|9&<&1I@xFF z8QINDwdClmB2~kKuDH;bX-bB0r|7jcSNQ65cOkF$JKP)G{7Rzgs&pYqE$787;e9vy z^bG=)Rj;5zb8m@yXo)ght5sZrUeh; zE5~Tofx-_L(yCvoTUrw{Qffk~*V$DENT1*th^7zW63%ynEatLBGIf(3sq41-q7N{T zJ>C%tvuCeBz|e54CXDp6Y|Yrc>A6=kq6BK~aW!dIBWer_8MVc%A$@5;(l2;0Dt=`0 zN?t$>B{1`@>&O}`+&jwZCtN^nQ@VX@Kz6*)Iv)08Mln6Qyc-=iy-7;RD}Q51Um1f+ z0DCB1i44!L-u;eZ?PIV{D6L)F==RSFcFYREs)y%IDVh5JMyOd@EpA_tldw#LEfrWW z>q&!vRDaOXy*U#aJ~I%>f0C2)oQ)pWlT4l}fcN^8Gb0B!?jK$%O&nim=-Al0+PcxP zHNL{Az{UO69-lw{)h!UOjpp|X?kZj&5^;X^qxHL*{7 zENu_jo&(Bwrls%M{8&BO@|(3NT`R}FH>VOeIzGLw->~h2>_30Nd^=h{MCY`a&`<8X z6yNM@v3m8fW_pG-+uYchtlGRPtD2n^(shO|om2{6zOB}}H?%K#_4x~>k_h~O*US~A zS5;%Py(np^{J1!BHp_BwId^?Ll-?w!4ss6%bceOJyoR)_a3Jhch)nF%&;`jr?{dqf z1Kg_~U4I6C9Q_a;Cn67SoQd=~eGWHW>RN;&42HSvHvolHcpq@k--9rHp~TC|Qj;z{ zuh|4D80<}IOedAw!+s4lK1mwjWmxgDvm$+Ix;dN8YUG~u0}B>H^Ph9fKbLgM1Qj@k zgUcd=4QWDXdj_x--7%L;+VU501Xg{D^Yh!st;ZkrdS_&X^cl<6%*R7fVtu_x)^uy8 zaqWEY^>J2Kl2zPz0g;$YAQ0q^oGbP|ph90=kvnX97B$Y&a_sP}7#lyl{$9%LoJ<77 zPaTw?oHjoK6dO22)dIyGj-}%><=sVeAyhTm|4u|)IXRxoc=Oi* z^6;tvd%uDMaRt$h1(0sHWwV8PV)Tg=gM)w0Iz|Bg&`|td@x%<`mguo1`8ozw236Ps%f_^ zW86Qr7FMo;Vmx}X4Bx=;h)!js2Tnd3^Z?>wBE1YqTbN75`eR21aU|yvmwZgKTq=oHl>Ig?Fd}0MWH_MHB_(wv^qI!a=??OM}%R!$3aOB6DgTnuh*V2{l4qGKdx; z$g@32{-T;{&N6!XHQ+>pZaCktiEuP?w>n+ueZl5nYfg?`bO0=*d$S&JS$O$3jyx6k z(N9bk!N<#3iVs>8ev+GeIry}YetWng#7_h+429(bC>K4-GbE<$994X(;Ox!N)TJ|P}>1Px;h z>WXM8qDQVS=`jT?Mv8@aEORYJ4>h)zm*S=y*LaZWJo8A$q3q|Fs5wjH$v0~J=L}-& zWeXF1AjW?bQ$6QbIrNH-O;kG<NwAoIczAi_fS%iCAE_Sitt-H#jGPbcnyjxB zu}o0i#{3s++SdN%jnM}aZA536IT512EcZ35c}Q5_f0m^K?tS zgV(HMM}AJ=r&EDt z!>ILn$-xk@;{|aix;cOGE58WIaTEX?U{?h`-_24H`T*8CvN%l|vGOsU8`@o0-o* zgjBi1*;cj9W!YQpz#=G($}Es+V}0#>bHw2O{Bv8%ylJ)U#6` z0jRbG8*OHNipz5q-)iGMDVj|)%LB=My@#>gki%ifbB#Ci3P+qI}czy#`%JEsSS6xhPQOY;p!^hMTdRNb?Sj-&kxV zFHrYvX6^^cv7JNvo`Hxprk0Q8*busC<7&-FHu`gkJiiJ_)KDWc2*lP;t`aZbDsg`2 z6a`3Ly{(bHTpn|lrRk+Og?PG@F5?*Uxtu$r2nx>BZ{$*9^Q_Kb?fkhQz9C%_EIFre zzsyVevGYp!Rm$g7mEOY^zD^0A({5B}7cjwpY6ilO1xhf@$oU2B)So~;6gvZqR8jZV z%EY?*Kh1Xzh39pz2XpC%<0V9D$KiOWQ_nZ}J8$^P(pOOY?jVI9@gK$v`!+-4?=S|W z?iUCi8LVtgQ?Mz0qvk-uroS|zT&LlFw4`exB4A%^2xTi+wwdv^_4DfO8-763jbYNknm%l|3-W`+hib}nB{-b z+<*Lp@zOnKU4lutaGuUei=my$iQb4Kf0}wNlDJ`>S!9LSxA$f|djQ}n^aME{K5ItJ4{g~kf1m;F{3?#oA=Mr8Wmk&!===@z}Rkr^t>%kUOAJJPN9HH(_i8;^xDauck!TuYUlzY?0d6u?a< zReV#AC^wq9ca=DWGxd!{hV*7xAS!o|m6mqRuP5@TqGl;&zg&QKs`rasj`yZL?QD?>Zxrh7KyW6TMsyrpI#r|KY5 zjo&E6mjOLU9u`b(wsn(YXH?4uaij(fkeT*juxa^SdC(=ha>w@Xt@NP#AA&A=Sam@6 z|KPZ^c_*@d!|KoCu1ouOBMmdM!WLts1W&vJA>wPBoF z4Zc)*fOW3G;@f3n0v-@^6}Bf4?;u)`S>M*4Ll(`?fxIVMX|TD|LaL#3`X@2r8|WHG z*1bPU{;EgQpQh_`$0dD+v~1VSdHMRA&5KJ**kI>+BSu6m*LzmO(grK1dQQ_OBH5i8 z02<3Avs$Sbf2Zq4W217#H_4nH+!%LKv@pIG+-&Vi4u1?(-9=yhfT#cEsiuQ2?Y& zo%!l~L&(W-B1Ynvu)dB!&D*Ca{6!}D6dyhg^(2&nuW_9`Ilz2buwO~`ENrNub?8!2 zWg5=`<)-fO1F~PA%kl#3b1~Oh9TcyUar=Rc$NA-Zy6?C=N5%)MINi|AnyVScX3G{U z=VvSVvsW|B$fX$(UhydMNOJG!1EIy)44*2`=(*P;fqkdcfvo#VWMpIq$E+k^ph(h# zNNnl4Z>j6wcCVPaDPuhR@Bl+(?EhOp@4LWGzRJEZx9cV|2qnXiyde3vSMTK3|I=BxmeNbSA@W~6>{BMnB&x=(c$N(8Rb z_7(3?7bWFlZbmNI3-yPmB=gk;{Efn~IqAmW;nmq?k1)5r0LF}^r5>%dES02qbm5Wb zAqG9tq2lW03(`;T$$!js2Lh@y%q#X5cz>}*PknaFU55H->r@Fr<8L(8Y8f=5@)v z49)}N&t~To>-&yn223aF`my@f7vvEDie=M&ymPfBAXQ~AZXD#-YmAh?-f+F^Crhq_ z4(E=kJNvmNwBjhXKCYctecFs7nLJ|jQwI(-e!sgG8axwBZUD@b52*o#H)BU{nu$~^ zE&R^iqB{jGcdic`(iwaJ;;dag+@tGm|3u~*@Qx?aK+#H(LNks=o8Bm@1Th8cb( zw+Yqb=}uwYCp_-XtoHhO_Bq?+apl6X#|?Uoab7Lll2?0+U4)>zP#oUKz{H1YS>Ee~ zo37;}fy&G_PsFCFdUnK(d}dY_Y=1N;yQ89*Hl>`Vi-J9tQ%)VB&x@ZZnVxM_!=RVC zmxIH{vLj#k_;jddq$k;$p8$ZqIid9BC=XQ6cj~H;obH5BI&Gec!ZsCd7iuS;~&)|*D*w@%}2YB7OcN)ZBNCXUib zOje8LS9kjgd~O8gGqb}G+M7Mrx_<4oV@on}D$i&3t-%{;w;IAiDGKFNZHnH|b8HjWdN>g?R%I zzsD)D>O2Adap~u^SE0D%3(n5nLJpC+xi+1l4{kQ{cjDg6v>a6(w&JM?!mL{!`mOY#N*GdMy;y}|8TTC>Z7BamoY8$n_ z0eCFTJ2UQf^FkU-NqD99?)SLPmNxMIx}GS0${5l*$^haLaP9h9y%O-oskrvuek|de zx{j650n(VVu{(dSZp3Jb92B`B=MrW-^%u17+xj2T3Q#{1i9!0nyR4 zL)QCLds8jVH~zBq;BdeUK5Zc{Q&K&ce4l;=LOHAj`?gtQ%nbyfDE%W2>YQ?Y0I!2q zm*Xjq%Up;J7_JKn2*>YnZP7NNRg}gPS~He@B}hLh>WvlAU(EPp8@iz*Cy32(;kj4y z%5n@$5@D}l-`sy;iF+k0M)#yAmrYmvwJW9?HidELJA0R+t z`T&-S^{OQ}vL>vzLD{dVQ;94cL&fpehnl2XL<{J<;@xEm%Zff;^%bAgtED^rqGytP zBWv{`Y(Hs4x1O#G*@#VFS$Z~BdM)dW;4*LFmzX0Ju8sJhZH+QF_%^bs?MZ(KwNqv< zGqaa){Zk@kv@~X+O#yS6H>aQ%@nN<5^R5gJB4jrEGQhm-zm`*c5X=Z7ysc2~A|<^d z_SQ{uc=5^;@#gyKw1xW`pfIH-qdUW;)q@!+vn6(5=YV>^JQr6ky>FI`T$9f?zxCUt zB`sE4W#XIVY!%W3L4~w3DL}E=AemdP0i=FvF`>-)oOlKkh~BB8H&m1i zy?^nok|ehZXPN;JQ3iuhshi@83ihpCE7x=&0jA1ScSHwMR9R<%wLP-goVmug7;}zM z&BXat8jA^D#&9ys(;$_SpOb7d;oR;h)1D3`=Y1lVCDiWj4K^&_$d6iX_H4{ajpsVj z(XDkn*XInnw{`P&~TrXW+-))>4@F<7gBSH zJRNWlsl|fsA8-s&kxq1N3(ma)I5&zqMoXe+?vn4z4hk-ywr2&H2-Cz%Q4p|0xVRI< z0k(P%$|;pEt0hg(`1_hB_32{Ayg*Gvw?VRQTUqxd6~ss|kDXmjGwt=E z*e9&LmtR=3$VzFl&lP;g)Cl+F@Uw4rR*@#zGwo3qs#uwx-jM0;OnrVfNERF2M{bQyL4@mF>V+4CKh!bUT4%+F_E)kcqbr zet8n01wSkg(>p_C&gj!-1R%>W8|z!;q0T}-C!8UJt?S#`h2E^oX>uW=?Kl0Gx{ako zOv~}aYt7TUP^6X?5F#$#fQbw3HB<2}xxg|KwPr5Hbp-ZCE&t0NF}7J%#2GIw>tVG# zD-bV5WXRf2(_u6jW^i(&W8qj{uU`%uGu6=@*rE6Wmti6L)ECx570vBJD9S$baM0;D1~kg65Z&DJbK z!z~A9?&Sp~!-ycTtB-iPdf8>{CY?c`oy(E5D+WrBCjon6#)Z<5cg1Ftq&^SO8_wWE zuxp4090PKwMLX5XHRf&fEsue5z=&Y@_Hzp)Z#-D0Eq16Y zU*MAolv8DO-xlD>vp{V4xRD|d_l#6&j2a$G8BaZs2v~1$168MM6l0yU0NQ-A*yZv1 z)P}&J+yh_9zcNyaS2(+52=8n{OFD9z1xwxP&e(BeAb)W4X~y++FAWj=g_f6j%xkfLf)U z?L1D_1%Yoib0F|naF0Jjw@p8w{efh-xnR80byJtjXL%lcET&w%J98T5;kjO%^;u)q zQ=ID|=I~k*bo#V`MR4t8apk2;dsTiH=gERH@?Ts!!Igu)O17{Gb(MzP)R^-J9J(N@_1>)ujt(u1c^H(~y!YU}*O;Pai0`{cA5nl|ifaW68 zmyGyDW1F|@hDFQb@%JcO#wa;~@%&DW2k+hDn`~@omsv*5{7xlWyO+lyulCVqe<2l%949x90>ByIGpe;WlezaFwOn4?H*U-q^fhDmP7YQ|W98NQmz36_v_I zSIA{4P}wkl2^n+JTW zXUf01hhQ84Lcq2){A*CpdWG!8`IJHb-oafBTiuR;s)Q-bau)!^b#?3II|p7nsZS8j ze;yZ>-KpUVHzUGXetopak#ZnqziXSNVO|;>FL2kbxF`Jq%ZtqHv|UNFmmzp?bQZch z900QhJSLj|=mvyxQ)X*W`??T=tw252vYF8t8?Pv)|4ls2`?iDX^0hNAq<~X9A@#fn z@+aIO<8I}jy4MT9lYS;3RYz~~k5^MF`+nz3JrzZ7cBCinE8`SlLG)DmJ@KE9f zVA7q*^=pYN4V^y9e3ZWCiER@+%s^qdgc?1~NZgaH@SX%Pm}$GZa_nqK=a~X`^vIbE zf?;mWOon3BZNKsudkulrjB-)ZM4n_O`<%yh=KQb= zmx9vFFua+ZK=39M)|3YG+HXPDDrYF=H~c&;YA{z2(rY%n-zVvL1N2$=pT!c2X+n=K za)#cyrqZJ!UNUgZt$8KExBLE%!}3E$n{p*X@70?AYD8Q3Mf3|upPPQ4Ota9TuCJ7R8`k>Lb(h8OMq~8+KCP1`i@UYCsya}p@?m6rM=_Ol@HRdo$}<(& z{kCf)vLRiA5ls#PZMYfiv3dZbz^*}X0r<3^aLGTC2{+ev-rZT$AKw^+-7`@HY47J` z(E`okdQZS*3HHg?a<%ky^=wJ`Ubx}nBLw6?vIotv=M@*Ln+qYJx~nKKNWhgpLa`<*i!VI~QA4?_Rxf7Wj5wHIJ-;~n-ct9rFccoQ9Ib5$ z$$Co9P`W~&-LZpx%Ib&dw{F*G<)3Tec0bs7eULQIc+#V(N(I2EFEG2d^53gFy)y_@ z?w}dJ*iQ{=KK|BnU|=w8iCHJFE$pS264evtzTM{MImqM`%S$K98QeW=A3pkrE27=F z0RE}W`gx@uif>Cxjl@JlH;_iHElHT zMo{C6qWNcUX>ez#UO3oKh6qbK+fjq?+yl)Mx0N}*?-`_8I%7BeIv@hZGHpSe89E^8 z=Iaw#Z(>vdFh<4CDg9{6f$(>Z3qu?7?o54N(}w)@mVBKq&DSw|nLgCPWb1s>=e*jG z9Q4H7OD5wRQW2rX9cXCh4K%bXjpMgA_49MEYbQSu#(r#1@$o-Z;b9bk2eD1YQPE;{Q zJ9Gzu%QB9X4Q5N;Ww@?|vO%h%_L*`ZeOI4%*9P=2t-H!Vd%LY;D9wIS_31M~?NMCq z`rb+9bDE;rsvpJK^@Uon)bQnj^lFxgo}PMth5{F60YGM1k5#+@{IRI2W>UQ7@oQ-4 zY^88O)2XJy;wabmh`{R+vE^9`He}t)v#r?0(=bNsNMg6eKga{C1p4)2F(sW;Ii1%l z1Om*f_Ac|WDPzxK)cL^bwWy7k?YEe}?_D!26FzibR?ioUMJ=#x8GyCx!CIdo>fIfB zDW|4yst0dvBACp+@a!lUONbO+$#a<*Y;Kn!bKkat|MZ@$$~nEKEZEy>4MsU!2%Vwh z4-=tf#d*nRj>qtyJ{ZVKiuQNf7qMnS+KdnYr3|y0>Eo1ZJ3=4Wi-4Z(^(#qpDw z&ixN$5n_nyQ^n}%HKpqAxEnq-mrV83**k`$4*SoojbBD2UqjT3F>iK1pzMT8r_We5 zd5_NJZcr8W!udIK*v9^)U#J6mrF3!eZ%#T(V&c+Q(2%Ja=bN46ah!asS9OhcqRT?B z=}My=IjrY}+%+vdZ8LRD)n{8Js^mH}iVs1|WQ8zbBaM8$7>sVt`b6VG3VlP1zS{4H z`ZSipFRet`;q-eyYSd%@#S?fO!Z+RFth(LBH+b5QZlS|bLH0_-4UZWvBDZrQGh?2NP%f(^NR1O z=m*|h>f2E0#t?b%0>BBs*C5fll){aO)Rl~bP|_S$OQ%5la>POSt@+FdKbZvOB>hl~ z4Y*%IQPPED+baLhO^nQqc9fXLmXnU{0F>P|FDIRgcavbRb>r4ze}e{u13M>m%jF2) z7%a8e7V2AtF!qPmn)&uV%=j{SZg|ZO7g7Lp$M+kd5zgQ|I^n(iU6HjXUUMDPtv(hL zcOyAom2=PI77F(0Gzr;KBw*rZ0WDwkyrSZ5YV{jPw6gAE+S!wxnx;7FC0Fx+Ul6E^ z2)w?UDAIKWu3a_p9H>`MsGMw2(Tf@{&O}M-C94JIS-VjDF`&HcG9(n@mf~Ew+Jhqt zX>0Ct_wJ`zV4`VrOya10b?q@rz}QX0tT?xaIo0aJ$(V8k>;f6s6-3ba)Xx#PjpE&J z6fTgjm{7SDw9ntaCQE5+a5iK*`3M#BdsUG$egdYoC;w_|t>U`*0iAOuHu>h6vkfEF zjC(GAGV#vF2bRM9z}@qlNo8;4&V{dm-*xp<|F}C-qO#4dIUz*o_&m+fIlCEiPOrnS z@|Cx?0F?gz#%0?)5XiSInA14di&-bllXDdUO}BU(%l`$OV%H0i_4W`t z4VL$u7D1|L&-z{9m#rU)_5crf3!XT*Wd(xadM04@qEZKnV-Mk{3;dcWhW$XPQsoI7 zFXlYf>L{M;=-3m@{T|JM@iLToacvNCNO7mdx8&W=%zVQTg8YUC(990U)wtI7Y(CWU z(SQctL@?t6P9G*OSl}CZD#*iUyd4Y%r+0Nn#4*V;Tt`GBkoZ@)l%Uz@ll=O;fTEdw zMn8$LYNJ{^{)cG<|5|*Kfray_$A55@QwDCz$TPND@?b-IK%ioBco_VHP!R2)DUN911V#w%c;-ylZBxkqcV=}VxQ3F3T8R$iooXuZ2vEyocvjR3eWUQcO!p|*lahno^Rq$604&e= z7%FWJs&}5dN;o8&zLeB1t$;^DMWtAFZ|x)ly?c}LFT6zmM`9M4*iRVz$7W^2xL z2x%u02cj*#P--@zBl|gleTdpV+u(Qa|FooYO01Np*s#qC$} z=PVKR7j{>;6y~)%GfODcpRK(JWnzNT zS+A?d{FnT`I#6E;U7>TSVYkNzB5m>q!!E-I!+n5SWU}02&J=br??$xN3+LNdud2uK zO@DIK-6x8W9xE#py*qgvy)dAR*eC+%T0;)3l9BUHXe>62xmylL8t7m{{EP7tXOks+ znU*Ph%t?Gm8TSx7yB>NPap@o{H9I^>t>u*`kY*TO)8*&N>Pnx$qy% z4TB7Oz}M(`-Y_GUbM(1*$#3)XlfGMmC*9Nald8I!>w}YD6KXql%++x9@BRwza_?QZ zG2wjLL^NBgj}lg%(F5imrBm)N$99>ZV2_VI zDu~Y248+H(48&rCPRqUhuj^1T|IwrCF_Wt2G(a`C8W%|Lk+p$GC}0zg)aBE9^@O?A zdeZli^LPcbI$i(CZOO zf5;`f@_2F9Y3 z7EiOG9ptcxk@D^ilKUo5os|kPNYC5-mgBYY4H@<+8~pG?tRx*fj%FT<1ADIHz(nk8 zT>-~S$s89V|10n11z>7TAAk>K#xT|>VIz7apd2aW8maVx2?viUyq=x|JA~1$GwFAP_U!z41gK@ z_i^qd(D3W)alY}t?;-uSD{pFG7yj|@`{o9>ItSR}IC4t5KmGg59nx!0`oDUR|HDT1 zKZN|hAM$06|9hq7Z+897uK)LR(cjYbw{-n2U0*ld|JjDY{|<{$L;UzFw|49}FMIaC z47>mPX3_r+)c^Mxcz;v!w^IH8fKpw@EY0q!^f`Y2)!m(MNCn+@4!)?h`c}D4<}x(o zpN_UCt-iD_?r)Z%fR0<@V5;7PmqCx zuQ;q7JMPI#23;`+wKe}^wf=D6@6TIv@;4v0CG&4S{9o`vkWc=v!1a!A7=PP(Tm1Te zTCbl6(k1s^{2%fUsegao;`6<~`LM-?|MmFLRr+OITYu($l&%TbA0CbUCrNha^WUGh zSo1d@wz%;BLq7Befww6K{vN&cU#}JTUvC}%@2+3J>LE1)XG~^(VW*_ubCWXJpOZ?! z_^;MW!J!+u)is9FFbQRLHJUe|H3+=E95^(s4JkPHtxxYPI*oO!f!g$sa97WLp9mLV zxKFFpoVfO_lVPg!UqE!#hB_(NC{H>(sNNA5Z!MX??s2I<&m4Rc{Oau1WvaGcAOY`y zZZM7Ow zR}6*z`30`f_3&VNd`B?zs`rweFy+%eXC2F}DBF=mLGL$yD9Mj1G> zL+$vN7HYQ?daQ~Aic-3+`Y)ZPju@}ebYzvjTww9z_65&+tZ)(W%u6XH*$v0OoRL~> zkNZ{GP;ot6yiT)$Fan^z2>3tXwO)T2_ZK7NUO{znhW#D{=umB~SdHH4J?Fw^FmFjn?>3qVmK zzr9DOvRb;M%chHuG=_&S>TdD#-rj8&ZSJ&|fr`LmveoMChNoRNQdmrnOxUuPwh zcZZz23t^{_^?MZo6cZS|m@v9EyIud>er~8;!8vP00(W$hmrKU3%$(nE9FI#$)2XwAU<7+NRi6rQn=J5$G!V#-6r)QGVZjq4&`?y&ro%bf30H zXlu={Y36Qm>EAcWBTKtIi|S9DP#tRv9=p4Jlfw2*>o?+94WifObH(r6pcl8M)IoN8 zl+r?HBjo~EgT}cL;{>gXg0(GU``yB}IIP5kynl<&+{?GI)>fPM_Sq=Lzoh7&HTg1F z#`eSxnRG~qc6ib686`jYNVhK7y*1o>{B16t&PePk4mO8(>^h!YoRiYFD$xSY?qGiv zn|-Xu8t2@c_W@6qPx!pWzOZffy-T3%v8+RX%%6J_JO#T4t_qwuQvV%revY$El8ML6 z6D?0`f7PmJmu(?MZVx&nKU+sOUiA84SNg%1N2+~Ye)%H8rC)Dr|AP!nS*eef39`{& z)xaQt&QHm%Un^)%!o+{Ej^3Z?uH?ly;pP}`)a zoW_=ifcYG~qoO;zws`*UWePG>BO7x*>&l~DFwPeQ-*5e#+KDee=TI6@1d!*i2L2+; z=GVV0!IB%6c#qVF2!FpA!Iy#Wu-JaOLt4lg{>?^7#kHX`J@Xk_=aG$H_%$co9s=l? z=>uZ$^jct$+}5Dq(YF;%@h@3k;rN8^heU2UdviiQkNn5hnwvW^NRkEqm;A$La{BCd z>>;I|P$7+5`ovszOOR=9UpA^+!;fK%qY?M5jDq^nas>)sblkSz7spLbF4lS<_(b&m zun}?p*33<3eX;xQJvzs1T(1n;X~Q|#mQX7cZpC1h7})*5zk9nPvJ}}55hd<3Mt!_< z2XhL6FW4RPuZOM3Z+2~(` zJGYwAdq4X!lA-S&!yX|@4$SCn_?4alzAw4(MWx--G3YFnv(tJy@aU+1*!pQ~NUY~%j0YfCk}gKdkw>fI{s?C;q3q=D&) zqer%0Mf0v_dyT42oQ)SPD7|ApIrvY2%&Zo0cqN74Ap|xp^*IY z(NFf5|AGE(PurByiHZD1XTIRDlRS>`X!6WRGbBj_imYt0_}>k$%|fJf=t-7s$JWBrTlZ;q4lolrR3TB(E(!nu+4I4zW#WGeTf=*Ba-oNWEmGIB3BxFyLcZEfZoG&)DIFR3sPg zS;~tB_&W z!P_FHS0ppvydxcDoyXB0H#cxEx%*>$XGm_Gtc=si4dWc&z%_ZLTYP?Wa2#HeN2~=s zI`G{nnOvr7OZ&5XjpAXZUZZYDzKXj=*&j*&s{=oUU3PH5U>Fb^evMeFVI4l2sIos^MBr&8#cyW#}zbQ?xLS21cvp9ffrjv(ymf9~Q^ za*rT2yCww%zKxlzE21C2d56(E zh%iqMsDE1S(fc1?jjntnjy+#&{%v&u@7CVV9?+4DzWd;XB3)7C#M%4*i>s9v5of<+ zH4~ZjPU(b6C_38R*Q+uF+lV?U^!Pzy3~zyz%wLFC$RQTCbP6|-m!Evp7YL%bKcn;^ zFEf$jhXC%ZXc`=+A0agiRV%C=qWVw{QBctnF;5^k5pM(pz)?+%}B3ad1W9{Z_We$4Jea5o*=z zh#?yz0n`>rThs+(NA&Fn9*hvPR5Iq%KHu}-&kxjk5`phx0E!LB@XcEIkaI^rzBX2+BF%Q(2Htct`BX9ow{oN_N4iNlcor@HV8^2#klef}>H z_1$qOHj>N!l%HIs%>vOL$pv>GLcEI|F+W9X`H@(s&UcC3P?2cGVN~HV08A`I6csw? zbW<*l87go6|3?Ul%JK|_GUCmO5G*^92o_eZ9OFH{BT{K}78;ikK`R{yIv#kpUVanK z7V67sJ!Fj3k&8&C*~s-O_4(k0rYEMDagaV9NJ0*wYOiPhZGNY=4MhEZfI0<15`_J9 zp>W&+YytN15|?)L)5mrH2wByWh&?~|n5Qmit1ilGjas!53KlUJUb3|t9pg@kojDk@;lMwDBoO${# zzIfE3%5VQg?Q=}rhJx`eWG~eWoi153LU`!U2yvdAydWc#Vnye;~7YdKbyMv6mZf$=1Y*g$a zXd_En%lC8_sFLwL$ax7Amhkp3XsOWh&!n*Jt}Pf+B#4Nk`B(1yYewpap^ev}Db_f+ zd0Yg)i5bF&{B%t;2GLd#9N14%g6%*SVUzos&g;&55ENtwxJ-bplR9&7<6aBSejdd5 zSgmjB@qkw1>jT{9;%;RY(?j@6aRBgzaNd9M#a{@O`8Y7oxN684!ph*XM7 z40+p{afhHmwJ+`FLVc;=4qgKhz2QCF)KwraYJuROQd|;zqXhwHcrQispXM8M(4biX z9ZDbw-0?n-@bTvMw@Pg=o;ydkaSvQ3S|M-a%{w12G6O<}cb-;QwhvJo(G#-bo0*7P~n;M?VJ}OJ) z#dM5Q7@)owt#5V*F((M|s7i@^;1Am;ic4E#;W)9BsRt;as${QYv@1q}oMjRV_N_0U zgot~wc6Q2g>ngA+IgpK|c1NS@o_!Nk_KJu#)4&ez4Xu*^Z5k)Xd$x1mr%T+2yEefv zxkY}9D%R}6mz*D$OaO+78fKceUMkR#FNjozZKW@MF})I^(=z!TeA!W7kkRRb`fFhRgm7aoFkJ)XQMhzq^qsBR;yB!%JqJE^_ zts(z0S&u_->f?<;I7r||UlM+^Nn=U^^mCX^x>M>Gb;+KvN}^R^7Q8=(zI~HhD+%A{ zGo5rFbeB30N3j39U0D%Q%9JDwh)k6xpViWt3cLw!x}1U~No-WDF-i#!0goRSXb;-n z+<7#;g-`~*PX&So-wL7b4RKTMlLfy#W}m|t{XDl) z_cv2j<@VNt_NC|`EN17}eEG$QFUkP#-o!VtbRW{$=~RxTMPtK)fdA zLijisVidFC!w!^$*Chg(fv|0Y}jkr?XxP>en!7Y~Ahg&czHqGi~u z=Rd)~0E_O4drNSWk~#tKqSLT(713KKbUAR9od@`vo2mj*G=b9bqHxH-N41jgCAz^6 zv08x_8vsO(h?_eaUcT8wH3AQ=oj-(aI(q@!LFvHGfwn)IVy6NCD1`U*f7k_A@XZKQ zj8O=BzfOO&Ec{hJX%7+P;>8>P(t-A5w1AWRw`OMmk@Pog-+eEzauUAaxoGRlGTOHg zD_VnND3S5YwQgE1^+3@sW4`B{RN3K9RhlFWkW_h1dqy&56@YNL?W*uX3$8XvCt#3R zLza{tb`V2|ol)${-64QBWffRFY4@sPxq*J6%CO}`~ixj>H9`(KeQ|?`YmFq@sm<&?K zi~+}>kpk=a;y){vcT+Ai0st}WWS-Y_aKRyuxTXB9cV`}(Yn2}ZW+s2z)VbD%d=|cm zoJy9z?!jt$p;ZaUbiC3?C%ud%u#$1c6u!#x321wX|drpUde3 z@XHSwjv0UHVFGtzgy0Cs>hbQ3UwAVh)4b*!=s<9GI7E~l9 zQ|YpO9^3xB3htmR?Edu%03(RIh!B&tR|?6mUOxm*uY5@mKgkX1F1#OHT;b(-L}$T> zs4xdm!NI<~fE;07z{2J1G>|4KJH#Ow2oK^CN}3fw2Zy7^%w#)5RV`<9XSd!tx+`SZMAa&JRgM2NBFO{Gm9a0nRKX@cp%^s zuY~AGDfDo>>EJ3W2(hgPaYP9TN#OdK^=$xF<8_Wml+zd36fj6&Xb8QRh|r|*<|3lH z4F!aSGe)r9Tr6A_JY3Cy6%(D2$DO}~zMDG^>SrodvkrX?K^=s6!$=X_87|_~$`wGW zWhB!E3V=crUQ(~Gx!u2^4L$@S`fPX+0jfO+zdp8?)L90nvqc2_9eWxaAE~xlT7*k5 zzepvuq!amqOY}YXcc(Wic9ZfAg5wjS%p>AX?j<2$$dZZcH;)5RAR=|Pq!Wf~J!m8I znsx!45D`HnQhecbvJr|^az71h+r<$vJnK%tB6ab=c#mttG1+GP{%jxo4UvjhS~j%d z834W!VbrMD5XL7GFXH=t=m)^yq6)*{HAkg{!OHR<7M_9ywhVLR;+^RVdG`8Pt z6a4?^WScGGGQ3DEc`gh`CYPZ9|I(?}bNxdb;8|8z5t%SR1T>clo8NPk_UmVC0MC&y znkb@cq#VMllrX^z86pb855a~+b;(%Cn})^bU0DpT&JqJ*b99mJPhJOr@31F#pFu=2 z1dD`vSI|rUf)E@@Q-qx$x03(~Q4tyNcXuuIUY-vaBmW?B#6tuSTcm`DOS9J({Ilf2 zF3%G|1OAJzL%6@1eJbB}q3j3<$|{4$e!6zTtvhxriSD{vV2~3j9Y3cKt`B20RA!9fqy?_~-usPGvdEo$ODrLgx`)*}|>i zbY=79v@tSs>qEoOdO3$Ij(7D%k=E90zs7v&1%g6);Aa)Rmj2Z4<%!Gnt=c|;54a2&;(xv$Fu+P25O z<4_0$cbMzGvV-=BB_6c^%#Ik<4t0dL1bB`} zT)4doFF^QNz!FogK?q2;gcFs8!4(Q3WY}qm3$foaU}H;(MfEVkQG|jpw#V559xalq zQe|jc1uQCSArRi!CA{(*1yWeMXla|d47-^&A{~Q4dYBE2Pl7!?JhjEamSSNLz5$pa z7MNx0niPUjhKN(t=w4O^kIW5EQ^1(CqX=)|tHA#7yRCY+tdS6Bfy)78$%*%{&cIR= zs*HVA&$3W_1j1)-2JKJnU!aVB1S%YQ`x6cTyy~WO(Q4Z;vIK-s7A+umsO4Jka-x$e z;KVQj5i3%CQoXMrwMH+TvxrW&k(^4!MvlN%jm)iT4xW2^a0&7HnuqTI9%|*4*K066 zwy+snoFO2{O-#?&AfivvgcT2d`krw%%uJpK4^AQCIWsr_=mC>w1fn+|VkMuG=fR^- zuVMH($f4j9(rY1JF@%FR)#h@)ryyYGBplL;m|t7N-IxN)C7UZq+>uW}_&EnVG|_MT z{sG*pFx<7z!GK{%sp@u9nZu4fVEk33)HfbyHW-&w6>_L$z3CoTzzHL z45Rei&X_`qdy!y+qK-6ew5>>f1=*fRh8-UKB(hyE)rxG_5>DO{ST!@?i5xQs61^5a zX!K6=Y;k-+ItriYjpH2iR7EVo>;OscNjfMx>j!_KxMCr#E0-3;^zw^A<4#8iO{qF+ zDrs2pB9+>_xjOEM#1>=_jOx_q60%5+zzu8whKCf$@tLq8HDkspO1_t@c8Qz!K7--7 zClyJ1OV+Rf11huCLf`+YMWw6`iK$?vBqR0dF9zULT8%rYFF?OFa2CBh?u?B7vEcyHow3DjMoUY*AYdx+>ogr)Y zv@TKDI!m)yaGH{#`sX{ngrY;3&f09p5(pR8^fo_{fzqHrggD@4I`860h6~vq(Hw*Z z&U}L-k9yBhes42nzA1^EKBYQPek~|zGGM!F-R^SJ-g~|yyGx7Xz5w?@Q34395H$TW zB0{#wWIDU6%`|`EhKPz%&<_k*oq+0Te*ew8T|2y}(@v4EJpi*lC4KZXpV8TVlk81z zI08T$NI(Qo)>qJ10pkD2VcitkL^i!td5 z-$)nv<*lo?&Cb?=)*5jH_95_dT)<6D@~M6{%EJuTuoWJf>#>r`J}MlA9nf2U@J$lW zk)G-PNYh$TvE=HgfZDm`EM(Rmgk=9VcW2O)3L3}#v^3}N-(q@-V-e>BmWejj*n=KoYhxY=^iz z-HdNwgR!{qacbEwpP*IGhG$IY*M?kJ(obu99eJsBtC3U#cgd(?mCrzc138tz#HqG1 zt?O3(sQE)p^t%7d^FO#fY4Qt`4Ds$&&c7F<@l5Q^_1nFvT~+G_Ga77uO6Ksu4e2&u zWsWIjptfBAR+$w^?u=M>R{EGJlX=f!@3n)FF{)5F-#Gun=gg$;D*nCBV1vZvEhnxl z`_y^k+>W-HE92fktTO-dg#*mEkObz6{6pJKH+>MBijuV;u znGb0LJFem4FLVM@|5;nL9-azvt6s>_n<^Yy7xX={g7j9GoJ|kYgMi&T0t&gfX@v;& z_xqE@(Wd@!*q(5&{QW;Uf36*)kW&6mSX4ZrToa`e)m&}PggawD@DPMt>Lb(LLtu0= zoHy@qJdVX)kGR`a+9)C(Ct+MJ_>@E2q&;arB}c)zYXd1T zygmnmRO1kKSC^0$b?F(&N!w(~oQIOxR3F$@oT^lwV--~Ur`UN?!J6!-A8DR^0a<)# zK(hW7ES%MFRw%0p@d>-+xcBKb<>_twPhQ5bo>bu!3+jJ*dRyoQcCFRR>;jVT0-N4k z0o4kehLo8FU!D5=o-ChTqN}G%z^Qfj1~EpN#OM~_9tCxWoUR%5$K`h4txzcLApaEy zcqPCuk;0ozUmgY-<3;F)+BnlESch`qA?^zE*_-WO&Nc-G?5gtU&xQ2yOLD&Ldu2+1 zv%n5AY={IGB@P)PBHSg-r&TVw#to8RCgo77Pd`T4wy%R1HWvo<)X+Pu!@9pa8=fn0dX8UTZXx7_#}|UU_>9 z*f!(@ceK1RK55x<&_UGB;rOV%w{JFV-Nrr{h0oCM+xV_Olb|!!x5o8Me0;78f@Q+B}AGLr!V!-b7udbeJ=?!u^rYJ?ub;?9AwX zK^DmWb_GLYHO)D2Pj)D9{|fJll}`3{lL2i*CIr2^!D@A7c)&SlOMG{!Ati4AsJ!;m zTJs#!7SWXI)#rL&Hd@lPB>$lPQVcM5EY}j58GMv_oTGX9?qtlMvKC*1LDx0iM_B46 z2&zQ~6?Z1B*L;f+f4cVB*LsbX*~P-eh}N9-(URRw8AdWd7o^h`@Kq_;jtmWKFC|d9 zF_Lkwn(y12=raq%Vds3qmb!P!mb#~ECDYW>3ik&UqxKC(Snb~K6R>?J7#;QGgSONC z&h&#KMH*@BcnNXXjfw4Dq_2Sb-Yu9B=gNQV_I_NsV%ogBLpoIPesgcR!H0IICVD$* z_>lcbP0v$xFmG(-uCe3l?<1COasu_&(6f|sg^uo%5zAAs|I`z^a%(xF*RA@-B2xQANKaFMv!*yF0by};j$dj&x8pB zqdnmxC#7^_lN_M@XZMn%*zpOInTE{dk=*n;AE}i3O0n?=<5~Q=Df_h%^CPjY!~9}H zFMx$a!-XZ@OnjLE|G=a5ZS^9H4W)IXa>2~cct3GDrQ&5ug-gQAlx>ch^60VKS?HLu zu8$rLqp})IqQ<1~3xt?ZqPb%&)2YCoyBekHOjjNJom6YDw5*K&ylZ$0gq?Q>)%}2A zgEc3_mrIM|__Tgq;;fClCa$d}BqoG5Rq;5v`^4=_73HXl*K1DHtd#xYR*YaX)+!X2 z#7bP&#%5k9PzuMLN}Tb34%WC1@#-q=KQ7)?m?xjve#q%N1++pGK&EYSyR~dKr`RCO zYF*Ww>;=8oTr4vM`$MAN2!B?H6~dwAPdiarILut@{-k)aC8mM{Z1e@+c2=m3T@_m9 zS>?7KR%Yj|dCu8NVGXE`HH~5KJ&p5Nr&ItbnIJ)IK~?#ji60$RY%n3q{_ADYe4E^p zD65*W>8Lous4p8CqDY2vuG1Du5bubkNM$KkLB&5i0|ic?ua(wB|CoFBLmKZJ ziy7G7n&7{$b&(RQX{7$h{-y)wUq&&#TUCkn)KAWrr%$9;aw>f|I=?QsvFVHZR!ts` zSeuHMWt1edouY+KO={)9&1h*3qz<3zHJ32*pgSj;{%cP*^rQK)=TEE-olxeP3V2jat9d|33rMW+c{(6(kSf;EvT27@e$nvS zD&EWNN=q_}GH zwXrIgMz>7;0x9-s|2CPrV~u9(#ydtJ(O0ZDtp$GcR&3tr)^modb(dpErq*Q1xcB ze|c>~r`jF(91QbnR{Ts*9jnHq6sM#LPk#RP2cUMKN9M5=8Sff1E)umER>l)13!AwOFV9R@ zeK7GG5^Bz=cfQVpqvcfn7}zpFG~IVFX;B#i*9xj9wXH&pLGaWt@-f~K5Gn1QigP~@;qhQ{9qHqT2BU`Yjt zB{}49ioI@OQ08$GLOIW0;;dY ziZ16udFg&+d;JzWZiT};>SsUqi50R-2BSqYWg@OphQ8=W>gP)Kz(?k9iL>m_;CC-B^ce~A{fIi>fZQ^7j#+r#1Nko&p{Y zJ&Ol#Tw3B9lFajM%cv_$pSZ;~&u7Wgyy=>Bku_k%k=a^FsovS_jKdB`Gwsy2KVtv=z7mo*nprSZjL+#?Z@kOz5M39TW)|q6ET>dNC;CNt zu71(}=6Cnmz3*jaPS_0}kY<;RV2|Lvfs*}|w|k6gZn;|%O|$oQWXb~l%UJ01|3$X{;iMLVgDIj+_bFj&3}x)SyudE zJ$|)EJZa^mNPQ}g_rgW>p|$R78N6Wbi7d-XM{=jVRVryZi68MDap9ml9+63m>nU&E zw9*Vn$acf2N~EmZv80Y={o-DdmE=<_5XjvWk6sCk($5w0PL7#aiRBx{b8IUZPYMo7 zaX0#$S^n<+uEIJ}3N&W=m|@E~F3ioV$tQ_{c7Ab?=A*h9y#6-tsb&%}!wd`J(Qia1 z2n<~tIkJLR5BbUTh(FFL7`peEJyx;9ZxiJq`M2lOMD2{1j6j?C}8}tVq zE)lF_Hn4bRInXQGHC?YN+GJ>bFVe+gF3pyK-m0Oc{Om<5>BWaX1A)cNg~G+s^OF%0 zS*4Xsystwf@QbL70MmDxzIBYrDV^o3r^Tb)-mcq4j@Hh3oBk5ze4FwU&oOnJ{cZJ6 zFBz#7e>KyH=6Z+SDli3EVn@tR_i}>S1uHB3u1WA|t-d_63*%BDDr46Og`V(fOtL3_ znqQ9{mA&GYw5AZg@{R>NYFa_Nw)MIrVi*0R#dc~CB)~ptM5K0hdo#2fr-*!N5qF+m zoHf*rNPvPS_@l67_Goqvb`>qVgbKC6ulFX`dMJqCEd8KW5xY~r+nN}0PBv(64CS1LOPnA|I*EAJiG-xqc_FljdK#i(FADdl9IyOu#7cX%hfnb)GMN7~$C zPCf3$PIcb~)wLs1fj;M8mME0Dh!^E4z(sRhq2v4XiEc#rmt0S0k`@o;JC1JG1j>;nE`{b*pNGkdH0-X!_Nlm`gsXgHj^co*N*t^W3bGtGxx zHZlJDlv;q0B%Sf^diH!(w*1RcSPl6a-oi}jao(C${GTrF1l=pvk20mnOlfMgAuXx* ztvdlR-2d(5wbs^|SO1y=Gtxd}^Vd!BK=+$6F-OxRE85=wa=nAY;dl_`nZsT|Tyt>oqzy>L;c?Avhj6>I-pI>N;S!z~Ag$gf;PwCFsBU6B@tCfv8bO8Z;TAC+oO zR@SD8Vk>$JOqeO=UfrM(;S#Nkx#fB6BLB&jp{t&rNn!wG91N29;Ieene};outVMB# zNlILwjuu_=ygao-;mdq2^b^%Sl{j$@hg}xx<;dHdih}ObJ|_qSyR8KJ4s}j{EjxrQ z79H;^l-j6loKg|Qdo85Yz$;_*n$JPRs4XSvG5JF@>5jtdQ?whR(DtdqrDfy&uGCpt zV9<;Boyt0)LuTXZ2}K#FH)}K3I)QkZ=K3v}o68Ao%i_hUYpAW$z!(_G{=oNMV;Q8s z3!Wo|U>|RykCh29;H^Tt+eW!>Y@?Ix=@*9=A6J&u?@GnwI-YyVv3+q(n|1F0U zKBCJNgMb&Yv3CDaHmdn#S#L$BS+nDzCHCb&aaAUqbPv^y;qCf#{^5Mb^uxG7vDEbz zyYX~l-=u@2qv-XWZl{lHv)r#cb4u%BtZv z2d>VQr>|ebo&5PoDO+IeC>61bhI7rg) z>e145&xajv<*8zSR@pJYJ0C=L5on)S(REHx&MJ&~P}b0NT;wc`g7zFB}Hx5NN#BcgW@He@ib51)9mK>$8&};xPXJ!pKnFWarA8@wG%lDu> zD=sTeQPUjmr^8wdvXs;-!czRo%*DHzVNMa2a#N>yNMoV9XlJ?3UH&MM8;_9%4cu?3 zQ2;4EgHDv2CFwT3k_kuRo!o9f)AzCDzk^Ax!@dPVG8Oy7r&#Xpw^^NK?e{%)v3xzq zo|&>%zFp}?Z=9r2cZ^~+67j9nhko1^Y#y*GF$YRZO`~J+7UPI(Xe&Hwa<=p^v7W{A z{M22gHMVIk+TZQPA)Ur&J~xP>N%=$ga@5BBxOZJVXPpePtBvJ%#TX#!7B>lR$Qt!* z$Nem;wd*N-`6`)>QW1rAt2@J$M1CdJ8O*`rVdD7PxQ{@GI4i!Ls4HBHh&C1AF*D{w6Lu6lGr07M%)A#$kHn3f2 zanr;d?igbuq`8jL*WA@`Y-di&VW}X3Z6U|V>%@53Xm`KG;7!?Z(D5PAyoSG{odob` zQ+lk1qEv*!U8D~fRU`sC5z%?Czw6h zv2>IZwAfDF4V+450hD$)z<1dA{vOdno@guBxfHXgve= zWy8cCkg2?b2mV$X<-lrOzT14m`mA$SG8?3r)es#%*!6YRE}<(cR-2I4bN7M02_ZHA zEdC=4_6SSb#HM#ITmj}G3!o_2$GI|G` z48qc8t@1o)?S;VCB=}45nK3*XL(hB9<);Y$WSp?G<8ttfXtw$!)MjuzD7nze!h}EH z_fF^JnGVURDv$)Y;n(OAHQUKHOf>o>!;0)u?{=dX^!TYhYr1N_u}KG#=-ix1q&?VqKsiq9YBbg4^Lsg%j=`ioDqgzZ$Nq~irVk+ zt?cus2U;Hjv9hEy*Xz58=*W9n`7xL3a{9(Z`D*|L$Tke(_iBerUyPW!2b?-JRxa z*WdNF?1HUX8D6NQTds$cUyq%YZTES;8R5@z@s0W&zZ~rK#NS;hJy>s%a%(B)AJ`iE zUfq+qcyvmjBoi025sv4)`eWJ3Y{8wN5_RHl91fzEtK?xd{VFCn|cB zcM2zUG)>_Fp*;*va~+n#piJd1yDYd$wumxhdFuVom;YufDh}&+ut0rJyfHysA*e6g zeovei*?)x>%3MdYD%R)WXT#IwS<$^oF(c`VPun1T(CO>x z=_cGQmcOjE#+GB9KF;UoNBtE;9IoP-wQ`*B6`)iK64tLB`;*P|Kq6a`{s*A3I5PId{3N%@J$hTuyvb`f^jpCpD=8f^x=_z*s!lwxG&5Ld!8R05^r59h`LHp2Ge-Jv4cN-oIdQLE45i;&HKA0=gY zUX~PS|E$Fan(<}CJMt;m+Xb07c&5)r1aL&Tim^Ohjf0F0_&bJGZkKJ!ox`ExvU`XVCnXZu=C9i>r6E)W&VKmM&m;dawu~>-+fxTg5w;%ev&M% zYi}g|SiK&38J87>3&oW-vM2c{3Yzd9h3AT?lOT#p;|=v@1)rjWVkuA2V)Ey4*ugsn z18s4vVA_Q*`^i3{f@wK6seS{qY^eFJOXkof3uwj)g%O9dqD9SuOy0-_OGt?qcoec= z$7`c7Ngsj5KSDMx9&zV+BArz~yvfI`ogaD8(j-H~%6!=DkZn{HIP4RBsa;cW+LODQ zA{)n3Ii7*`)2>4QcRZ@hzNfs>=VTd)q`&?^f{w76kZTeg>Brvk(4T<*ivt)NvVJ7} z!O$sGZfjg9Zrt*o^$FE+%opwlgoGaTmpTnx5UE_+B#f>5YU;dt(Z@XA8xf0vRb^?C zYz4lBA!8v0(ePs!!lcGTJbkcew72j z&rM!Mz^)@(VRw43ef)b&qe7ivw`cl_mr}1vb*wB;^rQeUOqN>@;Lg4hrDq=S%l~YE zl2RzAcz+j{;U#U?&i^>h@QV^WM72A+uW)CKUknZK>w=T?AhN`?B%mck0i}6UxZBw_ zqo7-vxMopPuYuHR097b_B`tp8euu5l)AGqpNBNMXmOowVt2TK3pX%jycHfNkaLP2E zqiL%u3EbFcHP8KVO76(c+Ba}uTq0XO7UT#DajJ3%^gW|$Qlk(Y6#lzfF|aKn&n$<0 z4D3j%j85X$GOFvG^$a|gqbS*GAQG091jC0(1W4m~E=&e(s=GYK?HY-4DHpuM4M_JKDW{fD^) zawJXiXV+7MlAr5IOu4d?Xdwb-ZaNOQcN_KWcsVK3@iW_5=(M(h%=b9VbmU60;tzf^ z`gBDQnUHO6_!?TF)!A+n3CevXr*xDNVS760uS7d=1ZSgmkNd`@toN;i;Sb+7+6#U1 zqVB5*rKk0w#a70vZu^w+XaSGEB^DJKF5eL|-rzH&Ug;MKQH;P!2DEVqZb(tneC z^}5yZPoId;sPG~PM`sJn^V?TCZe|2AzZH!L0;!7s4RQmgK1Tw)YWTM951aP4wu*wz^*j;fosOah3QG;5_7N?qpQ8L z9s?O)ntIxKoc!jRQu%7IPvOe?UT;4C_lSTK+cs@hzxXUM^{65RP?_N1&7@GmU3!Du zng>}~7}0>*s3rgXP0<9e?J2u}3jXn}#Pw8X7M3~-aN2DpgJo8!F*n3L<0y`$^P2u| z!$y|?at=q*WJ{NJE9Vc%FJ;Q8wB+XxS0!ep)y)f7uqJhOlf5_d;Y#&jE0Bf6@bikU zJIq4eHHE{6u-)5O%J%;JpYDCEVFY zI4$=nU>uK5RB))0MD7SrFr{Zr@zBONLG@W9d$3u-C$K)O))(y@hsxzZ)jy zl|t&nvOhWnrh9Ygls$8dDt<4CdeHK!ph0v@{7d6E9!KSfar>n2+4OL8ZUt`6fxoY{ z$@>YzyOX<0HG5aIgMM7uk@&UzX0WC3iOo>zzS7W%=9#W}+9Jl|7Cvfs7R+0sq)3T^2UeVkL4YO}m+b=i)A^!pz=!ih2$Z3a?1`|xb`gYrfLHLMe7uTl!IKV-fK z{@&T(<29jJ-oWj=tKZ+A8QRA(b3MfvFS2m+n zsUm?&d=?#E>sqVY9#X5y#zK`ejWBQ zuy0M^khP>1I)F7kfHig~up;WNk;AZaj$tYqRwcZ+n6Rhib`O=myF#D zzuGtPP3X*cOmALcunMy89mUes zf9myE>Q-?Kg*q!%q0iar2(}IHo4uyTJuN0Y?ETkQuD&NHb;k|s$E}r$B>NTu5fW1m zG*+ZlFrT|Ax-w)&7$nbH+jCN2aUWF^Ke z$6w+ppd*kaxk;1re4h&y^Uo^NCIdPPOIYe}AVz)}fPG!wJ;l_K$$;u;#Q?js&zG8=)w?|1=}=;@ z(=;Fp(%@9IQ@%C3^4st4zeQ?S9u`vB%N5R#o}Y_fPVV#+{`7fK6|#HFn!4OOxxo;h z`(D1GSDk(!;rZmwj}I{dhrB1k#MUObl^q^F{be`2zg%yC{%s@G-lC&q7X+jfh#bCv z@XsS8*9@^i%n4>njlFfxI>+=jiv>jgPIr@+mB#)L|pUE}0MP(*LUoKKrt$ z&BT`9Lx~N)<=QZ!wtT8n8@9Ew9js2u zA8wwq9-be-wx^#_9r)DOA~v)X%RyjLXwxv1eU$T{rB2cBn6-QbSTEoUAxx$XY_#VD z-qhoAzO!u8WZ35(A9)x+9!APdi1#b&yp7&9&6DVlr)rd^sZGy#DyFqB@9N8kggDSsXs_V}Dmb@R@_V|oZw#!O?I*k08|AhxY5W!+tW4+j8g|q_>)AIqPlzUa+29Am4WA+?i*dA0=YXxK>K-&CYZKA zpvNw+q-@_e8A(}=JH7a_7$-DcF{yVUIFo(PPk&{=wkePcITvh!RLM}0N~?6+?_Q4! zE{rYr3Nk(7=k7iwb(x%t!bMng-8CV7Z)}!m=HE63uab})$RG1-5$B1S;BtP*K1-W) z_AsvMycD?5CAK)4AHMq%X|fv}*q&T5ieGyrc(u!gk$2$twX01Y?OWAs4+&U(ZiY@Y z4lEV$4+nDu?fn$BQX-e29Zmg6yxpt8Y|IeNf2u7!r0i=&vcWN{rsd5p z))~+5cYI=a9O#YXL*AsG%GtC{(JTg|N+;>!g}Yo`c7|@Saa*0>k5i>ZO%6tK>sFVgsp<985A#{> zSQ%(?PcD}B-eYIau|=n;LG!g<5N>Z+{18e#t^98<6$XAXpB|tz4>{Qa&cuSF;~U48 zuwZ%v19T8FPW@MlVqij=+$|%d4ecvfaebEQaed*?RBTUg%stuisylPsu=ubLe(hRP zSAzJDzCyi*r?tkXTGV*i%}(ea2HUI;GBWmdRS1xvgoWDj?~?-AreJNy(S~LQ> z%ko^?df0hlVVryA+Ikh*EWa1eK}VqA_4)SrHaV0{Tz_Gu)u8-Dz7zk{KKC}wK@R#N zTjxOcjZX5HxY)EtaTt+{lwh)LsiVavdPuqPoMTr;-z9ea+2`2ntuw<-?|l9dKT`de zk+3Jif))Q={jBp9du8J6p5r3#!#p9QnraM)oZ|=a$MBZui!l9k(^s`zMW@T&iEG>a z$Ys>oq8-77IhBAd#ZRt_b1$a=)2+3K=D{*|@ou#p*W;?}m7QHoPLi>_HRn{o|KsYr z<7)i=z@Lf=g`|xLkrvuJBcVkpZ7JMaw_Q?N7b%)%X(trzy~jlZsoT(Ps;gAe&@K&r z@8@}ZzQ5n=_xwZmInO!o^FHr=-sgRsxk0*Z*` zI@q$n&$gm*;j0BE^;=i`xO2k9#r)DtnHovHU*V*uBq>4|Z0Q7C$I^9$ zjE)Syn%3;uLb-7yZ7P#p+}p+eSOKBED92sUhCL}$Q2FL5Cezg?>BW_eg4cVAb|L77 ziad7g25Mae%OaW$CUVN37S>lkE8`$=>`(5(d2Gxlb!*$z zzUZq%CT-JF@nwI$Wm^4KH1*Ko*uA5yXqgJgUn< zN2CY!=|2^PYUVPFl3q!cf3H~f3pL8|E-G8oE%15zl)ApDa8z98Dwettgv-z=hT>)u zcFij-tYq)>?EJwe60>9D&rV8uc=&Lba<}&o~$u|=qX+Jkp1;-md1HU|i z1R+RT!AhXO(NwW8<>Lf|y3OmU5Bo|uzwkwupD)%sEa{Vs10w2}hu^5aU=R;)?s)p% zV|w;0$^B<#XxlQwNg$7DoIL#Y&>AjDzG9|AVIj)w(C_&U(zIgPmv)!%_dKu(GH1Q% z+gpNkQf-8ni2~%&*!}2^uI7tgE7W`hakU6sSUDTk2MoO_nlP`+a9~N|_+@tRZgau` zYwebld403y*3^uhAIg6Bkt27d+$}1Ge2>B@P80;IejJ2WnNDYs>tA9&^Qp($m4AUG z%dX|_+a70A^$P4X<_^kjQ#a*r4h#YT2bZxIWiLxDM6B`sJ!QWMUC|uO20$p6#dQcn z-R`tH;$h^^c;Jp=Oo)_0&e_Z7E9FCXBfGN)9;%fw zOys%tn2je^kzV|@S8c~aJxW;I4%rc$B1K-iZ`AW2xMCM%&A@ zn+_7p7niXf``@jP;+Ot#n;E&laeSd~YDe+;$o}LFnSlwB{=2$Txf#z@b21cY$|hNy zwG?L)G+SGxOeg!>h)opsgQa-M4Lt&fC~e(TcEnmLMq_(C!<1;T(Pu?Fmmm85#R7rd zW&EDOE)lc!7kaYFgx~4?6|OTlr8+r7o=(bLKS1>z4J-)kT;Rwm&)D%Nc(#C7Ls1$^ zX+XRx9F5u{R&7G3x4w{(jC$nCq0B_5I_eOQJZf918@w*Sn(+0cSr4R53VA|REz*4t zNM*is)znDNkcLOc)6*t&rQ=cq`$#6?DEXBC8KW{&rU(D5dGr5@|k_#EvU`2EXqiraMf$Y8SGf|GIc-_aOsapt}X!&DBZY zD=T@G?`|YQR}k{#{-xF}d;iGOH6}))%?=yU_00pR3fanjZmNZ5*H;hzk5tqj`|;-5 zUfxFLswvlFKUROR$^23A3!Ad_h0843^v`WKM-(hV`^P&hg!xnFyZeDUR&W4gwvA=y zQnGEC$&sN7$B9S&m>3V=i$uC@EiaV%GlD4pbapK(HOv2WdXJ{Yl!VrG#(zhO5v1|n z{OXaYGK!kXy>&@Pv_wZ*1BM-bdfFilCH|{o%pnn?f&5g_;>4#S2Vj}8$RgD4s%89R z+|!g-B!$HA{4&gr5)1H9|GGM+%ywf-k_JS-;T57@YQls+zy)*_WD2GWVvSF>Y zO+b@t(GONi(Mi_Ksvy2vuY)bV5D9X38uZaEFk%Idb@SJoTBokg>|li0Hf{_Vo$qO? z(^q?9f#euAtaKd>Ht-&CnX`zp+_hD`{7FUkk7vjYE z1T{0lI;$;?zZ{O7>h|tAauS*F8F6{)^20pk5ludTCRqIjmH$Pjv9OD0j9E|DtD<<5 zXcjAf>(B!3g28*|pDu1jCuMpp<9T?$dFo#=s@mccWhX!fRt5qgr@jt59A)0qgji99 ztb9qwZ2k)6T>n*6@8@(J)KnxBE<=JUKW1O0X3avEoD?=ygbqi$3e>0YG6# z%b|>d_=wlr)#M2_q)MnyQ*!X-dWRrKcH-jE$T(U~Xur?oBYg)ov(XVStyD2v8CfFb z9^SR-yA7?C5m^M4E1_`JA-R0p^Gt7G-Or>-#Pmk-kz_%x7jg&CV`I(IXiOZTXZPMF zKvETDt+sqjzM4woE~v2tdUH=5&T&!YGrPKatt0b`-*7av6~_-?se)$6jK@u-mi=ncC4`Z@wvMqPA3U za$BEiol};ZrAIbLvY=rP6)h!@ge5>j%%@D;XT-i`3qsra>ut7av&Z0&E(2`TkA(u6 zvFmM4%H%45RsS>oH~)s*Mu#y|Zt_*7IIn)M6f7Q?{2xb4!T325kUzjv6#%P|Z#6)!aXd5EByYJWZ zeFkaNjB3UXuAo(}E{y0ua*;viL}vz#2#XWap zz)UC=QHDDVEuhGzmEiDrZY4o-@JXE#Bhjodv35mSrEu-@dT^04F}Y8^6a3A+C}9)g zallk(ua$115P6|}SFU{5)4awJRhrXgy)-p2`NswrkR&Vv1ZqRlTp1`;8uBB5tA_U9 zJ9SB@dS0!qL!fz>f9y-KX|=*Df`S?9HtYNwKp`>Ym^4~7tBG)HRw6!dT5F9k-PI&e zcw6Vab4Pcx*-1*?z7E(Fx5rACAe)7*J?L-p;`_pY)IW4HIZo6?eD81V@Nb)Yg_uh8 z_*VT5DSWPHS{;qKBAwXrePoCF_r@kST_{}Ttle_6tRPWwll#?@RZl*rOIJ$^5*>Iy z$0SJmxf%e2+T*^Dha;aXxQ3K(?U1r+zve+mW|+8I;T!ju1kGnlRW17Zr#DOxrk!qJ zsXein9wF}xG3m{_))2~vcybZ$7}uUrOSxPDR(O52caoSn)Zwubz#OI=sUxSkp?B52u7upceDEACPp+5*l&O*$ zs1wd!YN;-3=fBWIPcb0$4;WQgY4#aGU`fbGaa$Xo6NXpyDQ& zlCy)dlo-^c1>ch}R$e|mikNmQ`pEi}y_wjRk21`ZI|g~PLKp!~P1PD+w7vL4rPz_=GijWuF6Mov+`sy}8|2&y5@og)f!+54r^(Gj+Z^`Y z1|Z6WZg7jr4~`#ONj4d;b~!sJNs_O>Jn^ApL}l-8Ii8U#;P~Tg_(NMdp%MLrv$pF6 z>zwl(RpU1nLtB@pB%W17d*TD{%=SEDL|G0+&Bsx->()H<=V@2rT z&_uzymhMp%t%eoXvI;$tD2k6MtV|%%yaB}u&9#d8TkXx|X8j-Il|-9ZBg^$M2Ii?* z7ts7PjHujq#|TJ=f%x~_RAWZ^ppx>mhbj>@nunHMF~%yHAkq@duCDY!R}}&~vG<#Fc>3nFflp#tde9TLm5oSi zLm6wL$vRL7CH2x-N@+3aC<)?~%;3x6;{0P0Nb{}Y6q<4EhT@pO>pj%u-`c4ElYtfs zfb69wZfCj>9^^-j8PfRsZnk`wfhkt_1FsK)NDBuRF&8815kl(O3}I$r?;oTz^q4{) zFAhT=xJ%8y?Rma26uoMG@r#{k(j3$SrzaDyq9``TsH?w76HdL-VxzxvZk1C(p=_iZH)h)P=(&JXyL^yE~p(m|tUJ50u zV!{MBSI7rKE~lIDAkJ49i9U5P6NIi?klnTmOCLZIh)pt2t((^)IqRD95Ptt6P*I28 z2#>fz9w|;f%4eG9XRcA8N^ITld;VU0sRe-tRo(R9TvsoS%!GYBcMM_Iqfrad*?2EP z<5yQf>vE%cJQb#BiDMwol(g*8q*V@zuR3HtmcM!Faa&2#&qh~;B%UDHNh-mr$RHVF z-O8U~2j!106Tkmab3g6(in#J~7Q{Hn_&nP=ts^I)gm368hQ>5kRcC&H#+(!k(KJd2 zX3kO0T7Mn3_uYP8?1}4E2g$9+kPs~9=%kL~X2G$KbEdr>!RK|mc^V3j&2(P`1R2|fu`mDVXv62Eg zm~nTZ*?MePTGgYM>*58EX26~vK0C>KDeQN2VV}IwtwsO3bBmuW+vs!Gc4z1)5m!f- zwr0Y_3ce|mUaFL7O7@2~yeWANb4tW*o>K}PF9DXMoewz_sU`;Px8m!jzn#d|N6Qoc z!Rf$p>jXv(6Ev?bkXS`E1nPB*m1KQzLha3-^jjn^*J0<6LH<5O< zfxX2#@$lNydcY07DKd4&EepkRSi`H7xb@B9b~|?U`Wa#N$P#vd4Ot4{mE%GwrfjPm z`}Q!yAb0-ype@zr5JQ{Ou0Fi_Y$L47(lboVte#*K z&wslgQNK7)cZ)Tt^cLN7SLIEqgpJ0ibtQ-k@#=dVkD=n4dZORD=D3mYE4FIh5RJ-8 zD18Evl~sJ&e}rfbrX4V$Z25-9F0V;qii`1aVuZe3J4%0oIQ6RCyUm8;ca2kBDd7nF z7ALjYFCf1CaNX{|RWt_7njjyAp3+>pamsYAO%8@xKRm)Fc+Z0ko$bQaBK@^<))T|> z%8tLUoup=<3L4+Hr?8+Up2iL0W^01N2c?xgwnv7Hz(l67qQ}Upb(4%C=NSl?1iM*E zC%Lde)likgULEtRy#y0mY<0X#vufg@G7!0Oq4 z80J#b)eX;c{ofC1N++qDedA~Z?yMZ%YI)<0mx_vqzBB@=;mhhvNwfytQ}lhvUq_ThB`;<@!h1t2G!d0$5mqZRB*z z&1>%K5a$anoVU4q*SxQ+bmiSNK=mQUo$3;%z=q)x1j4($&vtEB-Slds7z8P>^$v|9WrxtJ_B!+vE|uuR^m3$X|M2Y zLcRd6hb@1gv~tp#7;x}$4pP^h>flNsUvrEylwPyx|{{*47}ho5|o?q zt_6@u;TbBG*dx8L-^fW-$lpl01H=g##}%6n90%*&o2-%RXHZA<2ir5dL=1I{{~4#7 zFWbI8%)$tVK{^a49ql?}ZFyVwMmlk)Lm@$VUQFP7{8HTg1Qb2}h;@AV>`>LoIeQ=V z6%!g-EA1^t4msXHE^F)%wZF19{6~9m?JL3M%mp6cN*45#Hq?~UfLl2b!%> zce<(9u>QB={fnEjNN<67dmyo+(9i9X?)$X~f@u_tj}^Z~JRD@%)*)6J9rLkGao$HZ zzn}4lDB;KEfZL}Y=|Ih3W&N^W8_v?+LR4!o0;AD+D~9KBBT(hQpGI7SCZf8HVBKZy z_wfwUjqt$^-0CXd9!6+E!K6OOpB=G0Ic|Rz{hmU==cd&~-vV`JWAmkcSZWVGo3yC1 zofn4PRO}2iMS{z17wkicb>GOJk1gN&Hopa>k);Fp%nq1R(~iN^1fFH~_lDWVwW|D_ z83x+?w?EMtpA3~q$?T0$v#(?KEc2Wwm~Q$S+jSi<)`Zbvj_8r^2GT&5kwQ*ScAmX) znST;zV{#?NEmjw=od7$X{{eJ=*Oph}eL;3dqQ;W;CV znPl{@rVVTcG2np~-2o|g?^bv;c#7hAe);~XaKdiDHW;nv=8cu5r${`pf5wEU#|qup z2iHDc=56)7xDriOgS2VPU{PPRewGR>L5>9a9+O+~&|8T{i`e2{t1o8sf-QW#V?ip2 zmLNVs7$xwRi5pa9@^!3W_|b+RXvbQ|Gkf7pG1%!q4Tl60zuhK-@)7c^Ja<$W6x8UB#mz z>2hOZAXdk*s=~g?`S6ji4gq~s25)UuHhbTh z-ZoXpVU`P`_g^jXBrPK@SdQ{M>EDWN3kPGURjq!)P%eprXKys`M`?NdSVsR#y*8eA zgm;1P7j{JjVsYpY*!Z2dfWW)H6=@D0PB9xKaHybHHdx`ADnE3eB=Er*u^b+g6_Y3k zw=)!&{kDgRVFiB?_f#VEW~C_!?*vS4aP@{ta!*%L8?FlQ03uM7{!@p%q!Z3GF`q$-nI@_GlYDq8xt!12rq{<%nv8)+2nDqx4Cftbwx zahS0#dN5U<^}r>VXv{^d-f_L**@8p`&c!Rsgq3JVX;>318IqhLE-J?b&Xu!szASyR zLc2}yZ`W>b7*!V&R?P)OFJPw^A#S<(E|-#5#Q2+4kJ>^$fz<&_9S}`h(E5-e`gUN-Lr-m{X710{+OBQuYK?#%xX&&4t{d9tI+e{dgo=#)wM zZzyW^iGp&W+mwF!{u1z5fEC&%3)jl)EWn?BJR{$gN$8onBFtt}e|+{KC?B$#39uXF zHj~3}_J5iD0Y>^`*R;72q*W1Gj|<^9uq%*%?LyAxjZ6%jn~duB`8yMwUAPXJORFeK zTpK+CsuMqBhe)R$awc!7+!7h~e#}WyjlKWx@~`Lli+UbFO7{QMpb*SNg>Ty zUJ|22waKvT{{mLhnqz#cIqMqgE^l}e#vv^b7*r6uy7X&lzWP_aAe7&UaV_=Ji5wtt zBBq>~Z>M=x!hZsa;Yv|7X)j5H!$IU7VMnJ~d6#_E-Nx2!@;%>uz1I5u1g>dr6`vs# zR{Z%%;zD8`Xq75k>cOPwUHHmrWu8g6yEk|!y3O4|K_EyrR!iufY;E}h|EZ8u1vAUc zh<)mlG4>sq3436$HU2cS3+O_8h|~JiWndV7*_JEhdd%P;&DQaGRn|(G&u_aEOysZ{ zlY#1}BhXO!F}8Ubqpx-QtAJ&Poo-a(!nt#K(#bj}KO0ox%A<&F%TWrlln=_0JAv zE-SK-4K-$eGz>8quL7xf;#(&%=eLb(1~lommGsQV6bDDt`$rY~@ZHnojA4b&_jU*D zol~(z2`b?qrHKj1$q3~#wK#jkFpp*Zu`*Sa9o%+2+b*qv|+CED1)EVx-Fp*($UcHK$sy-(nQs-<+iL>^hRWth~p%v z6j;5dUWQxXpGJ*QlNO&-K|;<8Ge;#D4oynwbZm`@*oP?Vew>_wu4uTD9nR=|shK)j zW@ljh(wD>L48%PSwt~i`FyR(gv}pj92;{J3jo zFLay0Y*}!{^tQI;p;2(+Yp4ia)`d-y26iX1h0bM&j&qr&p#?Fam&ekzS}yRsJqAs% z0GKC|{TWb|bKkC0!js8ce{9O01y(mP{5M_&Y?^AnI zL~K=h9vW9GEC(=BbX+}TS^kShkyF!)R+`B~mDp2~VdF3h*l86lOff}`Fmm?vMpVP= z5lS>R=^j5@E**a2kqC@{IsHCQqXyumr{W9oBJOm)y)SE2Z3~#lJ>R!Ypr$(gn&o{A zM(M;{nRLFziEh7PH#Q`ZtA5rTz2c(;59;c1-4XASDv~CuC zV5At>s@RYYWDO3?qfx+vaND?w)%8g6!Kf4ED;j_o>da42C5WCIpUwWxPsE|&Jz*!% z7@wna<>i`E(5y>4aOmpTLNbl3J?-0mxNSj-KXkqQf8M2Zmwr4Yl1X8>Pe zi3J}txoU+k!FIbcS_+PG5z9!U3u46N8J_k#)Pc=%jc$D!c+ffh5g2EbOJ2XZU{a|$ zc|n=l{Mn~-ZyG|3p!ZM=)zu{&7U2)>C8QqCw^m}*H1C37Y_Vw9F?2*Je8l6kd}h3w zxAyw+nzJF!`EVmZB>EkmBHel9@?O83>zqhc3MNm%`p* zfEXQsFNJLO5o)p_*h9{~zmWga3Z(EV7HuZC8;aiS40ymH=xl;eqHLu>+W2A87izGF zatNMB0g1u@!JUNkwg?J$KEjUOn|yp1mG?I= z3>!af*&h4wDBMz3LR58g0zQ~Jh51<5+poxj_pGE(Is=r0FQcJJ>4t(Uyje~V+`ZZb z_BkEriS$Qcs*!z5v-;d2D2d=5M@NHfAJ>!EybOb3coI$jcn+Mv1stvT{xX^AzU-;6 zP>|JQHfby%f&S$;8(rNEqpw^+on9ROX;-M7p`Sb1(eEKS|N)?Y04{q6Af#OZ|R@<;}u37R4GSc2Hp z?$R$$+_@_>kl7GA`5oBgeN07U8cR1iH$T;vP}8}8$6Fwf2^qr?irqp& z_TQ%Xf{sjfYpL?PDvON?@Yo)e$5mYVpRkK)MS|K@7e@S zu
wKWluhoQq1LFjMo3G$Thwih&6lp{>Wn%SrY$%50yHtB{}VsE87UzF7CCCi5M%ZDFiro$<87Q&?M>>C!!2eN0!$F7=&uoHmwnzX&_K9ZwHhDX`{OveSB`D^9Oj=qabWO0ojYP-T6&_MATMq{1Nd1p>i z>S6?zzM37hJ-q&Fp>^#cMEY$hV0=NR3w&2f_(|G$52OLXE*o9)+S`{FW{f4ZBfN;| zIb~r8bY!7i0sj7n=-S{$65M(BXHQ_#^tH8NRoKu_S1M?NAXOD+wYW>rNW=O8P4rXK zg?oL9)Q-?;IgH4}y%CY=5941@_Qfc&`Au=5>v8TW8B_U%162a2HtmDR&bH@&A4~Co zfOv?C26aNRf>k(I>~Vr~@vM1U!_}>a{EN0+{oVHruEVMsbW@IS83s05;{)-JSa@!V zj~{`}*DY|FR7~E&<=^JZeXNL1+Gw{t%yK*ebt=f4Pj-skCJf6=d2$%XWb}{s#ijpx z2={6ld#MVKh{FU0FzmC3?5_2aXox+xKI6b`tvOM~GX6abNe;l(h!ws!!p{XsCrw87 z@1(>gZbP`Oa@($Tkmm8I_Z*-}=?cni>NY~_9v3cA+G-EIwp+V)WB3(c>!KDyv`{ux zf~(9Zf6#i?2(e~`EA}>F%E#%_9artO52a$4Es&%wyNV%%;E$1?EcakkTsl{5Gr1Vy zp9o1&gk6Co$-)cA`~hAp%tL0^pxLWNNfR#f5H&LHe5w+TEecpiRnH8jgNTA=V_gt=B4Zj*qwhXh5RrR z=@16FYlZ9U1bXH~#zr0W8mZAB5;|MMwg8OJf4{)T6PmrrLnH5oZDQYZHS)E`SrIgst$F?PE6Us8;>fVOgi% z&)3$Qz^42{x@Rj$)N*IkRqPeNeXyn3#*cBOID;OirKn>QBkZsf-Q_jw^`dGMO)S_MiZ!zVayp0D?r4>^J+@-F zZqAkC`+6ixH`PS}q#@#q$&#fI{Z>*>bgC|;BQC|oq~6QDp?jcVv5oj}9pcIPHlG!O zUx;rWdXXW0i_pG@nE_0b?rWB=4)gK@hniU9L4Jt2Ljp`vNefs7Wmsf*D&(1O9KnG= z8LYYSc&X|r+X+RT_m__oXU!#38$bI;?J>C>j$VcF^RGI=27wQ=au&} z^7BY_^491MPOU9cXJlFZHjSF&V*=grA^Py<1e5$|tw%~sH>Xq)?!I?~LDJR< z{?p}>PZk!cr`I|@f$z4t@1OB19bG-F|Y`nlu@G14T1;)0QN;-&YOt8be1{9ahO zwAc36ovR{zbBu^X&TByXGA4s}9A`T^Y@Qj)FG`t5^O&r z-8^#a?5J1T{1nx#;}-%NT}5uAI%?;Km^8>?Q$oce`Rk`rUQ77VT_^_MqO8Kq?%M?q$iciv;r2xziyhyNqK!NQ;r zlLWE;Cu{8@6?jenkC2;cyTP~m_j^{Y)p6imkTpWy!(HH*%$-0vq&br{PGjnG*fjLB z!Xd}U{{8`cxqxZ0GVInv#N$l9%>SCl&)PS_m=w!)*Wb3l|LQClkd7xCx^}#kf~-Z5 z3xXmeH*ZFLs!t(S9T*6+P!q zJl@-~D_yn`Y*K_(#!)*4K5agXf<+k?au$ZDDBRW~SZfHf%9!S{_Xs|$ekkU3} z-WJEc6&f#{P+)r0LWjFfx=i|hfwSX4>VZLy0RokLg?u>?%KZbs^}sJi?| z@C}{Y5Or^{i=>bY$ApGfG>nWCA3_Ie7DE@t%1~=6gBKhPWJ<>HK12znv1p8O7#g-m z7Sle?!r(;AOUc=YO<~ubB1a?C$iQREPML8{TY}oCAX-hn;#F z@F0%Cl6rE`LF7upQ>cA>CEQlwvWjUvg5y0Vd*fNiCBN|6Ga8(8oE_g zyjz|F4h7j8wWBGwKD)u89qcRm9<0&svza11AJGwSj+BD2T7Ze^%|fRCu>S8dPh{Bs zt1v!V1Qr)ix@hzDS|r++m0+(qKtF*&zcYm1h33m(j}hiFDRGApCRt%&;rUmc&fwLT zCn1o%hdpE1hw6bpEM6XUGe*krGk&2*XY{Oj z#%`c@c&x6YOO&&>#S`5eMISN&2P^u2t475PKc$CSI_*{e;7q`xF&?{*5-{C?cu;*W z0`9SkoH}nQ@MKs1qo50D_symHq(d4I-N5?CZjvWAJw-D#(FdY6`Wv0EwOQ!6(Npojlk z(l883x=;8s@th}U1EDpTq2j~;;SFEk%@;CJh;w*RF^^>@{Gfmji9OPoo6dicboLdR z)r3Cc*i7rLV)79F=EnqFnCPp2v_!;sS{mFZLv(Kp9x^jFt@n8t7oeYDQ7C>~LOSi!KSVWScft|R{l|d#EywD2&g#O)6irOqU_{P;!R{Znn~$Qn zC2D8%WXPh@1fFKB8aGiJ9SePuFw%lsd*ZnY|E-xjw%x+7pZ*jCG6;?LLoDzewr4{; z-Sh};H6?ck-FlVAR+nGD{XY<~{YYW}_8~Nz!w8W7JR1CkhwO;0*k0H3u=9x^e~+@k z%!vW0`zpPg=3u0R8qV0q{%*z`H=_FgX5NJL!-SCxnaYo@83tab@jB|2 ze-rzGErI>#x_``Y6I&vI{D0z$ybBW?b-_PTPJ~Ahe;?c`Rr?PQbJ&3@*(+#P09;IZ z*t{R6Ad3!73AF!5tw|SAlFQkH8V2Yyhlwm%tS|UeJsZWd)d^HJqR+qA$ru+q%773~ z+KF}WPzXbb93KjP66ihX6s|t{_Z1e6mBpJtr&O%dy{M@NdkeT$!G2=Wf*q89^cIfI zj~VR`p?lmxr%A+)1=zp+^baM9*ha0uK@2))sY)0Q7tEd56}?EWE@nJn`+x$kTTy77 zrO==y5zn5*p_4-`EVB58|3Qm|31!dWBVT)OH4XSHzyrhB7vxwJw11B?7EkufGo3&& zN;c~%0h;(%6$EQSzlI_MecaXOfl>;v;A+BW8aj!Rcr@*#08jOX&lk?1BEbzs2Ko>a zP%6b=|NCNz5i|Yp9A~^0HUad%NnSXb{`ay`0G&jV!haA*V|jqxcmg!`F{Sapv3`&- z6yq5m@J@$Q3DAO-V5dCxdJA3$;^^*mRK@c+JE%k~EP(X@yC!J&Q}&ZzP^JKC!K`We zM;w2$MySyc``;+UxH)u2_)$NYaLRquj=^5jKQfmehwtga31`vVo&WEXA5WlpYKT%1 zNhhc5*I;x<4Ea(IV_-*O;0^yHtI}V7Pp|a<@t2EPTU{d#!UpzqiA zOMjkA0=kJN7ZQMe-xBy>1ykL^sS9{_%G{K2en$> zAx8O68OUb-VJ)w`+Y`_Zv-3q~i<^0!>g(>L{gi5@HeOM?ZPT%k`^_TF{&b)?X?e|N zg|_|13QHyJl4*w}lijcC?_*<^mLy<$iBg`&fl_oZ|Jw65$#Y!OtV@2iSNB?Yo?w5^ z4^?8K_pIAOK@~IYr{07eqaBJ<@EcIEPuG1fnR#_^Cg@wL%(JOJYDaAk6y^^Z63_8) z(D!D~@a^BQJR1xaV<#sy9Tpz5$8&Cx2A@7V?bLVsYQMl|{pDT!N7*hrs4<3jI1grL z9V=K~TkIGpD1Kn7BMS*6&60X0@TDO-%N&MduRJOXpRxb)S7VK8sal+{RmR!rHy z59k~hEiH<+=(rl*{h5BbuPQt;JG0-k%}+XI&3N?95g22o^cF+_yD{Yyd!L8;>geP= z_hA9euxmL_BaCRe)d6jG%U*X0m6P*x7LY>Z?<&Os=*4^n*=>#HG6z&`OWS-s&Emb- z6>EmS@* z{2j1meokCHbhV%3-r~fy7dd=Wf5*RWu&6ciUAe7pUb(pYZ_FcZgO)N8KngsGLO=(I};JOJ%d(D z;TQK?Ar(UMfE+M#4q*VquxB!B!ScF>{vwSV`%_IbTG!Rhri$2Rk12ZV*_zyh+|cRX zOK7P1J_s@T{ZoGT{_saz+{quSW`6c@q1)s4L76{ZXGZc7c7*<|mjo@d@Rl=LB{H9k zipAd@6nPp`{Kf&%oDAfRw1rt-);&%Tm4* zi*k?DGzckW6YXtgkp-gD#Of!jYnQ06{X?Z@!$UDt%nL{OKyoW2*J5 zYpXA+GQP}_1?h`IpB#jtVXuXU%|-|&96*`lfcL`tIo3wY194tiTc%_?xZ)JzsVf$- zY{+57;@5x^e+(yitW^VUzE;%_is|G02}6%mnpu{}{E{ynWEfzcx~pVxb;lD?Y2dNj zI%l3?-b7n2UD5z8|L>_|LDFroX5>dGjiuMYF#n1{xY_)oQ{Mse57{Icw{7tZy~on` z*OHdzHtkr-J)YTM5FP86>O66CAw-W#=eooB82Jc^Q%|nDVz?R&9sIwFF6!^ zsoow~CSDZ%Ih?=3s733YIO5ymf)klpI>TsZO{pr^8KB4dN^R6JS(@E_6Ml zDVSv%QMzu2FM-dq6$=F6y@TOFC?UOmE?@2LMvl~4|Ef%PCacAD;C3f|>x1ouQ@c^* z$A|pLh%C@iWU>-7BQH3dS(bwP=Z~N+VIB5<=Nrk#)FQ(8Z^a?8lz4{2SsrO-8d-mfS*@&yKA*|&KXnH^OgcI#(gWbnB zhAbfcs}J=FK_`dtPV`_GH&ej^dXIh!y&m3-t~i{=Yu7Il0bEtg!2StxY7ff2h-V%R z#owNk1Z-sow_@hbxcWL`?HN%>0qolh{Tk!_Dz)eixzc~ua3S(Xf87N{?L!d-2*3A& zW*{1F&OmhPz|xA$kKaRe1%24Fv_c zUR?oVa6ZUECp<=%;9!CkYKMLmEZIki*r< zXsF@aJ@^P#L?R`zmLE>WyzwfB$-U>mCu1J>KEZSyaRXvys*sNMF1^bH?VT;T{pUGu zd1JI4I9-7#NFmE4|Gjlt=3Hf{swU%wRVW6<3MdoFGTZiykoJZx!101hR zBtuwnc$D$wwz4|1?`5Iu?{biKyap9v)0XhIZXdQ@yyiRF6HIl(?HR~NhQ5aZJ%ygZ z(0cgRGwxR1UGoSsDAJ9RPUL|{XrGS{Dx{jKOfn#K)~It3+R%0yekI>8IHb;m)M40j z@!Ezi!r^Gv=Cdxrn~>0BXpe(9$l5=?oNWbQy?MSxqfxKJ5;&e-TCb(NH-{Pw6&E45 zD;Jf<2qMgtE@!j;0EAn;QUSv@s7yi-Z81h{G>^1SPFTYe|9;JC7XlFAan!|T;EZr2 zMZ*z~@iP@tAG=n7!g-@{^51PL`ti2}B#KAL3HJdElujIREF6UL)M1ycuuX(sn5Q7YaBwDcTUWjCxUv#`F z2|&NV!P{{megD((W*$hc^V~Gx02~vlhl6>}g>Ggh>jt|b^1sx9LN?*7$8NGW6^#;TPE}_z`ZC(@A4Z(jjC_GZl`;HL3YM2`y1RbQP&?Y^ z@{3;=%5R5J>QI;K8BU4MXxVSNOnerur5a__Fd~i;@A5NH5o?QsAhPE8sVi@xK$xN1 ztljAGi^~W-G60o0JQ&6gzxos8|F_qBz`=UP#9@~p15*3~oj|GQO+Y82ZM*h9xN&Ia zS2h4>f-?FOUZf-}86DuwzX9f}Gdh&BQxYpR(`%o=K_uafudw-DioYE_>9J5edhN(s zMy%h0L@EGa4QfY7xefdbia9<-cOm7Ki>B9>yH;wBxj5*CFpwiS(bqozUiTes7yF}> zK1%qduXW~?ybLpwBSIHi0&)&W#2GLI|g12pBgVV z3|056C;r;@&4eT~3P)KN?=5aMc?*QzhRYuVFQ>B$jXxW2gfzw$dS$FbD&o;N)Z$&B>9Lj}sS z#~5ootCOu2tL%6E?ceculpxrWR<8v&muuX(hHg}U{@8X5MzG>TMJ_e?aQTazvM0T8>29Ad^5S8!-lM$;&=^|R)9}q%CYq5Y%lsb z9Q8~@knFR$=tkl-VT=a@i)#s^vf64ZaYk?e77nPP%AC@Rf7)z4U~WOGH%c!Tag{xo$AU6kN;% zy8BTsZR)0S_>Tt~~0L)2q9&BZ`B&YOW*Y<_E? z1|wL>Yx$dR<$l;>x7?Ll+bxbZkVj)mWE=eZ6Zd)Ty`0&K?ol1zE$blifhE1M=-Sky zCJ%xH&VR{U4!VhUIZLc#RtuhXag#e}5jeNlE;wyF*hB zz_T)~Z300e&!+bqx+i}P`99X0C^tXeo~Qb^<8a8cd)9|GBA@H$VP`KKHw?xt0|?&F z6pAuPrZ=WVqfewO@P#rWZWuS@;v8=gVi@HeBVXh`-Ie)0&LDl49s@aW>iF_j*54?j#~K}`BdN*%2FO0S=wB00Ev8vRaDjd8nfk*-}X8%RsBM! zBoKJfqJaUSJLA+kSyPi=nc1`2-skVT*G}euCJi~95@%5hE$-nhvQB=v-Z%Xv|6&7D zUDs0c{Cei*EC#ESS>Iq5+BmaawEo$}I&iUz<#%EDOPaOoMuhFdkN_YGSM}p{9e%s) z;)kr~hb@d@DQ)gMSD-SBj@uIyiIX4NSxBV=9XkYjjYJfN1`q+{)VDl#poaYzH6%y~ zWjXnt*~@RM-*Z~G5m3deff*#1af(k3b{|tFdUDqg7CB)l$!naUz{)QFy}VD@J7UI> zn8{dBeoy3(@Eb7W9LDl2vS5xm_#E5fyaoMSjaPs2Om}_#GBC}Bj7Oh?uu^zqn-XA= zE)rRoIy>aXyf(8(tvrHAO*`R$bY@zk5wIOGm|*iPdFHW@N##hmTP2(>_v>|`bvzFO zWm*YYEr2I`3{Uju)~7m)t6p}AJ=S*VNjFldVYT$m`j-^aRvc!M4Q!@G@e zqEN)+RoO0JKOEYoqWc6EQ%!|2)0WD6lNk!*%;ePIt-Ywa-HnrX`R^hfWhL67voK>x zBPUZ>TPo*QOjiFJN}_6^D)YH=%w8QY?-aXbKFGsm1wcIUb#eZ7>i z>^jAcP`~j5^;Y1voE#S?wTUGn8)TGVa=ZNy529>bW$t6)2Nv8#97tgyIi;DJ{KVSt zQu)+L$<5X2A7LKn+CPHXJ;hm!>TOD@264WzCjVDPpHJLP1qM0D^4+ypqV$!#DVR@w z&Oy)y@%bd9EHyoTF}*(`$o5nYLOEeCDyIQ<5nOo^jY=d{dy9^!sn1WcFNyomgdBL652gn>HY7cry#t2-RbmLEAbsC^xD%qk&s(N%aM@yLc4h`f$uyrS!t!AL zAuZ9myQ|fEU@hZ-Z-zX#WcxRHr1w!6Xemk}zOZV+3WQ60l{wG(K3f`}wi7|cEBn&{ zd6?&t$_F1RA!iZ%UnL6K&5;9#7!>zOPNMBpAqs+I;%z^w= z@IVIWI}p_x8Hi^r@sQB16MB;Mwhk|gM_~aGmuI?WFQkJ)`x*d}oMMKdj83+0OtB?I z6ju2t*7;V*D^nF>RauZXN>0N57 z)Z%!lUE`Y@{+ppZsojxs=)qF}L%w!Ks*LZLR%`ski42vnh`7*gUV+Af+@u;K|J?{Z zV#cFV8yY(eXu`%NVs-o>?WFs{b&iCIGd?10aE~BOc{3Ba`Utvd>A9sCf_>m{b=VR@ ze%eQAf4!OYXz<)uc^+8kjx&HA71Yi}$Y)Nrx^u@*^p!1qA7MyLx7^%b&f$(sU9$dZ zf*BW{EI4FVvHyplEs1w}+q6vYdIA|N2r1K1GhDu~h%ln9~M(4!(@MGXf5Y>Kdo?>dbLRAO=A2n~E@5d7Zw3dQi^Jsi zhrYcU>`>7ZJih{e z0eWKCR{j**GoLa*EL`w$qS_bkh1Q;vy8t*!Gz9HOG^?$~^23^Tv@vjN)h;zQxxJ#7 zw-at;$N+bNwu)E@^OJpTB(B_V%;J2|v7Av86XhcX$(A1Rvic26I6K07M`(WqiU z{nut+tE#=0pXCP z-c{N6e~V+p{gRDm1(FPp_}| zIxB%c&kJO4mqie=VcLsTu(*kgjytMU-)Vl#1^fFl7As-Ptc3T$Zt=Z=V3H(6u@iP0 zi1Fqcx=4(NAAZ5BPocZNw+&)~k4v$byXWKCfbjc}5KPU8T#nh*6m$LA1<|$p`5rDF zgC{pim!IsRb(=D@fJpenpuG`poCgSClr=PcI5K4d5EbeHO8Y37$3iAiC)X?g4<%kw5!Ylh^D!zTRsIg&G2} z4Q8?1Aj!})Y)!i)7<3I8#8d-=EQ+iSbIk3>75n`g9tQVR3}VV*?2d60{$9`p7$Y1* ztQ2i$nYO%>rL$ftRjP}sK09ccc`_#e{`Vow)t{&-KNK^#`jO~ERgfB#1ev2( zA(Qd2H(MxxV7Bz;sWW5cwx3_~JT)>X_<;>MejXsdqeUO6NSY`*2`}G%`D}(7HbV{T zctpS~wQAXtjmAoygpF9CC^F63CBW&uLY2Mo&BY8bl++%0E86bsp-=>X-B z>Qk3rJ(vc#JWyV@D7t?F+_YuxD)4v$O^>6a#Q0>x)Uf9{PKcI|@$8({%{(IvvV635 zXQ5skK%xhdjO+iNrQ38a$vWRKGWBl7zt$H_)7t=!tzl9>TU%gcY9q+xx%EvZObBb@ zxMS^#lQ|oWrhd+d0Hno{4Uww-{O2h|dv{Y6?39L&g8ZRg8K7H_+y?Ch;A;+Gg69yS zL*-mvriS54+z0-tA2!pYGoT2c7R*O#+T#HRMIftaf-B@Zod1S%#sdUR5oep$!>U%> z%hQy%nxAT&cnHQdq2s^>f>QDv2@-pr&;xI%tND)ahOQmppd(CFh-B9x-CrPS&4+pN zQe?1|%+_JNPhF(ISgCKQB};oe(MvxZW{DHmVW*O&yWnb)(Xo1# z#uCUrwgQrIi-IX|-wx&_0z{CJnP5U9gG9*qBIe?3jtMpV!_^2%nXC1h5SBTiiOf<} z9UzI58ekiYeEMhb-XTE5_Sd`KgT0(UQsuOs%yIdF%q7w{*{xO_8I4V_-WUrz(}|d2 zZiF`7#*x279#h=3@>tFFyKE=|EVSka1F!-{Gq*~jTPWqGmXw-3^2-N|Wa?i1k-9k9 zGkF4dowzq-_>h}~gl4p$8e@u!Spieii-qUKdq0Ro=3?*z7Vt!tDQ)@f038X$W#7~QK;uI{OPcDi;G;x+q~ZF8b{3e$ zXe{&dN8^)4Ww-WIL1rDq&$O*qUE0#qUJ7*;SG-_EjJi z?t1c=m$&8s_DKxc$CGg*$F_p@%+uyv9csUsHud8PP`}b(;^hovC#wjXv=Wl%-oj!8D#lzjw!kXOP4szvxICXLf{dC zQHaOx{5V*8rjTS*KZ~Z!R@sP`E{3JGTOIk6(MPc`&-ZI*aWwk*d_6!=b|PV7jnA3g zfrLO#ajJ}v2R0ULUh#Jt9^wi^~Gi+BQ zFsnap^0=7?Iw^mvI~$4mL+7{9R9p0s4Fn=y>9Se?wr|Bke;@Nkn|+hen25!W{+_{= zn_)|^QaFN8Rt)$b4rQkasxGCN(;PTxIoJ@8ohA-f9bLrlz{ILstJg3%2_D7TiY~5T zGvQUo0sb8Em6H9hozMTZ)n`BOiw@x<^-Vx2A^}N@5UzlXCVe#6)0Ca`0F<3L=&AQA z0X=c;Cv5F50Zr2c-mb4!bNMr}y`PM-GeHw(kNraLBnP;2*!IU^^;@t|>80vlS+F1= zsS4VFEeBm6eoVzRf|e0lc{Q}AWqdjgLEjsAKeV?Zf+Q9NeyzB!#a5~M9fXQA0uD(4 zar}rW2X_Z4`by5Rw!aq9j3bf21q&e>SEXQ4I6{QkLN?&U!0Qk!t!X$`XEdf23%+tr zB^d+*=Ylm;0Bo;bv{KSMl}DQQNwy?Z!NCa9Z-fKT+R-e4QDPi;lce@C;$FPtSlB+A zn2nn+{16fIlvak6FDC%aimy$gI<|vxl#o>8_LfWa0swlsy8{f=4P{OlnH{8&I4Sh~ zSG;%7=r(Tm!0)37F;ghz0a)CYc9}~*oer7VLZ&S*3v>WT;Ceyu-?Xcai*8{0)z|`^ zopjZEAlsU4<8}dH^jp<&0KWJ$sWMHBE{SEU`0mNOgALOf`!8x@T;L3n6(YPTbL6F# zXe>=U0mJ(YNNpV#K`i684|P zOCLI`s;bFn>$P;~^oi%$E_)VP7!iIMd%S-!{gHhWI*Ha}$)aO$c&PxA~EA!NE9 z?*{w%AJ(3Wf+;euH#Mo@cZ8ol@kRFW4uWNH2o}*B6ohhD3<3U3n(C=q;B!f0Cv<%} zw3N5X#@J05xEz9a*>Ic<%<;hi^x$k29wi-*6;q_WjhZ+D(TpUP}je!`!Co>Rq(H= zZV+_T#?)YgMkm=ES(ER7mIH!-KMf;Ws$3GFZksyHqG%ckGNR&C>prmv;8kB|zN6btBps-1(TfA>HiRI6k4$C81 zAF$A$TzjAdWY6lr-$v{Ku0GfdMPfR1HV^b9NQUHhqMJiP0rv+c*#oa%V`-Xv7n}tf zGZHe*w-Z&2hj1<}00BI)3VZr3_{4Vtc}EaGbq(Y_ zCZ!+!ZJA5CA|QM3FS6&^@>7T1gt=D3QW79~5F%Ob1Eq^F z=LT4u4Rx{h6S%(Zh>@tof(TGJJR~E2K*8~Maz@2&@w9}{==in3c~*1dxuYjw2OmOG z)e4R?V1Ad-0ezJR)ehB5fdg1*C?s~K4Z$&*$s*Yptd8hg0YK1fmW~@2iG?FW-~RXElu;;Lz_b7fQkQjRfaWHE8~+u_gOcXAesFTSvHK5{ zfNB7;A)HuZ3d3B$JTy6CIj+d^?JICFh(WMqKow&`XW%Dey{`a*zwzAoqf@Q|1^z$) zTNd@u0Mb*nfS?xKR~VKT?El5RfQ9v~6nvc@=qHEWHcWROuzTOg@^44?`NV?D^+Y{a z0qgWHA?or# z6M{^{C7wn;(t7&kdz?{{u z)eSfcV#_sE;(}j&?N#et?Gfg{P4Mlgq*(QURcS`BH6#Sd?gh_lxZN60lbe1Ugg)~yBr@ZfBaE&;C(+kEZX3DV+*pnM%LEl5zPBTolj&$ALu8cyUgC3cLm zV9ZLn;$iQCDIp3TcmMbqyG@)D*D&(k@X|JjKeRqMRS-7!%V#|Fzy^A%TPP%GR6mRv z9!bgK>@QN6dJ61cza)bA9+3<%w^31o{^7X;NdsLw`>oaM5v=>XEIA8?oojPV1hPu8 z(c6xB48YppP_^=frZMUH(=Tg$_s6T-0#Ql)Z7!JtA; zkGo(CjbxxzoLfofz=4vm!7{8dt{__{rU7>3!(?>O|FF;=YLf+xDBvyo20Jb=ME6A^ zDBbv$DW5-DtJ%*|SaB;40epYA4HzT?451pGU{KRS;o}4Z8E#luZQ%(5+}{191lWQ8 zln-F;xEDf@c+~aUc;rp{ZYShTZ@`D4Op$o6+GiunF~9A$JIdsb>XkMDnsq;eIj-qyjfzetEgB5)`6~=|@G`IL$Kw!e#Pli<3s6pLHsqho6OyzY> zbFKwvM-xijX-FJ|Pm4gTX_j~|m=0GnyQ4@f6xiXeWp8e>fE{xvatQSKLxmxLL4G=` z$-Pe40`Uh6yW=7-;NgkJ#3KNY9HS%_$&h*>IMhCJEdZ+`2@E;Yk@ODiLxvqE!(!#s z33EFCM}gFLFyrC(z>36?185m8DYN}Kl&!YVkxN&x2wPzy70v_f3Igo1zLUcx3*rwk zbO@1QQXORZQLrdp(BlCBIu%5p-`)vKN_*x=34Mo@PG&L4qxbI$fk!TgMC!O$?f-UC z->z-&=58qbO@1j7mh~55ZUTW+vWre)dD7KpXBDXinQvoH4EEXkD0*b|h2C)Q#N|GJ2Tz7UUk zBdEQ2u?w0q*oGyKM8Od_R5A(*k^l@x1dIym%QLSfv8=`7@Lait@G+_REXEE-NaKqG z;-UKK3=yck$WY^K4d*fNY#Wjn=|7;IYp?57+jPWd2Q!IJ9xelb!ru#kISKWx3A*_J zN_SDSEJo_6*FNCf9Q1Gk8{0?Jgr*qo&rNK$K#RB%(Qti&!XYgKm~7O-%&_&Pc`fqSj8W{&oN9Wv;1@+1 zFp0Iic1)?w=fFz3J$qM;C9KLJOBd`;SP&%ES=&Q)(M$Ox9=8r^frNXbm4X}z3?M!# zQ2?~L_TdEWPfdE`;6m`thjegDYldq^RvUOu0i{yl{$rjKEc7;KHK|oOh1$1@TO$O= z612&uuDk+h8yyG{fmt6U&*_JaFKyiN!5YM9#MNyi`tHE|6uOfw&#INZ?^{-k2rQe# z1XMrSMDJ&wOttVmEO{e|;*WIxgGjmuz&HZ^qeNX76bHv?cllo7U!?_U}b1Ol2_^0`zH6r>Nq5G zNGpRG-a!Ov{8aCH0TG`9??ILa(JwAFZ#f+K8O%&I!`BgutV9rH3Z4Xyd61yHu;{GP zR{N8C=|oT~MGQdnH*#u8Ypf|g-b^RZgYP^SE80UR{w(%QrxWJ#<8(pb0$xYXSqqC~ z{eZ*IoBtG>Z~vdLrggqM#}PA4Ohzj^Sc3MWND`RunRoXKj?wB8)HN|2BndI#Lj1VR z0n-UTZ~A{)d$)n3s!NEZ&>?vB%_^;Q{RGhsF$7wPjW*vw&7W@uBhze6yxF=400A>7HRzgyeGORbGjpok-Yg%@cm8SL4-jWt z3JEGbVzz#3!*iE8i5Kf7<}z(rjxxO`z1FwkQ)W5n zV6$Kh;`pZPx*Kib4O}FO52f>R^{<}TET?!6q z@F_&R`$3qHjytvSfOk@HH7i<2w64BqFj?_ow}DDggRus(WguTR5WxY$x~F$5ge)FO z_y|1+yY{FcWCoZj%#{pA2uwpqu^D;54kqnw4l!|r^-z|lW;R+i>Bjh2DWy+X+LP8e zv81dH7~ne^;J*qtU9=TrKV>SitRBp8(h(3m6nAsitN>=~iRl*Svnf%)crc+EC3r?_ z0f!fRb9mVU{e*7gckq64U*Kkf!)!Q-3$YFD2M4O{(ZNPp&Cvu!*%9ZzlGXy}d_c^F z55WKHHtaxL5!!nsXVDV^kwZ-S(=4EYe=Tw8^+HUcTxXYj4~{|#Fry4RWXi~q-N0?h z(a0Umeo!F7WMwCTYb6Tu1gE(jb)52*5-nO`kDU;N0~W$OwR2<}c}dDGb&)B~?yH~S zFkt1S19`l1(N5K;IsyX;kv`Ke10d4M)yMBZ#k@V&HGWLx71UBVJl5B6dbO{>T% z9w~}j?a5IIhAtyOm6-Fw-U#i$?~x%5P(p7nus>5L`GZ)pd}*KpXvizfH_Xm}Lp5`; z?qslys^DWpea(wcjDk7irMyL;rBCj2+>Q$Dr2L6aSOt_LshH-b=@LNkd)<_03^ zQ$)mKJvTl5CNWlEVcVKk!kq%+0%aMRW#(kM;#MUA)eF7q&VS*Z(2@LH;Daqk*Ni%V zHXY!`+`U6$NjeZat=oVIkvn}DM&3iuctV>gs3so|y5kw|u79i1Z-$k0&&1>vA+jEP zELsZDjS~1RU`MQC_O^qBEZH|twANlPzsz8=l1>#NRKTgY?x5eF;AXM|+>9Otelc3(P1Dm({?M%}zxTWB8!-VvNd8kGR&oJY z0)3bCRw=*$XpuBwyt*azrSl3^q<&6W^@dqWV#oLGtKYShw)URM>XDevZ07}PiS}mg z3@30Ml0k)Zro9)@6nH+n>E<%j8BOmUrI(uI617nvzb8}ygg1w7EfdR6jywKKB5ApN zBgv555s+xWxb3}TO?MkMRsUr{8W_aMvA*`di$Ez4Wx+4_tl{cM91Cb)7R#5+N2V`al- znX9*K4BJReu{yrc``~C}iSf)h_Z=l%1EB1lHhWdJ*RU5AKuv@#2d>gMI6jmw*zY-7 za=0%e*NQ>}qYKW^34LFjM6(g1jv`gw`-M_;)`*X(hOcU8sy|WU)YDbmcT_nFvG}nM zbfk?;&jN_W`4R8np_|bI;!jWnr9!CH24kDK66HPy-mK=VzM$2Q1rSNG%Yo4@NcP+~ zL0!wuq(JQ<-vyFD;Jbw1BhTd(KEer(Lyg;VYKCG9V$xb)g5l=wuwW7nOW36k-*qia zNft{B+l7C#yn#zT)xjN}wzMtBqz2cJ#>H>}qa%=dac0=j=CkS=lby|;Cght#Sr(lJ zU2PR{5nK3;OoaQH&Y6u7Qt`!LT4+C#DPbOSvO1ChzVonApGO|Lu=`n8*e|#r!!m3p zv*bGMZS+fB+-NKiQ%4K}jQ__j`KFka&VmDtr!FW7>)W*9Av9w2>ovcpN^G#e4O z1}&i@$h7b0DrgNBTKJUWGRt>CY4}i|YD(f~z0B@_p>)x#$vha22;|&>sV%`6)JQY( z;Y!jNeptM9<6gY0zWVvY+eh=r-LC9}s`}W;l})5O-bX-TI}1QbusN&m{QC~OFjr8s zc(RmI>3r2&<0{Ha<4&Mqkm@p~b+)ja<!0-v(a= zgt|1)jL72;aYKJrviYxuncwpa`3dSd9 zei!^ImTx^h+HZ%{N)Xb-+l1 z`spy&Lpo6fyQaOz4{>)&T{ZF!eI#EQSa(M3l7Vz1EB^g-erJ;w@s{zwt~6tRb1)iO zMzV9Xh~ZcvBLT+jKhuBK@|`OyZ$0p_NtSuD6?I*G+pTDIyXfZHbG`kbH6amTo7ROK zWr6k&`>21!2=`~--(8#(o0Qir-uT1sZSw4Og}*V|b1jLjGoSCP6Lm7%ZONy=TK&@q zgik#8Wxh*4TXE=iAH&_=sWbA1o$p_rf{Oh=HP(o-FDw2@{X6txgmL?IN-PVT)rjCX zfnK#w?w)41OW%V@2un!9TyuCV`elW1UU|?%vBv7+jW0j_PT44@+GPJLo1Zh&-T2E` z8e;q%GONg{TAPbas*#&7J1+?zKD(&FW*JC5l%A%mp*|=6D^}A$V>p0eofz5n+#tD1>7-&bl__q z=NDLOIbVSzcwj>zdr(jT{s%djj|hef)dBsYn`^}ZKS291Acq{m0q$@sP!x7n4Pk*L zv{#5AbC+w5JDkr<$)?N?Fch?eoH2sN${c5oTJ|CX9Li_>2sJ=0*veVV6ZRG$$MBtp zP~_$;{^AR)i=tKutueabdAOrNnHz1J?5p zC`o9|Ipm*9^x9GKieElMfODt`9+ZaQ54286EZ9n|u)04mq8Mm=MVFA@T;h_ZVl(Np z(lAeRlk?eHgn8^Y!DZ7_eBukJk^k~O%(yvX2pfYtPj=D04kvw%VO1sSFqj%Yppl%SK`K!^8T%QAP9qnoZ zRg*u+-2p+k{11k=;kCsNZoV;G?5yjvBl0D1sbUH$VCq?-wT(0#kYZ;ZcoA3gfnulu z6JxVMh>!%(vUEqix6Sq_LcGl;99r0yCQYR$tD(Q(BRepD2<>yBg*`CH-hR~4MGkO6 zsTO=53!z6~K>wF5ZR^(mV3j|jr=bRZ-)yRYo@Y%;+jR$Yh5QnUEhTq+3q1A1`ZLGzJ7u+C@Z}=JJofByY!BxLWWfGEsd85 zL}U-{(i0EZ8M=y1N8Z6~zLPJaZ(nHyZZ2ENv(WW`!P@q}C-WqNe}+J%BmxxS zAKHD@|GW*vfXlH&XRZN*wc}uXKUx9`PEtYhd&S{21EA5ZVG?fYO;8xlr!ZMd`s@!Q zE5Wc)s4Ev1%{8Q*5hN1~Kt`OI5!`6lkQNN@pCE(i6Ub3^EctZ*S+M^yZ8)6=iUv19 z%gah3ea^@uw~L@W)X%?(v9F#tNuQ|}lu=RmY!@WPH(y}y=&+gM-pQ3_K>qvN0FIkz zSX8cL!yk<6+dE%pPaL_M+o67b5>_*XoXC4?{);oBxpw!BzKNfUl1#q8hr7x13(w0S z$$0QrU6C!j4qtDN%G~?kmZxX?SG`KQO2oMKJwBPXQnW`ly!;Ny38Q5a+1zA{>{bLh zcLHfb*LCv=?x0(J?exorx;=?tffEI=z040Bobz0^CI5A{ zfm4u#L+ECwNX+oEFi~k8JH=WA-Dt-U)SiFuNO~4WQmzhrV!oZCJ)#Gnqc!CO6Ul|} zve5oayZH1rm_fiTFmTl$`0%)i*=Ku@xeb5SbQPYBwz#>9zB20&H9lwO!boIuTGmk` zSSdlT(UyxGBa_pZ_daeWcT&;K45Nw_9K2Lh$`2>qqy{&2Qq#Z-kTc3Y=CPWJ@AV}5 zGOgp&?Iyow!n}AAX^#eHj@TpV=^%cIO0~;+)nwBOYx)}yO2Lxm1>a=F_ov>$FTA;m z>LvHo*=TIk+pNinmbTl?9}%qmMg^oj+66no{rA{=imr*&HDssTQEAT+zG8NX$|r@Z zQ^Qi*L2d{7iuR|N%dFfx;(yWJ;-|q?EO}ZApoMUJ6FbMiKKa3id?~uRDlYoR++e~@ zg~O3I2vCotk`@Lff8Q|Mc-Wb4W0wsx_Y`uv4<3pygd1PbGD+<0`~ZV)j+}x)&>@E- zXLafAdiSlgjN%bK;6ZB+34?Bc5?mI=2Gv%A2;8bD=H5IUYN32?k^Fh|bfT17>nE+& zhscJXpu%$FQ`W5TGc_k-<88ur_HZTYZisrX6oJwb5gRRl^Di}^%m zcwI}Za_8a-tO*EiC|{hZ6xT~3%_U1nW>|jhaO-@12@#!1`SpT-e=5%Yp7Z~=`tKun z0b0JpV2hp)r&q_srBc)5QV=e_UIj;-5R~VU=+$<|QHkfq}PAKIuW|DD8{C=YN1kSCj>E~4Vn=Ju8HK3E7V z0R-L-E`Nk>ASX5uWH7P%xrMUzqnQ5%yW9ECe!=v3gEsm?c`a_fHGaUV>e`Y!&LEUk zN4qOdDkP?1OE_~4x)4PTEp9T5KA*hgf~}dwSHQF=jlk`vh+cUf?I*rqE5;{(EHxqD zO#o5j?YyW=8-RW*+ZV4}wQlFz>2?@!01(XkP_1+S{iK$n@NHKsiGfVJxO6T=5O|OZ zMu;GC)zxakz%y=?nx7(pkS_>jypwx@ZZ%LtxqK6Iml;BI=Q}cPZU+-!{%}M`n!8lV zE@=A1WE5v*=nBijXzND{Ucq-4hNl*~?+gn(rbs`gG??KU5s#C1Q{$zTgVHh1*AMM~ z7>J_p9YeWMx^>|zh5SsnDK6dSod3^wcs1sx{fQqB0>^|(UFuh{|Bsi<(V{;nK6rS_ zXGZvExC)TuRUP%s3R({# zyUV$NVzz#vEDehb-HmOW-U+6IGST+3i?`Sl6BTsnG17J!LI@X~L=7FJ=9WSdO}BH< zZJGjo{6KkFpa8s_@Ybc19(+YmAh$`<@HDKlZXK_dl(r1+oIhC$;kuJsH{S^Ul{p)Q zb!h>`duj1=+3@nu(bf$}4IEJSwo@Eb9J!t}T4*$mF1o;v|HsOwR?4%NjeA;J)6)K- zZ17wG-A@Lbz(yBUFe2Lzpo zMg`=y3SOGWXR6~eU~obm+DCj~)H z|3ef|k#ljBtiHZ>O1nPAIwRdq6CuK;i3^+bI7nK5?dbkj&1G-X1%$EDkQg$*$wiBmADZCrWLSH0u>m zP_bc~)=_K5iGZ9Vh+;`c!J{hx>t_3rJJ&!{78kE>kE}S3$|YXiHvhHPgn_11d`dhw z3e2XCWJWPu%*f<&6)P=%1V030^qu8gB3_zxQd2Rk+%~+?UKs|2Q2M`T_MfMv>q;}T zG8VbwU!!Yzq86XY5A4w^I!Vg@eTSZ7Y|Z)6>cAak>E62fHi20G;#SQaDm@u2+-grIz_ zaC!Jd8uTt?z$bUeAHrXh`p7@Np#d54ck|6)0Qm<6r8x3;B5KHyzk`D~#Ec>TutKqf z{9QaA5gO$0gpU6|mLOEJUb*eIegnocWQ+EP-gv%?Zb~<44MSpQ!ZQ>PdnBG>=NQ5C zz)J*#7j02*^#);;X=?#G3BjKnw0q*>XtCe&X-xcv68s}gAH@WB7!7FZj7azP@CxiC zqGim55lj*^6H9RTMbJA5k0+2(raXUWz<{yPx8dD0(kBUD%MW5?)P|juj10uSdV33D z3TPY!?>sxlH;ed2xdDUVaYU4$v_#n9holb=bW9el{@{x9_3!bbWWhxM5aB+OsfOCy zB?me_%#LYkz*Y>xqx~)BS2O~!Zwvki!oNL7ol$dsji=aw;)N7A5e`Au(cR}f@;kz{ zmoAt%hpc(=GPLn*n4~DwgR}}uSzYs;RaLDfa z*<(u9c&;WYxZ)rDIf%+zX8%!=+mJM|%f}bAx`019sPUv#rZ88N^cvSC4gwZH($3opWwp-^hbK4_iRcyc?OLxKeB0cvNc}?LINbsFE(R3_xjk(+ zVdyiyyuu!5;%_QY0@oLV?+>8J(Lea4=2pHbuWurFPLqn>jc_>acibK@h;aKtNW~wE zk0=MD%G+E(!c9bUlc~{2!dyVht^_`@gv={YTnekpt$*uAIQ%54Eoh;)_A4I))#KpL z|Kx{LpvO}eZvTLwQ=4SD+1!ro_J4^oTIj^tdp;>h%mf`onJ@DUwMVlE72AtvQFe}Q zeYUAQP{*0}bwY3YwH?X_0h>T+a3<}Wki>V28=p`+p$;$0hVp1;rnX+vZmWJd6J@;$ zvsK_NfFmXd>O-}DW~Lf-R*jWC?l7nw(I&E{iI9oru3cyBiw$JotL8!o;mrbSe+xO{(irNMC;UxED`Dm;vrk2 zxY=gGGzeY$_FQn;blU?nyMn)?eZJziV0M({L;R47d~TMLTJ44b_hF4&p0qRzKje9e z+Bw+(*iQ6Jsad%rBD9QZ%9AhTKlf8UZxEPi?e>38v%M%U039lTu~boPhqUC|$=nlW zCpGri{~@6p*+4_2>%h6}3Ql`4_Qz$ey-0Ee33QPQ$DoUR&lXueIqC<5@bTe8xV{OYTD;F=Wbu5R!OTF4BY0%b~>{FM}j z%bn!&?cVS@Xh`_nkbLn;O=3y8ddCxTSw0N&#oe38v!AfBLHhN#eLBtrqACV)`D8a3VNsmgzK4Y&D)r-6QX&2ua259dsZeYmgHyv9%E%2ul&~|*Rr&ZFTa>}Yi9*-$Zp&mzu?=%tMC*mo54hp^-pca zQoIV=Y>(aPlS=-(ibpY%mm+x_if1IMt>CdB|})S?WaaI5oq z7SDUi(xCgg-*mdJ<|Q2Gf#iqrDHG@XKgg2@F%d2*r>+P&hd1?>XkT_&2L$vmPH-w8}1*A)tK8adp0TsT^rU(g^c?>&p@HPt->kmo$C z@E-sgIwt#j&{MN3M9m^M`GL?t$0@;WWu%fp`=y)D-kL`@6}ebE&&IjBmjy;2B54gS z*4fcLZvhI@*ii~fJC&|X9o;|QI*IfA(NSi7Oq=B@cU-m6!oIIp&ma2X5MVU+I7Q3v zzSoKI0J!q7V-wH)*I&{3xPn7&c<-fdJMiFP{HMMxqE7D)txB2rYef3>9V-}cMK*}) zRP(J1>aXY%-_ofwRILY$h1L@$sk?Tcbmn3UNl{xW3_e*abZI}hEx@~c1HQ%&qQalK zhfcl?zF=`viR)^{>O!T_;qNUANA?VJeTV)Sr%ulYwa5Kl!kMjmS+hwsW?ir|I<0tk zwYo(tvV}eG>UVbC`ziGgb9OqN73QxhJ$Px<=!wv2CrrYU8J__1?E%fl|xtDBF`*=B2 z6WkYji;ktIaBJFp)5CbUw&r~vyHg$f!Fiau)H^9hy|_pOU|nxikN{id;s{HsFe_;- z@DBYVKrNiyU;ah?@8b6}TK9hapn9%;%NTl|FE~K;Vdt;x9Q5MI4v9EHdfMJwHW?xJ zcOUQ+G!PxdC9(Zp+Pg3z{NMGn^8~dCBAGYf&8$|J!^>1%&Bn~1+?Y$b?^?3U)DQef z9ReKr9K}g$&E-CQ-N-kX+s)6oh@oPj1BnNfGw zy1ib^7LVxp7ai9(m!rym{za*XlnGlklUNrq(|RSY#KD&*&gh?2nICuB3D!Y88v<{` zf0z=FnQafFzzK-$^kSxrHS^y7o8@s0TLm5v1h3u~Vlcl+Ewi71PukJ2efdRqB_#xU z#&0BSxoRtKOap`QznM zHhVAn@hz!Qid^==FCbCJRA=Axpoo$pE{>pQ82o#+_0w~`TG_e0@5g>5F~!QPKEG`I zkT`A z0+qNl_Mmzq1&$AqGL@+|)x92DKK-rT&7*L4n_^_x2G^IEHsu40A>a!dR>j8MkplJ^ zMqBDG_-j?xEBekFE+<+y%=cyYB=M@Y?QQwvZ8mwXn zm6Fa&t=_4-zWdMsj1kiaj=y_2b$G4?Y~0A-othZ+5Y*fXHgC(KE*NAARDa5p!#$Ij ztIIXh>G@Vcs>v4*s>9p*+?8PvvO@Y)6>D4~UXD)ZD%@DQRV zB)&`UY=~s@`&edwZyKHt@*(E;tmwabv{x`+s0#9^ ztYoL%&zO0BOnJ<;hph{KN6#(Y!8~Do4L*={T6y+|oz#$VuMrOjUoeP#O*JJD`MAX6 zQ(ki_@u-MwS$ZvYW#pGmj*G` z9yyL>$$lUGKAE4mbi+h$28SPZ?LF%roOY|R@^c54Fa4o^E8hhx+_^DpMzWmQ;sG5| z>lx`Lc4k?^S4F?H?3!Frmw*Z_%9=!2bK$c|AKibue;9i&S%v{KLJK3AP^ zQxNXb-okMZp@&Ej{pOup=-fN^A-iZ1vtWDPuB(Q=Hs3Bc{Lk>z*OgJmb#8^05X&Gj zhlY^`RfwIv(~3P{@!gT;ws@hd!~w5mhR%K!GtfBhCQ8bx5<6xZl)8&-SMconHb>>9 zZ>x{+W&*%o5{7c%>kM;_t-spK)0{eQ>0QXLP}xFJ8}D+r8&4ez?sqtDw%u09GAN(w z=ByRiP*Yng@=iI+o{_MD8F{h9M9aqeXYYGvnj&FKa$YpxEmB)L} z!>=xPcX~?cDJvWhc=|yotH#MLOej(gY+5KvwPGXYe%jdMs4ici1-g)!q$Fq9;_obD zBPZ;XYMhs}T-U*e)Vs6(GauzfHCE3^1KdVk@cq?tLWY1JPLTDei*T+Z%Wym!A7@)m zSbc%z%e&RoIvI2<{q|L8Z8G_Iwq219F|-SRep<|1!}lY0CEwyJKiHN-?>N|2jgj-C z`_4+ghGY4)OLLc%`@}IGr1nKe&spy$`BjwQ;})TJcjs2A)Wg(CMWM~ zYd+^s!WPI$u3LEO`s7&Q-FX$JRJJ|DWk?3kkJi?xvTds+%VfAllr~yd42`{Nt)z^~ zPiHPeg<2d?tY5+{qd!$=R1-yjYom&!VM3{k(l1mEPKD%mz2A9B)pRY1U;CB7{^+5y z1nYagjZE9lPCJLN0W!H+B@nR!Z;yE%D_Fv4h`4qzHV+( z`bmnA^vyej)848yc;6c6kx*S=_ilXr?~=Hb=*uZz+#A1v?LUd!%@+#Jq->Nh4==U3 zR_ya#`{%>;#^UYr$o-Jt3L2v7wQ}YSd_iZ;Wo)r+b~k1S38 zEjcJB(i-t?XfiydQ|rcsx`Sg@_Vm*x720_BqXp^RjC@(aq#9g}n;G4kJooVs{qWpp zQi?U3XBm(`^zMb4qld4jFHHNsxL;4!sJk)Z`gg9rnz*un3%Hf|r2us!5$ZgS4 zQ!R~OxmTnXCx=POlz8-e7rUcwcEQz~M(g;yUxi*v*tIWC0+|r&^#eSsqF(l_ePMFi z<;DGwoEg{jI`X7nvFy=*J>xCLhwsW{N?kZ=W~5Zw~pKqk2V0V=8G{ zHbMKXHh$-#f?wj?YXR?Bzah)hnAM_U)9hxcg(;^r<%hsC1PdWohP=6Mq{-Jc#HS|G zrc`p{=#RTyB7YXoZ+UK35$6=z$)!28()lxNmFvWxgKw_{d{FJ)gCk$OHyIK^$5_=A zj#owVn{dREz7{M5R3ukXtmCF`4yJh};~wnSb<_B6$6S#)K}lph0*fJswQpp5u08r* zcs-BOy1Y@Zl0}j zbz3syW?EHQmYEVpVUSvP?^#{kaT#99LR&1Z9R76VPec!^)c?2E*}zv%F|wE5jf*C3 zd3pY#!dEIb@~%Q*>BdUL5?27$pX?M-a4eRMUdyA(<}}p#sg)hCI9tGD>@Z=_NtPL! zOrTd%1j4g3GDf5(C=NAOB!X~daGLrCay#{naB{)ZqJkimmsqZN>fP@e+;3j{xpPJq zfZP&!x_cqT^b}X5z(7aq(MwJNz6*gn3(U?W$U6sj*)3x#QiU>R6Yp&JCgXjn^DaYg zPm{>5;C|12=TwsF-D=^}fiuWQ1kPO3ZhoQOcb3^9DpPQN$HU!~GSeM>H4A!SkH!)M zx#U2v?+J~zk?g&_83Am^{Ojz}9!`DyZ|3>u3vY1Yx!FU!6{-1=xX|DS^<%aCLD)G% zFEXvnTDUxS^iX9I=l}yb86*uAdLUO%JFI`m-FUm$o~7*$E_ivVp{t-JMeJB2y*Yfx@v30Kf5=V2q$>+F)YJoP5F^4u%y@Z9xL(-lhoWqM>qo0l23zHs{E zKu6(&@ex_l9ZW@6?VoNBXYWQg>UN+T4mFm52(r-kgqxxeDnSThIFDq^em987xb&u#f$DFY%` zWadR*sIf@nKOA;ty0&?DTmvJbrdx_jR-^mY0=p%#`Ho68*S+u~D>GbgTT||R%VB&U z(0M3rY}x7eWo)i^Ea$!si=i6G3Kg;ymzQfj&CENmRrJ*8>$^bH z3*wi2#$?reu|-C|?ZLYCnD{@&^!m~*pAIUw1NDgbCzaKgs~a>V?fqM@c@{jAwsyB8 z1P<@8JP(2{yMk-s2P_hor&iw2*JN97(d$d?^K(>V?6NyD8yUR+=|eMNMOUIl-duNC zn^o(=J<_aPLRAYT$7*d(W>CmMqkDi$sMhTiV_J%ry&?$2t$bZ-N*)R`1=L36_Hym! zsoFa0>Ti)()ityn!zSk%8k7X_y>%7MTp>l>3wFYHS3(M7z)hs_-DeNib*z96yhSA4 za0t8SyTum6{VbhsbL8;t*-{aAwmmdD_c&W_Ju|8%d-cX?Kd$CCf$3juZsLW8V(hE> z4v20c76#2!CB0X*mJ8fpCCcNy`tM)hgJ$L9dxGyOxdcpWRecheNeIU7oh`5sm6Kil za%f9!%rGu6vdUy$PO)P6#ACnYikcwZFUECp#{X7J*((Zyok+Kx@zQ01g%y1+WlCnL zq~k+JO9Kl7HD}4rg+Z2s{SC+&xB#NKYvKgojO5hl3K=J}Ir(O}VXhE;+yU;<|PG z_YymO;fSpZk9z3+mIA2nCj#QmsW3FXw}QE_U1n4dyueh za#m8q)t9L7BH`PHJRw3@KKzi|V5Yo<`D8u8;0g(Icjm?hdVNjvkesx`%G?SfOnap$uqT1fJErxNeS9seypw%(vl^#`&#Lnb4=y2BF>Gq{hxOgGwF{hujK=5 zien;`GTw!&DuNH77gOdAPWu5xDmv}hC`0~5*2sh|ZM3n}dQe8(6{e{1@qa)VOnllYu>X4Ml@a)F^r6Nu#G2bz5LXqLrV0GxmFZVA1iJ$8Z2?gMv z3@R=^Cs&%C!?TmK=M+G|GrOJgk`zN0a`<}d(bM1j6QArkZD0RzY{%|Be5AWGJ6i`6 zwbKAl+s!}^2w*xa$RL05FSFeje@T)p-@dMEhRYcM>SV>p#fESAXY~RZw=^o3DTwoJ zHRJG0J?O$qMcHz!!`uPW&(bYZ)6ov?VAv_l<^{st-ub&ufPXTDS~zLyoT+K=ob8_f zoyi=|Z^pbqwy7_t9csj$G}mz85hW7x&4CYC_fFX3j7Ce^By@4MU7ZQBn8CB6YHyUj(uxLDK1i%_j@ejOgy2Sd9 zN$~S*wUXrq!<2KTZtS$di#jv2@dF?K1XB*rX94SZXV0f(REDGjOZiBx^Z4Rsrf%u} z^Un#&iB4<`--cR$O>Y|ikec(y=1s+$zTV*2yQ1!}DDg>tId(md!cL4h%tK81^rvsb_LN zU<{>kbI!zWuVCS8F3W1kNzoC^Mu^hHTZT?c8?a+@hOm+{ieI*5o)btcc<~G(3;^yy zui;tS`!j=T9`nPaMu7dfRfxImksp!B61xjFINw%=o|$iN--!>&a>5AAG*`W^i$xZX z&q(gtS(a=WV&nrUWLz?DLLD(z`1AAH2Y)>@rypwPbwZ(EjQvBPqIw~uJ>1cRJ-pNz^2C6?#~NxBXweP`h_YzLjstJCn6l-ng_ zDWd0xI6(XPfv|1->?)LT6qFL0Z5MF4*@I335vD!8yY4MZ6)-{m?x#$+ppZX zlkivEGZ%Zz_Rxit4e{c<@v>-qiI?yjh0lGLlsHAo$Q`BAeVV6w$cBr%;n+koQ%v(M z6PH|NC27;Z_@!dj#EnmHFPscl1;(d_34hb@>+!zoKUus^+#fyDv#TX2T5*0augGMq z(t30*x-JRcty0e#GE$s~l>yyf6OI3cFU$xWtum_t#~B^?brCHW)}78SYM$Sw2Tgiu zl(Gz&1JIbDhKG!Cc#)RbQp%5BA%C*u*E$$Q`H#Gbz_dv6Uthkr{-R&Y^O5Q#LNr?F zXd$L<`)ab!%y9B3EXl~Sak8guhNUzyTP-B3ZMZA_5ze^)0EKgZ(|tglRk^qp=8tk8 zxX`+i`~<76>-B)+SV+0LrI_Yo5KiXg{g1EtWFYoN)%kOF;T6VTOT#&M>rGrg<5X)4 z_Nq`!-C^>aG4q06CPYd9bB$gAJE{_+oK)tt83m!uD@uuRIaPUsNsP4@hkvvL;MHo- zZV_NQ!`Da0Z)b{eg6{DRK&xYiuZE&@Pg=z{l9VP~!n&^y@tG6rSD_nYVs!=J`*xFT zfs_0DN8XP{#R1UhGN;sP`KAH)@?mB&k2=Sc_5|t`ftd)oKT6&SBz4~EIhVSEt&B9{ zb^qQlas3`?Jf}PldXylOEzsE8#}_^yB~!oQje!7}1d@d6#Nw&wxw<4`3zsb=E=^^E za>mg}7x(xmglY!h4ED(g3p z*jY0%RFUoFGn@lsJU?0nwTfTxbLRd^FAw(JTPMd)VDJ(1gtexveca|@aAT6yYGK{BP-Csq_188IGl!(roQ#8LGfI)7S!z^< z=;n`vw&tU7A1s2e*_mDXK1acs@|ghW!7&TNr#lzGABg;(sme;t2Pg_T_1(PVg$)3SCeV5jGBgigM2 zeuy|9{rN_>WJSa>x#?IFbGnJy@`3E)%pqs5(g_6W1AL7oT0@yN=2QFxy8u8p)SFUN zK%`i=;xCB|io_mRzI)D5GAUFuq!b>uDjw{Gb5=|a&SVK*B1TS()zxIH#(0Yb*$uE> zoo#0O)utpb;+Tm}uAGK$rM!^&ifNqT`@T1Si!iUrO)}&@sKX{toRI9U@F6%4`7ukH zOxDZcG;2^N^xEFh96IRlwTHZ#UQJQnmdhmn$_x%aMl#EkWn?CO3YJ9b00^KY<)396M0nZ@SZ2OcEi*ECl87YQK;Txw8g9T}Ya5zv zt3P23;QuOB#F!zj08>JP?wv-kp+(9vvCvu7Cilwv3I%Y@RlKS70L zVGWk7K)5tI*c({I?^;09d3)^#S^`m0<^6t3jsRaT%->JtDr}<&coefdkfiv8ZP0)_ zn@!+ayrKJIED^{OR4UyM_6Am;a-8~z*5JW&@^`v+n?ch90D5F^MUPy+tQ*v*z7DFg z&A`L*pnD!Rb8U$SYvBDgu>qjn^QBLS!3a%>z?%MpVHQasXqZac{b3U_T&^?}|7MNo`b62yH3rK#^a8W9W=fb6LvONCj%eNW_0lqgejx26-isD~La6;;MHmg;fuX9*Ox z0Fz;+Ovb!I=Z$UZ_QFAWwSOJ4f>M>_+fA4!OJPeL2e83^D=>!Q>iZua87wq64(-+c zBrO#H5S*Ph$jYZ|k#_BCU?bdt>q9_I>5LMHBwlf$m-+4Er-AZG(DO;O6dX$tq`pia zc?uJ-D;TPG#(Y&1@bx<6t_#N81RM+2)MHlOd9~N6Tox?&F;95qXbf-z-b<@dF$Mh9 za{vndF6=7ozzGzp8jN%~(nSJZpbfp8L`wn27iu^&GsTN4F=3F;zkT%C3i&wA)Jr4- zCV+Aos}|R!4lvF4NMLbn+avbKXEfqaib&G_mjXon3P2qfDB;#GkIogzTmU9un@ikv z2?t7by7#aHWO*1BdDr;a+AQa$$C07ISNf|Jj5Owjt&Bd;cja;wz03fr<)yNqkq(&iHQ*hs z5(C1)l`j}0mbvIFkaV@bSK_ApNUmZ?ea9ZD1K zt)M&3_;(Ml&s($oh6rHsyhG+1J?R%kL8yiD;#s; zrujB8TZ_ikA+jm?-7h(dECB*`DEQLy$^6yq{Oa0#!WZ9U;fpr;7d_|viGa!HIsq!R zMlFm_oQhNgRNQR;OYaRhPP07pzdnDz=q=`PncGKLnHc~iCzk}#gUj5D04|Y=fFgM` z4%ZRpb@e#q6^C9V@Vq76S=ZWR5rW+S%cW#am`*H^Ek9*8H1yEVo#_n<(9(g?xibOO zx>9`M*k?%k^HCK|?cb0gXuPE;V+`p zZ}lJD|3aF6xS7$sve}w#%kq%xX@{T5XmgOB#n5xdsYoi$g4>{iv$`Sr|Gx(oDev^JFSZvVWZ9F7EX!#I{2&(9h&|znkM+NSt=5zEbfFe0sYChntEz1 z9PoDM(|*>B^o2*4txG<^dxLX^hWz`!3Eb%l=lYG1z01}iXdkH2-bdhkU5=pyXTQwc zx-0nMY|ZXHvLY7hpSN}TY=$F&sm(9Zm|l>*UgiC%?T4OHBR_Y%@{ZE@oa6o_n@qTv z7}RS92iQ`0F(pnwR88=0bAK+7YWDMC(KrtEIN4o_&#xxA-^jT8G^UZI0%LWN=H`fL z=0i;fO6{gLssy|Ku};;t;Rb#(ZWVtD^SB~&#a~DLQapRocqfH_I6&8a7~F)_P=G`A z*sN#p+_R17vvy90ezCQ1GCFK-)GtjVx}(2A-W3TDfC9HgLBJCY)KmBwb^n9Im=kGl zcMg~$hifZ_vd=({o2n@>P&r372d`ZGfj5{^C+fu&>MAb^f-B5zp(2BT}LgUjMwd1Cc zH^2L3v@9*vD?fE(sRfF3zOI=Em=4s%J4_5_7Ak0AzUnWUBoBFqN`An|CderelmC^*1QBNhn|{a%Fiy zhLvT_*%{?>!M={qe)6Exq7e0zo3xz7R45xZVa$Be#R}BpMBpt?F&H=!r zm}X}w+HN8Dn?UgIKIUTnF`3+C-;`h!kYHiYUWf%m32MxBk@$Ibn4gFY@td|%EWG)b zU`*}$pz16ACl*xpFN5^VcUkpr7`YLq1O*Dj?oy8?`QGqbs`?v+b-|DNc5+NS#@5%} z>~oOXN#iw)wJv9CD7*R1xh^TlHkn%DjGFOYBtCBaDqWtD+tJoT&xZl?#+jJBxZbxa z_|i|fJ48m=h5qk;p%Iws4xe0kQx5;||G$Lv6t9w2Xd%#cj!5hSK$R#D1g}w+8sX0yPcJT?lzCKX*eD1gi+`X3l6i zM1a9?vj2&@B{NbL(H{9wDzGTW1qEwp7#5WtLvr?$;ao>XV^U0rWlM)BNH6)I^x~cJ zN)r(gv?n|8LdxjW$ALh>p`mLlnlwAG(^B{CoOH@Oibr`;4SmP2*CQ$G0$K^xw`+cW zJDFQ!xey^7xnKz~;88yqzMzs;Wgf4kjC z@5-#dVFR$}6A=`W``!Mppqe@?b#0S4MXOD7oV#5*i1zr^fYq)ZlTg7cw`mLvZQLAK z{?${A!Yu!8zw4N&;~k>)w&DEPbm86E({ zAK(B$_=7nB5dNEF<({xsF+Jm4MNI~#lH;W8?@VgSmp{Y{0O1d3qoBecwhsW|e|2b$ zEbIZQ?%(a4%pU^!ukx@zk_Ui!f9Mkc!vBgs{{ZI?aDH>=KN1Z9hd&Yx1sVP@1po+t zI3@su|6NR>je>^Mb`V=WxLgwN!2d8p00@5=ApnH`U5xOLE%*=Y z0rdMnN-{0nSv~&b{bu*!ZeYcc6I!><2K+n}`JVdj<;dJyONlc9*SU@~H#aG#prBxXaEx4HqR-AS_C~U=C4>C3XkRr9(pO@w zrpu>9+UlECSR|iU<**nxb&jp(>Zx^A_|>Ft@*5^vp?aU-S7+^vvy(peNToChPrnO0(v&y!sD7y*oh6(mzc? zxY3s0ZoWHF>eSDh=Qg|L*M?~#?$||6p`|C)Pek2oNaB=tkJ(wlVqa)h>E2YsXQ9H5 zD$#v~{pv~mtI;4%T1Y%UIt-_6A%wQ#eO+2sJK?>QKYJ*N*>|Y+$~#UsxPY_cDzE!t z7S!|4JAn^$_bcM*n?YCT(zN2ZZTR)+s&^a2lh2Gq%A>7@OL}Xwb)NBRRSG*8fa}W( zqU6y=)q6erODB;Xk-6Qh55fhW0|7+;G_9M!8lJCB)Ll;2m&qTqjyp-~uLsRZ0CS0< z({gGfeX>;XANfu#RI>@$#s#b6pPf!_aX3<4T}{2G;a|g0N12@oSMJ{Rt$uGYcgG^h zVE|iFep@%XQ;eT57X!V_=lOIMv|l2WW;{5DDCkuV`Bz`ye+u}D@1RNvC}bZyNw(oP zslr$Z_nEDN8eC$@BqAZ+<>~2hluZQGB>%Oe|L=pA+FNCY2k6HjJNxkihTBccOXR&V z;&3XEQEG0v=PsjAhp2`Da$C=^%+8|2KzPZ%3eHvPH%P%3Anxj)_IvK%dBVGP4{Vk2 zmvy_D2W1b|o5UF+^6BH`XiH0iK6fbgM?f!U)ARdrh0FYWTf&$Oz=x0U@!CJ5(9qbi zol2JcIGAsgNndueCqhV2hXKH~h#gt974n6lZswdm2o$-q7bRqb)055P>r=2->iywu zyt-x3StcCib52hT>a^vFzyRU$|1^~XV9awtp8-rZT63no9VUy5DPa_PcSq48l?9D0 zZsUURziPC#I3kGlsc~OX=k4)*4QjO?$N}AdjhX$G7S2HG0+R-OqvWCbTd`-l)3}B< z^Ixw35tsioJKt;P*goD7qT^c`DQ)xJU&xfA`J8=6TUN(Yb)0P#TY>3LtG3hQ&3_!H z%G$lZ-o&_a2)dtp;iy_z6bJ?@AF1(ha^WgJE08LeoQ5$CX5j4dS*x?1*T&~iWNM}k=Jp+^0_$*Q>9BtwA zpWDR7IPM69f&WMQi-!_3{U7b^hxLEQx=?<QUNNVE*L0GLTN23R{)C(F6jT{MuhA{9@H%F~g=ALDtBW{V+*dgc1D)jv$i@Z-mT?GVBP%e); zXo*L?&~daBLr72wn1PwN`<)VU5Bo*owlKo{*yk0OKf`7Rjr88(<9OBlWG55}NuMOUf7V_x|I5oL zq_|Vv_S5@LP85&=;pX28PI-d%mN6ff5bKD`$ z+0~`uHcmQ(C4N+XRcvTS8Jz%|&cMC3daqxl_A1YfdDz>0Rm`<1MkIEln4Rs7(RC(x z(Ko>rpRe>s-)MjAKC!sN%#zi&l&KEyok*72v!w8hl+8~nc30?L9uKr7&m@zUZ8fU; zYHNwBHQQVs7aPOm7H{gVN{INccWGbIn63s`cDzfb*9PU`NS*d47IMm-*A3wpA1?Kz z2Fh;r+|{T$a{|*$+gnzb{YCU9b#*i!yj)u@xMJZ-4(_#w#j>S`G~%;)rOO-1X;@Bc z!wP$FlHYy>!gXA#Z{w|Q*NXJ`b1uW8ZwEt%1^abT8; z*gK;id$}}8(xb(ZPDR@!*Mg53v6HM|k;TUwG>lW;_*|z+RUGZO9&$^ZqxA^5eNOe_ zkN%6cRcFp5$*Twi?`&DnptDgj?WN_+ca zk`(`Dn~~FX706g_MPn;NJx*x-#x`7HC0uUwz-!yy)wgY?>*`5v2Vg1I6L6p4g~}!R zQm3}3_@CTlbHg%GoNJwTTqrlErT?uZQ+&IRj|Lws#}OisH2yKm6S-RjJ3;TXGiGhG z_kM^P=gZ6#iDCQR#tl!{*dt8%6z0_sb${_cd&K_`s?`lDWj1`w`s;l8t2?h3ZOV+T zjWkWzzqnR}jszsx9~0_yDL5O&XMDpx@bTjH-+_%ORr|9|j9nsdvUur6z6owwT-mAG zeZdl^)0oU>2j%@1Ts5Yw%j^vh1dKYZ=(qJ8^8>EsyN5Ts43j z8Jd(Z^PT4FgM5FXYk&8|c2OjzpVszcP8!;%vg1Ubo}${Ta?|k~^e=6adS=+lB7Naw zQ^sqJdfxeOhBQpP5$ygGOu5VJ5b0%6P=1)GVh!w}e666-UR6@Zu5x&r87F%|HT5zp ztyrqm;4aqAvJYN#$=;0w1et0SX~oGPxSjclz{x7XG#AEXYojp3=uSmnBoM&<0W)7B z{QI~~S@40Ztf70+YjNV_dQ{cc&k(f5Np4H>sz7v%HEKUrb~~sFSHOD)ot^1Fkx;Z^ zU7GEf>~%Odhs%&UY~wg|SH&-oHPN7G6B}F?ynpO)cCCw1a{*$=LvM>>OnF(2#4D(V)c0J}rN#{o#L7Bz|Z``2+!FnR^iqhM{qL^jy@y_rX> z1801}arNS`+na~pi9U?V=5uxmZ15Kf-s-R9wNG_wpHjCF)wX*w<2IxJt#gg54`!VW ze#QY|4DAc^F=EAzVY<8# zsYEs7yrg>oh}zeTK4v5Y3d_8ldy7aJtAPVadq7ihBtw2Up@9>?(i=|3BOD2i;v_Or zJ-JWG=?R<6aF?GeY7ZYz>{>f4>+LTXx3{T7VrsSh-h27sZSd1=+_9*UB#sGjXpUhl zs@%bLVxp|!OI*P7uQ>)`0eW;^e6|9_XP!j-l4Kjyh(?TaKYftE%9y|> zgXBGT%BbElf`lz}ihfQ5AvZ=ltgGKH$OsSD>@IYqi^*8x>Z@DJlSerQbHcYruG6u~ zg!GaS0rqSY$xl)FZN461BrFQ^4!5nWUXGF9M>&%A-6+MqY4}+m#h!5al^Sg0Tc05C z=p91YXgw#PX6%bYr|6JHT#0d%c2!~SNYoDiV8%Om&)w-@Ti^PzAzeym;KJHc+dl8o zpW9H}Y{V0>c+<(}^_$^`c1TCBCS$jji->9nqigr@X+p{{HU_NF4$Q>?0Gj*`yy<&~$$ip=Zn*TX1w3px+2gws&-Z0i72; zA?FR>@@%6{2ve%0t-)V188lxe{buQl4+S`E1X7{HpM0JA{^BB6Uw!Ur1QV3{kbC_) zW7j+VJvM(+CviS0`c+9b_tEr_C740>Va-cW(f-g^UP#1@%b>%sW2WlNra%Drz_HT$ zs!7CSbe8~n>h^fV_=g9nbk+qcH?ALr#}3=uyjyheHiH`uxX0NJCGr6*flxBa} z86|`U^w5}{J&Z3-95GhzI6k^OQ76BGA31tUBk|~?xL~(V?bM9Nr-p%Iw*@XyIMi66 z!M@<&z(7V~n~T|-uU=ynPG+t1zZE5|38fsYHF^Z27I^f7BTelR*Oj7Kw+Nv zz)H9z-2adhzW^X{AcJBTv;7oppDwx3k;kOx(W_f1$Ya{C_WN%<2n*GtTY(lk&M?v? zA9WL}6E)#^e!r@}912`|>bhnZ5yl=p8HvcHliJN&-G1XS?mn37@9v-Msh{c%{rWZT zjX~}6y1Ge}Q}k?6Y;~<$1F}e1a^_WOV|Ae(v8F)26o#sDn1i^>pzPx@=+bIDP+5_t z$M?JvlrV^-)>sOOYdiCnF6$prM~O2|-wH-=9oYrZ4#PQb!ZJGx63{x;~|gx4&( z$39666R*>hM>}Ba(Y1#SCvBR{$U|ky`*wZxq+6}alTJ?yjKK`bh*5=ukds~Sl9#NM zB#CI&{heD-L;cus7z|+&FNNzjWsTK{uZU@4RQ&F{KFE#}=hT#F!FjM|=a^V9yX~*I zEpkZ7Jf3g|%r;P$4MANkURaI3elR}@UP786 zmwKa0M_iSsjbc`i-~7&_0qCO~u3fim02@iWmtIUZAYWcQe}&m^b*GJ? ze$V0&I;{~FDHa~b>PKewhVg^{*7$nHR!HkseMnHGY`!fce*28DsB&TUtu}6t1le*` zO?;_Ymz0U7%n#GoyYQL>^YB;b$~AvHCaq9xt(F)zven9hpR;J{I?OY$@=od>Fm{>H z@2Wt_Px$V)w;?V?DJfl@JLD;hh2Aw-bQBZxMbH@+s6BzjkBDgVs^88t9}w4m_INFI zNYJpP+a0!0UBlr&0hUU@1@|z^=ng+VA^~Dtng?BVjcoT7796Sut=4(n?9UJuzxb=S z%#O`J{*uRwBuPyxN8jN$H4f2<#S7Y!<-298q7cHeXvS>yWPjO{SW}2S9A?rwEm_yF zdXGY>->w3%HlDi~MJY1Y+@@Dlg^1%^_ai#rV zJT(XW&RiE8d-Fd>ry(UBxdfd51-*oFyC03qeusXpPY;g(vNdaL#1n;vgadd@oSEWI zR@DK7rwfT%6>Z}l8p$)Q7|ior;B_^Ioy5ma3QHYBy{KM*xiGr^Jbfc(K3YiJ_P`I0 zpIu{N$1-MuEgm-%>bV1FOnU+E{pnjl- z%h^4K--Ao%n*+`0s`rjm-jePvekBGvU|WUl@d;m=@7toS8R!bic?;$;8H(?`Fz&%{ zxu3^c23>f^#y*7IvT1MS7SD!pcGar%fV=pG29z7KUT44J4JxY)y>^F3i)OZ{i6Qsb zmA7XEL7NKpWd2)4vwhx%3;1UXoyD>ae`_LfxhyuQswLoTZe!p?w+>0g-tZ?F^-ce> z>gt^ok%oIOz`M9j4Z%`SpQf$lfhGmQq#F9oq2EBi60yu+YfKy{xR(G8v&Rmqqu_{z zkvdz;*BPgivwNeeTlG=|F1Z;}j#PO--AXmlJptxe?Cxc>+g=`RI8kNKUEO`6irLU8 z>6AbC8Ody*C7_|yO+rZ?`bx`CDo%4~8&?~YyG+bsi{ln%QoIqDH04U)0z>ghoh5Ya zcsEr#s)A&x@%_D5LxFWun@X&<`Z9?yDZOMy3fWs&J`^pis~@S|AB9MHBCXpPO2M5h z_+U_O*HWRAm|FB^zjcID(MT!gNq+<}eT{ENyD!W2k{lEmDa@lKT8DNB3a{*R0Of#^HU5%}U&KXOC zy0{y6EE|R@!3=5q7Gkgm`6PLOodc3X9OP61QA3-y>#gMWn3V|HWvl%*i$ zycjS$Ln2-aFxAW}xs4FQdW^>Nr)wmd8aXKdB72dEBfp*$t~EH~wv;|d<2D~H!W*{q zkpq?c1~ESb9O`X{-^Q$wof@o4*t&VrtWRaZZOHdPTO!On zIvy!>p{ddt;w`aSB&_0^>eT}&)iAmgbaWueLV`4dy39x)wzrz_B_%d~Vy!tUgZo0B zedK6{z0!Cz#lm${Byv0%sM+_sUHtXdN-mD4e)z{(|7{UmGI!Q39-pM=-Fb4o3iUf8 zi1F0m*ziN!h&`+-cN{X`5U_Q~HrE_#gm+hcloh#7Yz04N!VVvKAyy;C1=A*g~)sYTZu$;#Sk7EYnu4VK} zLZ&4X6TWon8eGZ}BSD#Gv@~M1AvMvpol85qw~F@h{YNw`LO&JP4t$A57=u;_NU;VKe|~-&*&wZjc_5#+HHo(jVEbr*PTyzD`9Z5`$ki zON33&6P_T0CNf=v-P^610Y#z(`8kn4xuwY)O3}t&b_`eoZVlo;cHo<8-1VhRUA0yv zUW=i1xGxOQu3r}OG1d^Nn4ny#m_g`hjF3@943nIP6jNK6B%|`?TLUfPYgxc7jqh9Y z$8PQaGnojhU3B==}yI&)?l9XZ?HQ zF3TVMVz5~zAmZT9@Sm%e^cmxw2?t}#1z0O7DAsYb!pX^fU`0x#(8S7#s7#9A+mAjG z16Lq$cOA;kC`=yE}Y(HqyxdewsmWDHzN z;P5~hhfajyVywJl+=DqCo-9nD4@}l3a9OK<=+xwFv6~Dqec82lAY3T4#$i`|Tqg{* zFG$sn(MSI6tLJY%-=-JO?Egemh7*$Q71CAD+tHLVcz+5g;OJd zX%5&{_y5}j^|J07A|-F;=R8%7G4Svof2zW+kX1vULJ_hG-AI-$#~iljjqFyB zRN6)T)*L7gy|f%H5i&iM=Gta;mL{d-oYJwlt3lnXh1rq>v`ikHY zf$u>%HeoeTL=|xm(zU@UV@??WXepZuW21}PMqOWRpT_b{vPZhh1m$yiE#G(TXir3c zboCzcA=S1;$MH>aTIb{_S#56ou# zwfOEfPUt>-dN!}g)+ZdSOccR$qYg|q6P|+{DqS&3X!YGe{kws7j`j6kd(nL-02_m& z-wafI4xznmiV}2ZKNr7Kv@iro_TJ|$#YLjMgisEBg#Nzb9W1_nVW6(GPS!E;2P9x6 zT`DKnr*NY7`DYA-t%Gt{Pj(NisH5sl)U6E4o|`xr_?|PG4-*9pN22H-gDW*%B^L`v zh$N!htwcGbxC-AnB>^74U^te{>D{`3Lpqr`vNh!^?`35BO>6Fu-|s2k()i&Qu3)_i zPam9sFDDsUnc1&s=%z+&i4+)HAsyh@H?_SQ*r*k!*fWJF^aN`EbE?fU?>s``aQ2Kq z7wTYEd4*(lU>6{pv2^-6E6@po>#sMrPx4iob6%M>k=s%iFY>@2^xj{1ZWR4PqPEgL zzlyv=TqbdUs2Mvek9P~~burFcHj?71>@-2T;Wujtt0AN}ib!n?y`V|CFp}imH^D9G@DY5o`XOp(PkEGBR}H(B zne+wg6(y>XA>=yUt=rxsj{3Osj84qeg8vb#iq5y}$*K5d(p6i+lhY!665EA`PL7*Z zu9#Km*SL#5aA}4*C6kBCYgT|DvnDLU|ar9UoJC2?y9C1pVyxNuX(&L&pk|V+Ny+CG%a#ua@UVu zh-V<|R}Vv)MtK)E`xL6?qM`d+WPLy48+RR*C?V8m)pw1qYj5eX zoHsWiPO{M97M{EIhXn6rZ1p!XC!kS;vMI$Y+Qu5xyF@JLjUz|iV7AyBgu=NstG|D^ zsl7|F5^e`Tg?EE-uhtDNYnwkhcnqS?7e?Zj5oy^u*gm&R=k3-ZbR~AJg5U#FygKu) z{aB}uS>61BS3hIA1G8L>)lM3&WjI_W+5LMf|2c`D#y;E&bq9+}xNKgyn6&A3`K;9j zor`7*SIzL1I`t)&t9sd*4Qk51+1%ZlLVIad-m_YPcAq=>&{Di6*onPwg)3GZ>E9F2 zKp)+uMLte#A(Jj2n(@~}5dRW7du3HTW96fgt_3ztXH8Xlj-&}-hhBXPCSO|IM$u}} zam->fHNsi?!`|o1&i-3WledqF#5f*ySL2ruwiOHrEuO+e=%C|UOf;fYV~IzDk77dg z<4(N7lz6Rgi?HTu**e5`DKjGOGlYGyu3nti|EQKlH8`S^F#I!yog29#1#axI@wrox zFz!vbyYsd2NS#m2t5DBZX6Oht%QkPbA_BXZFJf|Y)fXL_CL(;(_vtdyZQd`SO=in8 zwao%n{~b*T5IfZ=38M3emvqpFDBheG8MWkuiT0_Oq|O_@xbVA? z9lb#qJqz`#BD7!hcm<;QA#|S~6}0tA2-!2ze$^A|3aVn>bZIEfxd)OU`OOw*v=fGz zJQ;(^B|c0Tff|9%%%i$kaHZr@#kISpbl+g_$0f-3HG}mL_~>N*l%Tp`#O;~>%4pK` zw@qDn+c+h-ne`H~e}zWrON=LTNV z9cZUA^+;+enDwi~1lY=DuZ(I#Gj|58=$IWRHlnKLql!<^t2UH6S4>8qWxM$jr*F}_ zxe*v}Q@t7qlI$XKdv)~J7ySjDI+lHa{Nix2Db7AcXX(|^{_t_v5R%{oC-#KS0#M%e zP<`QJC{evw5s-CNTyI$omf{MAH7@cp(<~0;%k?f%r0pi%oHts)3F-=3eyx4gcuq1j zS8MV5qlW82-S#%7mx)FP{Pgyy5!YzmySBGS0=&Ev<848m5x@qeWfG>o{f|R|#L?SCXJ57Ykvu=KPtNrK~$Pj)tJy=!=b7J|i8r z#q&3gk9G&u8{1(ROZUQ*SAQMrtMzw%98~OPA=Ab!rTb08;udX7z{*GAdpLx$tjUs2 z@>)WSO+F*pExR#+zbN~2EMTP)(bbPLoDi<{Xs124Om8PR%F5w|cBoO#n&kaTGy3In zxx3kf$-_G|`J0^2X(VEDp5}ihgqYBFWHJ>mnl5&agd>h)`Uf(rZ}x>pJf=@tP>uC} zT_t=x#G+TzKh{CDJo~6Eo$^9q7JFaSs{(axx&4j&o`{;m&^1gE0p&;RdY+=%2?nS1 za&NK@B6HHSrec4Uu8X|04(JLPXmDH4f_AQRuR6vf1a5#V3bK3L68&1x?s3dAeID=0 z_SoDuk2Pp5UA~=vKr&y@r_(?YE}E38o_Ab{QVtWm6_u(|&m1{^X z_JRSIQc3+9a1@`VNl$ZSmz&6m52Igv79UnKzV|I{=Tbgb--fJ&FzpB9j}I+`f?hRl z$?fgVl7!wBeH6cyLDVK%rTFLK zWUmqRzVhwR{(0u_x-nYhnbb*ZQcjPZRLwl5Je(AINLv=xi#y?Ql_=?wz?&K;C9NOxt40OI zH;@-+mm+_yY7=00o3yf2u6E=Mo8?cUc7J#hD^UrK93;t(AXe>XScZpsTFide9oapq z`1D*)302u!?B}}s076EeyU#&ryiNLRvc1`E1lVD)3#083(I_^BHB^!L(0HIajli;OU`#dhr(rt3Vb>Q-reyTVv zfw@^%KR#@gk*k0Fz_a(h&E{?@QqB-TW0=|e2zg&^(AIZtPCzQ-EF;Zr@_pFqUo}$s zhKRFFwU-z}c>uaBZM)lar$*e(D3(tlQUK1e@z`uTGqv2~ph{zDnH4Hbv|99tt={T- z&{k>kg5Ttv$a~$|j^{ZaSy&i4`+2jfi`|g5=O>UkQn(K&Yxi`T6lK4L9fOsi@y14Q z>==yrYnJ4eTJt5xmX+abKHW))bkE42KX%s2hU@X`_jt`$RCD=@9IL}SR4d|D*eF8r zSw*~?ZkUvla*=B`H!qLX4Xa#3egBK+XrBw$lHJ+g_k@=eM<+nuHzW?5R@?h6H}72D zxyAaj`tXw>dn+GRAOlPZIy)c>2fG`CapGI_IqxspFmtJ&hH& zstwoP$0M*C`ra{p<(WuK?C468QGpa|PUmFZ+KAL;?*}vR8v})-mr;f-hZEZC>P^~y zIWI(=_Z{!mWvbf zuc|sN3k_^*_T6UK#j;d8UMPX&`+SDTi=)E|wrdEtt&EL=hXb&lkGID)Q1v(7Fr;-j z(*-H)+QzIQrpO@gs`f`_yze|?L@yk9dL@T$G-V27nVD0dwfe7-3v z2&XAcJIGwE3o13Q6wFv0fraXCt52?tYF_5R&c^}%{o8m1sdhBDAh&{1{a2nBVAOc6 z740v#k=-+>ct0;?`tZtdNu8VZC)n4gYZ>RF1e)?3e}t`RjVyS0Y#NyKkGtZBzn)li zxF7kAQI1xigV)nW%~g3FQe!G0I?MkwQk+!|50*WzAQ0*XHTv)|(@XNFKk6~>cM~WKxKFF>jW08v6q;U>@S$lac z;sN)Hf;>dZp~Gv!U>?A;9u7VQW`%|{rdQr$ATc%7BcgRrEksoh3$es{z81G`_)p$G z*BJ)(J0%u5&2HENek*B3+!JGdH_6G|Z-{y0o2w^8hBMa30i%&RGVrLOqpt@@8DhU$ zS7Q3sp5mfxktx>{^+W=`9$W>cCAV(t*Wgv&vWyq8qfb|!GF?#WlgRRpoA3eL@H(Rd z+^92N8M!#*!`n5(qKNxvuumOLw__ST*-&sx&8y<&pv>VJxg*Q1g{W$hY=F{_12(p8EjG@ZNq%uTVu3*LW8MN-j>#e;$-`=EQKDZ%ctMuC>o;U1NtN z$LXQ|IQny3fdi;yYd`-L_{S3HqM!`vc4D3Az*aIT+AopIs8q?61lf)B7%lpe^QLP1 z*-F7&0Sb&_rOiJoe zyVaa{Np>?$`480#0xdYcczWy`z}IO-KHSFF8f6cgpucN zpvsnREZKck>$^V4Fxss|oMK$!{MCE=7HJqq^K2T~T3=yuO6^sbtv|Wxy^>1ai!DEV zQjR{qStO=_s~zMDAe;)b&`z6xPj*~nb=~O`Z<$Z%fcR+xN@)AvYuw;B*%qKJzxRp{ z#N78zP5+iU9H!f&hIhI9^RQv>MT5Aaw6`9dXsB2)bkiI$A9(Q+PRJOXIsN9_?wC*2 zm8bxleK_E-jfkAnyYJxs*BGn2i$-56L2s_OXnmxRwe^^R_nM-Ql0@uHPlV{iI^O%n zd}mNgV=O1}pfdVCrms_S4?a)`{u5gZFhetra)L?mPSTc> z>&%hLVL3#+__Psgj9Wj0uuP_NSk-c8`_v>)ICoZ#)X&Bvh+;dl4%4zJVH!KXO1=}J zPJj`~s;x2n+V}qB4kPsu)~_A{5h%Cl)_)BSU(AU!l-7((x?%Rr0yn6XToREY8nNUp z!fn4qgxIfmn(&H+>Sla^mFTAm(ZbT79g)!g9@ z>zusbWzuVS*F7M8<*HUUmrwlycu?z+DEMrzTw!5cqOQJp<}7Qsue33RS@zn#fm3z& z(H#g<3%g#Qnh1Ck<<*M(6Sn>JDqYX1eAWWgmBBpi0@QeFii(2;i z(=N(b=$=+(?8fsqX(FSh@5MHTSyaKHqc3g^)G(Oi5 zmv3AHD_v|rhb!IJQK0Fhh1-5eDH|v~5qlH4 z8Gf?H7NY-y*LXbKF$Ueea3)xi;uJi?lySSEW#7udc5QDZ^MFQDq&xN4DJ}%NF8NU# zpFF@vw~6wl=nm1U9BcxsC6Io z_CHzES+T=osaBimt}lsuLzJry$LyXll#Sgxzvxr(MFx^BIE}*+%waT>dw+uTZK`Zw z%9P1q*F%bPG4sNYd1y|x?YqEQq5S1qRenA^j@q$;7_O}qTB6!c=^|K5cksrl+f=i>|FVl9%_S@3|lP64uW&Bzq56d`UfJ`@vS^ zXg|R%{elv7o~~Q-Xl~7n#75|k!jTDfkfwR#@;hbjkvab9oH=)3yXG5JK(^FbOdr}K zj{ioJW+b0ON(7;5u7d$1N*3Xy>cNpH`z=3~g;#Z$t1}R|VPRS{2bSg?xEMlT2 zCUV@ZvSQE4Lg0>SmS|}=`TC&u}Jwzggi*_@-m`*`j3Y<1I zlIX=WR0qou&qp7=>RufY!H;TvJeo{P4JoEs)4{`Kyo;LOs6fiZ!Gz(k??=MiqoAX@ z824Vu+w?3kj(FxC^6kJ=Dc%Dw||5s4_aSb@BwNW)Tv7c)|~LU9NskD!lpX! z=q9yXJ#3)JZmmz9Ju`!GSYi`ln2jMf3?QP)#y11^Inbfp7Ct$awnu&ys<^3cg%G~T z>|JEy_Bb{F$>&q4D7f+8?*=T_zF^<|sNYK^?Qhlaikh?##1R!bj*usk$$W*@qPWQHVJ-ZyJ1xa`#CsaW97}Usd+eyrc?eO|R*nU7V4H#?ai$vldRNcph5_@Xj~42b8y|bAUM)KrGL0| z5A)Y`$P53QEe$vHVimqV=~wjF*Q>JQRm7>d{7HMl6}}51pB=ZON7?O0UwYWE+4^kR z>%|?THpdS7h|Id=C*I3@W2*us9w;=}pQ1W(UeA}?Y;)&>{6(JM;V?u%nRukN@fy9A z?%|s50=;})zN`(B==_T3tB+-!^SAM)gs>W4_c#weIcOI6CoO!R5NUkB@5ek9+3n5w zYF7G)y>*;{4U(FL*Eh=F4<1KJXr}go%QhoIDzuDiT`M&$9~gDW;B$rmX(_3h66LTA z6dHhf!py*tb(ooXq5d0TLgg3uEj|-_c}QRrgJZLlG)H)X2UCS%maDsf8rP0lu|CrV zh+X40G8wx(sy-m!-@{gf8|^FumPCp|<6@HyuwZBW`xY7G48pLU8l}dQT8B*QfmWZ( z84vApms!4GQ|ix-@6>gOZ8$&#!EVORoL+@+D@D(RXgs ziSYXpAyU5YY5N`lPf;r6I)ktRvHZ@3a@ zMdnh`MwGe)->6?K@42$c?Qi*CnRq-TxPIMvN2(*aKDla?Lnj26z&upUU87Vg6J&jF z-um%*5NzB3WQ^)SHty9Fnfk!1SUPs#AovpyX4H#LGVa!CPtNP}#P`m!!sj2a-R#+m zk4f$mtD*<~xmFyhnj-lx8bd8R=zLcaF72Mt{@C3WQe;qLNq?Yk@yF+q<$v>NU^EeMF_w8k1eV3fC;ONohzH-RU zuJjWJXZ8mU)QejK2e&Q|cn^dR*ayP0?v8Y;jm;JlxZxB_LZxM*xF>RL9^Q+~s^T79 z_I6SGG7tNPrM5Ft?Uod_Cci$o5~N+GHxLiIUrHSy==TaLyeX{%*_VFMIU=EBASH`+ zF>-aAV);Ig$77iGK2Mgew)a-O)|Yx-FPO0kH{8FjUD1V;okWgxNjWu|C(Sj@s6L+! zx3o#Z@4qrI6*b5|+vqJfgZtr}Lj#IeC>|^Ax8H%|_ZtW6KMf(qDVb?)jtGTh3p}q? zXu%+k4uchY=qRCtgee<$eD{%c$F-?x>hB{3g(8aq&Ai+Mnu`(9rdUU{l8Vk9{`gpd zhEP~68Y$JVsP-F(NnBAYNLMTvHTeU6MMM7!3U&(lG3EC*vbKgRMe^J1YVXs9o~hy$ z`6tY>MH8Y96VO+GAM9PJ-LBPk@h-DPaj1?YA9mc(83#45u>@%xUXbn!)zxlsYWP(z zRWCEivnv9DC>YKP`v20EPgyHW)>S0fUp6UvCURs+WYbB|-MAq7iz}r(>b-(D+`3rF zs^Wo_L0^)mpGaV>5jG)qFGC6xS4yrPkp1W2>h6G0v|fdy3$^G8I^Ao#&n|%$&1oHw zC(h<~I@R?=+mSYpV!3(oR)KM6%++{l54FTRdzyH?{V!I}4V9Bix{c&lkE~UUSwy?Q z&&004TOL&E?Qa$i3;vsZsPQe!fToTON6Y&-vI82*yYwo@K<%9QIkm^>o`V`EC7*@KPzOR}Z`wBu zUG21z{^xaWcX^ISP}Ov{g?mcFBBLMXPw^)&z?goc>k@Sm=-+1Id;3oOna)}6F8imG zI@n2D8@O?cjjP2+yN1ZlY5#AePwVbG9{g{_S5z}wf^T>F<8gK?N@lFj1wWMc(pw@V zCHLgp=OGu*BN(@4nQCpVF9kwl_V}nDrnXxqzPLZ5AN+zS1&Oa8P_F8}IJ4<}08H@$ z#QdKKslG$VI^5eceQl@gE7(md`E~fO&{7r4g0Q}MvRy!bZKr<6GXW;`5kjob3zdx9 zn8oYOKW4cwhG^K9)uziO;we!axF;=Rp#3eApr2VW3VW@k@Ak^eIL>z|YGffDrz^-Af57;wyNGT>{NomYZkD+3Vf2Rrpdsv1(r%0Z4XET=Jm?6CT z?w_%E%EIDQQom&VtA`U7mEp-k@#J{NKeSI>R@(0}o(4b_U7G3HztFGb66LKjJcDNh zxRZ|de1A%--G#hg2mPA#x!~(uTA`4I8k}{g`mXyn>*YStu}FCyLW2`swaVwa*H1v2 zlL$Cr^xFk2LD}=0OZ#E7o9ghYWO5uoa15<`K}4i-O&h!-yOS_qXy~fE4Y?0%X-dw} zkCNP4r8hA#_P=x|lQv%NWIpb=RQB~zt@b-(;_`=%`GZ2w5!00ryd*t)JEU>; zvY)7IfL%k9R@rGA$XmMR?me^p0o%KG>*~V@Vf3b@K8R^Y;mKn9+Pl7Ho!d`u48l*N z>02vt9>jfXbt9v*owR}JX3g-RLb1hZog5e0L;dUV@!>Ju!e;Y81%%-$$j(rI6E za0VSMCws?Ez-jMMx~7r5FORD$auiY*n|+bhD_03W5y=~p9UZPV>`hex9&L4`KaWuw!>vpGp3aY)%lp;th$wn*n6iH-F+|$g|MYU*Z2Mzj9Xf%ZVwAJs6vN2A$Tl@fYMY1<&s_{LGtJ0n~An8 zioP3)S0B=p_Q~DseiJthS?Wc3^U&sa?I|gG_v#GBi0Lr!R0M@FPm<&rN4=f7QXWaw z@#QSu1#f3?_HnVk?ZY08V|$&`u9N&`H^;pxLpTuZiK#L{@M2>-Les54_LqJK3?2lUrlY`0xRzKe-4jSIe zAV#xC(}!O>r^t$A*9n~Xa&rO=VPv_Tv8(@O6dM-+{~KOE9nuns%$XlWnTYq(-`nCn zeqTO3{~n?my~UkOMpR4p=}HQ7~R91bFu{AIt(_tz1Z`7 zgsvAiXUE74xE0+RK@bsI9jSskO^cgGKS~lRL=%6CwU;VJQsEB51>8^#N>Zw7R_OOD zZzbNU``XaLF@#ax{fYO6GV zK~y+0#;ipAbTg6!EW?%y zV(+URt(g%x&MZowsgnkuU0GU=K+zCTkkG#jcss+4{Cl0hHKdP!2_nzIE2L^cSbUh2 z{)zJ<4`~+s9o=haAQ52r{U{`3bRpuZf%x~goHPi(%f|#01W61UP$22`d3Wc+5C6G+ z?(~I{I~3jr?9X;Zyoj^eA-1FI7@%z6LGX6y*v}zZ5QJ_Y240re&Jz(l*cEq3iD8eM z3?PQB{6*<6;zS{RX-UyXX`-@!z(h1LZ2gMZ@1GN@Ir>jED?NhRAp+cYxLTNfZ`#kN zxvk?KwZiL3P)=5fD^F)pkHB?ph%e06x9aN3MbrKgS{R)IJ?7bC&|@M1C9-G zceB+2@xVqK%~Ov}8pD@P_|WgCkG?5xy+@p7fAE}Po1VKdcbhDQ*Zzw&OuDiEz&gr1 zx7=fO>i2;qgFD<1KOXH9I>6OBKYW1VAid`tkLkaD)}Q><@JzWL{ZuhzQdZ^KLmytF z2wsQP47_MDT+|+>_{*2MoaW9iG%9Q`igDYFcRtt-aZQvy!*yIw%B^rS{)xGIQr7>} zUDClzBRJrlVEj%+f6z&@$|xHu(u4s%k^58b4ok0(zUE*YenMRJlcZnY__3T|wGEUl zmV#R>ZmKjpbrUl6{;>j5%KC&z2y}v)7(W^Y_$6ZmXq4>zmWd89bhF_zpK?hg=b-bU zo5igO4J^b39tO(7t+kHk- z1}RQlZ!Q73{O!+f(pML}6}F;)Z?YRLqsA+@6jjCw>0=%vh}CS=J(oXsxv@;N!kf88 z$BvHDTu_JOO`BI z4QkIAm4AJPS_2bD{81B1*9D#3tnX=VW&T1_G*Jw1Xg_NgjS)1g(?A=tI(9yHcWflF z&b4xN<#~hO?0i=d2d&wcW$&f?sGvYw<}`yo%P_%;j;^kILNmeLY4~{(=+lU z8*P5S)kaRG;&M_}r-+e+RwE#O>*gkADJ2SbtomD|xTiVoQa~9~#7n0P4|R8fry9?) zGzcsKKN0QKzKH$l&nr4n1|+%6zWAECRt~ z!H=mPRp$??lj@*F*@NOfQ}VZlnLAs-KPP^VC{I|BO}EoVg3cC?pS8bCahTr|lzX7v z&`CpoeUa#qSgZO+Nt;Ya=oc`O@}0{Jnp-ey_<&=ciIR9W!+Y-oYI^ zKhs6&Pq?WKw7@0gtHAl;!{-&`2hn3ql5X`(a=GPc(?dUr9GvdBRZ=d-HhOiBy!t`b zO09-hUKOu4pRD5oB7q#;SXFL02?f&*B zX3fJ}nM~z(eHlTwDU2~#3#52_%+IFRji@NI9I}^lP-$~OS1VI5Z|PI4J&6FOtO2wb z{!e*(5aSBv z;;(tG>!3OpV>KpZQ|%a;ApcUI>liFB&h5qSsFS%-axHLtU@2%}-LiN93^mHdj^wFY zut@nC!b$eq6MpyUnL-nOpSro9J}8@bx?L&kc$rZ+n5*orKg+ z3R8ST06j*0yKb}!_Q0&A*AqEvnTj!r+{bh++HyukE(z(RT{uE*`)}quZ#PtZM+%*# zLEcu3!XJgAx@uD-Ppw6~nRo`@%x_uw#db|vRPK9mu&RREX3oFyflZ_bYbrtL^ z-x7kt)$S}Lb3aCVxpZ49g~L)mRYM!;qvXZ@*UN@e8cMa>j`z(H`x2@W%n;WMqV;T0 zM!Jeqhan4EVF}OJ!5!}&sNys*8($9Dsw)$|DjF1XM@?K)VZLAO>I@1GE*}tzbu!Hw z9Cnp+d&MVLcIrxcr+m4^#C(<^Tx`A~|HsC2km~S^;*XLAe-W)(ABD9VL5GJq*|@)+ z5YSF8N-TVfmmewh75H_M-@eV+N@cDWZj*lr#x@95(X(oowYY&+J(T8mZ0H$RCC55+dzO%J7cDYE6LJtRy&2UAHWVM_}2|9rTn zF5F=X3qSdyyg^Ry_6tAwybwuL_WKg9561^iA9##gu2qvfnvR?>Q~)!tE7|`0pvVHm zyasPS|GZkqtM@Mob0<6}>`lXp(HNH9o23OKdq}Ku_S?j2+SXs!?!l>?uSm(i@u^K9 zO*JSm3&*x_0pUy;^_w33x}AjcA6FeX+z^nfk)`4f9Yt?{yPiZfX@x)B-@Oo|nzC#u zNlR9xt}ta&aQ*f|68!FJwRiN_o{`Un1ShF;)rjvDt`&Olt%`*mn3RY3Wvx$%Q2hR( zd|sb_GEhuLRa`j3QVo9II|k&$TfNQWfLSTt{;5VQG0NLvkK_2?Th$u@6P zCq{yF20U_VhcCT}E=hk}c_$EFE)SfkmnL+a5^=+dMcWi^{->?VFoOO3XoS4|DAc6r z$GuiFIlXaelFfXO?m}RribDytfLiBFP`NN8M5_bD{|W7jb?d!Y51dNQ&b-4UiwV+F zxkAu!@=1xJ)nSBJ%J>Y39%6)jeg*bz{%Y)8H_NiDr2kC}KZM}2eaO@_wIDn+ZKSMx z5Li_zm|EwE4$)oa=-&QO33L_GhE{B3_vvcNmABK)vDcIGeYy(VNo9HNFV3{^{XLD^ z&dx5eMeVjMZb&&^N3`K3@9L>+#;d3njb#P(JM&TmoQ-nn>Nd|o7mbUWQ4ep5f=ms0 zZ!f$0uA~yUN)LpQlTU1Jf!^yWs6x->+MLZ9r}!mR1X~ox-AzGh%n+MnP+dAk!U-bh zWej$Svh56F{%2x9vE;X%{SsHfvh9FI#a9Ohui)}ZDHT_)&9~FUU?kHDRaw1b@?jc;={GyIn9raClr=m4iQt%*Pc8d ztp{65)4lExl;bvBQgKs@S5?b|tM{V%5StvxQnT4(AgEg(scW+MHJ{p1P+-4&iu1Fg zdM$5PR_aJMEbF=PSeRsCfqmjY6sd%klKjJNdorG}OKu5HD|fqP(|Z?W-j6hC|Dou2 zz_qHyc8%iGYs!o;8J3k~WS+XSt6MO^1gY_PzJIidx%&=bOrVQtC&K3dm1sBfH&)fo z!cD>0)GyZ0?Htlm8tE6e1vohf`tphBK zQ6B{%*}{{U`^$+TEY?*$-NhEH!Q;3w)xH+yZNd#LeL@7c+ExF03QF|;rP)pN0Jzyk zS-^B%!Ub6#H1YIcnw*khIjgwr0#UG3%~7ePlStbeq)YR{T<2eAq}*L!d9TI2vVPj2 z3$*b5Tjg#K4hC3M25JTz^WhS1O!O)UbmoI}zZ(@ZUOaD0Ccfnm9vK<#YKORUDY-&&{909pxXYT_@^_veBosZ?TQR{6CxmnmpmDz0IyzXdzr4<7os}T zCmYS4UGKtQ-z<51I=OczQ`G&E{f=+16veg6C%)>%E6_*U{m_1&Gg2fX%cpJPSBX~* zK2m9QGtr761$GzM3+k!Wu-nth5i#^SJ2*p~LGlW9>zwntw{&duNl>BgY&8>d#4yUBjdu@an&$O&YthE{LM%pPC?iM;&W|unGdD;n(FLPcY z(cV~Y&5#?mjh}*Q)BQoJ7_>_|c*ne^_p(JovNvJG^LzqTW<{60`u8^GneKL_Qp|18a41`LiG68+9< z-hdl1Z)W84psgn4-ni9>v`uQ7^g;JarTQNHq3?qFTVLWz+nimazYVK6tRr$DpEP^R za5K-af&JB=$6JS2)_XK2T1Wan>pElw4zb}bM{{O=^>cvVio{q?>-H~xbs!|{D3;Q{ z4}>`BJqDcGLTWa=JHLEa3-m`rzec?XF%9AKU!^#%WZ=K~-JH`aXgd)dJo~leu~I#^ z|HQ5p`tm@SiyWV@a*2P1dslrF1E}H5YyO=xRQo|i49jlKr;GJcOAW_HC{zHwccc{FZtDl!I-nz|e`HbDBfo(I~aqnk=5X^%>)a6*IC*n#`GMYQuGgtjO z7tDI0&x))wb$3wA^RtTX9WEM5AysrKHvuWPMp!kOr#85<=Y7HMAlo5^Tg?=FOAAtI zpMD|OqsG!wF5j1y(;56GlHq3&?+hLF)1g(7P3jlJ4S4N>f6#c|4k|k{OK@V~b7LlQ z?{$1oyPO_anc&e{-3E7m)PM!bx(aZrll(sh<@6~{X*LM*FlBNVAYacyrX}$G|DC1W;1`lN0JP}ztIANHHYA7aj{`h5uxZe zC_f+O9hYad$chtL^ylv0%@O33>BHxW^%WNEix|Vi&idC(3p)D#*{%gWt>&5we`Mlm zjgNnNvJOX&QH7nd&;HZg8&3XY%`aY4i1G2svTBM=E+?mm%jwvm?91(wwU~A6Zx_Vx zx$KI4L&52#r0sk)!7&GRf=hO-z}7ZvaN4QY^(!HSfo7)4^t2V6ELwz`eJOLg!*Suy_L{$4*L{xQmXgm+*oo=mw!EE%;%RP>$y9oKrK&(A^CYN1 z?!kQaFxgj8@`xius@^(xdFXSToyuujtio6@aVpmPXJfcs!V%RHU}zO2KwTU*`+A$* zvI7H?IP-PtosAFXrH&$ZyvkW3w0w*`CoU<*^eG zlV4WS&G4-j)rUFaq$ddx0l11zd#9zOQ4otyz!PYAu=mhLm!>NH3 zj4x(^L~u`8z9Rjc*Asjo=i;BCOB;<8SzVnnGM#%2dRG!myyBvulQ1z}I~Hr_p6>^( zd70&I1Y+;S>0!sttF_<-uoGYIaD`0KA-(FvkQ6K_@l82LGkwWi0EViXZ=3ibR-S>MlRkC5w}On!(@$wH_*hv)fojg-(T1%qtH z$TK7E@wayt%2^;Q>;(zIINB33eI7`&G(=><;%OMo3xmXmD_x(|?-Ze@xRDvcSvA48 zafshNEd((rxapnW(wC5$5ID;O1s@}a9Q5mZ7scrG+f%B+=d_>@zs!mKlKb;JU=OvU zA3Nat1(*PmL+00vLM)90`Q3CuVQHpIl;0qkok55`9%VU2`7EVJ`cykc0kDU5rTDd3qw2=>vJgngP7foh{EgLpwhHH7`X!G><6tkCEVb?|ffPFmM{ZC)-1V3^`gD`8* z;Tq#Nv(-ioez>19kP3yA%214OUWQ+zF>eQa*?9A7d}5aDf#Pjm~8+>-s`(6+b$21K*RHc0suYIs6 z{`qqIBON461&=;Qy=gv`rL%zNMy_#<3c~VQ-@yOQ=LhzJ(4Jr6=8Fg;%GuH&k*vv) z7rH;#^jhAZ;pNw_c-Mg#zRkBPIb9k@}GWa^m4nq=M`0pnNrd4eOAIsMmTmYjUy0T>$2k!Fzl?$8*fk-p^Y>e zlkK0p&NSuX^Lv`}I~cDKy}v8cvifFvOjukk&ihRyD%chmFZO08@iVzjbdsnzB=IY@ z_<>&YtLa(_A+>W3?}>HT)6l2nKhXKvRhb;YkyO(AtAxrb)w0MMRg!CZo1myag5tb( zoqjsMNE*-hg7`qNi&;#p=n@$-gGXP4XAybh59@kfkQx`O441ohscOaY3GR%^iJfhf zYS8t{vnO`Dr!==v^&PHtqt9@rRkC2`^bX^A<2*^l}9G zQj>AUyqi+<`6t^hfk#EAc6^` zici8iS6w_I9lF;StGx40@PWk!uk&~-V@n6UFy^cIG{dIIkXA_$=c$JdfIHR|rHhsO z8yj4idm^22lY->n%jwMEfN!hXjmmT%aa|jsoR}^7)j&xM^0?-D`gXpgEI8N!P&~VZ z&~1DT4WVqMTHly+D)w6EKKKp&d0%xOad*YLL3`2Gy*w^jcN!MlT|bxT0ae!!R%|Wx z5ad<%5mD-jxoSHYfHoKSbJn1@FfL)4eN6P?w5ls$3zlP^ei7?D`JWB^oe5!h9;|ks z-ag!PxTy8cAxkjYe*s-vHP#%rf75~5@CjX4UlCSI@jBVNv-PIjAmTi`hS-_>fuiIv zM9E(7(`D=|STwrWW1xA^KHojSC=aeRT>N^>8y)SQveLY}SVk4uTUl=?<+MPVNAk9< zlNFb$!vd_gVo3gxAs6j|yk0#LtgqdxO$BNnza}Q4HYh8dA|7Pp@2BsZ>(%INZmY46 zOYYLjM#q}lJu7GU1Lqd&DSH=PUWjerj19_Wg1 zZ+V=)D`7PbNVV!qU+yjSl?LCuRY@^M=lq8m4($PdTW>_Qsd>Qtm+qU2%{^N6>d+ZZ z=*oZKar#8sontmshvXu|`+KyH_A<6YW>Y$zaWbB43Y}|Do>=Yt=bi(b=oN> z#hVotiDNJo?~+F|>k;SJMJXm<*!+(vyY56SmO^>Yk$WwypWdwZ^e)j1Jjyl9ZFgsF6a7PsQ!|%?v4A`@11xv9zEK5ngJb$%Mt z<-!?dXu}-e<3-D0w~fQYD=6y;#MIIA#`o4FMWa7{Vs2Tr?B@lj*Zn+UH23h zbBQ9qB8?vWe?Q9j_uIKX(^o&o4E)*AeIOtL2k%mULs!nX%<}FQTv_jI61xYBG9rnjZG!UCE0;{A&PmzBR)}_W`r16~|3r;E=91qaFl|dd& zsMZhwu(dDl*t)R$)D7yX{p`A5$%6*!d|x>APIb;$x-+%5^`Z&`;8eOz1^VObl^ABq zz{}drHE#~kk76cr9VWKppA5}I+BLcVoGc#FWO7%cXS-q9_O86Hz_%X^ z^k9VLfaFmQPpR2p*ZCRa4Iw>rXN>B955WnZ z4=VCW_d7)tV+wt=W*>J=z~6NAMZ}096y$}Fne%&9=+-_f>sW|$qlIl(^W^#y|H+zr z0|f_b%WC8ne2r&zSIx=9*w%8uyMMz;JsfOpy#B-{?6@lKyAt45*dtxR(PbT{kppRo|2Udp z7A5{@anFcSHB0dL)06WOVpBB+Um-OcjEVJO(f>wSbg^cSR$H-@ccT1^l$a+I15$iw z!+!8o%*6ar;&~sZv=SO6te7sEF;GwTb5sf_9oWp66cH0 zxI_DmgPr~JgO&W9a`t2TYkLw$?}3RMV$Ta_6Fe)?gDdX@+@HC+%#d&4b*gz+G;5AN zEi+B>%c?ta<_AWm5S5XekXYc&zs00_fRGN@~2pXfks8&ms%_H_^8Z zPM`G&b-w=j=1r1(BVJgP@27vl0FO=SIuHwAw>^=2LLsJ^^pP*{9cNyjj`7=*CvvN5 zNiAw?A^#zPc-?y$Sq?M?^pn*vz(84EVLdT;_dV}L8trh{C{Fyrj(;JwY+d<ZnV9g9bigrGJ8%Bag3MJe}bOWaUf5C&s*sZSEUxU(y^m;?qwi?y%vBC0t z%cLj&UBJ2jaiBt_tNq&j$Vt}s!p(3Q-GHGx42voxQErI`pjNJeIkmvm#s_yqr|cd4 zgNz!q0Y0110MA2?A)4%A7)TetTB_->AYO7a1bql`>QDvl^aKg%VE>!0q{$;jkH4Z&4|Fla%og${8R%2GM1hVt@cMg*c%Gq7YhX% zu>Ql?)hJ=e`b7&a;F(4bT2q1EY1%ko4W9=>QyWFNn`@*V$Z&XVGo-r5WIw)=u_=~& zKjf#DgIQUVk9$t#Y{A0DLjAREHM>>TloxBSTmH(lusYm<5AX5GDbHD9aNkA`928wL zUUNW%i;Ez57nwlgmftmX@E>q;>8z|*PXT?71Gp1TEC0i2>7O)TijBnZtfa{=&Ch85UgW^1GHxSR;Vl zvwocdJ}4`#-|h+A6yoA9|GX)9K3j}LC(nzxS8CgHpjG*y>y|! zjJ`Op$I}_8SsqK(K+iiC3XOHU;82~P5^85q3t5Uy^1cDJdZr4w$A*{B<@C%`p^JX9 zrUC$aL^g|khNaz;>nrM6@2j2HtN`bJerxQGR5aDkb8kPep>d?cg@--VIlaKIr4;^@ zQn9zZih9DkI7#5P1W^b}Q^%R}!^!`##S&GJg~G8yE)lZq4)yPCY}?HNIQM{9s-MPb zBT8fY2G&g8t4@+;LXct`{~*xbN@qrhbb?zEv-I96#I-{oj}kUUdKgTN@t+>aXO@ z=Gg~i15J!7VB-;v(BRZrU55M^sv)2)(aOmZEYUoshW2+__|iL%(Sf&4o3JN5*lRiU z>|n3ZMAGP-){GJHHpq7PzT6uioJ?ph#b`Da3l1RP8Ic<#1r8Ri*WcSf-6}Cg^sq%Y z^j~wyeSA`DwGQo!ubWWA3B4I`$Nd9(1f&<@_PO09JG`Cx3a(sMw4xnc&21wK-r9i4 z?C%eM|GnO>9hZ?~eM4^()m5WC;;?d$T=d6`LSs3yL@M0LC}~ywp;)*;bcH(I=5DaM zZD~(dzp34_moZ^@gy;Qb^1J!J5UNk$e-l{rA6e4Hk!T)EZ{9ZJaWN9nRzo*IsAdC5 zKbpL`1n+2_iFo?vmhxi-Wk#KNh}hd%g01gK$s@TyJ%E_)oSOKDVPyH`JIl;IlP?z5 zp*`YWC|!iSBLL>v^YH6;oToT zk}GeOl%ECcU5hGn@8D1{;coiGr0!Unis8HRdjFbkS(VR01I*XuIf(5HV54$8n?wA2 zxpMPz(gctC`5-A4KHjfJJ6PB!g6T2oSX|)$!uoy0oHB9VU$nD%B({)K;(?RDbe|ja z-ViM72rN!N%T_-$z=%7bMJB}Ol{bxRczaw$rZ`Z%oSnYC*v#v3Lsu5*o2}KVA}Ks8 zhOabValXlWvVi<_V2vzz__*pTtZ4O0`UH;*X)>*WZspZF2yar*{! zB1|V%{UtEI;CZ8bBl88zZ{u>;SZ%K-yWn%f!ZFR1OD`*Z^t zT0b`O!u-T2^3w68^ThmbRf%#)7T#jNjAZHiKeBUn+ZTZB99bO>{$lAQ1{Ljd#Khks z6lMZ3i_AD}$jI1BYc;PzpZB`fYspJ|fHr)1q=qCZoKjYu^tG8gC^{SlP)CvVvKMq* z0kmdOO$0hGnlRToxIVUgF!E+-1moboOw zix3<*GaL+3rLK~W1HHJMi2o*80NricHhFLJz5wWchKj#g(?Sin*Y=nJJo?oNJ4hOJXH|zsu)^^t z#T8t?br1#I?sA;$U75!=Snw z$*0V9fq@q44H+YL2!2VeGnK%Rn=PHG{?dl>0#z_OBkrp6!uY^@801G~!;s{HR=h3B z-KMzd5^w8QBo5-z8icMiv(r2bdnw3k?Ne$-`daQ~V=f0T#%57Q`1ymt*dp2~Sr}S) ztlBj)u$Oo(-c)2xtxEjb9Ea{eqioVKJLJUM{|#|^n0D>c%}`zbmSoVx(F1$FA}o3jd!{vc=*Fn|~rx=;P2nVdZv^U%9So#dL-M zLibI80-}}(bskMwr+$R!^KVifFysP5C^ZNjdYjLq^qil7arXjt(cw`Ofzac!?(v+W zOlzKd@Dbg?*=QZ8`AP}`WPXW^2X}l}=48u(n%>=O@;sC=X#)im;v7~dpFLYWz|qvg3;SnpZh;H*M$7;v1cE?jqu3gWGS^Z#(9Wm zu(M>l09v<4H(5SA3_z1N8qr}o8Hs!k7pcV`>LnQd>zg$90G$dx;(#Bh^kMR$_)gKh zc~>X4i{~ZA1^zZTdO~T;Lt0>rv#_%$7p(Kw5=!zx7r+iUJNXXk=h^c{tg&cz0m5cv zt=ao*M*prRetI8ZpOyh*fVj*nfJqysEPv*1%@O@-(@Ww}bVseFd$mQuT-CW#u0sZL z_weW2P6ZxrQIqO+hnwN#ikEbivGN5VG+(yk!_wMhA?#FVvm%ZO9iXX|#>bp=$~HET ze7-s#9<{y>uk1A(mRW1N#;7_%xV`CzRvsU_N&nXdVgEcV4?X%U9T<|+ZJH&{&Eo1n zS%=F2v}u(7|Iy`C0f|mL@0T`U(n>7n-WL0rd7djWRbzC$VPrwuL%>>SeXNJO9f&CB zG+d|xLQ|A4e&LUbEGN5t{aTv3CSOh`!Boc``-)J4(+K=!p`??m=ttt^-rTD-g6e6dCY zNqWTwQz4L2atc&92*#3X>KP-l3v!E{hS(SQ^Uxx>+7QBtLKLj`;WGBU`{8Fpl1JY= z0YIE_dS=XQMf{hV9{=2v+@_9ze5%*~7iE-w!|;}O(*LvVz_Dp5DK+Ohk)qkaBKel6 zL(u6`{+s)MSH+|Oi#AqhuMwmf2m+pk>|7Z?ODnM>_3{5SR9vikYL!EL}{G(WdKGT^0QH zbJt$^8+txpZ%lBseG`9Wd&bEsWBY4$z>TNk#+8QxKu%dunYA(h{=UEPqjDF3kJ*ge z_Q-T|`g!(m|BnMZ7FDIImvLX#0UnZ-m_Ik^t!p$RN7l}FioeU_`%eQ)`lScTeJ?vb zh2L3sK}XZVwL)vxyt`I6K&@p4nG_I-0398O$_y+zh_0U_;wCo4C2C;DJ4oKR{@AE_ s*<$d>71+ZFuPQCL?Tg?6Sq>@x<(V&ERatyx`%;jEr>mdKI;Vst0Py{dIsgCw literal 0 HcmV?d00001 diff --git a/static/assets/img/blue_bg.png b/static/assets/img/blue_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..ecb993abec244f38804eeb6b90022583da1ba38a GIT binary patch literal 235678 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

ON|by(woKtrMKk0WnY4H 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 z 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%0ANF2nOzv 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 literal 0 HcmV?d00001 diff --git a/static/assets/img/killhouse.png b/static/assets/img/killhouse.png new file mode 100644 index 0000000000000000000000000000000000000000..7d122d56f438f11ec94cb082645aa8326665055b GIT binary patch literal 17403 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 Eg75LBB>(^b literal 0 HcmV?d00001 diff --git a/static/assets/img/summary_report.png b/static/assets/img/summary_report.png new file mode 100644 index 0000000000000000000000000000000000000000..c864be0fb32d2ae9b08e13e703ae3e8ae8838b95 GIT binary patch literal 241154 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%0ALx}@|@a-CNT)2Ngat z7I+VHI{kk((>-Fr{>I3$+5}T0{C1qE`ffQX>*a0HW4A!BYJEVPy2#WEmKx(i>Id_R z6M)AW><3n>#exb9I&0Ez5P0q8wGSqM5b&6}KLsLgu8{1P>KbMUE;pR4;*$*%Xn10C zDkG^haL;r8$SR(J3q&07V>0PlU3HUoHO#PBzm<1d)0fY;&ENc0J_M6U-tAM;>80ay^Ma z#uYk%7!U~glncQZSP2yid%+BmuVx^15 zGdCOC)%lyVsf{4-J8U@UjTwy^w4*;+{d3t%*mbnmy7OAtd_)F~X34A0Y)uc_Q<-@nEI4fd^w~=>3xg53;{?Fu<4AK;zy(;vL5* zL)Q%f;QO$2_a~yren(PWf7@Q(oiBKS&zIw*YKaVe0o)8b;BL5(p5YL8Q=Q;G*S6@P z6oG7$Nx8}9nk~zmE>}>^2GBsgHdISy!N2%}7OrPvjnyytkGt=c5=vpW(OX+Z^Qa85*We zA2La;X|2s=evK%4fjT+lB3f+aq31uQ#lVfPw^G9;*{V!CZ9L>cnCAz@%(*yS7LE)MP&UFe!U!Tc`Qj(np4t&;tnHVBe|Ak3OjwYXBA z;W=Ta&LE-f4wS!F0sR|-UaMPP@Pb(l5D->5d~B7}4ts6iEL;bUQ4Bu)eqRrP($Bi8 z*IC(8C;fncwQ&EjD%w=4EV(*c_Aey{E*3Jo+mdoTfXnj@ zm!2l018&Y`XMeH$7^Lh7qvR@V>LLs;rS5t>vn?wau{R1pKgg5g@0;5aHmerKO+Qe0 zN-VQm48jtvK!(Tb#WkL@iL$QG%d(7_QdnlMv5D_%x|_LR`jsEO*zQQVB47j?%>Po0 z%^sLtK+FNVlTuxlk0>&~r9jmUQdr*>?~nZ2WTLXUQ4Pn6zJ6?cR7pagocLKO-E=M) zc%@z^6`*-CzbXr_pq@PPC3S(Y_M$WK>mK^28NOP}d0a?-oxfU}d#>%7(E@W6*%B|9 zqT5U5Be4(iW@uRC2-!~Uxo_#Ujd)QhYLFbF5To*`@-gbu?xn1oB$i`w87_ruNvfH_ zYg_1bx-v3NZt=U#0^cY)e#8t%r<0qs?{f%Mt3A=NWqpYX?R`;rXZncN%1_UiDrr^J zZdaCdy1|1t2k}Kuo;1|d`b(2_34Y9%)D?01%!Www6UbjAdR~v*!uUof~AUe*n0g;Hj0_Ef)<&9*w`a6WWu(=s@roI9#Xzl&Uk6Qm-O3^LRRb zfqNt7ay&+4nHWB_GyxCQGV`_l?bzuD#^-v*|F*J>)PAVU$ML5>k_IET8B~nL`%&S< z{e$$!SnE`IlReFcP+mT;#os|PGE{ls5QF(p~4msRF~=b$^}57m9>(V8}GQ_SQFHcgwRrz z0Gd5J=$G_ul$7}$$CsgCvMM_0;w{`C4(<16x9*!R&6^H5lbD%dqeQNS@-aY&Rn9d}d;e~L)B4>?Mzr{1NJWm*9VC2rJm{xg&=714 z*>-7n2rHJpkaTUv%7`hao$EsXPa@(F&Ox0>Q z{UY%v{7R{rVfB}|YUY!}Z|F(rP?t@{W0d<`2SpbT%D&RK&&ut1KRt`NhnAdaFYACn zxcr3OOHh1jnf^6sv@-V-q`j}KqLK@2!kuMfqeAP)#K4HK1{5JL4-XB?YbZuX-dO!s z0YqF&9~8K?*$~LJ+(KVR4FlaYHR{I8gjke-{U#|amj^jL5sPy{jP7%Um52D4ndua7d;1!3NGn%b!{hW1b zjZvyg+O6DPcODZ-ckVhB8Zxv0TF?I+^1-Yg@gU@l0f#>Rn9q66vo5*{Gd0eN4!2o# zk=@bO-@Q5b+~@#8IJlGO{&}_drt&nqV7oiN7pGQt3LY>Vf6KT~Hvlvd`*c12ZRDID zgFL|~TEQ@+e0bJ!cts$-+Y^=vUK@-e#X)=mpyY4zwPiM|U^I`x_WG%d*?FbdddE+! z6%u06%JKu%m3FtNBf2#cpK;8`2ATgrinlmhoE4km?uyKis-BxRJ()+V!50{a7!#YA z8m#;v>8kUMIhjJ|$G0CB1KTU~_N8Cyhe`YFJ4yFaQscsFBUz11O^NwNxhUBHR#HC# z%DECiI~h)=6DVjpK8Wy%^u1zG6`f=LB+j~6S*{dgr>l6MoKJJ9JuooQ4W6Pi23C_J z@`qLR_TuvI&2PVGEwjVR@S(6JTOk%7*&L>FQgQ(j!jA3+7dKCo>VL60 zbcIV?V}acaH%K-pGw!YK?d7MXx!FWUveVdCHp-epN_jaGoDI((@Ojnm#;P@4J@gJ(+ev;5%{F+NDn6q4)Oo0MX!fL z^*gyH+lmbc@V7`jIOSvvaB%QUm(z0ZF!&v*$&AQ$mYfCp)GGYm4E{PC zpxKX=r6j&wy=>p%(%eoq9y#w%UI)1LxkW8J7w)%SF6iFW6Bz^O<`g6D0b=Z$!C)i2 zA559Y2k{E6MvdagKY8VV*r&Aad*8HeN8QKlr!xoq3KM>QP` zas986V^MLHf2KqsxA8l*gOywYT=vqKRr3J`Dm!79tHXuKa7Tma0`r{xs{Z1{G6#a2 z1@4Hq7Pbc#XQaCEPH`0#cF5jW=B+YefH}{8BgBIKb5|^u0FeB-&rHkae(i&gF{!itzs-r|c}d5e0}^`*(rpWgv*m|G zSUXTT%m%}COhj9OUF<_I9YRs97k7stSBo|JNmwOyMX2*yG_ULpngul$81K>2M7FYG zW&*PtS!blKy3h@+7+XU_Z>45so-0XxS?wdNlX;pM?ruRPbP+k;Agzfdmx-bllQlyQ&-qmi~ouvoRZ@Z zh6hFcGqHaHC6%k-4B9DFh-paaZe2@?Uwks&h+ujQ^ot;^A}d=~)z0d5T@IYBxJ_Cd z@pwP}A1Ys^5L|nKsi$S@-25)Bn+>n3`!AYLU~z+47Ot4}r?S7+^b6WaItxasN%wRE z8?G}qI&;hQ***AO5@DG;Od<8}Qe+cxyG!-`-T))Rbq_g!gpxjqeI)T0_mkI8lePAS z&Wfc#<<$lC)54{9sTp>nTfeGKo4DC&%LNYOb^~C~weV@-FiQ-f3F>apP?` zIB~q_Dya~xXZ5Vihr13(thGz|u8_p8zXXDtNijfKDF~wN?jueito?q~VfTJFF&bR| zk+GfCH#T{=iVknHWlsHj{Rgwmoi0)gOe4i%)C$yDtZ8HkbVck;y-X9KXj? z{c|h&iM6z;v9M9pJ87^LF?NjbhJNytDCm)IH|3>v%s5il{1Kwvu zA|o)_2z{66sJ@g@5QQF+)|Pl;#fs~3yf1}4NH5SYV+c$Du#ZX4D$o|x1BU`nt7DJu zwjldZ&g^fEu*ZllL~3?K=JMoZRSas7VL#^jRcS*73OYMST|b3EBlqqfrKTR#O!;xY z7wy=;<`QC5|25{~El>?qr$Se@R#zw_S*sARV6-v((>Is-#r7d9J$BCi1;#Fi7I`Yt=AVgTr5W9b|Tovjkzj z8ow)(8}ELTH;exFEIl{}nvJ50UU3vBrjq0P9gxwJl89kjy>#wNuik6^QN0#?vzfIifJX+?5OVo=g=Oj`4XALr#n zpd|9~eD*dXqeh48I0uvBe<^vgZ$xlw)nP+Qvba6`m}r!KI)-Q4!y(`qVqBuy9mF`N ziZ=l8prefa!;^LF;e0bNAWTyqZB_9;i?FX&SfFhYMfm#&-RyDah6|#-TS2hJaEMkr z_OL0j_KHu?w{k25t{e(`(!#8%PqwYkAK2v{@M&~?zM$w9!_}v}7bum74PAf@Kc}G% zxc3x+ZsIVHDr-q@;0h(Hhi}C@aBJ6EsUuL-FLRXRL!^Tg9j$vCHHfPc zH)Bix6iCc3s#`7=Fk1yF?1G79o^^IOWlKlG902#8z*BN*Da7K4eFX(=^31}Z0s2ms z#)?v)WYDs-Qt)BAUJm&f0}V}3vpwl087siNth5w?=lWVfQ8998Nb+OPr4mdof7S`uLb3*LGdd2Umv)a_tgdo2-&yoxB3XbP6-9vipO4i z?qZrjN-Oa_dMQ@sjm}AlF;#~A_?KTr%+Rq)+$om-A6sV`71y?`?Lb0sm*4~l?(PuW zoyHv+cXxLU?hrJ%(>MfocNz&0Jh=PU`|NYax6iqEjWv3V{ypcaSyl6`_wnp=c$TBz3~{t8`zZeOKTf%l1G; zrG?pHR-So;iLGWP5>-ZdVhYkDZd+jT?=PlB=AZfa2yS-i=rAoeOifFQqtAFObi2Fm z_dm!_mkNtETC5^j9$Hc}(Dhw0b%t;a#!CXI-%T*9iGw))8n47o+ggog>LcP>55bwp zETz>w=Bku*w1gMw`97DcDmS)s5pi5nC>;Fwmkz4#85Q}}_D2b#INB2oO>jM&H{X}`HV<;`0N7{)# zd9_$zdry?KR(e){(Hq8`Nhw}iG#EO8&NVsZRyhBDyrQ;031doX{9yxpwkEpEjm;7~ zb*4)C(?fRB0<4Nh-$0J;bGIXBYHs?O%%8&8TU!NTRz*cgO&jOMNNfsy$bJPxWZ?Hw ztjVWUF%h7(oXQP(T_C^oaPW{!?P@o>F z94=GcmihLNgQorpK!cfw^=~PDP8aGuM!gW%?ac|#DeZyOwzjB*@}?)Ipu=|vYh;?WbPgz3lY z%b5r5Zz4J1jSbr+4z^K@!k4vhk#?HaFjz?B0jRRrQ|Ffw8OEm^)F`kC<&x*JG}EL5 z(fS$qxvThJm8yemw;${Lp7y}~)|-)$>WXBMgiD2;iP znOCak%DBz@va*BN6a?5doB)crGiRu!#}*PNa=(?4kGRC{L{XxI1Q}kf>k7{UQuHJ^Uzn{v-6YRQ@n;sVScZrBn=P^Q?5vGvb#6MyVYS0t#kMpuq{o*fE8vBe|Z6A&=LEI1) zrsjD4%$Fa6c3ro;MHOy2t~_-V`!(%@S&bgJ<7K=Q!8T*+)x7}()kB#b{09*KO8}U$ zf%82!k*u!w)ue69>udYPmU*7ZysBcp{Mg>iHy!@W!n>y^%Mre+@YW8IgL*rYiTi}25k^6o~)%RvTV<-Z?5@B$e97m{~BAsmTdllVV@ zL3nvabHn?}^sgCW&4j3ev@ZFSxIs)d#%m=AjzFSJU^!=eSTzP9B7({8lY{%vEq8t{ zthM@Xlw%*9Ha;gT*}aQ7a;ioopuB9b*cQLgwmdM(;RCp$54WKX3EN4oIj%NcBkyCz zaCjt%TXNqH2imM|>AstZVc!=Yea2Uemw#m=NicgJRiykaXjy7 zsB)oUn+p{jC7T>5>`H-8v}xf(w$eA^mmMEB(1Jwwp992*fecg4vf7ppOY2T_aS*mt zhYcaD6crwhD@vr=`*ojNF~Igj*-JfnYf6CW5aJ{3sUWXnYw=dzQA;_ zxC+xe@3+-tx8lBR{`A=*L#mFXvnB)bZSR9PF`MWB$& zQt+}CAkJ{P-`KHg##0bUM=zL1T(}6^$2^(GRldg`NoI_)zVKULrYlUb))e>Rxl=Umh6Tg z;tgfn{7V;xziPx=eH)1zt^)Tq9H3S488%GQjf5=y`hn^weaD+PczizDqD9%6wr0dS z@-A^yW<2*Pnz!1hdB-S{LtLIhW{I)aAo3rg)K{^3>;fbhijQHY6l{28iQrv7JlZj= zJhoYtouOeFbL?$GtrHt-zb(5!ay-rgf0BK7<-YF_2F_m_?if&&{(fvaVFtveg3k^B zn@waO9w_unhJ`h1Hql)`z_(MXLm_=eJ}>Ldu1D!30n3q8cY|RJ;Dp@Vue!{6Z5I?a1sN_ zcoZ-6)Txt5TQ19;`1vojVqOgSDZ5@!P>yCP@a3PX-mO+Y$<0rV_Et`H_eQYT8}=X9 zKrRDBi1r$6KDc-?VBV;xu-v{la@R|uhS15>TK#@M{Py6j+4WAhq>46Eynn$Lod}WE zN{Nu&(A(v}?StKzSmJWp&ZVJbKaPeAw5wv}i0BW~Cgx!})O@v)_XCfITc5q=W&09h zkBlV0f3&V3*VM%bQC#aj#kiWunO=gCCmSn#h;lT_Kc*wVBf!zpw5a8awAAd4D3=7=+5RuPh3mfsf3LQ*ZZ^X5uQ)9(n6W6_GNF#@Rr;Y# zS)5QKtPiGqC+xrvQgd5@am3*~Z{*cy5cp5I5?m&D_d`^_BRXGD1EUZLIvt^X*Vis11(dkMnfEVK{GT99b=94T>>Er7RRw-rs|~kp3`R7D0I_`J zXGW5P3QXU5zkp~$LT+3wUhnP6gU8m*Ol_apb+yex?`#wfGgz~hNHW`r^`o8(&uQy} z8N2_vU>D4os6N;ErR7R-!K7gO~#-fKY13saD7tw0jO;y%2aQyr(&fOv*On6-6j} zGhzA?g)5l%mc-P)PnKPqmHt#sx@P|^8PLp`()-DAQIpMdm&H8esC~VqQQ5bWo^F7u zSnz(pcSOcQKqb+^1pEjQ5Wox4UH7D((48<(9yucr6F>eu`!GewA(*G?#`q|e?U0U1 znPjVCKJfxWLu2=$*QhBK!WKy_CO4MIcFS;zEv#VTG#S0FnQ_vS4XK2abL^5_GuZhU z+b^^q2|8@dK`etD>kXDd6JNVD!P~PcYHEOjwsM4p1&-}bZI~UaXTgvlzj+AQw@!c% zrH561WlF6wfz(g6%)wj0m|pbx8yRg8xA%-lGC-Y-kNiE=4KE62_r1)Y#X_zUp5y9_ z^oy~nqb}7fc1fqc61cSAg+41bb-SF;0No@i#g8xh+D%rWcI)@uycGXRx*-SADrD#n3DpByix9iuQ%hqXN6~mZVpQv}462vpY9NNx4 zXEBsDoSe=n$LE@bmY>r1dSJhHJ*=F)M8pUb+wgcRktBiq3kRIkAuT1ZAmL?&uacAq zIImRh3oA`iRqXsxQX(?vlB}WjYq9-wKvMNbFYE8(&WOQSwO?{!nWkx?dP@-7;W_r1 zv-!E14rx)22G^|1zj|f!pwpPt9w+V4BZo3$OU{i)2Y$bMN6OQdEeT!65env`4->yH zJ}QBwSi1x+R29^5K&Rv3cDPph%}5>iqKqfu&lgOEP8X=m@BKK0JZ-zjf-OT+?(05B zQ~``a2JrhhXXbYX;gMM##LQTsjpy^CD_H6~@Xsv{5;6LttUk#BlqXbdg@7qcIvdS4 zBbHjr_)#FdCO`>oX8fGm)1))OqUez6CrUd;v1$Wd)tDrP+<_(r0+VibuG~$ffMO0| z>@UfR*K4X%KbKkTqmB>m1?mwr#ev01k}*wFF=o)a+QXV!+A_2#eAf<5W77kx(XO;L zmC7fa3@q;Cw=t$LTr3ZZRp9U7{P2j)xZ?8IR^+sMy`ub*!TmLjFWLb4u%Uj>Ds9kU zQ<`4js1+V>g$Og62sf4r;QluqE)p3oLhspKACRv5{Z6lc+%~ul|C)xd&W)B!>+T(nGWy1Nh2Nuor3ZB>6+URFws(4neOZmVwXx*P{2CGE_Siu@@XeCf6p=uY281Ezh~rZd zX&+V2Qc+8|V*KXF!z-fC>w#)UnOfPHQ+X_SRxixQMzvqvIsjuB7TFYw6aYN40wJg+&pBQnO9k*GA zc6QO3P66liAa>SsY&xkudS4M_p1Nh4TvK+-Wp3gR$ue~1IjLEZ@5Qq$y>#u^ZPzqk zXff_!gP^b*orA0*)H~Ze$R`GFRaPDu%xn1w=JGh{l`91Qk2-3t4`j>^C zFB=f@c1?kWszY&_Iqf5s`v^bEvvdn1Jbdrw_M zI``zPi2=!s>)%_Gl+;vWTBC7dIfo^a_@5*Q{X5bi+aVpM!6eiA zs8rj5q58^*atxgI0wVdc5pAv1n1K=IOphC(6B`IKShO@PCqE7m_C37w<4bB%T?W@k zS^N#bQqQi_P9(|R)=s4w?iN~3EMAheu zbV?Li#lede8jGyl5PMnLi|0LKwJ7T)S+|{*utRP^$ry&k%LN8-UF|qiZhpzC{HWZ* zG~a0t5!WVknw{a9WvTkxp8*~h8YN_;J%t0m-h_CDA-I=kIIiw9Ye3# zC6mmQ1M^S8(H*%cFw&L{cwbr2Rx-(AQzi9xa@1(PdkmqfQ-Fb)7Ou~&v{_eus6szK zA&6diLErmH!dQ(*9MxDxIublA znPyp!E}Tnpu!w@q5+UtKGYAXChEjv++tw{*fv^^~%3w(b#rJP&R4>LiOf((bAxZIt zj0rr|P{lZ4Y5vb_qnfCEET&Wv)YlY&xg6}&K#n{}o8!RZH`?wlkoLZGRbPT`WyBW< zNICkXqQl2UzGY6mh8j8$|H-Hhe!7y}(zKPe9W%~T9DuTdB&girn zJ`ktH)e?yWzj&A0vYAf>oj6qlBt*@MHE5>V7T&RRZtr*9Y_wl+rp@r9n=xnyT$<;F z@r}G!O#E~xJ!0`KCzcqNI7WRUOLQp*Z6>jJ%<&f#?01My3Aw&EjJ^LkluQM!(Lopj zbQx!EU6lDuqE@|N8q5!bR4{ZL-@e?BsMHei_x4`49a7G;c4Y;+<-MsV^NtN1m7867 zL)p#2)7(R9e8k{#sptxhg@@3**o}IiG&hm&Ud*cH*7(eDDMNi z%QbEb4O!1cveYu3#;^F#I4}^&j`>)AIMAE-0^CiqMJG$r#V`77IhMG5;AJFXE>g6 z&Qmd`l8ovyS2x8(?qy%}`}=4ZnUoiotOC z%9`wswEw!{RsqcawwD22vJZGHm{C7w)d8eAAPS(~A4%uKM0W+wLnx&NOqdiYg8L`{ zum;urL3~J^#f-5F1TVvr)1GhqiuC!9sQipu5vNVuf9#`wms5?3sn?Zjsy8C2 z%T=Zn&iSfFhYb`wWy24}s~VMga8I<#^K=;<*18a!`SHS^`SRm6qjaDoQ7MQuK>P{@ z#|o$OZFM+;hE4)EugN(WkQvEYpnt2${B<2a{S<=93^Dz#)bGae%Of$_Ac(*5^qjUO zY8bWoqGRMD)!?Xw@+|~zFI9}WMyzio7XMeGgmKCmuTL9dS43nULIra(Ys6aZN#jtX z-0~J&+?ZTXaTNhM-%6;|vWVxfSfo%)7%>4jnA5Ks?)z7yCN?Z#C4K}|iR<5NbvaE* zQzzTbk46XUci+Vu%*uhqskNE@A^e5q^{eoSD{d#el6NEKwMIkgK9>_%D}S)U%s#KA zgg_4eas=11t)Iz6@&Nhi!>p4otzK$e%N}Wvnf3K*2 z#~Ab%Sv6bTSknnH1+W6`8YbL*ozo4zg?^1HhnzdKj1jpz~^1v5?k*`~5c6Rn#LPD4XGX8fzb%7@Lr%9g}h)7D`bKmyEII~ONPl$1IskU&N zDH_}iN=Esr7QJ1`LfAw>yRk5F9m26DjCj&R8kLFZz16?e{ZicaN}ayUsG`GBk+6E%I$ zTun^K)@AwUMW~w&3!KuyXBFfTN(VVJ*0z#%qhd`>6Fg0o)1f07q04enxQGGfLWT?!S^LwP0Lyi<_7<0Ge z2fiaRMGLb1z}}BG*$APaOBfL~eNv*!q{Q5Bw3sDa(&PUcOM-~D_vusF8LQgfe513r zeYv4te=oSt;2Xt+8sD-Kbx71Gt(rQ(WVgIYv)d8#G1sHO>dMLKXeV(`f%w68kC)+)hkaj2e2{{B{x4wbfzv7gT#2(iD=%V^WEv zKn^Eyz)ei-w0er~ey$V|Bkn8i-%vB>VB(%S-#DSJVj7q0iHL)rZaTr{RX-&%BB~^xCSE(0E))+|+ zB>-wFJ!BQA;(!FknvP1LHTdpASGf8_cbvqn$9C63Pn8x9wo4AFdiy%`U)<+7mVV`+ zZb&);TQxr+UX>$x#Jc?UkZ(la{1nNf$iS7*+=P+RQ=1uHtwVeNWq(7Ya-wc!gu7lC zq27fcm0J=ND~I`s8V-sL^pLN^%V?Jn(@Kh{Q{K0YLPkry)a5Hl*!cF!{pVNkbhA4N zyY)Qx1}|XK_7w+1)ZC4~p!v9S)%8@#?+!Njf(>GawIlSY?v@nq4=ck(C32IrVEAPe zf-6a#d4+iN{7AVm2M5PYK-!kBaHXiDk>kl9<0`$vg*8)edA-n|NK|N)g9a^z==wgc z?0)+7xT*PD6R1NF3#uoRpAY+mu2&@&=UdfxT;^LU<64bh0S|Kn+=7nw(P>Nr$`C=w z!KuJJCr@qz|74MCUo76$Ub#VTLUPpn9)nU&H~NBg>UPaP^vC}b8%~^kz?{OaB9Jz& zj=M6TGPOn%WsEhyFXCfbwp2QjU6b_;8S$D{yI*Iy2X=)DWuIy|VXeQ5DKh$8e~5I_ z`7bs_vhGGPO1Jro@+d%KZ$=D$25T>-ZI0!TwuO~8yA+Nr5osK0e#lDG5s zr=2I9jn?b5UT5kqUj!i5Bf%EP$H1McPX_$}uFaUlBLqhe+}GMLqU~?CtcH|(*4D

IKQ@K*^?NQqcnwb^h)XX0Mn(z{K4!d}i_^X*5{3RJh`q+cSZbf!q1Ef~F zpjTyJ*->kv(g|(yB6Rbh_YM}9O@sK;n0^~ybR~5A6*xRRtklzFx#Rz7t#P@UXkCKwStGu)?6nuE{WAVWZf@KAQr0&m;g~rPnt_Qne4Cm%gHAS z5)huZF_e&bwx$t>e3MM)NtgGQQ9P7&k?Si?qU3@;SrhKd|$Eg@+RptII_Z37y_*Q`1HpRJ@Pc-885m z1Oy&Z$`q*Ry^LGyCHXL{a$_>`d_qL~voY;Rwdduc!;4I@8PfJdT$uyRH}PW& z6;6UF=rsPYT!XB=M>(ssx3c1e2Di`5eu3y<3q;4%%Q4dTZog|g7mCWTKC(~#^vfVF z@}&QA7%*0k#!3z+DF?CWV;Ak?&kGz{0u*u^=j$gT{$Q8u+0mgrx0QxVwaW(-hI#xt z^>%}&9-wVpx$qp}U?0fzd7D$@ev2BL+4~mE{AXZGv(YLAlb$UQVnyALmu3)>`y)GO z*Ltz^TP6`n@vVNv3kPJ-Zo6}AzfiIwX`no7MCjx7s+HBusQKjzxDLa`>c#bjFF{yB zbnOQc>F8pv>nX$tW3I4UmSx>tC?kgTLU%rM)YeH(3oyxA7^~^ZAr5v@u{L7aXipm2 z`L)sMFbU8w2AqC$_3!zrRB4oS&x>cwc$G#kQ7H)Sc{*eABT(%f>I~s_w~){l|^pzoUai9$6n-evT)tMap`;Nn=||EO1QY>y276RDtHK1k8|) z%jvvyPFA~RQn^yet%btDaYLEG_B!fjXc^u#a$5N%_Oat(NLn^?JTY?92vZ$*($b0e zJ_=EGxkbHeiA|2h$_$#O2w0Lw{Yyu9dnDi~>SGoCT-hjgg(;5hdKm#PWR#>uZGnSo zyr@@t=E``f&I-}IOerNF&&sY9%$YB_iRri#K<79#(Oe)MEOD`zTJNO;83Dt|O9`7i zS>3sKBI&<*Un6mLH94@CC~`jlvoTsTn5-hSif6PC)WB<#|AkN_9ao#*)ldW*yUx_>VYgjeq|7$ z-fOWwWAoAC|8l-vxsb$q()tr>vg0f1dKT~GL`-C1$Lw?gl% z7po=uXSXX#B6qlK){*>~1F&j75otF^3XUHz(P)pz`{_{7Jw*!P+1>`nM2tK=jx<0B4DUQs~8fE7poYqoNUPZiLo)!GvZEWlSd>h2}JQW z13v-06V%f<-!@l~c=EWPsVCqjbHeXpzOhFOeUkRE5)Im}Xs(zs+MKET`zE7{a9t}n z12MhS>dTaz?GMkbeS;OpgySpd;vuV)Hjt4JO)WSZS2}dp0t=;1{H|9Ij5fC;!cw2{ zsy}%EI>*Idh%+UU?rX0HaO3yRjN=_naG@e1(-J`pqWzyBaRex}5RWGs}s0r)BQiD~rx%-r@FTxdjJ2@=X|8);@)&z(}&d!X_CmL?O>@|ukF|IoltKweBO7B{ZnIm zeEU>%r(=?^r=ZQZd!mF=WKn7IrgnUuDF(NAn4@lAZ4M1+87jNwncMCe$6p}Pha--_ zH7By12}CneaP1XdA2U+lGvab1kU*k?pSUk9`+b-Z?ti~4>nqImoEerqjs>O5wJG0j z#-F^23CE)D(8;%A+t**Kz#>m+4BCy{Rmjm)~CG7TAr>7_P zIp*(4nrfBz5k1w8b0aUDQjq(!+ga!6v+37zF-qF9bvZU&vfE|n`(1@kM}u23j9;G0q8075v+br+w*mi$t|gi-jft|1a^RzAJ%%T^w4^PgXR zgtko99M_Rmg7#A@TyGG#Tl_rL5M*I%GgD~$+>rig(4bC;@+r}ThZub1b?1gd-E=k( z*}{V_I`#j9K5yT^6i3MZ?!nHpwsSANlX0`5{)Y~3iO|QYGFO_bO)HlgE zqXsJf*uHib=Vlg%JLKk_C8n-HD0v-(=9aA~!O-?x4?=eVUTCx7Dr@d9;JIt~ex$yA z{U1*Q7mo@)vvq2&a;ik-^GfffX(wvUc6hfU%srslm_l2wO?ug|>*tc~rGK?}ty|G+ z)x$xIqcHMyn+QneaqGVx&zm<_Nx{$vwmmRvJ;Y0OS|(AJsuqULj^S-?oC-}2-lc{ip&yp|j#Saw<<~=n zDiiQsUbz~nwTMYt<*fOTkG4kXi!CdGZ&$^l=R>YCH5d=4B_6pkpsLnuacW{bRYOoY zLZ8$%BjTtXsGE}Rr&5iZO53MIrv!sZ{IUb{{GPDiDs@BChbO-Vd)zNuSx8fLh6GeR6fvUVO&UCj;hEKU%)&9ImYqHuKmhbB*aqRRSdoBUV*faASG( zr!r&)%B25Wh!bu2RqupB1juXI!Arx9szZZ}hasx-)Hk2`zqxxq*G)UEmv^rU=eec4h zLoo*axcwa6)cuxAH7MEoC_m4#_1*C5qbVjz`^aA_iTAa)!8%Ncd;_)Z(JsdK4+?v^ z4q`j`7k+|+R2Cw$37rrSLsowkx#Rk&HrIcj9gxUyR^sqNyTzHJ(E#OCA!Gid>3B&7 zmKG>OA+8e#2h?nkKt{iG>Kl~T?C?lHb6OE}XOG;>8%6JdCx_%4g{@dv5+TFzeo&fN z5sB%MmyTDH&4tv<`k%9B#G>LhA(JIJ4DGgh9DdI) zM_zL!z4Hy!i|G59OHbHprB)VWzmXe&BcB!NL$FXmHFmJ*Z6ZvH#1=D3ib%Kal!-ms z;{di>xfS7F=q*ja3~IH61=&geE~fzRSHY9?Opb_3rNoD*nSwbV!1i^v$8J&(zpR#k z7uI9r@JtVEI(Kh@&- zM6jq=haH}+^A{q+Fw!C~iU6TU3l6_h#@H%Vd;2wWztw5wFSc7&IS*}(Z<>*sX4ET+ zb@OO8TCn^njRaUPZN2Gx5T^nol?sY9U9y+cFANjobW16E@B^8UFG(YR;qly|m^ z(3@|!I^#2_+BW7!DQNF`hs(4`PIi%Agzaqp8D$?pp+jLkVBk`pg6i} z89M!WDzzK6JGW}rKen^$GzY|;?{3zVG;R#k*bMa(;M-Al7x?e!0NG-HI&CYEyf_OT0Wqx_n-4+B;`eta1*v5FxsupkhKWla$1<{CsTI|O zz~;3OY&wlm)^ArCI(OFL>suflECs1%#Pi91c#pdz)Z)@fhRsiq?haG;%c?V}_kJPj zMQ(e9QYLM7`7mUXY5q_U-I&G7TcCxIDYFFa)-saJ)?~oNnilz?rfev7RlQ~QVRe47 zQ1<5VH{Kisk2ORZRBB<8@R4Vd$4=%8w@y8ryTG{tw#*zlDW{2Vsgqj~8$m4dmW|m@ z%$_R!ZsM9a;^?3t=t|8_2?W%w3i8PLwZ^|Ym*^`-|h7zXgz$zk*CGt{|Wo<$gptzfNGxXn@_y2DS6 zUc(m*FfgH-wJ!N^BNifI9M>V@VHhthmJ9|>BB4LoL*_CIKNyuzRjat!7I133D?gLO^Wqdgr1h%EjW(1+0GqOCm-Yh5k}GC3d= zVHxXTqcJ5E1DUlC*rVvm1cgGLB&Zusu;m(MLE0Qv5g_rnKxAdS-g+-PO&e=1o&r;X z=H0@drqJZALOT^E#cnU7T# zR2XIOmZ|x>4iF8}FK6dqINc+6C`@$ek=V%!P-O-CXSRIbjrm-aWD3m0APy$Im5*jW ziR9B~B8{b?3aMDXC>NUa59a2JwD5X)lr>7fv(T<3oU2GW41H2F5r#vw1?b=F9{!Fl z8;Go<6|tI=vtb$@^0(^-R2KQwsqv&3%g5+oaCBX~e(1P-4KF<+7P2Q)LvhQGobVri zhjJQk)3eR?SL`2ocY<_#Ft+1<{4GnYZPNVpMA}1rz_&`bE(k3TozN@k|0plCDsx}h z%!EAol_NOLM+r! zGctTXA=6q3&FHUtP_T~MYyb`XcQn+fu4W>87Z2a6&`@5rGK3R^F^o;HF%q}PG7N=b z@K*omQGbZ9sTbwi2@*w=^K+`T6*XQLKN30R*M?mW$9e9;ov#N}3ko27*y|P2c20q6 z0H(O>8-o1zL!8jHg|z{qvE%L+w2Jm?;i?z!&jhviF@LQQYsd!+?GRAAsGThqBRk$w zHrLmVIKnrUK>;@^$VW>i81MfF1*zrHPFb-N`G0+~NPWp1{#`d8tGBoZp(2R$Fb}?^0<6Nqc6IC}3OGP!wQRp_jkdc4wo7jQO-kp7h%A(t;Dw$Zq6=J~y9!DZ8PnR(KoyQl=)u%MzF{t`y2I{{&?##dv|9o-Z zpozM=ngb0#V2dlqasgX%eiF) zr?=*8IS)rSMK|lmA`;X&yL`4`-ph>1nzC7Ar?YoV$_5Vs)?Jcuk+dzhbA{#kc5{ zSz{2XBVOb<{v+Y!!ONS3;I}$&{Qqm6!m7qT{d6Kswx1!EMDoY<6-_;Z@S0~xQQkwd z#j5tJ(6c}xE3Sf%eUUc1A~&D<9rdA0_PbK)F{i#D!jGEW_p;&iTx9lRntM{*P#EEg z9~Fq}e#w4vJ92N?4}3EooD%9Ct}Ck0?GGbrQeGhwWg8<#re;i zHa#a6&8$_ncolg|lakYRErP>(arj$G?tw&jY77`NmwrguP9tF7WtZA91?!{bP3Alz z9&dKxNk32MK(b*V>rsbom0f-4Sen9=y&{EtEfRXQvV=YR&L~AQi>YTQIBf@0t&BNw z)qc#)n9;Dn!fYHyme2Mfb7bbJe;!z;K4(Nh1H0=d!RLFsVBYeOYeX%E)oL_WRS-D3 z#T-|u1@C5uJAoz=ZiQV(j?v>r74&QiK0j?kUjCB~r-g(68}C4+ia#?Ak(`Su2Eo&l zyH`H=5^va<8nDpC2u4r_QRs8 zHrj9a2>z{1MWiCk^RpU&k%F9(IItFpPT|)cZck%pROxw^%-Zj{n8OaFZqYPE|+FF z_zRuklOGoIJ=-TR9(Jd!a{8@!vT63{`Cmd0ChL``s8H|RE91jaH({xK&iUM0p6Ioj z2-g+)7fv(vR1)!p(O#v07#m~y8TLaA=Ve7a8N@ASD zLzjpjb2OpQk5LUsT|n=G7%jRkek~|QlA&X%J<3?#cWLx;5T(x5-EcaQ4AF&?ha_y3 z#@ZsLN(ti=X`CLx{X5ks#)v@nz64zO&86Ckgm8NNoS|?#%jB?6$l9Pw=XC}($IV)S z>&xy|K|oB>(}Ft+quJ!cgQW&GH>%REb-qTZ|0DkV!3d$2H(23k$d{R$Z4=FdW0aBp2F~>++znZKMTt%^8%}l- z;*0us9%fc!xRY8XzBrNDTq`C*i&2l<@yJMOd?lLKgljvSjOVzS@HtjQ*UFvUNe=uw z)pGfpGfSzzJr)C)OxFWU-kZZffMPpRx{cVbmF-NxGn5cuKi|1@>Q=!0pTY323UF^T z5J~ayXKfL6WWOvWyniJcQr`u;5V1_@PAG*7l0`fl!w1Y$<1iIiPmqC?yJS>f2=hc7 zS7Tykp2t4JMN^r~)~U5Oibe!ajb#Jf&|Ps_DTW5#tfj1Vszqm2zoa(f-hIx*v(YD4 zyRfoGvr%|?TeQkx92-vz&hAsW!N!=Tiq+~Mbdmf{qE9cic+SmA%%i2tE~7ZGn>Ms+ zq0XwHwdcjEflqW?+g%`JhnGNk$AM%|JAqPLn}p_Fu{vI>oy9}C>3n^FPpeVYxAu(H z1iAL)9%cDGYo+xx!L1aOymAM%17|AUJVNp#opEUNXH9OO%?J< zoY}BLx*sX75rKkS_g??w%-GjR5~A)l<@U50cP~OOUn0y+ODazP%(yqhX=o1Bt|%7! z(HUTR8_{~Fs8R9CHQkO3?7zOV^iF6e67o;17;)%d8fnXdmvR)lRKz^g2^$3%c>VRl z#Cq9Q_j!1*UCEt(;Cc0xXVY=tY1qxKTS8My$%V}8&Jb?&JiHS zG0{*c%=L;6UjVJP(s8rAe8xDLT{{8Z9(=sz+3X-W8S=e0iNj^PPRlhQ;@?eAZ{!`4 z_V<`SF;mH&%ZnacBc(O!S zkGz{ggqjlB;t#fk=$I9JhlVq7^~rg?-la{6F6qCLv8MZi9ZTI_P%PQF(r|-RAj~<* z&vCL$WMR(vHmOG52YmImG>WWy)aO_8v{}!7e1|$8cO&KG6tDB2et%Aq-QJ-qvz@2{ zwR3KX1%EX5W}%}F#z8uK-1p1S5<#3`*?}o6-E9hmuljk4I&j|Ws}m!+VX)&KqG>O* zW}GW!mS5OseAUI z4iljZNjgW<$S6m^q2U9h)83cS@!DNDrVE^ue73Mbj>Y&)x4?3ewd=7n4Im#-+BFU1 zOSI~WCypNUOFAEo^%*%MVv>r0|LrQJsEA}Pg`R|CV1>)p6zzNw#wMpO+%=ge z<61Z~V>ZVpP@0#-lld$2#8X+0I2&$il3&F6LB;KAnnNv;Atz!K{auA1`IHk1Q^C~j!}BU^onU@^@sp)t=*E?%BR@%N69d~mjBc9{%S4N zaKr-e2V7b%SDKJYpbw`nJ|ppNcy0%a7OS)qm8zFTG`k(;YK-X=>ou_h$VT=ec6zBy z?lCBhFv`Ou>>&CKEcbsB6wfz`-g*oXap|2Bk!;|4a4+Kkc>IMlpUEE-b`Y>3(?=>X ziVxGo^1zAN-v(HltOU`kKMZ6Vy#=cRNfB(kW?jY=74FK%z&%l1%CLc^Di`w z-`ZRLxY)T|WEy$x?j0Sc(+rcfPS9$!DK!12-#^|cPY~xN(QC#%kWrh@x^ej0Te0Qi z*>`RBrLw!xOLW|kw5Qz?|Jh}FOb4VdD|?ayEV1*I#mBwon z_}LZ{u_X0dFjR&oA3>A6o6z}ZSHAO4D{do9cu(UkjZYh)RhE6u=-ks{a)Vni@zhnb zRNrB@KslOaNuUap<&u$3)ESGP>)!&unZf16%Z+H_oFwkfSLm1dIgTZ1ZVvW5Ho7EZ zCsF+9VEVTHdJlc($NAo5{p}s%o3;cypJHqNYK!qxqut*8MLDiSj!6r5?7Y2{Rt_Rd z6VjGQCLWDm#4X;NvGIMRkc#%weY+A`=H^*35$~vsJ$DpRyXniehB$*l2D>U5yXi+JTL{a?4CHYQ?gnJ3ZJ*of{GG zsTD+autuNF5kO}y`DoTdQW5OE1tlI7%89I!H5bQ&du#z+P#%W(h3sNM+;_4v47Sr{ zfi15-9cZNwHC%P5>Fj0B86X64I&qgvQKS5K4eLU3iQ>uOII^v%s*NfhY0rI{o_AZ})wbqxpCqjy z|GEIr?Qj}kI^ozWsa5x@b~CSSD1oY4 z-=u0M5nbpxRLhKKwJDwj24ScWUi48fZsjrants@~S zP@CfdXO2g3>K-FZ6sB)*PC4N&9}R;$Qdn@wnM)sSOxAi01I9$9Zb)y+j&++*>$3^P841vtuE)w!JvDrvhJh6tSB4LSK~|v}@3Jc^R?LmfQKLTb zmY_tyAO7os{ZAlk7M%xBDaA`vNzLPuIprUzJ>Pm3ak`P`DXk1Mh#i7KR8lkBf-#8P z2DQclakG7)h;QvEy1DqX64LZcd1WQBT(*+s@6C2A=xKWHDuTONU-|b?(c4vEW@-y$ zlTLb{hjLH%5EVtBA!km@(me)Kg3@YHYN>6tc@K(B{$NRL>U^69Eh|^yS%XOfUZsIA zoKSYuRLV2{&*z}r9Z6-Wy=t3)4O?7p zrwjRougg&fmjWzQ6hJL@TKTI05U$KLo8!O@&*rJkZy=;9I!`Y>B^N8U8<{K*2@o58 zLADA_mOsJ&y9T@^kvbNKV#IKX`}~U&3i1LDJa7q}X3WSr&BzJn%1_#8&=-IWLP2tH z5lhp788gN0+k=HY_rBj)B%%vOuPbmI!2KO} zJ3cb>Wg<%`J~>eA^NG$`sDuBjH2l2rdU$gqY5IIwq^?7&K~qj2Vl)OOCKaTQmqI?9 zzvF^|xj`c@8Wt1jfC4UEk{7iX>XE{VE-nx?-9~hM2PIO`*eW z6C&z!b9KIiq^28lPODiw zp=Nic_yu7moz40j&8?0JL2OJ-J`k?+3}#)^QHY+mbdWPXfXMwUF9xc~NE?6+l{mfc zJNZR8&_Hmuy$$6wuz|)ecX)pop>$KJD`Q zMYSM|u)fcn`u#ZYVPN88Cc zh#5oJ@e@M~J-KZM`J{msVjWqTN(3JZr3A3CsAmj+YhU4DFBKZC>fnb?QcfA%q1bi( zi$4kw(h)`QsXlz*eH6g3QdS#(%JxJ8du-E44}D8E;X8C`jZ6;rlw@j?AH^@1{{9iq zd8kjtk$Pp(cxc}>hBu$*aQ1gnK8!QpacovKXUKZq$T`6Cb#Hn^sYQc{5@Sdi*)}eP zu>w=m9@*`d5+p}?_DB%0W-Gb!_Pa%`{{A8uh1A;pcQWuk$c4R?l6)X&@} zzZ4r**iU;;ceFKognro+)@LZcQL*54XHqQ;;`*0jY6wALB@&J7OL%rIB5spu zT;zO2G~xODeU)^4Tz8GQY_jn+_-u0ta!#;kLO5D7D*(r#{Z9Dx*{41J?0&UBqR@H# zps1&?GT9t5|0@9y#Y3Iu=f$Xl%)(={^j=WTps^%O9=rhD+S#fKyy&l;Aa;vC=_TtM z&t#&L7M(-9u7ARL-yU=Dt~Ox9?)AoBQ=f_wV@ga5u9Bl^fr#oTn&w!%*RkINu?j}3 z7>U3Yq#2fSr8JqlL^oN7HeYAvnc!8m+T4ZAUvCL_ne@V<(|Mi*7oVYO@o0$sIDfbP zAs5T5ceJ1Jrd1^0zh$XAYE2q(1h?H$U4JVxD4>6JIVfP2dQaUSelRB)cABdk<^H4} zmGhZY=yeuTtJOORtDJ5s)sn>nJfk2i91Z_~kBXp$Ey|N~YHFuXo%IZ)f#deInR1G4v z-IkDy$m!4IY#0L{MovQ8vxOX#b<8Me>g4*Y{{>|wFxCDVRwBbPx;NurUXpI7NhwY1 zcq@fb37MFr!x=x%p~>n+G?ApB$C9YWu+koMlGF3JFl#*OCrp5IG9|b*{#ZV zjNsrr-&KtqU@|LFL9&W@x>wZm`jltBL$9S8%QAA>E4Zq|Z5N@#RfQ_9X=%Cmy^$D~@5rp-wA1l8^S2+JK1X<6ee0JwK_ZQrxAX z>zbG6CJ?vMe*mSy7vyM%Y43FUYLVfH@q^1=g>s#0BxMtFINUYTbjW`;NV0%}Vy|ZV z_N()|*-``Kr@Cd>jQhk!pw40q@7+c|fZ&R>zO{T=)_6Szk6GlYOG zKgGa=MbDusS@qM0Antb_{tn+};Rx$#l|b;fGP@CK>D3-uEb64B`mvB6Eq*JdCCeOV zs^#p%l7{~amHzvWRDB?(qZbAlI@t%V`d1CS(C|M|i`8Cb2nzTy3RI>*AfX!QfH?%H z7kfVXrI)!gAlnnKVckVDNa&`FLQIdC-!=GTvGSzY6A$i5$5|e6xEc=%a-S$y|*Y6Fw}INV}307il~zB}IW$t~XR7 zuT3ZTBjO_-4}}&R9_;|#1q1j)jI=_0DaYDGl>bVwQj_Wg3(OeV4^~=1j;RIkUD_(o zJCFm36v{+Q|KhndE#$cZkK)QQym|U1MA_oW_qO0Qe+j*F3CZvY##EjCt(tG-O^TdY z-J*&j5Fm^6CHjyHBRTZ;mwHX}pd?&=A|A;3WUfsYYN0muh`{$ufqw%=@a6HyQ7lyw z?6ODC$S9ZUuq6@w4dBsIiO$fW#h6yO^XEmHwB-PwU9d1Oh%?@EG!VnMX?+Rhkz^jM zsX+4uf5#@;TD>YD{pEaXrO6o6ngwCqDn3jeZtwZ&@yG^lCmBUr=C?kjo(mFTSfqk$2l?PpMDrozWHQ?2j4!auPwhCz?u-B6#T(yua>Vb@^BsC>9^vU%9oR>B#*?bT5B?)kQw}yQ8{(w z>*~|BFbt~DL*l-q&?S**Ls+7i%Jft>Ee1uO6(whaiVT-TAFIoViI!HqJ(mIL3l5~p z(hj;DymPZ@F-ZYITYFH=&Tgn=Hu@2HzSkv&UJA*&2;A z*MG{T|Mf`~Lg<0>jlyNX4@p$E>WbXL{6U34WmT#K>ee2v4Ngcw)39ow@9AFg3Lx_$ z0>CzHu-3NxpzsLUIrT8j78VE4ExYGS;TP+{y79i7D^mlyQ(@*%t(q-GV8goz|MU}B zaqQcHYkBxAkj|&FCceq68a9c9PoP@xht`7^jET?3`?Z7Ha{V{)a}WoH?vj&&!KHw8 z-m4@DU9cR84(Og$IXHP@POhx0>=%5Myv4EN+<>f0_G`83L&LfU4@R9`49Ti;jW<&# zOQmWRIWg6@8NZut29~XghpWhZz|)HVs#_%@Vqd*mndU%d!wM3`r%3X+MP!c^YQ1G7 zbspkPm6(#Pm_t%c;i)Z<;V)c5E3A*TZX-A<17`FMd?(gLhhHAVppDr?W)rHoU5rm` zNA#r7c#dM0;6OAYI}C}TqT?0^`$N?>-qin$|0x3jj`qvd$Sn*tyG-4cG=>+#4OUB7 z|K=w&COR@0l-N?k<)dK_+;kUF2qBNy581 z4qdtJ)@VP-SYtYGmEs|6#gYiky0b}E`kWE|wh7YGl7-#rZsM)>aIjRQXR_3JoM30v zX|A;tXdGGPSr3wSXa@>sw!ovu4@x7pA{~U9^M+VMsas$y(}i-=AQ1W8qvsx_4hZmN{uB~5#Uo~z8m87`=+kv&qm87I`SRJ(Yy8&HHm$H$ zr_UMlFK=Vt7uIx*O$-PW4~@q`S5x^$6fj8| zEFBm0yG*(WJ?w%Wm8oA*EtSep9&e7ybO3jm;G#QJ)O^Z?l##KXDM=!_VGExf&8_*4 zk}Vc#rQcHXmi1DiNM7KJq%kzv=+e1ZPhS~shvi>@q<*nbB_pxS#`|<7Z*k(EoC5za zlCU7Nf7)vM`BvZ{ch`9q4E!p)lR+LQqz$Z@!TUR4LgDNG@(sw>R3Usa@I@cub+1&& z7EtPXn=@p?r9dWl1L&9^8+`fw;MGCuBDtkmGlhAv!|y5oX{OrqA~*FRRmTsaY4wQ+ z;h~;lH8whqr7i4+kh{Npp+bn?Bi>DElU0Y%%`n?{!|PtR^X)a(e)W86zu|o9sAB6l zK>=XTOWCJFj%3bA%<@R}hc8>X?dkdyKb8sK^XUbZ_2lU+GBL(Lz@7KqQ@v&3^4xi_ zYBg1SLjwwzl_!dM$b23=x=t_C$Tr34Bxo!o@v89^-{Ec!B3o_L(`4n;ZzIl`1 z#imUK*`h)1&CA^ikUKhk^Vwwreil)y#-549^Vtb6xxii7n58#FHw8p&)L$3={X-;< z$@ZW!B>&3(Jg&~b^2StF|0r59mu@M-MWeL*nQ&6e^*U9p`^z224F!-~=q|%07762S z?9Hbg>jQsjOoW&gGLe!5cYy`tU&swF#vi^{w;#5{lX%$&SL!kUl#~RLi6h*uadJXD)(gQ_(NP_kx1S7IVo}j)f3Sk?KBtmgY zHvDiG;t+b!%p~BNY_nM)-?`tvf~aWDNW+6CoM#Tfd#oEsxMgX$SQzaAo4T@1nL`!o zBe7pc!-4gBm8MQ{FU7S<4C+|q9AKx-Qu})`?`cuw+>=v(TNntbGkURK#jGv>Tz|ja z=Al%kqYjhVZQo>rhf}V%0R+Ps8>!hz;jhpQ5aT++aGduo7@FM7Gu@jXs!`@%eaTd+ zQ!#58F0_U2csEwwVbr&63tC4X)3tzOqf8EDm>ISeWFzoGYb_tvT%5a$Ckmyf} zvi&}$cjwbDk<~Tfs$zxNAn4mT=Z)a}V>WRJY*uPAerR;t_T9yeNcxD8rJpxVu-9JX zT6Zodkd2HGHoQ4fEfqE{0eWj3^bnmOeE0t(9=wpHE#+Ja^pm(?zL0uXcEO_3Udq?% zRsV7)y>$vlwF(2?+j9!m{lzV(B}hTOGKkA&^bEGt>JW~{>D8z9 zH^P&2ynXR~9e=V^E8-@?1hm3X>A)QyNIz>wo~ahhNkl@XpDAM3J@q+M z?EwRlT{erd-}4#y^4$nf<^mor_t%;*=`c*nH*bK4;)<%cNKJGjg6EAUPMheVTfr1D zz28hgeNE7?e>TAO181ro13S2eQN4q0JPu1i9yGr1f*HwbgHfUndv&PVf!}^DXEm8B z_Wwoq^LZb$=8DhUdJ@;@Mv0Zq?NX2CiF~+DnD!aK&SZHsm4i$$UrrTl4%3u0Wuc?k z%}E~j4m6E-ad{t{%h9G-xbtt#?p5>|PLnJ{nYt}rZaEA}E9ICC7qTnu+z*)r`&Vg2 z$lYm0C{gQ@kv}$_-J#Bqv9NIdw4d{;Awj%xD{=5c1ET~T{<>B-&01fXNHs*RV2-;W<=s?=v8rfOD1J2! z@c<$fJ*P3~*zhot#?TL*hSY_#nPd^3?XKo0Yzh|An*W4QSo4z>y?g0aG{cfceM^8v zgOJU9DSUvgu%$weP`iGY zZ2~A+z7Rli0k5uzA5>ec`QvRhVL~vvBbgZ!ijOR+)=XsZ7UQimo3pMe3dWj3_n#fj z`=66Z3zUxN6q@YLOg1jZAG-Z)7ZWPr*zm&ppApOR&LHMDsygXs(rx3EvgCfP66j^v z$+^OZG(`b|^Yvz`7X}<|yS6M7rrjJEl@E9SyNvuhRf46_mXyn4647Xw{}gWETJ^2* zS=%^|R;v|@w`paaGd4QdP86GL1&y%u2Vpa)(~2MT@8F?468TD@OG9K>&A&bz&asxW z*4wUvD%#V7#E9HXNk0)_=hBb`k>{W@DZ>VoYehjnl0*oEzTpD1cxhOK6xUHjb zvpo?Cr6y>GIr6_%NTx6ct|0qfF6}uE(v5LmEHxMo_!X6CG$HVN9MfJ)1B%Q9vd|{s z@?k4nL7JS)vqzF-dI`?8mpj8WD;`JlOn^THnLD)u895&;uH)1K>g7^lG#;h^dR|ZE z?Nv%@`QmSW!Ve6scOBB**mAWomM*${OGCm`aq~t(K9BvuiJ|gOM*Q=?bZIhnc9}Cs z;Rp!`9VAJec#+b#Lse#JaA2suhadOn*D`M3rr;HwM{Bb9mIfH=GC7Z3XPf_7la%O$ z4>c`GN>ylX?gQ9DQg040bCBTpZ+7l`DJ%&nHfO>aW-|h3G74oprjk#0)kdP@*qf{( ziKh^zu2S!66pU$?V>+cL#f1(ySzc^#>{H_H;=n0wJna9RJp5Ia9+y}Sa4@}}&IXoY z)^;RqglA@0sySfO0A)Ce$S1QNK0Gw;{1&*l?R|Tn6N~#pxlurUtiMndr(P1DeoPGLU) z>u{l@eAwnmS3J@E&HcpbIL`0l)gl`qC)p8|L%!B#9%JkW7eoBp!n(ZE701dmAeH?E z)^@oaIcX$`Wtu&d#2KzV<57rc1noo~MIU6;;>Hp9t%Jx9w5UwBUv0}o!m%=;%)_D@ zd`QWrc110ZS=;b^j$xtG{f?#!yYBmmM^mlaPGz}{$q%Qch2PL+>h{N2ox8Z&9TL{f6tqsrA3WC0xgE-XI}G8+Z6Ka zuFIxU50focOguah%Pltk+K~C5UF;f7GTZd)C#_U@ia0gNRILxh6GRSRF$4W@pzw0u zNarl6e<%6?X=sswmpa^p9JWMUuNb9TsbL-tzXw09mZk4?Uy-A8e$fwf1e0l=1k7DA z_ME&JUO;eFK5{Kw#O2RcK;_povQfi!JkgNVVDnX!-k-88{nv)(-M2)4p824m6@~GK z4di~2u}yxk$a>FFd6Iqg+8tCNOE&lQW4-Nqpk{xR!XnNz{3tre+MlM$REC1izgnDd z3IqE__2u(sxg`v&$B_nQMcC77Zh>rYaWoDKX=Vk*$h$fP{sn0WIiUQM;35_c@#9Q^ zN-Li|5l*=_bOMY^mQ{v(kdJY?u1IN!;rx(YR@`0&?qgUS~uR-M5lTL_jg&bgEI1zD=oC*y+5vA7eGO*gBj0RRr1^nckz^5Fuh z_2V6u=XA3X2*1&)0&%f6Yh$scKGhe*@l(JMx9&ba&^%^4v%5EX>F^mz#Z;tj;q5Ht zscL3RNmqNX63Auq%`jCkiOJO77zT{@U1E<+{j`4}=erYb6d>{5wd!ONXo?*oQY(>H z-93_;A_l(s`b@)m228`~1zcb^?(OOt^(L);8F)ecTo8d>Y4+s4SdX-^RO6CD{@@Q$ z>93S85ymiLLxwfXUv*>!*49;c#Ix5gjRNV!Bjj-~rxb2@TX zV`0>{JXfrnM;(+`w$LT?6@*8&EG2Md#luc%S#>|P_ks3<@8-~_+2j|H0EtNB4cG7v zoh1KG_+C?U7iLP|Weln%JvT?qp5{LsM`>t`M7Og^3C4dx<~@nXYz?%!e(tR|IwU)k z)gG5YNd2&UuC@0AKUt%c517rp>AG0nTSLxSK=5x+H!(Q4bBx2N2Kg=^ZJY`>Lz8kZ zI-Pq1vi1KtEZ7mGB+&(0)~fM#16*h~FzYK9=y};PF``kMCXO@}WkY-; ztd?9k1sf$tqJTcuj+j)TM$evELHHF<@ZqqmGWcGOzmqKRiJ-O3tx*n>oWIBs0DU-D z8ooyoAQ)IY+^MPB-UpI`SzeKYyB~BJ)7Vfe5jxRolv8{*w+`jRB;>Y_kX0?kMYfHR zFdefM*p=Mvoo1a4fGAL^bxw|TmCltp_KAN7*5I8O1LZwdw6tohsSf9h1HTeN1a04Q z(QEcCpXjz$=6y?;HX0=a)BmFJTiF1GJM(!tt@)iN)xW%+u$@$h$5jsKFhSV!#x_d3kVu;~R0B=|MEie8+cDs+OWKWOF|_#i_r z8p1{((7%n?NK;3q>u+QIfJIjaF((DFTuQgbW=8lVDzjS&l)Z+Rjw-bbG=$V6|jo%)CIg+>ELh(oxQe^0-9#$df zq!q_x<|p1MC)u1Ky^-;~xJ7Mrr0Wft6vX{h|Is&>@g(AQ_udJ>YT^Ccg8sTNM`zMS zFTu+y6K4laos9DY>(toz`97mBUp7@wv|`5vus_ALXz)?ztOoV8ZA*h?yNp%wYK}+B zo;EmZwPoXFLgXgn(bO;aKxg_=*>gG&B7gWncJ-pk`h&G*2`Ibcjck&qxdVx4wL(M! zM2I@Tp7>`}LMASK!v+y=ZO}D?wp#pFaQ0u|_ur_lP^~vnAq1CJN!H@s#JqG{5_#R? zo&P!qM&D@aivaZ-Co!TXV~;sa1gh|pp`LYM#?;w)&xV+tBEX!N4Ysbw`}%X!N^7S9 zJE`iUo7dTQGVJdU*9UH4&eDiECZQ;_7HRj}+n*;md!h4 zrjY!h1b_exF8(ExM9=$@m~ehWll`aB|Hbd2_wg!{ZvE@-uchwjan{jB9ek&FI{aak z=b{E|kY&AQLofu+cnI{+C}8e1Bw3EFo=l#?((J3Ikpgcy+n!Z@QkC&hPUpGiC9>>C z&jfK;r1L$1Q?$Zqmt6jayr^Xjc3q^hI2))4qK9_qiW9%}mFs+)crkfDnM+xGsvQ6F zwN=)mQ*7h2EW+Q~8UGfWSX+=oFjD#6SAlTHCoP1j+=M_h8tj4-bac)Lp)OzAb*OaBh%o}F%{XE@^RWqR|E6L`}5r{56zXWt0mu;?O;R96PHxbrsZqNl}I&n z1U!5w8$usLAUpoee;g|si$w7yGqV0WqeTG%_SDWdQ0nul8gEF6m?6KRJ}w;rq3dxt z@Agl7ayiQ#`lP9!21477JM~dt!GnI}_TV+=1%1{PJ0z+f)x-f-L@fOIxC-%)3ml57 zgkU9Rw+lP+H7iZlJ9XYtx*|@={yZ%59$|Z3Z0riYu(KLZ&Duroi>I3-7d-pcJ(8)S z5W{aciyZcuUrab)A_2de1;ha8QT{%HkTV|hFg|?6dL`_jeJ{AR*Jlp0Uo&95(m0|D z)5BC&;}TDO$<(DQ29v+nx&CKm^>-ku(cQ3$G)0oA!^mR$@w&!p>~HbW7-U5t3Ky7v zKFTh?jk~)Q>CoN}{}MB;+sQ&%s@?YSk<_18`1zPa(UlrTD2^88Y_3I$uVHV`rv%3O zlU_M3rFqkeo>ZI$W44BTx=FSM)A>NRxaEAU)k+pwLk2OJ^c%{_-Cf4IN>ifz{Wb+w zGmwi3TJriBxRQ}U4#tu|K#!J)OpF6);NaloI`>@;`!Q0>QiuGn&Pul}bPCM( z-+#X0hHiRnZO^zrmX49Il3cwb7DVA<)R!ndNobF&xfB z?2OZ+recetBLQYZlXZLxJGkh+p(FdJd*QzKbTM<<}jEz8_Y3!h5j%Ue^F= zPu_&kS-k@zB{h6^aHSF=QqJRI7+;PTIjaD*TEeM28J3$1N1P-S8%9-H;T=~rnXY+Q z7OWe;Qhs!-_gs|WOZ0K@+_xvCg^&K*k2^{v?X}zE`L{g-s6XC1+ z-W{IQ#k$D|T?6&^g4e&9Ds>gg42lYO|5V36oB>wXs_<^++T#c?7TnPBOB97{I}1)SCwwp67X<{)G7JBPn> zH^QnXW}%;{pt(H@O?Ern%Eo?!8Ae+XZj?eG2R5F?g;qNENK~Db&}4j5AVv+wD(r)? z)ZjhF83?g!+M%S=p8ZCgQw?Z`d@8>oMc)YNH6jl|4gC&J!*aZjNnuooxo|w-Zqh?F?bHtU?k7K@N@rD zQ2dh3ZMzf&pZ&^GsVKLSWCC=YYTA3}u4WtX#I>-omjf!nC z97KXQiuWDs;!4p2`RSYxmL)W#7Hc=r3;S-#Ltc0Zp7RWHYKLi6#q))N1xRsGJg9sr z;5E=d@~-FTteplxTW_}pb+_)HvOE@L6Dk~f-Mv$k9Su=ScI1WKP+BZE(MsZo(un@C zRe~PF@FgB!QzBko$nDLMG3x@+zUh#kN-5Hh6uhPqX+X2CTEb($7S$l~hz3jQ!ARn} z!M8}J+E}bCB}?Ce21_4D2AsSG0H&>XoT+crWd_Y;F4By&|7s_87<`9$Ir{^8L+TSo zCLk{r*Uw!nwCs3-oZ__8IorDijq#ZRr66O+^HSpzO%@c9o@=%Wc?&9PaT-< zpXQ1_A!z@<6_q(p=ePGAzZl1n<$%kK27Ft%TlZ_cAhcbvRmF*pON@`i9==m2*tppN zBqV;jR#+0`mTT46)V_~&jIsy?QfOviW!v>E$ni>8Y|))6u4+-Z($>XL%HP$DYQJ@m zA$KfE$(9#ZJJmLsymQdv!S366J+GPPn~e?Uo2fjGYT50)XV)B)rCu(aHYlk(b z6axqn=v3qg=+-@JkFGlF2!#V;axs$i+B7*3`o4}~ZSRJd@g;(>`5Lgd&ps#7&lyRS z*yYh<<=fiCyU&#^yjzz`2U&@{z>TN{v0{Hr7?uUc(T+MFnWQDtw#4#UeMz~cQhieb z+k)$nA=-vr3p0hA0SO(Qk4)+6_p102(@HNJ`@iSx&6RbBm*wd6t}Y!v>5mZARXhcN zbhE7ItiL`7qnbS({`_^yJ!PrJJL9(U_IXsdUXL$pXp}ygAx6jTa3d3y=Cj)m9;jUV z0EgvTY`4!~CEi%tCR^&BiE$z|vT=6gzHDpwUcH*S=cIfBohoL&QdqZxg&gLd@IVPP6TGfT*2RE00KrE+Eu zes{R`M!3-~5$qY&`=t;+Ip=ex7Jmr-NMx6WZNshee0o! z0pa~EnpL*T@+Y~D6HRmtwOMUH261nCrk<(NmV47`T9K{F^nW!B6W z1gUg0_ayiqumU9*#Z1_VSlnrh$CXt~ZXWNQtn+fAxQCBKQuISiP(=U;^8lk*SBCAz zNV{;fsAM>OE9oxm@NrtAe5=y7f{`Bwc$H#{5(rCp8r_t#VO=YUU-8MXSEjL!Xjh58 z8!&a+MUD}28;>p5k-JhAST;S(1gJ<9b}R8$yLFSJB4FcdAQoT(KrO37oAQiL>DM7KLSI^K$VEX04=u}roY0-e$Oto^ejHZ$cX-S!86+&dR;9k|j zWG?7eRvFPrRGF*QMeFGv7gaWNZlo~trl)qe%>qK4gRe4eZ60KDmlDiB zBZgEJcK1zFM(rwszf5#Yz-_lgjq`VZ;1GNXJ5J1>EtY(a$u_;Y;w&e#mGH zHXUMByO+aMj3xj=)SA4lU<{e=P9hbB!mmCeB|`CHq|j|(BqFAsh$*$`s1q$+q2Z6K zlobnsbE|Hzw&XVniAIf(ToI{W=oWb zA;!H1*o7n(NB63458~wBQ9f61TQo&ei5Ye$jX{!;LT3Kr=*3OEh{N!N+5`Pm+Ciag zP_@hsgA_W!O*VQ0k22~08+|hv4jmtm+qQhxf_mA_H!ZE;{oCu!3m|lZ+|;if($U69 zMw!o_D)UK-j9YqCv(DIz)A4D5x`B(T7Th52(vYUM%0xGcX>T!H5EBw!4m5M(ugE3m z)DD<&*`uJ1p(@ibx@=H|+G3wi#=g8{-3~&e)hJ0croR*P9DvRLGuaSh*qz4ok7&q0 z4y20kA0f~Mq=1j#f48T9_-lQx22tzKAm9n59Ub~XXY{Yiq(<{oj}XCdjx>;wGe0x| z&85VSi0Ya=PDL5XVQ6e5A&3q8RY|gi5`FpcME7Dnloa83&$Hs1rQmHvH0DnzJn2Ta zs-pM;w7^g8t&f)AW~y=C2g=sRUe)`9vI^w}iE?s#6&(yo8@q;9O7^GQtr(}y_9y8* zHf-z5K=5g2(|3jF@WVu@GLs|sd!uQKeZS8%txv;*o)>Wgj>~K`xehT|_xm>u=iqIJ zxH6*dS};Lf5*7d$XR+hS<&=xk?8Xb{Abi27Gi&!wx7R#T!C)C*f!Dq13B#e|n*O)& z8|~npH1?%FWfJtJO5&9Mc9TZ*pyPn=Vi#k z>6GsKSIN9->G3M{MMckL_JQOL=}alCosksDO*RDOEJqL)OlcQOPb?sUDBI^joN}P^ zKeJ>7yXAgzn@1SiDtA!%&+6_y>J;Svvi%jyZqHDp2`7@z zWs*u!mnmwq!MRt45nfIX8fQ15lwXvS&Xu?2cRi{-q@CLy>pcz$9bL6CG#d}0l7A9S6gvx})6XyV zvgyWjboCG4Ga=Xe0vXxxM_Lm1( z!G~eQd$U)=ZgkM{G<#x9a%m*8XO4=ET6u&LZ}6Uh9|=oz0Okk#OjP0hcP<{z0)!o~lA6Wc!FDM;O8b>p()@#sjV@(?-E7!Bx@pKtY zzc(3YY+zRZlS&yI8Iu+iPyF zvz85{4BzoBG*$a8z3v;$WwQX&pZ{u_XT3w;_!2^hwiatb30)dB=*r?ouN0FLOBt*Cwj2aH`RdOJ-%lAj4%}9#;Rq%b z;D90A*}|n@N2>7w?2+)pPWcfh@VQ3k*%(sq@$>WCx_~o+jg~^j+jKk&r;Hs#hCXu6 z!=C1Bg@Ym?dWP!M18b-6<`hHQC$3w!L#OfhUNPe&q_fZ`?-zCbE$aoIGbQb$7Y-ns z<|ZCN%OSucq#74CB)ZO^>5WAYa*vZSNI~Xa>_~UMEVO2vpF&zjMQ`S9vgex=mQxNN z(B_Bh<8o>Tw1vJie7)Vw-nHjc+A>7vbCJwTB^6-ygBn1Y>pbGLcm7oAK0@t*s~Y?( zzuTsP1H!)4m@Bo^?hs}cJd%ST3ws1*H5SA7@`SSkP2WEn4aHMsIYz_Sj1h8n2O0W{ zuJ@qyb-GM+hC{}QhW?r1d@j3iISY|29pr#eVg5^PF(zmTTn!l_RqWLy^$%;;Z`tb7 zb&#a2CT>{cK@w03`&eha*-w^|=T+Y9dAkuBo05LCyNZUJ?fzp@0Jus{y1FN&=X$$j z&zEaC|C7Xg>=oLE$M$pP4=$&XfRLZ^S2&(~a|@G=5=??``&;CuJ2Q78-$LqaBHhWp z=x18bIUX!o7xh8Hp2RClk9u*~IOTa`2(UG@za2-MPY*2qq(W54Mc>*G33==t)BE}%xgiq0VKrhbojdG8xj}<# zwp^L`3BqiVyg5bgQ3Vb8yJo=sCUySc4B!jH1@+bEO*ub?)4&b=C?{I1y~5`kwPR-N ztla2{+qOjaBAI$p((_+?=;l(0Sp0+O&`*lWK5E7N-5!eUpJu@uzm(@LE)p@g1^yPN zmLbJmFwZ+{x#I(UBI5TUlraJ|KuhwR&=h$zO|D|f$3@l2Q@H=gDM4gA9p45Sv*-P< zS<`PbIn5-NpB}_5u0KEhxcc~Q2xVD*e7(@SI}qGtJ2`+NREu{+0u51c>^_B)N0>D2 z6T8zYU`Hi%Mp>>OeXRqHzo)QoW>m11umc>W=1yLCZ`h%p)k>$wXB}|_9&);GYHl|F zJesSppkYO-dHOQIuu5|t^Ik^coJgUf*7aSJgS5nfrb5oDDJNe*t)M# zYt0vrckq)EYd$9=ToOT(sP0m~7Aq_)1e+1xvher$v`-&N6BN`J_?s7K&}pK})fR+8 zjH;uzu71X!8c`<3EmIt@P~~z;3=?`Thi)BR-P6SZ&0FfQaxHc;89IoNAP&uw81!eq%JG7W;B?w~9KF%rbxs zc~J|H>DY+I@6J%e7u4^C*->d7V`5t&(N3MOuwPdeooKT)Nsz4#C@9cS|=&NDL)IcT0nG_s}KX-Q6kOFobkUcQ-=~Al+y7IeXvxAHH1gTF=52 ze&yBU?U}FA!H2yMunozdZjXaeb(-_M+ag*$F9ynV%CVYl)_zqaGZ_twr*569DhyT{ z_ze|n=!QsR3-t`(=Y*b2l18b*=L8Hyru@8`se*V7Q`}Dm3lYA8S+wOb$i$T$B3^_N=!Tdfpu08$PO$ID-s=`Y4i+_hDp(V~Fc_NrCHO z1eCT@70pkWYtBz!)kgn{ue#dS89$+UKQ5P+DHjqE&DsBIZ#w?Dp3zjM2j-3eTz{?9 zYap^$%s?2c#c;eMb)57`<9tHDhOB5I^t@(W!B@odryCcFWVb_~tSI}BSl$RD;MT4g zs$f$z!`t)jZLXGyzr;L1>z1nA`|dZ<%!9v5zdcbKU7oJ~Q<8XMJh;2mC0QVoJZjNm zZ#`G7tO|M{q(lGXI7AxB*7f|s#d=Ys4Qc;k?IN_!=|RSgKB(60g;6f+xfsK5nm0^> zlDFJm7)9vmnOBnIjdu~&BL2x8TAW(P;FpOM%s51=#xwJu#GL-`4;q?*wr;YkUrC3=0YuOBWNENX&_ubYyJKn#gpH^ZV z4!6E9%iRUqCdlHq!2(R(G-;!e?CFo((-yH1M>1KyHTpNaU=7v^3~xF3!2%B+zds{*%S>fZr*` z9(_F+Vaft!%27IilZbf5<5$c{4_piuHofV^o*r{1*#x$q{+x>X z9OJK@pV`XYCBHsSxK5ILjSA{tr0KP%hOm*O{^?1Wfct0vt1upo2A6MI2xL$E)Zx(b z_(ZSTco8+R+^**q{4P3%&!>u2cH4B|=yD<>5Ufw8f454?w2Jz$) z2jAM>Vn0cj$6%-CplH%Nzd)bLTW`AWdeF2eJ2R54x6-%o3@@4%cfo8zf&10J^*b|= zNUgRGbNvR7zgas%m(3}OisQ1BVHkFtLdn>kkSeJ2gth&jT6i+Cfq(lB3%IGfuxb|k z0x+2#*l-{tS+mX+l@+oU z2W#ua3RJtUbF#*bQrv=gAPQh#3L*GxHCTXKi(NYdR8HSF(#R-f75|Qi1djY);)tmu$v;q#>NwcXuR2f(+BN|EZoE~l$0mh9c54&qZP+c zp^5wdyw@QQ`0SoLoA+NaLh2P$AD4*lcS84pnvxVeflApU>(T3z_3+{2&rtJ^h;I_Q zo1$S;uI9r&<8K$)WXuX6a%MEf0}7*y9`0~7sb{f*(l6y}J`f7p$VnMV2g)#7q4KI1 z?9p@uz}ErMA?dG0xTN@CtDR}KcLiOF)Vzhp(WBB68m5TZ!WFF#&6dka!RGH>lV_*? z0~jlC_Th-Y&U#=#4uu7FWn$1m!7V{ztIO2bIhY`YBG;STI}@p64OdT1RUhHrJ3muV zCHIopaxp*TGt@W?bBixgk2zSbLR$1Iov3G!lrT)TZkAU(sl%?U9Q351a!zyHw(2n{T4(K#M6v%IQ6<` zX-0&0z-kc0Iz;9lxN;gBIRU^oMyIG87H%Me!56{GE$eS(LDOwIOF za=GVYCV`vbzSf(9F^q5=qk)Lz)}sl2cJrRivN#R2d8@hpp|>ZLT;DrVMvaOf#jZyc z-ntj|bGGNNS9GTitB+@Q8zR}--!4yO3ze$9KUFSw5OSK0e{YF_FEH%%ydSeotP1{g z|Fajq^(KUP`r#Lxqr)Qfeh19(b-m7UF|d#QX|fHU9--O5^9KZ2NGfUXsA=oE1 zbh1?b6SFJ=64(tAmYVBB*4D-+Q*GgHyc$k?6vHE-$bUqgmj9Kt_z>GM+ z>^9D(S%=~SpB><)?}=-x-Etf4k^Xsv+Iija((kPke~8qV*N(sy{(wabVU}a-UerFK ztoU<1p?l*0%ua7u!>Bgn{T_}dQq-U&{Vh)ksM$!6`J)$BDQOFSF#b9zZ>8)D?0FC97|xSWMrJ1B@<^kmu!vJ3q#0tXVESPPAf|Z zX;{51pFe&pS1JFio9vIu2rs3zb)PT2Cg>T%^FYdg!IufV9Lt_eG{1uU%kTTs*l>?t zj7*&gyXsnzLT(5B<2n7+7+)~<9Bj!$??8$j6(xA8Il z(ND)OMn#s+Do?*COJKB1=<{xsbwbPR(|L~wJV>nc_NmbK zY=u5GH53L|*qI$M*eW&f!?n}Tx&G^;Rqy&A%tFwref#@n(w=}%$X~6-iNjz6v4{2R zkzlKyr(N+dIjouVxRY92CZVirL_084`x@p{akW{EiL8D_@5+2(>dL$V)3X(`A0#5O zGbCF6eC?$PYqfQ~nqS-*;L&%?olG4%<5>%uE|lD@gD30#ZM-422!{rYq-AlO?YuJ@ z%;FnH44$sga-J*GhZBBzW%4!XP@*;m%huF}GkrGr_1mruH`tDte9BC?(V~ux%m@0( z`|1jX;#T{5-@Mgx+Gy?Iz!HCj;Ng+!Kk<~uTfq;okO|VKit~*pqXf`$!EKXmlcGHC16rwf5HAVBusW+OeNHtcz;BV!Cp>>xYhegw-=`-w2DKvF^_K&d z#KqA~yubLl_zI8j0N%eD=8Q@l4y_kz5p%qrErUec9Cz7nH%P6V z+6?l!-$pO4b;W&<_QW(ESU2m5*ypW1-{w8*SN*ybggxEQ;udKpAD5U&)jTZ(>yF)k z-@Ft0=(c`mAaFTKkEHfnB5HfzE^Rq6s_wr?zypJK;q_8DI7PN&R^U!qb$}W@J{GVH zF)>kCsrX#eJ4KIP_ayTCm5}Z+k#eZpu}8Y9jvt7=ZTaDBI+GQK5dVRJjwc=UJrUVS z&qxG@%c9P-$wQR)q(Aa|C!J4_5Y7U5Z)LgWM!>*DbS`u~-wh#$B{gy`q!e&$anWB_ zoA-=!^6Ge3v&Am>Rqy*$is70#+k~T(@--lwXR>F4Hp6ZF`|rJ{97T~QAosHYoEhKq zoIb}chM1}eWz)&aOzmMu!?3pD^f_^1@kg)?9{o2VO2em`4z>g998>xABeCB~oNDAk zM@>%~hrY@^+8Bi-*R=ow~%X6skz1Xh7tzk=F z=hAmvY(SoQVb#k6-oiT1FLB4`b}O_?i|M?yCtj*p@@FG{elw2pADAlONDr^wzOjsC zZ8V^+pPW3seEA2+S-(Pgd6CF({dV0F;OcSp7RNBXnG7odF$r3V>Sw>EG8YZ5V@saG(G!B+ycwuj3Qey^{?nCjh zjJSw(xNZNWZhD8ab-nho1TX-N4OJPP@sNrtw=Y$-TQqo0cUY+@0%u_!&-W}@EXr- zcVc4PTUxo7-44~qtU#N-{3`@c27 zM+ad()!-Mh)8W`&c2dlU2Kkd_f}2NTf|s5rsO#^G*(|Lx?K(=|w=49@&E|ReS*+Du zPEeTz@tAEk?3SLZGDbrKtr{(_+_W0s!_ntuEK~2O>@bNol`_)<+V<1AcO~VXcT~m7 zDw}bV5rx?e@eZK&!xuH4O|T}eB13xBx?n^Yqv%U<_p#PccB zPaSQ}2Z1&Rp}kqIj!%V^s{n$XQr>55#B1w||3D^RF|KP04eDrRoY(qmRFeuJH5D&L zX<|`K2Nd@?NKLy-**GD}$Ws%@H&d@2VF!q*s{O~5wVQTPIbM-4ean>u|;rZTkH?yuo= zq@zr{gvlfB^M@_~#it?bdgsoNnBg0ECVDWWYTCv7y-N`MYYx)apeaH8y z@<$w_{@}@=o80%CTmye-KAW5s0!Zr9|DY9#W&k zXf2Ag{-Z`OaNhbyxfrTu2}qJNNps{fd6p@&(H;BT@9_-3Et|e#9ESDOFA`(@2B zF7vhIZ|3FH>>J&&Sq4R2_5~8BiGh-o4E;8VkNs-Q<7ru1{H3j&En!ok`~5Oq@vA~m zGM6;zeiuNq**kq{7;9DhVz}XruF13Fule5>(eSb&4B2L4Q&U<09G%)|yL1CG9wJw+ z2*s`^nZ|rq8csE0{*C*uVpzL$3RA)H1>y$Xo-8|MK0)F+6ypBv=jD2H&B|_x(K;<* z91j)H@OiO^7ZzJcCyvbB8~3ZDjOqvgz@}|9}!tfZ1e9;j`M*-cq;pX~BSh;h<9u!{NEiCI)jiuEK(NjC3kN19y=Soob1&}X?fU^CmZo$26)%V^@^=`XCavU*KcEO z`OsfXL0v7!I*FjFQXG2)^@r$-xNTEQ$U7SRHR~TJONAc^UdfFuhW5mU9dmSxn!x-F zcFZN-%V-8==j$cWz8}CJu)1a)Q)F5j#Sjv@WIWIB^|sD$67)H5=eke!W4{^sEk>yx zasfgg7cs%d=NTXp_`pfZ2xmZv^SkJ5kl*lLDH1;k=eR;}R(ci!22CA4%3P(gDuS8R z1ywIPk_Mw{rV547pOW6oPrFHY=Gr=YRaize{XmMxyXf)&9J4LX=c6yIhLO4pK}#d? zJG^XsXU#O~8ZmT197*o-p?Kd+A4vPgX4RYkvr7JCyJF6JA$S4C<=jf*>@O3#6+%YH z^Jui;&r+?$GZ=&VA(+;RG+eW+wrcte{SC=Qf8%`Za#AKP7p(J>x3TSyW-Q>?`(j`b zMi~mLLkr9_iWT6~;>azB`iDAC&w{U`>py_s-1NfwojkFrexxi(DW9E4O>&(Ri$=^D z8F9`Fh3x;1qQcb;*`8l!zjjsmLM!T6VbaOI?{3uD+N9|L!2yy`>UM$~P!QpdnO~wK6GUDB_PXsKw_ojJKRv_upg|m?k_(q<;hQPQp%S zsf3O}khfpwh)xhwGE$GlOW!EhEM(_0_q86mt<2SS(jl5~i7cRq!Y&7h6Xq(XTgH{7*fXL)Sv>%p(f(xC2YWT`6_j5H!J1AqM$wM)p z`i^uQDk>d}H+KlC%6~ogT}cL?dMgYOv=J)vHTK1NzlD1VwwJ0IEz3#KIu$x|ASw=P zxoC*kCXE+|R1eJgn)>5$Jxm6-cdG=)tr9P(2Ac;7mC{ko^BKFLgWEWRbKCV&E2gf% zNN0c)B&=aNV5H>B^D2qLkx-{{z|;9wJJjFn$VNpQeqbxMc*X-y1R8A{)A?n$n+egi z$22Wl)-G5E=-zO9z6^xSRofDSgz`v({F5Uz8Ay5>e-6b_(!6MO(6zAlsh!JHXg4s+ zhD^ZNb)DU=-9Wi8T09nBl})P}PBulF*8~bdRNQ*3%T-mO5dAd{UNdGkN&cjCahWap z7A8NBcV}M?`ulA>JM#xjN-$UnM=y~|Y6MaCcg*@hPEO|ODdjWlyT?!|kwlE%@`1zQ zeTYN+o`cycWo5Yozq5fQf7s-!%O07zbyc#JIjmchq)F)!C_ux!{<9)v!4wn7Hnd5r zJ%hIzGsAvuE*jAWYgm9ftNZGJLkU&fOZ)PUHrxT?JBmAAU;`i zgm;x*(hX+OtZiFN3tDS8>J2|_tPb(8n$VRCp!V^M8W|hJ(x@g+b2ZgY*y@2X@KH$U zSB%G2=9fBb;w^@h_A7?}M`Q?Dj-7nFp+ zyP~q55J2t6o%f#Z#NG~y-IOIa{K%w~f#D*?j&ez|$4Dy+PD{}j1_kB=3{;Dr_bZiMga@{4X}_7<(?4;;5s)3G)ddWcTF z(W20K-cz004m|*N4MbuGugM+i#|)wsx6tYCMpE71<>6gDEGj>x6vJ5*wwLGb;^IS7 zvd#ilhpqcGr0=Goo9Vq2JcMS4stvpOlxoGD*NV@Vmzop=#4j`SC=f4dlrjH!V8Z=8;TY{dtPd4Dyel?CoHC=`p*oZBr|N%Pt^tp8UCjwxYEX2?_L z@X~cLRYfJypZI{UTI8}}C&1$d(+tY23Jg8M3RW3+L)2toXkf63f^U{J6v;< zq!!Bu!HWlaA<-M2Sq|fbJh9 zp|t=ts&Iyx;A8&Pzq6adbNc*Da=7z13U0s@{qn8>#7}SX5X4VJ;1zb6NbliJigkkw zRlno9Br83w_@n-IJossjvbX%<&*fR_3Hfy3(HWMXZghzk;^BiO`jWA8GlG7!fSOXT zYC4r@o|Rk@-`BHhcxo}s0=vyU&YQ_$uJu?M&(7s^>h^OfIuq`B>oTXn=_w(Az!H>F zrRX23x*_7r6v5)1tQQ-?uJszGXi zk1JUFB}K8M6>hM%TzaAM^qJ6v)sij%UgeD$wUsOpL2~nH%qzZmDV_RB=hsRN^ZDYl z%f@=17eY5vLKlz1j|D+3Dg8AcA8wM-fL_jknALiu_gT=T0{09v^U^1@ zw-<@}D{sdskFWH)1?-{<;KtMNUCB2{-y4r?K{v%1$D2uh_N@QwE#0Eg+c(B!svO}W zi}wA(OZmfln-{$in2^CGbgNtW_$V6mm;ROP%CD@=0DjJ@89nE%o6cb~V_viCnVe!A zYnwrx9+)p*PikNzX+SSa!B~*Y@x8zSOj#GNxi2-u)DL7omI{}!DGqhOyfHSRE=M7LY+jMm)iCf<^Mk>3i`@pt~eb-u3n>?CvJL6dVj02xoy}k<7UYPKQS_^4YA_h^#HK}B%#HI$kDC{~Gi}VkGh$8K?xaYo0@d94 z3i@)u|1@qd_K{w)1kJL_U?p$>(moLAElybp`r^M7G!l8ay(jKy#2ygjReEF3AZC12 z@8VSyb|F_or>w0N1Sl3NsaJUf7>tIFb~XTimteibm$4D=e<=+WtNz@u4j-B>v?b4# zo-y%}Nf0!L-lQs6S#*(kt(4GgkCT=(b7VrysL0{=i6QK%NOSQEq5iS4J^5qSNIzpZ zh6Ps4XkCM7#aGp=gtE9jk>6bL_v6HHiZDy3}&unotDzi4Ag6O%%b{?>%}4U zf)SJqu{XEKNe+Iz{|IGak}{svY^>f%c!a4pd zc>^j7EP$Rlz^Iaq+E%)n2i84zM>-(iON-njX)D)DqwN}cu{!rQ0yQsF98R{&b825B zrJHH`6EZ4uencW-Os_K}UEvVE@+n&E&h*Sg)};W^9_dbZpmPCYTnYOT8AX{nttF?J z^d^WY$j~^F$WyP($z^becF+P`pIO1LO551$KF^l0!kH%U`Jc+0R6Gf5W$bl$)eVqu z>qT>@IJjt+HB%ld+z8=q^MguQcD5H!1<$_pp-gru-uCISa~8RuLGdgbII}^ScJX9~ zq)0|~>T=Rx&?dpgrWosWrmkw;30rShD((nBj*fq_6d*a}!85(N3ev;a;cn^Rm(9|} z`&g47{u;u}ROYApGF-z8S(Dh8KhzQf>^3pKRhtmdax%`_hJ79~_=S5e9J|(QdvDvX z#3khTRr{LneUtUP7^xe35{KMzX~&nyE~O0Lq<09#Lu{&%(sLZL%VDcSmof+aBO4^R zhO>w!n8RZ&8%q8R`2&_YKV?JhKs)`07u?Ex#Ae=vJ^?H>YCR<`&o@BKI(=`QBb4kv z&=3vt^;D_26#C-b{=;4B;XbCC#Ky(q{IoYO+=zMEv5R6jwk9!Z?eqSZ!j-A+bY)P| zVDhBYvu!1)uHLH&->6$tf-;Li4##Hw*Rp+g*u!~Lkm*ubh#ZN-E9uv&Q|ZC~xn~l0y*n zcpJ{+r%3-5C&pN@x-Z$hQ5Jk!Op&}w)Yhfvpkker5-kl3Iz7EmLLDgj+a{E+T7Y;^ z#Q+OX~TvVzCl-O7oQztph>vF9N2B9 z_*tGyj`+nS9qC=b5Im_U*K`(rN42YMJ|d21HzystDM6lAFJBbx8v|&r8ZSm|88Jp+ zIjBE~t1i>(L)4(CR?bNo`3p>?@`FWD^PH*W^B&_VYil^ss;CFp<#)u=%B4V^ge}Ao zlQK@5Ffc_J7w`;vjCc$ZMX*k-L53%3(&3Ak(M;aSx&K#+b!)m)RuD`!AToq`zBVk=F$*gwOIdYEqf_%T&ywiDG}$rezYJAHJJ>O)Ae&R>&BI& z6v@ZKw(2P)2S^ap-e0O}C00!(misCd2X`lF)YlcCx7}=>`sR~l!%0EHZRd2eTciw!ejlVPA-ah%l2xoJg*P4;m+iQlTM0fY>HB4YI=KsOxE zH*4AVUTd6X(Oq6ki?<2T|(7fm|?)guZWi>;lun zwHDIZKiqB!q?Igp%!E-L*qZ>z{yoU=n%XP`%O>22Q8{jRZ1bhm30B$OvMIFGNonK4l!Vpg9_i7RJ|c)VLK5M_1y{32Wse(#C+`r&uZ%QLW7vCFapGO9Fn)Hp0{9%DnO3HU=$3*00Z~w+lCRj%zpjW4n33 z$t2Eh1>@xZ|9uFIQ5`93LI!eLJyWobr6MD0RN4SQG+01o0(rkzwyvjA4DsT=RAJ^x zsXs0-br`WPn^m(}dM_Jwhz|=d;et8YA;$f3oe#3o<(dv&i-*MglTssd@)?tW{FRrc z^_PA6#X)%e=N0qry>kKl>TBrp^)F#wf5oXj%g1>?hXiefDRYf4iPH4nt%hLSY)ab0 z2-(7-?GLj2>Ea$Tbct0v6d*r04mPb!8Z34UE{a5!OG0@vB@YYA0KW%a0WM1}m_18; zP?H1XhrQB9i-|MHsGh@xc5MP`mc~gj-|JkYb@5+T-xX7g_!Rse#M(ZV{mz)@&-GM( zXhh~PK6V~-PfhFlP@E7QkBp;kQji)YI^f(2zd>%$fi}Mx3aSz5If)iRKUFwfgb8P$ z`$N#BVnOPH9<%#8vt5UY)8_a6q9+n0+gAS8wyAIF{hT9H#{BN+ar7vj91C;SqxwR_iaH^jVpbMShQj(Og> z><+6AQQ6B3rkqt-HUyx7mBRR5$1$dn`g5^kW{ktPS!YdY=@tW(7bOexi1r9*;5 zBOPHTc#5c)F57ElXK*QudeR?;DRhZzE!i*E_@Y~mg%|CEM2ncZQ1vImegl8!iw>f5 z5%Ygq3xAB~M)#fjzQ+V(^o4B3*1%j2YGqxg_x+|QVuXsy2cNq&F8j0?{Rd~D+-SoC~C ziCh#i|8$#CFohDY?Nz*K2Mpq+gepJ~e^Oce{6DsmSk}whN}r`fQcE)mzLnr~5USXj zmt8ZQ7GgMyoQ#kV3aM326|kJ;nK8ZKH)S){?k217r4fp^i{A;~#G+Kmb_P!xaA^8!T~7_T2UY?|zrjG0yh#tX{N@ zc~Eld*lk;E=i_ZYFyd||vNv$E=Q6X?L0=Zi7qO@8;xbC-|rT` z6*$au@a~yOY=Ub_@OzVHVtXr;;YmXUejPu#0-M?YTg-5p9M{T3*yI*}AGOwA?P0DZY`tE)&^36n!&W`Jkh-gA?d z$>IO9zP8!)Yl*0|brlmu4v1g}?`h}toqZfxsHuFhki_uR)XQoh5_FfRbs|dn8PHkT zTVe`y*b#t`9GEAtB~4F!54&A!PNmFH>@Sjm$qTeT-?OCpzfbL{0}P2&VHM{C)6`)O z_)4b4DgLcnn+Q#qq%}t*nXj*S6e?@4P?-LP7|V~PSnO1gHv*~WCC3QQ!nBY(wK*J6 zn`)KAv5L%d*6KFu{lqCwAsMemxj;k1`&N=%vl{zqy%EN&;A;t=ypv~K$2=GbidgYj zyh>1-d5V$ysOQ^H-R`wfDDbj9Fheu#!ny2`B<1o~F&J-5dBu3PRhSVOM8C3=*G&J{ z{dmK$JE~t5#(JMI4uLj7daNl}nx&HT7-WVJ zk5aY|ubH{l zDlxX!%~-74^2ri{FS1${1F|#fNKY-^=gZi1(TVzqQRGQ>Jadl*WHU^8U6+ha*O>ns zxy`ePH%wdq*!MlrctSiC^Sp4I{V>nyg%*Jyvu=+!7-1FaHT!)DiGqg&_?ne_F z5xY21$@7Gs;-*ela2NLKcYudhZ__AN03!v8N&xHVB1QqDYFP^NkeC$njBlTuOg)Sj0*fK!a`sJk{3eSZ9l z4<6#X@+e9{$vq0&WgBHzNgtTN(`LgMJFc2K0va=EcPV@p=Yt4i9hG}dxt6fZmUxd) z$Tg>HuengP95*Vh2Cuy$hKDpI!DZ5rY?07#aHyslfYW#PYRy835is+yppL;oXUCJ)a0GT{ih8ZQLxT0S)qHQrQ~5 z*@H$ejmNM7&DZ>l@%7-PbacH$`Fdu|-L0G;7x{0~1}pV+Py0Rv4lZ6uo;zKYV!>SR zOI9me1yq8qWw^o>6Mx~jGAF-d!Ilh=OUwS5@I#UI2$6==R~}~l3Lb1C;jBqYzn49X zkDwt0aGNA1C~TQ==vz_>F1vEz9Gy}>vB-Il$-DY4Mvc|qGeau#`{0wsSIXmh+iPk$ zmq~+oXgbg7!!ZO9U|*;y?jijzK~lZxWodP}a&l=hDC#R$zYKy7@c*8nUl99t%RbQ&+bG*~#a0HD+IZx(xX*=n|!_4>$)O5ZM02Fnc~5p$kuEYot1 z%Gu;g@6{gDCByxYe#Mi)`|(vBwtVSTTgucHm(=cFi!niFfqI0V4ULN@Vndde3=_f8 zQr|+3Ixg@ErM| z{7*)VmbJY&_+!c5O!laty~fLWKdd)?Z@w(_p!5YEe*KLb%@;}x^4jwO`JEbHlkt5D z?cyNSgZjvaP5lFYKIpnh`kHXO-U{fjei$TEj>+7v``UvywCK9vIn=oj!dTG6O9#?B_T|W$IE6z9104P>*7gv zmnk3_3(`mj5n)F*QYZE@vS?!GCKqNp^--pB)P3)kiR2OuucqYN5BkEqhtuvM8O%hK zyj)jE`CNn%(&mzA#K|Jj5R4#KN#~!I`J;1pQgXheN`2jhl!O9+JlzZ(1%ze?LD6Gy z_fd&~aFBV~usOAyf61c+xaZWTr~)+ma9&FA|6GGh1-74bg-A_+H?$DvIy^@ zWY0N@rs=FfJY#|XMoSUw6t^1}Q736c_b9cjeNAU1I8|qGqicUgPBvVv8#R|sfO9^Vz`Lz797(~V3& zObDgcRlJd%|9nl_mZ2>5_lw#atYsL9;TWBX$VBIJwQW1fh*&_m)Vu_;?3Z82uaD`p zsR=KDZ(6)UGKHBLB=R@eenx@+u7u^}7YVmAxPZ#a4-GGo`kqp<`JXv4-9CPDC|_HZ zAp(l?i<@v*CLO5ZgDXKA(vhNBYVoNpdit||3V|j0(O>O^k!wHU#UlenF>7ff=1lypIv+hqA{KD z6>i*Uz`5+>&{*{@j(^8oqWV>XwTx=G)vCC}=YbXQWQ_gN!N|Tt|8l!Kzv+GId~YEw=CZvlRrN~c=^TER4Z0d;_rf&I&*%l-8_`o-d8x8d}-);*-D zuJ!R*woY*uZzfo_*qBi{vs{>IngI8ESY1+@6!NZ#rWC0P#{r7O3fE9QMn0e{0I4nw zD<#|^uUSDiv^5BU&~nywpD`gFANYx1jIcNC3;e?{J2EB*6+)=Z-MmE1KC2lHpM?Lt z(CHqP*n}4JFb>myA1BZAR41xa|? zjnTXGk&gSv>5>!M-+iiq_*MIjxciLK5>^f1x!BKdcG2%k zC?L7in4fX01ZOPW)mxCh!=mBw#_=}KADDA{2wy{~+lm{r+QtH}7n6lFuT*UYr)DvQ zTG-wIoslhBCgZ zH(C88uGE-qASaHdr;#&_rUz%l`RKjy*8m5zS=rN9gNP?0rQS5|~XoDaPz5A>5e+ z(;Gn^eQHR^HS|7fI68>Tm-exkS^o107o;cO&uRXRR4{0M^T<%C z?UQQ@dCx0dRyc+f+8gOj@Y|B~ zH-<|+BJ_WjDj|a|1$Bje7_?5Sh$%e8agd)RGLjWjtRokSLbTYY)Xp~r&O1f%eUVv; z<@ODvuc`egYM-%=1TzLO;<1y%M8WOU{IU0w;GW0nG{xI&yfe%9S`}9~O~ST`7WEnb zAd3y0GRV>9Z{O@J@Pf^091lj-R$*{tj9n&Nq@gO%3AuA!mi$wMA{u$Mj`1`IZ`PQ zLaUrOLC+Nf;xqhj-@Nk(?1jWKn#8M~xpY7Gb6LiFwipl;z56P>67u>b9ZtS|f-6}y zXdPukN5xCI-3_Uwd#^e$1Ln6o9FuHcRO&X->A=UaOfnI`%^jk2M3*&Y)LMDv&Sy_6 zLkFcnKx>5wh?$ncKIak&+JQcYxj&y~+E^ju={8w3$UPYooqiQwJqh)5bXJ9q8K*gQ z%xir!`P7RiKl#mOMXd4^ld58QWOAX?0f)UNy_72ksdbPg&!VNeWI5(EXe;DA$GBSL zH1zYp`sT;CkU8Tt=stsPp|Amfb}0F4mP<3~bfoC3<}T)R^9XeDrjvx_)mTy3`l2)$ z@zqQ0kwUq?i|V~L_ryNn*%dHJ35%JfAD^3s7`obLpmm@KE99bZn(V~#NaRVtPK_p6 z9$m+YHus%qjbN$h=X5!miF#Cqxq|yd?l!CRk~nfik@%@cDaZITyV*QtV*#hTPTo9N zO1oSgn~v0v+3e*N8SQw943(&*pU^xfaMi90H?jKx?XB}oe>{sb(g=XGpC*OQE|Q4H zLnwqx62ALUV!Tt9>2KK@+e;IfaOG0a+sOt79}XL~lV5(KsuABuaThT=K9JvqOXZUb zV4US-t96-6=mcQ%c8H@GL`TwKv^?TRV);U|Dmr#V(jxPjn>81?!OS+l9qXypw3K_) za)n6m+zWARgFL)eI>!|4I9CYAg9ZH^HY2mD=7z3?m*Wv?7TI54uAdPH*+Yn(X+Mh?%%*#RR z8l%1gd3xqy{K;|F)<-M1+%gi4J?_$hu)U9xyAvGS((5FOF9?bl@HD_88lr(PFjV5E zV!qaLA12vCk%yhf@TxaaP|=0Zz)1hEH4Db};uvJ3rsApI>19mNWF{5S<)HhvvY0Cg z*k=0X+frwS%7`eUzDUh#e(e+2{63yI{7>UOYciY;2VIle)5FQl0Q%U#Z#?jk&+vdP z%y}1d@s|yy@Mh@NE(&yMv~Qx%3+B({I??McEh3>L_NvGj_s7ex2+&|6IcGC?mP1p(~Y|_eYcyjMDoD<=D@n+%I}l zSoAX8PlY?#;Y<2eAs$${?FCzInXJXvoZ#$TD&oi^6NEm6@ng{&i9V=fFo?8gcSX31 zwq*N<7-f>!BFuTG_i{fO7%j79k{BVTpa7c41w0}$zgRVDT5!bCZh=TSvriZI7q@3r zNV`oPJM+8P%Ha$w&-tYUL~W(9vwE(uNCW4pXV=bO&U8oyqWwWNnXh&7F8NOX8Cqca zC%GzSlpM#8+>bSH@kmj|BZVK8XL&wP}s;)6E$yyK3bd_xe54VGTY6Q-}dR)P50Rm#nywr1VE>`nE2L@8&(ljw3J# zX&`G^DNn!yn9sH+17N0 zx|eFVEYEO>cr$E#FVeXep*c) zJ?q)BQcUpazRS7C&Lm9OJEEupd`aFn*ivv~?!Y{uJ1eRFgW> z$>gZ<|+P?dolY#XO0Ig~L=34t~%UG#NOULHXgUF`OX{?lFbuCq@ z$2F+8&BF7*Pw5ciT>D(e?$B%t%qEj8D9JR7)*k|o)lsr#m%6Ka{BWMF5s^JNUUzEq zXn)YK-6Z7mFjTW_V820%)CURD&h~3M|LZ5ix z5JP8etzS%nW~oce@x7$x^7#WVoa2JKcHiOstD_o$LSK=fjR0tIoxmIVP}b;xr0}~D zZ%l)wXID`$_`F1}M_4wc;KujtC%-ZcAQEv!jE#|kI2zk&kr>oF!h7D>pj0J;yYE0Z zwi}j3GBx?E$iMyZTDT)t%JhIK79q4fEYmji1dxLvk^TDNqeu7^ z$`8-0a%mm(<&lKREXrwe>-uVVeqmG7*l#h|5aksdBDKhMghx3FAodO0yzxTEjranc zbC~SMCjV{}H4Ut>__39V-t$%*F<}Ur!uYi4XJqD46-#p0iX(m5 zr49pa02?%c$CB9XT+OmOHs2Ei(gDVwVyOflPTT_Xn#ohe79`@flNRRuco-z7HyN<_e~3EExF+AY?OTYF zN-8NzNQ0CxLP@2&LpldY!+TDQ|f-qogbRZ9K^(n4i-+v-ha6u^1V;J#fny9Ra=Hl z!tMi)T7EmFmT4piWnP&NFFs=6|D}rlL&G{RHqE#9(=A3W!iSXUcUQ|q6P?8MUX%1R zmfcgXIJodA^Yu^RnV|m`R6JmTSeP_l8OfDo1=uFp#f5`NZn^z;@Z-jjO@=hJ{#p4d zt58mx^WEFxjI0A`&SXKVVX^F^jZQ+1od7jf35_Y~;-{kz4llhk=~`xKNWDAsVreOy z9UZcwzA`^{c$(5d_~hKSTZ{KdC_?^Tm+14Aes-kTAi%E@dq^uXFbMByZ8T4r5RqPH zKCp@TJ3rSg8x-`aY-|JkL+};)Fg=NgE>s=bg{;c`?|->MubsWC^i)pARIZGfvROFI z_RsBuZZIcklrj3bXRzX0i>=|=5&it^j-f7O=E?br4}h=zNbzaMWOYMnDpkhFwKuzj zFFK^~iZPVdJdjN5X~@LC*ydetB|I5P>kiXW(23eJ_d(A2YF=huq=6hR+P^G?w(qW( zG=cU0jR0!d;ON*nVdJ|AbKlxwXTn;7Wb|js73vUy=j__+yY4Z{JgmQ^m1*C|aVL>* zh8Etm>Jt~5h%B-d9KaZ0*MeFms(tLzT7F}3&NZ%Aw11qJpCiFn6sxAwwBjQBy$tX+ z&G^BOYMcv2jz89#jkJDf9B&ha9aje->Jlezr6g#(!jmZ6hsnx`A_OC!sl;xjkRSnf^l){(``**G{*A8^ejbN z{m~G{ZJ8zxDcZx|iHp7s{c=T!EWh8JwtvyjyKOeNx*2S5xfVNMD7Yo}?f1idhCm)V z9~qifivJVL9>{6fCCje~4J^byupH?56s$!h9%5G3tv4y%b?OTC2sa3(aANa#Jav!H z`1)Rz?l?0+;R;TtZFRfk<4bO3j?`E5#VDB0_*z_#aYXa2^X=VMG3Eoc-6?ieKT6>+ zy(~w!%9$y1KZyP5^DyF6#GpVL@p7O(kwMdl>^oZ3&`Ax0K*h_Tj9>n)w-MoDn%tSH zoOBGl%i?q@^cNbWfec% z%l4r7ISFII?QhZQiPTd%Ds9%qs*xJnNS|R=D(wC1vS` z?w@!Ye=KLYPO3~0*e|uFduA`S$)^NJZ~N9ik3g{avbXhTeb$y*yk;k_S&gD9o@Uv{ zxx3~)($OPnUmlfnFrSawy~vYhIf|3vy{cOMOW$tY&;O(>$tI*bH~7`oqiIdGeZt@E zT3H&Ze~%MURYy`6f-D?~n$`GIstA5B`(98}QSGgs^cYL|a)S;&|3(id0}i#5$@a?STSkZFV$~ zJALX4hSCo6)>Z(1K4v*@1e6?wML+LBJPcaaMx0kfKT>Y`(bgP0X}kTx5!@md}g zGuAv4^T(@7Q$Aj#g?Syx%YuV2itjO?|QgO{`>+hVFfCT~>;`>nHBcXqw{fwdqxIul{E!$6ve#BYIC znS76}iOp{(0y~$jiFH8$nvRo~i>4lchh)zp6Zt!1nQyLCB5xnsvOwkMn(u{~lRK~O z_2;_3lwh8ItkapxuJCE`y^2vuJ8lizblT?m?PS4d$0Bl%c+Nz@ zH9;uliCKwTI!Nw?`u6T?UkU1c9j`AW5iO2g3@}61s6x^5c`FOyJ;0+gGAX7o^v*4X ztwQ!o!1LEZ*;Etar(rG}{Wi+NRU}wKwr9S@66-exKA9FeW(iimvIw6Or z3Q3gTN}`lVuDkkfnh>=fpKa4`S8L6&Fn^@+?NY8uSlji9a1Aw&342N^rP=3xQ?56p z%|@nWi(ZQg8uk9DtiEqPB}Eb|F`g)*B-e~dMp*e3r;$0^b2oX>KGWI_6%CSyW7PPQ zcb{d`^IAF7*e46*lqbF8+1KmKICLzn#!0!J?wz`ogskaq@FydIx6|?9JqpGWuFlTk z-fShU@GYLb2Q8~d;UB!0*sy|MY2NMDsBHYG0t_%DMFW_reXj`-->*I}b8kMRZu2Q7 zP8DxzCsDyf8Yr2G@zUKU@&ee_&RtmKEmD0tGIHF8qLX5WCet{RPgDy8Hy%Ix7fbXz zv&rogZaX8E;fgF}1%5aq$}xz3HFIhC@fT40oVdY$9OpU^E%N8#fIMeU(}Q&(qnv`# z^b9<3v(ucGqlGLwU*$Ff0_H5LZA~Bh=y4JW|H0a! zr(OR0LdD(5LI4e)`8R5A17!}LHN3)l;S-`;jEu~`C+2?Ff^QS=8H#TSSYov6p^Nvh zx+7ofYy{yl0uOwqWmk7rx|!$9Lt<8*$AB!rgtrusK9R=NSQG()?19ar_Zb_H^Ik4q z4!?Yw0*!4aVJRti@>7|TEzD?;dPItq#U$7-A7#E*1?W zn9N=Q1^*Yz8)a#W@6{Vp-DPzG07tU%UL}PEz(v_d`cF8$D%K;9Sd=%>Q}vEQy5+jh zpC%n74rO5jHi~bJU4`MUSjB4h&Gy$n1n-l2s>PaRBxLG8%kuQB-px%d(`#g+;W5q| z%mZlCe2M;8!w-Soen9{UOK`1UMqgHF#TsyXnYi`^q`?@deMZ5D~ z@1Fw*x17bgtHS@+OwO{&pm+~vvtFXwV;0<@@wcj&?WIsX-bX|d z35nK^)hI5^?*BP@q2(8)dej=m8p6~!#s7y8VzH1Ot{S|YyWb_svSdS{N_8>xf%10A zD#bgRT3D1aeK{<{Qi6r&KN2@OrA23i`!OIr^NfuIj0 zO4om6uVUYOw~@?np{-UwQKOzrx%oy*LG7Khk_5z!9WAmzMLYSRnQTs&bHu%NPkZS| zy^40>?JDZAFwa&`3W;a^>%H?u!G4+eYqIQKGqL2TiqosV^J#0aDm736tjIP0{hN%x z+^*NQ$beR%yc5FI)KN2uSi{fiVqGT=@T#od)MWN31nVPk7U!z%i}ev*hSxp5uHvDi zpBFkhPni>Jsg2F%1hYmpY!wPN#ImcQfGpLXzrAr8QpIjQ)a4IE@mL0wa^~=i-l|IK ztgV;Ti=NtCn}SRE^*Yr^pE z%ey&3Uj5m*JubF3CavdZbp*;{%h;dtG8A0Adn<(ON9H_?D&Pv8{8Z~d42N-aU+lPodt&-(m*G8VicP-~N<$T%gW8 z@Oy+2&F4B}(3O{i6M66D8l|;(%;C?}-xdwNP_Z6L8Lxl;%1gYOJ2)FhOv7iv^}wt9 zyP9x4%VJ7TytTRCyahmbEl8QaaPl(sxzBjFj{qpMeJsdykOX&3g?azeM7g zM$zh&;^pkCdv|xfeEAi_^kC{6NBbmexJ6)E+~cpY=Q>fY#HU3 zNhV2M-dyw~OztTrvtNw>V+6g`_a8;YcPFs`kj!OIGLy$;eJN#P`pR9^zNj{rN646&)=e}UriKQ%CWrsDFfu1jSs%77$0^6j9Z^N%c>a|yi4?|%&3l?hR5(P zdM7RQYDyqb?FG{BI#J0I5f8oC$CghvlNvj54AFSMY{JRNO|*R!(&~UQw~$f)4vSPI z8sA<5eAlVr@*(^`Km31Tl)xLr;J4LO;RE)l4D|EK=eO}ksr);@uG$gVQ#gm*nvh#d zwRKIt%2e25Y+CkStdH>x%}2RB_SMp2KQ-2O-0GEvre#`AQ(hCv)#dDjgU53N!O_Hf z@5!%2$rT^t@^ZQlE;vy|j~_2+KOS>9)+Zi&L~)#|ADA}4%J{ysqcng$V7Il7 zBTnv8GRB8m$?+AY5Y4JqKoooXARX${cTxwE(#*EJ8grUaWv}2u_c~iniQ(DJQt4Gz ziaP`Z8eWnmnRk|S^4-+{_dAEI{z+&q*?9b>c=WF9X7}o|8Xfv&lq^O1H&u=c?YPc` zk4x4RHQZ>xu4J*`e-lIXR-Q>3i+(K40`#lNtShkg%~lQ{<;Vmw)f|sP9Ea zJ#8FT3b*t_^;GTrZfo)d&y=PwurciJKn{EGR5zf4QrGO44>GIg2#%T4lM<{vp@&u>QF z1!azSQk%IkweKBQw)AUdU!M)=R%--_|J!e^)gDvrOO&Q%y~^S;`e3HKdJ_soGh*aK zkB6w7tUJgAhF3zqmfU}6eRj(Kbh+(e1xH6%D%MwNnQZxJxG-U(sBZMv;)uz&Q0m8l zMWRDp|Mj>I@ppD7Mx1xG`GYORr8Y#0?x+MX`*?a4$ zp2C>M^`&q!x`;2{F|_$t!P%OPo??a~73*Ec{!QrEWP#(~8lSfaXxEO?75g68!f71E z1wI7&Y>yON8<%eSk(s|yEhL+BpenC>Q7y=PmQNY!rBD#B<9Ss$rR09 znH1a4h~Qg?-`Di@ZnQaX-G(E#P-NiT(hJNF?0^Fm-!*~dZ$)Tm!u!xsTy^WOb)o;4 zApX%#<-rNMO@KV^G-+}XQjVs{Gdmfdeh_b$ScE;OS`)#Y?rAgA{+yO5|5s`Dkj$LU zi5r4F)Ic*FJ)c?AWn&#mvAI{j-V;rn22{Rcd_4BXJGL}zjRR+Y3eT*G7pMsTDia3XV%i>*-kOW zKX|wKfr3ioK|;RnC?SX|E(KxjnAq>N|9FY3W5ZGZVK-OEpdrO)752*%{V!?duM*ia z?(j~1{{uMb2%UVH_|CB^h*aoNl$o|N_ji?taTTgP&qA-5Gqs=ni2W;41EMiw(@ETG zr<`#!d@ga=KwS_W_F5&W`AKTnUs#c5uFZar-mJBqJ?@8{eG=N=+91qJ)f=2z#vj6R zr`$Z_CuL~A`R8*yTe~^`$2ajI>$9piRfU+Bw7M;QNzY#6m4vAZuo5f|i_h-~OTnY* z0n-VzE0_;8J5o2RBn#JwZ3>S-@G?`W54nV zY!d+fa5?dV2X)qeQz#v7i3zN1^KkgQoqB-*;A87Q0 zuyQ$m#hbg}cso#@``h;fSsw5quRPSF425U3KNY_($JBC{HaCFFoZ(!w5B&D7iUA*O z0jnYVEO0Rd)|pk(E%UHfE1ra~{AcS2R(qvFbjMLQH!-_W^sJ-qfnL#5(z!guOjeUGSp+-ui=4p$mhWulA2|PoW%j ziyy8Fh|4r=@rrWiFH{`%917^MjEJf(BM!d2OK;vpUeXGC{^s9k33R@VH@ds*>v!9H z$K-9pCWo&d#x!lIZQT)Z-9R7IG~=o&md;rW_|4X6vOz73t6_OAx>@|k1qNi*sm4uX zIr^jY3496vr{YVHMk`q><^P9WFQ~9|kw+C%h`S~}i~eTK=6zmJe|t-Xy1zR~9>zgp zh~|upUt4f_a@FX3oMM}J{umRD;4{i%Ul*pnN}?eO&EToD6(BEQwUQcy6?NAc((%>= zERzKu{jO~~EALZ*)H2;7@|8o#(&dSz4T4WD}N_!@2q5)|nW_M*nsJ zKZcoRuFKO8FytyWC*KPqTs15hfKE1jnE1WOcDEE}WBUiwsvM)MI z^07K=qG8u6^W?+}nsA$PA`$(cy9sb#&A>>wZgN5IV_WS8un{igXP>F4JVgs*aw2b+ z*5}>F+7iK28Pl)cn@aRgh&-0$`0EMv0 z_z&e7(E(Xkir(fxEykPN_SQS!A?Db(_^f$z!xkOwUv~(e-amu*ksgfBje?-gG5#p@ zomRmrQlA$u;wY4Te|P(g41;onJku=A<{9S|#t#Ymv$NmsfUT@{uDAUU{vJ`EOJ?_rlu)+`sMlq#!$;w*DV_O;Gg7@phZ}g7kL>KTl5! zT2$~%5WhYme@LxnCji0x@a-WCqJ7ld=@tSW;)Q4~l*7$oV)#b%6{OB&l6?sTtlvp= z`0{oY>ar^Z);n)s-VV2{XmwlgRP#0t(+}i#!EU6%pF!h9vyK$iGCR5sv+8((poNar z^P(Y$H)3!$f_H}{>&W(NT#z_)9a&%AqUp(&Ew~_P;DNHl(o?f2(yG zTrQB4Ei;)C7wTtiS5LD&G2&PFe&(}<$fraLzA$Sj6STJ=taSyu`^wA@(<~AA>rOj% zuhbQ!B=*eavN%seqw}&Qp3yJGwFAwy9C#k;v@aQf;W8-{OINI)+?fMr?{jhP8sK;M zE8JJ_4(|KrwZL5qh-vwz>NKSC>D`))(#<|+$bS9qGMWoMkCVn>h#Pqe35HA)|6INK zlxSEn=nztVEn#8Wq+BzeVa38pY@*Osk}(@H#qCRzt9z1*OIG$<%F+++Hi39e08_iy9K{bt(%n4M#O>=Dbw} z`Za%NAAg=nIS8GCbQ~drUbWVe^Ry#HX_Cs--&xz-W46OAhmaSbLRTTuZ>4Mwm$}=Q z01jDy8gH9wF<((>!OqwvcA;wUmjx3zLk(4RreUMTT|}sh+Lf2(8J1~B9212NI%Yd|0Y~*T}a3tDVMJ0 z6y>LPR#Tf|n#+>-0170HZ|8!?xk42|EPzN9({;tVpgpoo6e1{}D+FP(FPM4J_9b0v z)s5@H#&T8d4g1xe}q~Qo|Oh2hXAAx8%CLa>zfT#XzFS8Vv1v6nVE10^=#SMF% zgqe|r^g_aBvBM#{)Tq_fHYc$e$8-Bba*Bm9)MW#N#xKi+b2_c7+la<>Wl137{Q6Bj z-As~bA0{I+aM=a*Ft>^e9J_$j_nvKxW0}}_!GDnXXZ7w1a$RnQAw9}s3`*HFHv8z< zEmmp;(rUKxdo>D8OdYD)ygWU~mb+nJN^rwh{XpAlV!qw(4_qDoS^X=r=~2f zfL%Ox=FcUfi#d{9T>-(gy$PKff^|Zw0O#5fvrsF&dMZ+Wqb*pTMWeKPC*RF^XG7r$ z-p|(Yoo^+ETSi1}ncjAQSyj)dOtlwzTp!ryb-Vs3I;{+Mx*7Wl5yCTy04H>pK?fAX zVE?;sJ-~=@=RZRr;=iR#I^g=m%r{#s?ccO zYV#NX*T%G%Mp7WU$LDE4=a;k82k%I)%-@5XqTdiKZNazdi9X$a=_r~vOfIn2 zarud^zh83%I8P;L{8@96y@$0*$1dx587=L-ojL&xF}L#l9TwX4?Ay6k@d##L@C!2k zz|+Ef@k)AYYl};!Gp~(nNic#uMFG04Mh~0VVW_GXPfq=rmfycqIonR`Asnd3+9J93 zy)F*qaLk`vFtcC<%CNl;I-FHf=w-V)K=Lo4(B~AsXwqx+F!_ozznKp{%$4Nd+_{CO z!=%fe08PI`3hzLCCOMeUJ`YVyN!*GM!($oF%8PUJgKXk_FV@BWHde<5ZZYCY16BmXy)Jw>;mLu)C^Hn=_6h zPe-)WU}@f3kMWZLtC@J-`7DdKucy_N0~qOZGEw6Ti`Nb*>uIV-zLFR*P^8)dYV0&7cAh693&Q<52$vlpiOr%EUwl&K>UMO<jtS;WebdT4?H9z-J{>rE9{)M0Bb$TQS&!Ji%sbIs>Rl!R6zP{5xuj? zQipzH7Vs*RNYA!4a=%qDc^MG^%Z;Kl%eSotCSRPjG?=?NNz7}`VB^mkO>SB?c?+cs zW=^H8vFF=uuKEn6P%tRae{DRoD%LPjZ>{G1wo%~BNe33e1p4VW19Dlyo-NEUwnFXs zFP_~54>0XeFG#lGB-q3ka7GKrN--uAj>g{hh`N4_YY>;oO;j5m=+Yc7`HA262HNBb z8KOV@UGphN$}K?jjKTN__jMT#Ie&-w0pB43$!KQZ$HHNY@FOB(T}<0yTrV8jI0|f+ z&!xwp|_E;I=sh1lfx9;G#6bx)RX23*3$JKr zUkuiqv2J`5B^j}-ANK`Rz@iKjvVt;6QzD5>e~4sb1Q@1woZT&GxU$6@(}B-4#=F+onb-^1$$ zqxsiRpgr_CE)2UO47z$SgD6kf7jr8FpRQ`Sb)4sz^bS_wxB9*X25-@9asoiv@sj(m zM}CUxUH0})C|ip@1)b)a`zvd`@xVj} z&B1H~9${OVWlhsckrGhz+)E*N&N8+ICG=_n88pF=y4uY1B=+GB&+hihEVB%-6EO1b zQn+wK`|=vM1r-_6Sn;X-JjmP_+i~o8N!?f#I8g%{q9VPx9D*6RF#18?1{s4phW*tz zUvqhZ`91Mcm#d(ZoHWR0rB|xWj1Gp@!mvu~EGfzRU7c#&FrT*NcxleE&#VmDbp*Nv z8Sn6gA6~N9;Ek_Z_H=8at+2N`Mt(p9d+nqbrr~v2rN@awU@smM_Es)Q-!2u|? zVZvwJTloqyVJEmsYN7C3d3HrGI8dMQpok9gS1-$@8H(FB75hemdpC41NdL&i6OrM{ zz2X7yM~ntj9)>DC)D18(A*Wr!%N5TVDKux2^a525RA-gpE>UD_}Bpr(sa5Tbs@@w>8c8f>6BPEQ74OZ1~?$S7dhnWMHKEEU!wgHG)KS? z(X)|%(Z(p>NoKyftp(i~X2e(}#oWK9AfP21?~o)-EX1|985q^5>Qmj%Me8?|`A1qu zr;>W4q}!gnm+YP!DV)hAsK-F;gAE>Tj{2eo)DwudPl&nLS1>1Fn{HD>752BX`~>S` z&we@Q+Y*+xCvzn3h$S#iSI!T*O!&H$!}S8&Yx1J?SS|qzX*o(_y^8}t9!+pyWrNAf zulWvNY%1wrM!`d4_|7pc2yT$qSxaeegISAwqQ7 zie*4<9U^bJ0pA9J5o!J6W64Lb;w;EyWBKf_EbV02oLve%I%h{(#$^wAW)anX9tkGj z$Kiljb);c2Y>`ZV4nByFueWU}$fOoi>dk3=XmD}7G#l7ye$<}1Fb(P%30eZW1S62E z19zPIyDi&0Fzu&<|-wNU_Jb&a5D9wx#yhX$|nRO96zea z@NbH5B}L?fj$;tH*1rmS5y|3Yx^4Vh>e7Y(1P^d zZtcYC03U=FZ7#S2vs4JHt*uRIc?w95R4S7lg$KyB@Q~<%*764vUPDmKcFFbL$Q~)F)=+Mnxk@`6yK2{&yQA z*ZXKzWv86w=x8@RV8pNlxy$8fs}954(uJU<%Vwm+!SEC zUe6eCaSqQ6bHH>xjDtq}K|d5}BhJ2iR+f2t$e*ZW+j?LUJT;_sg3foL#Q31Zmo?Ge zoCBN^d(%^=XX(F1eAhx8T=*zBSF2`Sb=I`iE-Rx&aC)KkC3iACtaiJ`}7Fyi^^K^bjr)|)mCUj zW~@xpT#L~wAaEj-b`LF4b@4T*0Hw;!R964}3vVIgld^*^tp`fO8*wztCM_e=+u&L!Red$K(1H&#e)P!`(=l}d1Rl3c+%w>jxd zJn6bZIby5Y`7^f4A?Do9wOc18 z^Vs_6T+(T1?Uls{!PuR=g4z4(Q+Gd+3}qpc5tf;bmCVWLD#rO zB0~tz=JgJ7>s>ZtX52qqx-!5fuf=Oot8?UPgp^I8dzN4lHu*)vU?s2)f4=X0<=T^w z`4$u(zE!fHo}}oMs9VyUm{&!d;xIQHSsxgGEz<#!wTCb#{3tST_1DI4Qk9pLNorC9 z51&Wrzx1U1DD8hXU(kD7l_M?$OHP6SsyekI7y|Rm!8nojOSFk`n^n!^l#urye8lb= zh3MYixDFZ6be_`+@!a7vZgFW2#@Qy(@S8y%pU^tZ>^B(K@tG*}hK+jNa+WwarFhjyk#h#f zG~SsKJ#Moadl}Sxd#iqxVLoT4+MK~EE)NF2(sK5!%l>TmXymzl&rXi7oS*q4)#y0L zb^7tYv~?BN-r3@@Rv!J35z_31)0Zr$W-MCb(<*+yd5X^o0f&NeXDaj^Ct;oY%?1`T zw@Ht|P^Xo87pVr9$)4=bFT{L>ctT<) zu-xY@CJ89&XZI-g?wvc=y+&Dz&Vr7XHPOGPNtryEy2uh6hQLIrTBH>W)z8kx?BKd z&n&1Xb+W!%nkW*t>UG=zL1T;!KxG$-VVxtU^GkVN2DC zw&O2@_hKxWopXb+oIt!JbsDu&j8j-)kRZqKrP)~fb@U3ub;uQCV4g>GOnuW^BPYVthLEAfFY?skfiYELP~HJsnYHN16ecq0@vIQT(-w3{N10h`POI(XkMys5YB zzf9V4HT(XU07n$oU4u!P5YT&Da2#zSZP7zI%{d$L#`x*T4qxHwC8{!6W5(Y;yI5k> zUdOHNG7Syd)qU&?o+e&jweDT2 zLe;%d5(%$^BC}TSxx@(aX|qt*iJjjOd!vNtDM(vGjquO9gM4@YnVJtSOL)UF9&Nlv z4JN;%=|y&yWz6>I5`Dxn#I5ygw+fK$-8hy5f>bvdQi3lPU~QNrMfD3KH9FBL8FEQO znP5>>W-zAQwF#?k3qTAJcPzwaiZuK)DvwSd)3HO+7=NeLwDXXML5&OfMq7-Gs661d z@*{Mjx;H`R6VwJ4G|sQ~J%0yO)YY9~PxmI4Csc-;zrL#opqWrhH?OMT!={5qdRWdm z4;yPnMJz=Qn$sni{lCI(zm5GT$Udy>-Cn~XS}g1QXoPErDs*rzI%}-fciEf)M%jCk z_&zG!H8NTm1~arBf)uJ{H}o-uk{=!qA;_VwU&l;Jz{On_dIYI`SygCq?g4M?!U;$l4lBd2jMqztz~P zgJ0vbWc4ol_fO>eb+Yek+NqGe115ZpQ3D>z6eh{(bul5NF@ELH*{m#M=82<*DR>^F zAG<1eUDq)0>1ca*HPZ$f1@Zjus`J%aXW_jXqMuj(`OUMdI&(KXiI3)VpF#3knVOWF z3%aG+aq+ZD68Uzf2zsz%b9bHfC`3P#Lh=tLa%^(#8s z8m9X^4HZ)L22SVk=JbcKgG<*kCj)N_SWQq}P`PNw9i6QAs5k;;DG^-omrk`itX!OR zRT4R%!fi>R4_v&H2VzV*`Vp>!F3Va8OTM{eQb#tt7VXNxU||m`pZgA$Vn?S_f83}~ z2@6ukD)nr7c1&rt{_sl)Ul=uV&Bqy-mpi+*>*1+7r6Ywk5kDgXdNh;O3anM7I~(b$#0ArhE`G=S{KV&N3NRTv^@?B8K*ZgqXWIS2J z!35JIxRh9KMqf{97|hY|);sOpBMsglkix9kw`@+v2p^Z`o^6lkX9@&G%ew9lAF>TC zX&SLs#r~L!p5kV=8(Mi?(SdIA{~mx|lGBjJ)!PkUn-Mb1ThLkr=9FCHvr1I4YKiNT zsM+H7eKD83;bB#Rdmquq-(+nE`Cm^TQ*$>s>`{zl${47m^Lv`87?ZfpE-hqAxxrVk z*RQ-6^OO0cZe&Ss{>o+hj4oUOCrs_{tr^bLMIzn^S#|asgN+A=o#XbPjUOtLviN;g zpvQI_?r^;ThcPG?%gV7=0P48&jn-+L{$42iiuZA9B zf~cNCdCOGUNBRn%?HclG%5p_3q`L##YIoH~gwED|z!xi|uMPq`_V$Bj_9u;cHr?Pj zrfVn~e`9a(s~o@4-l_>ue{0jJToF4{wErNUr`kgy4C6qpCs}4xLz*PTACSJ#b(5d4 z)HX0zy^jVXoQU6m(A9G^&TFPK&d%P`vq-yMly34}VMIrR_mgE$1yaIoJj8{b0elJE zO0YzXPMk|m?9d`Qt8C2hoa@|qi=d?Z1QL%`Uq3{JXh=Rd{B}(TbbLLG@dTllb@j@m ze3!KvEKU5|`!HiG8Z)QJl6ILg=wB;6ixNQ*>c9;*$~z_nT4PdrK8t#pfKBzC7ayzo zqynLsw#(-Y&Io;&$r0rjB`EwZ>7HET$Bz#bR)d8mZ>(uly4By0Mx832P(OC$?&NB_8cOCDd1H_z*R6t%+>Hu`XbU@s6 zH7dTP&I}-;syx9v)>+{jPBv4@3@#`Lxu^EytrofT(Kkiai-iogw=E>W7XHNQy?Rv1 zp3Py%hi1N^KBx&Z+MJ-0s@o1`Df~a2@dnRoQn8Bn-wrJ24=UYX%rJyr#f&e95BX9+#d!s|vcQWtlmF8@$ot#ZTm z$0^k{%`Ni*ozv4)=k|6Hd`>GsU)~H+wcm3Rhf^vl!VBVocF0#kB5K&f&Q5gup=+2m zOJ6~f)yM^^aTiY3FB^{jfg{3p?=M0c!X@$F=u1q*d?6(rUa+K}HH2@FWn+2iDaK%g z%r?dDWbqKR+s=7M(j9b;cTVxRT@8SN10RFWmTD6Fu3NfEJ^Xq8ihP32j-Gv$S?ZUy zfCasog6hIW8*P%OWN?wAPBZn#KA&bGQze3do3g2W__Fe0K|*vMA8NmO2U;-eop5c+ zq+91W?AdpPpYs&^QH6UyQApP%=JI+`+Pgqe)f7H}Fe0e)j7MKZ3_;=DT?p zS8tJPre`LKcL-}ckFuHbCpPI2Yj2i+=0nlUxELNqc?4O!@>D4x(ogWjkv z$nRv?~}Zqz<(=e_h1>dxUdfph3Ug?bk{xGF)b@!5X9^=x2vm z=oZ&#KhnAc9=suzJl~)FI3K_TUomgCgJRpxAty}W+g%CT77jeX;aL!lpatmB%4${w zF54REuEQt3^~cyBYzqU6#y_62gNW*$1;lldA!I5}&Og57nKsTIBc`x~@nU||jj=)k z5^f)Qb0>|Dzhr)2fEOxz%yQXpQ(Y<(H8^dGRt0N94Tb zwVEnvyc3BL%;n_L*YA)-$IBZGctZt|#y5sds=zGaDJ-l#-**+HanrIDfNODp`z#h$ zknJ{>O2B~?MR^vK_QN`L!sU7&JNCWNd|>U`kkKZ9qW=D6Lh!T(CHwA51k>cym{c*V z{gv;sPgc_X0oP(!o)yU5oJk6^s?H=z+z? zl889Z-a?Bs-`mrPqEopI_Wn_-PY=#;pY2tz1#H9_oSlhTIG_&}xVZRc<3e4h*CLpz z7=L~~Tnge~l==68(f8tMrhsL^?XpxWq{ASTpHI_wP~`$PXT(X zyCOa>R@E{2u8r|PZmAzugl(u#3KjoD)^~0G~CS659KspH| z2&i;IuhLaSl&Vzey(NSI2`!W;2q-1ggc3rpp+pFw1OjKz_q}J{b6scu<>xgoEN5i$r}%Rt^=P&s?4>g2OX6ByYIjsI9imd> z_v7Pg?pA2;Sgp*gO7g%{xPwCA^@5;a1M|8M;b%(Ik=`WL=vhg$^IPs5_1Y0|w8dO= z7-)TWmauam7NjSzsEl%3AAubLm;vodO@|jc48eabeSUHrH#vx-{mm4A2Tbp#MdVMs zh}U#4yW_2bCp`P=flKYYghEdnmHolLkdl(d*Azg}si?uOwJSx%c6TnC7hS-sst?3v zw>Wa6s{a<~cb5_fnl~DE>U5)wwuFaXmDc0}2J7)U_kyL3dJX2zsM*^jjN^l6LX4N& zj#**f7j*RWhajA*h=G$@U1kZW>eef=esLu-jsvF1%%OQF6WMuWD!td=dX+R|jd;+9 zB{xyx6kb52+sDl`Tiv3&KTGG&V=mg+7nX%KYf^?9` z_abs4E{VQMhy}4me>iH2vUAHqKP~S{Ys44WeB!wn&DzB`+&jF$YgMX?SFm;}bE?YN zJE~-^>lRsu9T(_ycgeu;&ttEs=!EPn7xhG}q(9i?MfOVdhq+<3xtP29DqB5heEnl+ zMh0SE*K8$v7dP}tFM*&qeMJzFT0W9mZt@8|sVL`G+%4JsJk=^Rt@W+BjO5>(9Sy6* z@i*A>n2#jZnt;TPe~27Hv9B06(h^B^S1}V3<54^?eT@yo%Aao#F_hjD*i{iye7uN@9BZ`v`4&S`1e|gotAvVERvn zK;3*YiTKUT0)HPw9i&DQk!zm{BHX`dl!4Y0H{C;-_%YfR{EiJ~TVb^VcvY<5c=C&8 zCSxt3ziw&07OeLTVb2p*9lj?&xuda;%6`Hf)m!i!(j%lpr-8f60WV!TBqy?vfXSKa$6h zUPDAne_7DUUgqt?kP-JGw(INP-b6H%!;O4fs@%I@9lRvw`1F(Dl4C8_gt}$Kt8Pk7 zXLWd7GuGFqWF5p(y7Ar2=4AoWlHL>KGFpq+c(7hoB>~Q2AgY{2d9GbuR5lp-;r(fy zYQV`zrKNiq7LB;$ZAPsOW(C`7kD-@DkLVo;!v&Bze2w05>W?8fWT6*sWf?%+94DIA zHoJtF6TVQu&oI8W>p(rcJ-Z2id7GgeIDaxop)Vw{OH4dqX7M&BrR?@ti(w-7+cnv? zNtlZpOBarx<3T$$vG!=gb0;;5dPd;|jy|S(<@kXQ>4Fj|e|Bel@|_k?7jW|Nln;e^ zt~lKIIBH~Xbqj6?-lY;^8|Z`56V73>FTIcAD%Q|%d(*6a)uN{X+(4M&VkK1WhC)?# zERq-O5VrfLBBD45xk2vh4Gz{CI_eD1iLd5=b}iNFZo|Q2eGjkwpD)!^u`Z& zPQ@Da)k1Vce2%hd5g0%GMOjKyV|FOxa@O=S+Pi{tCiQpCa$+tOB}|;M^xa>8R=tV< zT)X87)%WX|HZpg({dgtU4t2G42GWFc3K_m=8TX@8zAM89W|R z3MGuBk_Fjs!iY{G4AocJ_)azNI)D4lwz^~C4hjs^oZw4(Y*#eyJ7P&6wJ|7t$z%j> zzl{V@$`b=Pc$V25$c=gR9)-$E;K@AG0s4k({AaSJo#N*2o7+bSRHMWrlXu#lU(kEM zA?B-I-t7Dj3{LVAuyVGW&ZgCbO67w`z>%6w&=2sgTUy4kxWu>92 zLx#0CJsG>R(V3iTq($wqDw6Wn#Z=atBCGi*?boF!odaqs$-5s!|Nf}4_$p6>qc@^J zPcO^qz*JZQL~Z_E9k@11XwZIoliKu9ffnk$VNwicvN?B}xcBe8|2@WY1Hka4b4qvY z*)&CKBP!k1eLc=?+ifB(b2C{Q#a-;xbh{sq;|z4`$VCxRvxt09WJHHP{I3&@8(;46 z-Sb?zZQ;^Ed#o>)9W{qJk#6ZOp`gdainyIXdN+zYTpm9|psn?o2aUmuVw#%Wf?8_j@<~_pC;Z;&1G~-{nBLteiZ1@E7r1?dVB6rBO#z&g3J_#)(rW zmah7n2mJNT+=2t~#+aNU==Wy6pk!lWT6PrZt$w{KXFw-Pdu#8XmTD;*f6IPBWtm3p z4YhtbQ=tBeja*mgnhkord5*`uo9emNoF?$+GuyD5({Gv14TF}Trp~q$H{p1YO?79c zp8L0k5%Ab6>B*EUg=2qD+7w_#Ij-dGn7^KXufF5Wm@m&1vk zn{u_B@V^Cvwe|Gg6 zVUCroxPySl>krr6)4RqIW}S<{JXJzrb*J}&Huq1%>vYxZjt^^E+xMYL4%pT$#7tZ> z#vj)rDk)A_*1kaYvRIIi@1}~^c|n?4W0SsQ7r$$LXHLKCWcf0i6~{;b_DzT(14YQl zbH9iL^_O}Xs+L7FpQR<`IQ-=ew!YG` z6DTxZSv~FY%GNtrd%H%uf;aZvcUuW4_F0=M)3ijPuIl%A9vfGGYf&_v`L)XJMK|@F z$Sl6i0r{9Yz*FR>ntl*nY7!~Ox3xTnoz2%xN=rG9Na7J#ih-cBd?9_!@pUur@Ka6A zf%M@F_m(2N?o{W=!vJR@wz+Y#deB6syTKqn%b$oc2{T!W695U{)GO$WAAu7PzC?(F zBcY4Hu-&#r{^~PxHm*K5etbe@=jU9yD(u6N_iC@GFY5*<(L`K{H?DUQo-3q8J(vol zTy_v7nEqAfeO$6J4;)W{)}ZYf?p_!g`?Wq^r_@Nr?9i)A|z zTL#AB{2sz*A4#Kp3u<0acsN+bYxfZ?B~_n^wO-#yBz>#yTS00Na%Z}$bWqILPW2nZ z;Gc!nUmW{_V0l52+Gqup| zcPacPW2<_0@%vA9aglZ5%)V@sNndq`%V%mTpZPSv$5}y}@cw`$n28 zp?k0T)D#L2&8AtPv!MUk#>Y2Dk&3I=Yg9%75^P-|?-glOZxg=erbh^9mgCN$!Vdr} z9=V4zC>KEO`rGPTwGi8P!bo9jeziHIP}{fY@z*NUl<80>o5_T}OD+NM)^=#WlOMvJ4=ShzFy=H$C1Bs>!}&*Kc-L+_eWgZHxeWS!xbSZe-|{()M^*4SMM=>3tj z7=u_od85$KFJ43>p;E8~gy4y#Z|iY6*GXC?N@-(RF-1(XfHB%`^lWGwY|RjsyoVFPAV$G!f#?XkiJM)RFg zO^J;9=`T z`CB0XU?P^&hkDm~gPZ%JqpMYwRnW0h^BzSP4}(-(4Q0ICZ?)TEIRsels8Nw>)z^!) zC?83VPWIl2%&^#M3dMRUt3(%%GrSB;|MigI2lyoy_8iu${!M)HPWf5>l#LJV?Cdl; zsb`8l!zOq~-XTk0bwNhLy2@}&47}U{s~A|$>3m>w$5-DDTIo@xh;frhjxbHXIGD9N zg*sNE$@CsEn?F0Wv) zIok#WQr4yE!=$bY|YItQGOZY zwWD%l-&2dzDt{NgCgoG@jgY zxwP?VgP%aws!a`v>tyZ8p&^Sbp{r5MwKsUR(t!1b94*}uiq z?Olb{qb@FBk&jX(EJ`m+J0R|=S!a#Qn2>hXlZp9>!P;qFu=ff>MxNP9odIess53YT zuzllI%5aE-9RX1glaw1ptRN`4x8wzVXet%bOrR zE5IoRWnpYB{a0PtOG+Men`v2xDL(r?`${i;2T{?q!V2)gZJG=5piZ>!ax_WnmEA_t zm9xuZ2ZF=*PP1XJcdSrV3s&6KT***SNvI0FWmBU_&JDSKeg-Y^Wbf<=c&F%RNc*3# zd-wP72#EasOkV>~3<2^t>^AD{YN`KhZ3Ya_A=wJhlvIIH7-Ib}95ooxLGVSn5G(g6Dlx8o}g%(Z4M>nzV%5uLuSL0L1)B4NSM zCpSBf%MY@H^p6ZjIg1-?yl6o$eO*ZU@#GNH4jCquL1XpB_Y87(*ZAzSJMf%bxOnl7 z&|kyec+6I`u8jZKDZNbP?`c*~n*GYn<&bb3q zF14e=K@;iiUy*`NKR++giN{AJPwy^+jSu!o)a^xn)bao?tJvD}MSp)*YoF-RhizZB z&Id$iW~b!y3Wl0So_p}aa>EIwoS!Dxvh0#jX*@WD>7@6GH23aUEGYFC>84sl^b#v9 zmFOFm-XVi0r%^x0t)MK`vkAt?=V6^@NLR9ZO_wa7O)0W;@$wbexBu`;z<& z0f_?0DKxL+P*H?O$YN@GpjTr*xa(K3+Aj=rAXX;+~yZ~S1{dBxqKMvxz19PiCC7y%JXN7PG+e6_l(dWe)BE7N!6nDx*S)}*S z{n!lUU!0u~^RCNp-5QP*n|Bsh18Hr$+cTAY!(qp#eU@@9d=}3Li`@L2Un#x8%>v{0 z+L(*}(droL0AW6IxUapj|3(d(+;htB{8AvonAohYl@)OKDe!2sWVlvOi8FK^q;j}D z*Ci&}|LJu6V1AMA_E5cN6we!4`#x(7~q`h&c*65MXQ^Q0Z;EQ!Du# zQUI~7T)}G<06BV?5T~-`m=(OGjScPB6ZI&zd(`;wZtm0)p4cC+YI^H0k2d=jM?tW> z>Eh9L`>8PS8Hs6==0IQi#^==S_#v#2T2sMZS3W;=*D*8TIsTQ=W+c!FWU#v=H9*?MzsJb?p>>yC$8XMcKPfYi* zS-te{iP=LqV@OBrIU(VT%^s15GxvL6&qyvvTIW}EW+VAg&6+KRZ?0b2a>01oLoh53 zcmd1LtsqrBWTUl%!~~N=lal!ULsLkCJxQ>q<^7a8JqE*1^WAi@JCu2TH%F!M;6W zTN!i68To#2C3jQ0WTkuNc!<`gS}+`A8ge+prbt;X0GTF~tX4FG9kK%AI`p#3+v3#p zyHg}R!`~e%|Gq}{riKL04@B17mmhIuIz4)TLt6nvF*oOU#Eq(Vuz~3`wOXzxkxOPj zA-ocN^20$=&G0P0iGgOa6iTi5vS3s0Eo*b_m9p`5HG?~7vi|twdDYV=hOsAus1@I- zq2Qx~MX*XE{gc_mN=)GD=6Y>Zni)$)vh)$07+%9!vrtoM1-8fH6*l^z78@FPWtZn2 z9J&APRAKUZJBrVahM)C@Y-pCrSnH~W>g$|?ug;XLc8FDY#M3N8R<9)sv0N01eG=|i zbuLpCXAlsv&$rdV!PkHMP{4cmj5E17OZE8BCRvjhS=<^0{#l)Ft3~zyEU82d7I-~6 zgY_LnVIB5R&O>)~IfoLGum1ieC}Q&RLAlG)=nSRxR1s^q;?j1a&jw^k457`BM0wZ` z?TWc~#BWKY!)x}7pe@c>#dt{Jm!T!t;RNU(ecWWwhG91tDdW5*rK623Xx=4h8K^Kn z9^!o#dW2J$gA`eW&)_FvO4?HPh!C$;;lb5jg^GCS6x3X5gN1W`%A=vnHb23|?Mn4)I-G#y_fC*_+cJt{JgL z)~OzvpLb9?c*T@PRzku*a3-aumgKj#ZspbM$&=qXoUd!maE%p6m-p{D%7y}Zpa~q{ zrJE{9%V{pkMXzaJUZMCB3gD!?k|XwiRG-dSpaH&(rmyD&?^Qta5MAaEy55=lN=w(0 zrXj)KU?0)q8Bi`i(wroY%v=d@80F$){OqMnR%JOSL`=9?T}4RB`x2Y@a=892LzOCy z7>lq7{YHJ7b%VuQ!?ML@W?|Qs*YI3nv@hdV2}1oK4m(W|!}#<%M?|-|{qDM9cI3#V zzkm8<2)#`niVaQ!{Nflsd6#l7wNL}Z2-4)%tWbI38}EbT=Q~o(d#$?ctj0CoBY5Yj z+9L4MQX}9&_qEm0fv3wk7q&=1OWjdc(lgWte2eFZoUp4%Aih}>cXX6t-;*{cZtzgmA)w7oY2Y(0XwuY>sWNU9HMAHZG@$DSjf6hDhqh788Pe_?gPa1 zs(m>(Kwi8!EHY$jYFPi>abhR8wmg($G@=HUDj5j-t?NA2)bKcBRc2*H2{Rqpmr3U{ z3d|B;5AD6sG$?&?`dKiEDc5VZWz(r<>FF{MRyoZWUB;7P^1rW4)s!4ejf z{U|OMOUWv-fj8&t91m7 z$Eo+d0lhWyrq9~g5+x_-NS(b{-72E{m)94k?ulY{4y z*@amal9kaEt4B+_34;JUTKkLaK?7t9_T`~h6dqspU3K0i2f|RH2g^Sa^^G%9TrrXk zS=DGWB{lD)jEsW({NRYkFIi5VEGluRC;WicxD?F~`z*{aVnIW<_4Yx$mPhW$=gp62 z2LG1*2}gjD>5bPb3?XS2Z+kl?9O|<9&txNy$wZqRvL7L7MY`tocjaVA4Z1?0#$!?$ zpd$u2f7G~)fsccBLj>+m|3wDK2gWZ*_I>LgV{RIJ9^c+#>5L3h@N>9s<~^p2TMWs5 zNHB&7?S`9}F&XQ~!eN<^du!g@JRR>Gszlx0zDplCe3xFD+855rS8}^l7_%+IZHF2j z4MGjWr-Xk|GN}xk6i-( za#p@{v8w9-X>Sgkev>AaQelQTHLv8ueOS$WKt+4D}@ja#PdnwmALiS~i9OSS-Dfw5{>!fpMW8!U&;tCgW?p_mlzu~hT+JIxpdM5_4+&Lf$Pa>pHmrwLDb-_h+_RkW0t02sHZ^7r z>lzN1F7KZA%Os5OPl46fufQwsx*$Djts%F{dGyj(Yx&t$KA+|y($ra3(|A8P>V;NV zwD%%yd7|pqAMQ@T+?huQfC+kkX`_kElW9dVXw1q-C|r~rqNiHH`B6}41N9i5!hiYP$?5}q(mL|4y`IV(l?`&8ugna0D z_mbytgn00xrS-jUb~C6*RO3%hYyhny2Bas=!;Ze2NtRTNv0s-*DX;E{B67x<;yyeA z-O6=vQpc#*=+^KygXQ0bSL;Am+$hXqYtCJXKhgreCu|)xN2ei|;C(e*a3_R*;BkBE z_77U$YPN8;p{LU)Q$8;ae_(^n3+R)$QRmg-`?u3@D<5yhftVe7bn-{{8ZUyVtn1(t z-)f3uJNEfPc`wMzI4xLvHEAgK%g*|QDGflX{ z(lE}JaUb-KEOX-bHCi5~PhLGNO^~jhxEvWxEOT5D=k7}{RPbJ;B$P~!%(IC3j5KpO zPG4t(kGPR9YU`Tax`_P26KyIYrDmPy@#OS5X34qBuS?@pH(qmIzW*d*KY&kmR+zar z^yfd@6n0$>nUEbBCqE3x{wI&J+?S8&!}E3QnHIdy+(PayF+QY0#vS5Y6kp?*gvQ-$ z#x%{qXGeoq#C^=mcVhw~)w1cl)}pHSbt^h>cf6sAUStMatI4BMNYobNtiZJNO_Dof zf5}Kkw|h7wUbQR$*E>izvno0>*I8e;f;;|>rA;1ecMn@%jC&74S*1v-?mo`)CXVsl z+Y%O#`F*!8q;v`z$~e6d2z!ppV?DHagBEzlm^xPVs7quSJX{bk3E8+G;hL7^RO>up zZt#Hipz`?S#-C>Tf{1}#>w<(D!~#b$T)VFsLu)?<8QX_2x&N89UCi>6ag)euS$o3J zr`iroB5!|nN;VQvT5kVVlEW#@D6#lBFW>x-p3KrPE0zV~xr#mr+T{;k0xis~z}6p9 z1IAU{SHHm#SsqWrT%(Y}@ew0(+^W)mcl-8?^uOmS_Z{Xoa(Is6AhR$4OFBMy;5@Rd& zo-rhiQvAoovrhxs+eIbCKup%libo&YeAexFMP%JubVe#nH_FRIE#%B#DN=+WHT}Uh zL1ttu z6TSV{2ZFc&r496gu-?ZS<5-ryrWcmtukCram;0>*n|4yt-`-Lg#c$DfV0hd*i3*g1kAG$$!;X)z%lXlNoG7&fQl?zObzXJ~4g$tz5O--* z-Cdru(cnEki>r#!4nr!t^4BOAf(Bzix6#)!Bf825(^!7YqUu)0 z=sY*jPUhEo5H51SLgC2Jskg%}d9>h-Ux-ro(_2@N6AK?wf_3!z44t&g#%0{{`=$ioTG@e`;no3= zU#hskTKBv%1kFch$)3?Sqa=pb5(J_@^UI`{U|riH&}x?m>2+h-9yr3%Z#g$h31gyD zZ}>L9XzQRmDI*n;Bdj+fpJ)$T#D2z7$A>sUHLfFIAYuyYph(;99hq|O7pPn5ymwQ= za}mt%O?t}6w>f)IBnLF5@R3QdQRv(3V2WqRA>rFkI+) z)2^`aj>y+}*3rjyFS&WRMdZ~C0JH|%c(z>YnSNxwRO{fhKp$#F zNp_HCU(;5CPS%2yn3&16uWRMiSuPWP8kN z1A5L8LcP%imc+w!IoEgD0V{R@ab$-GDydMS;OZudC9@hSRV6utXsPDhS;L=}laAcz zN0F$Wk(gP4f;`V~^Iw|e-|QyHJdc)z>8R2%N$;FijYgI%2OSOBl+&}DVc zBSpQ-Ubw|jdN#iw$1Rp&`d;+#%jt%&mFcwW!L<><9R84Qez*G_2y9udh?Ee+&SsZ% zlOSN*?@}BlHSj{`G|(9fj7u_)qWd>djtpj+=!foS!QXmb&tN0mIC>9}wP)1@FDDsR z{ud_hHJWeD38&M0T(?->u`89lh~62WgEuCPRX4YuUm?g(4I=^CyJnw-JvB+hg%`VD z;MmyVctRq#a%yS9+L=^eHW|oJSXh{+G#jWAf&`mTnI1n~BgbUhP(cP$TI(i7n(J5* zq_5UKQpHxgOoxMGUQE)swA@f=COBEB#Hj}Nb`d3JLfa7-#`-D|V58=$IYK2jx-1mU zgmYeJhJI}@&N-ysBzx{=@hLbp@mE(9bGI}|P|a6DEv+d{>=81*b58qyALDgg!duF` zoOlqT=JlQ*n(-hc%G=kx#Y1L(p>}lJ3mn=2YAfe6zxB6Qo4*8~%%D}sj%iM|itO+H zHf}Gs?T-FB*?B@LM$|v6l_wN^@Sr56*8&FF5iKgZwYtwHXxKLFqjG#m1NKTbKELxK z>j~pvq>>PmQ9%3&&VDN1V!fX5WQ7bYBf(-a45ZuvLoSy8{JB!7Khb@%HImNo8#$9<}duZ-<+ zJ+QPZxoL_%$21djpKvwP!?(w4p5HnGl!j5$>gl1HDIGKMjyv1i#t)z9Mirr?Xkw9h_6Z)&) zGg1JsVJSjgp|!*L8oEAAJ$cy9gn|y|6Pa8Cv-Qzi>d5;;!#{b6*<>Y=uV2dMKlIMS z2v*-a)-RTmOt;t;ic5%{B@>&AQeTU!a#{erx`3#)*J zQ|a`ym>(UBAlT|)8NzSMPM&E)4H+&D5c3_)3r`WZ$OjC(qQb%!4g33UB)tsHZ;Wg z%=GoA40Hl&F8#r65ffRri3df+#c=JR+vEN?W{t~&sLH)P2+&+wk#eb5{&b$c9!Xi` zcN?BJz6s6y?Ey$yN1KnGg@X(V@N5(wWhZU z(SQ)uf8sToLilC;;0m!xP;Kak!x5tTT@Cw#T?5$o^G4=@6=Ag=aU}U?j_Y+`pf;?D zdMnBi6gwH?VbTtNA^RO>?ex7i%2gD|k#GezNNxoqK;Ep$P|z|qdZIRudn~Y;4l)sc zYHt(Za1%85_htV7+c{3Wp+}+3oH}TABGlBJi`x3&G__o8<62SH5ml|rabnQ5Z*QEW z?t46B;5?8}#2$IW&F-GmnC&rF1o?I94X{WLub;XFPa9ul-%0E-k+e-)_6(fMs*`y& z%q7afdhuyj5-ltX3xio=4IBulj66(jR?>tI+djXH$u-#_&fJLZu8X2S%~sNdx*#$p zYO$9K8Yhpyx>1Fx)`1Z3#lvELx5i$i++wT{_;GM+GhE>d~1ux_;z^b~l)tg%1;6S2$yJJKr~ zLzf_h;~Mv&=kbTTZggs0opkJ*EwBXP$I`}N^*!rG!b~uJ+^Ly5L-E7|SrI?`r?hi* zQzh%zGmyYqokCXH-0?i|+y6f7`>POnd#`;e&qu|O=|?(ABdlJO@&M6Vt67V0#j?Nz z(X9@STqBb%&)ov}u8OXM@em-r%6&K3?xZvaW{eKj>m82;`!R(|u0U2W0K-+rg}V&7 zxi0Iff}{Ps=066mfLN@Ui(Z6UoXV~-jg?czY4%C1b>)*BX7$4_g%=5&++r&JWnK1q#se|hqS*?M zG-#oO1c=G@&}dbl)812+!yB+(M(G_lH#Uf@co&*lH zGWapJh7sDv-CbH|hPU-g?QUG&)AqZh6hPoSg zIHVYW9XcZ>Ct)qK%_EXyiD8y_Gw5|rft0swga-w2q5Hm3TirS`-bXI6S9Z~wvHXZK z>5{TsOh3f^Je|^lcEfGlCi{>%`F04Yic8heGJajCs6P(fGW2j#(C^|z=5W>{h*KK> z(`fr%qE_EU3qKALOO{hk@U~Il-2QdScvWIhM*9UV$6@sm*!u82{Aiobub;zlCDzCa z;bYyS7u82@rNA6e3aB$d=xYR|LDL#|>Yptz>r_B8f6VxE9tzMT(?2K3-Jv1u!A z(>?maSE_Rkg6v#k)F+v1T#qCgn`4=K>I`>7Zt{zXQ#BGkH?UM{HIx#ycgP5xe`*;zcdZw?d?os9Byuh7BJA`E@nUq!lvjhR0@>Nd z>$IKvV8o?Za8>hXeU&&Wa*HPz2SNjUE*#tM5{}zLL; zinG&UltcqH0`F9CS&>+ZljWnhbXiwG2jw^NlI@(~543>`281H!KexcD?!Ui#*av}G8J*(43ae*>L6 z+BUMuIQ{Q8ago09vN!PH9`e#rE&mJlgK$xOykTUb6e#|rR^v&G#}8DHV1QwK^Mfb* z8b!uVcc3BN8yg=ATGYAonZpU7DgL79A6T=@QG+ zm~DKOV#X3(Ul(0J^B`cCzQKKvBcE)3PhNhSyV%5{kHRy`??1#e} z3v(Y))jV0~z6Mv9Kk$cq_5^~8{8YY8oTAQ2YoCn6qjh11-OrG%1*9jU6ykyE{*>wz z*@pkDCZZAM@V>A1F97&|BfjDuU}XEG1x<>Uk^@)LPW}6GD_tSdzL|?H^wKDvXJ)rP z7aCqGO**H9=qyWxYo}V0AC5FdaBQ!2qbLLbr(!2E9luu^ioais7zkdSbFhl)uJ}Yy zH|b7s9d_SUr3`t?*T9CLkjuUka-RbN8lY*-I^MiJBZbysguP#h7)1wH%und^jBaxo zMALYhy!C~t57N-{;$YsMI@M=9#`R6h5y^`xDY?;srrB*mv|?rW2RoJ$;TWTI8BQh#q<;TQEdg$NE7kmxp9` zSI=MnzQ;F|&3z_(B!E|zBL6VYcTCj$f$m$6QD%efyazWguNc}+N!EG7^k5wwudhsT zM0Q&hC~z#6$y|v7e)wPZ-n|^3=7mYEWKMibX2v`b3xst4GQat28CQt{jvbj;yuwm* z5r$s*^uriZ)nm5S)VGSc+#G+A^L2Y@%7`M`>7Xg#po_|zl}gOn)jx0T5@>ZpqB?ZE zh3-2tv9Kvp`()tYk5{zK&fY$Rn|(Jg=YmGLd@;Wv?cnr4N>0^**5QC*x~1Rjz0T!i zfYQIGb=DNBlitPdCBtkp+opxf-*LyA3hj&c@PdaX4`8X$fX9!#>mRzyv3mZ00nmw> zU#%}oEWP_!ze{tZSORgE$&-_hZR%7vqo4|PD?o<~8Ur#95vziH)sO0XyzziOb-Wyi zgFA5A&7d4&4lV(~Bn!e<2Ce^nrzieSOfoWy4HV4PY+NgAUEnaq1b?{^0f^#5$``|E zYTWaSrEaUhA|il8;NFWj`VY1o#WIQ`q8CMQg+DnJ10GduRVMTPWzzmTnU@juVKBJL z_N&E8PYHe3JKS!d5E9HHV_o?8qWJ7iRgBfN#T53w;_cnmQP66*`fm|If0-vd%oRzk2X5sHB~Jq)EC5tq&I-#zDZ-fZMDVvEvV&AL% zr`4Qrjs}S-t*1AVPe7Gn5i2a+vyk6C;|`isB|K*Wgc}3onhrJhJhtUN?a1_7FMf%4 zm9VuxDGh6O8mbL|{@MG^4aj6j?{fI}Eq>#9S~2xRk0Fphuc>ERZyWbm0d`SDf{49* zL1w8je%?Ua%$`>3JX-qYsET@|xc_x-Vq)Y_C_33Ji3(PX2J_O!bs0pq&R6R)H>+}Z zh*3|7kqxs2ulR|Vqqo|Rt3yQ>T;*axz)@nd{}8RvNVE-=x8?baQ+|^&&!t#*rvCJw zPlDN5-?29^?-jh1K`1Up8|1au^q30SY;}re2FzfW?V=7`L%3_+OuWxl!tZ&(X5JtZ zKJyWO^>g!DmZs)}OhP)DfYRP_CgBzHsGW`P;Kw!O-ikNic;@!mxcW@br17l-ES1B} zERg2MQ13HL;s8R_Tuj9O^aHXpQ`vsaLN2-3fPO;TYsN98^#+*yu0;Q|znT#IDhutdZ#O#qqZ&QQKqyMl`!lYj+bxiGJN}lG5Alu))$=q;FxeWoW*+yp_f5SZ+wx5r4Fmpr3YnQ88Q-6)BZ zJW7qY5$AT`DE38Gx<{>6P*& z13fz#$oi3Of9&v&_g}JwX{7g64lzhN+d!kle)tZ!mBbx)@HfLJNQB-V53wwWFWNg^ z$uu?7YhG}}p>7P-C+YUPM;|QFYtAhrn*CpnQns7-nK3y|sjOX1-|(7>dVut85o6&`VT0VvVzwPV|+IM4%uGd z74>$L@t+J{A1y*J_F3n4^rll5>Zbb7vk8{x35MqWv)8bpXoiY< z%ST-B?Nza_?NGap$F{4TmU+C6E@S14^eNY}6)9YgE6NE(ya;Z?rU5OUwmoRlw>%+@ zH!X?FO3J)wIzX{YXW*szm_Iq8(lbhB4@Qs^+|Tqt-Qfnq8zahPnkqY=r^Yl(uZjYi zmEXeXexRyy`if~uP@IpLoX(qsYv@xE`kV$ z|DNd+E>{6h{`eKY6zH~^X17*wDN9Z>d=}K5R8dJh+-_*O!YtyWHl;#0yuXf9eRIca zor^3g8Xw6YF7bsh*Xsh03%KZQrAE*%83>ODP`w@p2iv8aZkKwi&1beQLCa^q8t}`k zV@ObDC2-w94{t`wRClPxD*^E~w`qh%^rEOI&E_P)?ir3LD5NU{r5pwHzYU}&8ps4~ z1ltulz(KT>K<{Nk%g`Bsce!KOcU5U6tW7mqzpe=bb+LRP{il*Nht>^#&B57m&+$E% zqx1YIDQtNtjw}T|C5doL0WK2w9H%z>be&KKgmBPdNZmF&A?Vg>U;4p9BUIt#dsE|5 z+eU-JXTKnv1p9Ag&MkdkbYP>;o@V}koWr-2N@qKs6KJ>%FbeQIwzvdKb{c_{_UHp$ z&;1`55EKgQ`R_{iTi{H>V>^Q*ZSP3cvetHQ?j1Jntpm{Fb6&^M#}E~UbIDD85O`I< z_B{G?L{00<5VcvhkbR~$?uDKM(@^Sb`(qRjW6`%zBM^NRWP&X zloO8(EucYmDL6ck?t3_(wb~zk&J@=YbZ46DM?UN&w|GX$*i=Y)fLbtoFgcpr$4$`Z zbfBG%)37NJDD$wFAyE8Kl$=}p$A84)zs+8ql#yBkl8OHFyjYEXuanH|z9X^kRSGt^ zybhM+fY{yLH=X4ueKca_+&uE#dD7dxNZy$b30<5(m6n>%b;J&(PKBXzI${S(Fp81$gsM#4eC zcbSYMNu~9|5XMFsb7#yV1W*`ahKENnt)gN-hYkm-#J>!=-26-P% z*EmEGLwM&Q>I>QR0bO4xb$X{O#=i3gwAsFGBA&Q?Xm@8w z$pY?pwj2}8VypM44PW-GW%z8(nwp{BuHs|5-zcOM@*fcQ-~aQ(@a;Oj@!@;WLjnmZ zZ5MMxNXU)5s`_K!EJ*azAEtFQN$0Uf9N+G8(QSc7QI|(DyORSS&8;52?T8aVc_s?4 zq?QfI1Wlgm%~q4*dqC4bq(UNOIEoui-m@-eq$!=qh>@4I#%S0--xKG%7R|I@f4D%_ zUZ{%(OGQr-c@adObCDCDA>X7}5>NjFnEh5;(25vXiB;nUJcO}cG(Z1hLiy&FR_p&^ z?>(cUTDnEig(!lEh)R$k0wN+wBxjVQBA}v#CJG`AO_M<~Z2}}35F}@i4ASJ(TLqNR zQz;cN)e`gi63A7mC3htq$%=-Cm568oiX z(Ym9;edrLJ_IMw8?tQW7rH+SDHwe}mp7VJ*$BerAq!zU_BU;%nPKOvv#mzStUnCy-LMbyih{ue& zOF&wI9znUplse|ERK9KH51)D~8N?vA!aIL6F*WC=l#~>z+BNsckt28S-c5b|`UE}0 zx9s-?x6+84po%ym&&zc8j^l^duV2GO-U^qwi*j;Gr%y*^8DxZB77?L;nO{X?c}|B; z;6zNuwt-}7^88zrgl~incv2}%`}}*;udJ42fkQWJdiq5M?sQ5mQa3UF=1bWXv{i38 zU%jS#Lr3Wap|<4m4p8}j05!2w36Z4b?s`~>ftxM ze0mvG{n~G3Fduq$)}fAO90ZN3K@f+3?c0nc}@Y-)GB zHO{YjeYq$+R$uqZwB=cWPc)u~-e{kqJpYxEvL5xIQRAITW8=^)Ch0ZjTYAO|cf#{; z-H*Sq;uxM#t(x?N_3gL(d*=+N&i4-K#534CP5q=+!z87l=7`t&a$iTBqI|Ep&Gxq2 z%CdW=plEin%>VUl7h?$<@}rUeX;Qe_ccvZ@vkP6Va>WilLVV5l#wYX}qeP6{gC1V= z{mX`)-{ighmAsGRFAZ{=rO_x>{u38<%FdZQFXy}a!|#)qtsejU-ce6BY5Et+O)>rZ z3st&QEp~6)56BG@E2@g>*-#^zEZZ?6Dl51?_ily;qeaQ=`{1?V zx9uOE-kBA5CU@u)|99^V?S16`O@A#rr8!h?SbOt((jEF-{k(~{)OV|_U;K(_*8Mur zebIQqu*CN5jTNW6IxnYnMBg0h`Z)dzr{9;Ap?{%y3$vBHD<%*$<+R5b`fOMyimrB) zCSmjG^&?yF*9Y8#@7N|TP~*UUgL0lu`~(f>{pZ8t(RD`{886-qpN>5etDW?bsD(*5?ZD!?^$l!$+@O{OP|2XH0bUdL7&ei_&^YRkdef#GJ_w0X? z3Un^`e*+c0TYa4J39WMfT6=&=2%}UWdHJ@!{Wc=v{68m!He`|({{7DXW%T|xV*MXf z{+rvz9|8Rl5bXW_xH!Os|E=iq$AbP?&>steIRHL?EC}S%|20|bAHVWn=2uKUbCA^Y zKmMLj{Qj>e5a65tAFfXR$oaoa&i`kYkN;N+XlZ|bI7DZ#{=oD0R}Z$Vz2DRrCoGy_ zraT@fT^l&hI>G*RM5bx%Wlo8eVh*=Fkz^R3KmTj}{pb1*PyXn@A07Ck1Albjj}H9N zf&W)J;QF6iR5-28mHb+2o(OPw=OtNmvV3LW^9eIjb`ed??nL{e>5>!?63P z$?Vs!1^M>a`v}Lz3kYf1u@GDR_wZiZY;fm-GfH!hzQR{H-}mYdTs@3@0$OaXsM?8F zQ2Fik>j^;}aAO%eDZkOO(-*`PH!t7~dVU^%w;OsUF+}c$Cv^wKZDzPzFAox_$E;#Q z8+J+_uAPa(@{4c3EltBOKEWdo6-JWc`q+4EMDu{BsSZ28;C5iC3*L%pBy1jj{sTA4 zL4v{YyUoUST1=#{U(4H2HOB9@AM8>Ikpak(r7w1kL$t`+^>pX<#b_oPcwj3X{4#N< zfNJ-A&(JKd_{mtKmcixNNy&)oq@h}*p?YaPomuhbMg0Ofm4yKaP~X3YUX+uZE7X^h ze>7(;rx}EvJdwO=AqrqZ#}Ux>kHA|@tjBG*JUmKR8n~~r%qPJ!$_kK}^QfKJVAazR zu@Ss5)8B6|AK}DY4--vrB7wKp_8!lP|0HrojkY~~*_l5>42F%HK1(8aHYZjtEIw{^ zQc^37MC=lQRQ)y72y2=0KuJ5DoZbBWRPxbenKBxTgk;Zm+c}*wasR-hKBcioi-#%m=mHi`lyKj{e z%SsK;HOEE5gMEu8rN+@!azxs3JHT^p&eHo(Zhlh#75IF&9xaK?QL6^_ZB%56_m;Q#Eo3d!pL1+ZXHm`RFXK-NX~Mu0{8U4TA)JV1%lZ+Fjq-RVt{FN3 zYhu|+1T5j?oP^)8Cc2o9A|+No$WW&nMWq8zg7&cp}Xjl?O z@i*m0jzveR2`r&Ka3w5$7IcW7&XKqz`|3>W0wA`br>My1=(MfVs_tajP-6EK`9_Cz~z%PTNbCYHK1>#(~4^jB26bmYOon{Y<>vP zJhM@;T=hi!6bw#Y9RXKx-zmFk;=jqQ#mpB@C0T3E6ewd-T4TRavOuNarQ~ z27463ssa+4*4|cM2TtTPROK8eHZj9{nS`PuQq!I7@9z{!ZB28x4h-1--mQk)Rvay1 zl`?&999btaemX~A;TV{%P7QuCcqxY;F`Jy=I+4DJ@eQ}r8JCYK!H&i4`~&~BtjY@5k}$~rU#cmCrC%pjUw#6;KIhT zp|>n-CR%?X>s3M=;I43Wuz3{4=ss*?vVtVxvn|XSJ}k8yyRY%-mT`S13?p)R+QgT! z=Tqr0jLy)DrK4v|_L=ray)M)ohJXLtO__wCjAYkE*{3}13LX1A;&8A(^AbUEtp1pb zpuZ0FlHu0CeOfJUnD>Mfk~1A@8?u(tQ+Sfm{i#zMHzf_4Ae#izFx4qkQw>V?sbw!$ zSFd{n!k!qC9+W*Eh)xlI{76pLGmcgrao+{^NLcXAjrZ4}qz=^d=2Lmo+{VGK-R3O` zV&H)L@=Z62oyc9sbBl)XTqUZAxa?K7#f5;l6+{fK!ORs$>w>?y7%O(;y`@?9R^Nvk zejk~Czf8S&9j7%*hKi&8ZV}rkS@s%c>l}g?j@l!rX{+s?flq9xk$dANj}{_#%G%(BOL7QVTKjhA~aAIhdK01 zo%5t_8TnY`slV6FZdU5Jx2dK;fmYf)o*nn8xKoJsK(SC(ZiG_qp)tO#d)upSH2onB zEM*5^GdHb6tYL{-?t9k4j^0RHW5jyS$bsVZY4&|l_IMxacE65J|4uslC-~Mr>Q)@J z9%s*_$|GjAUSoLlThi#i2BY<{83ILW0WCGNyJc;YbDKLQ+;S|M`JOL(Jn`Hwn3S!C z2OZpx4IUIsV;>*1=BsoF--oR+8*$fTGurGu2;!~_|*6YCEd5HlG#d#t=b;*8uGF~#F`150E6845p5FB^uG>5u|b>%bH?P|ZMwKz)*EtcE&6^dbaACxf@>}e zvInx;@>TL1Fdgi2&1~loNh~0e=!>lp7werxxA5pj-ouyNwUWC!S6wF>`kf&Ly*nxc zbccRM{nfU3f5YyT?Z+Xf?IRW^hUS^C>g=_iu9)$nQ4d z6^sw>|4_3>Asn$KjhXFUi4IEQmCw$9y{e`qq}kvYsvhi0wXG90EC(EEcP9H^{O9>>0OgHES!WNww`<>*?q!(UgIip6(GIs(0T&vC~g#8RnxbX-vqp=%^A>`Cs-OGAG zEUWM}P>vxA5BSb3Mi#AWn3_klX8v2ht0vNO_rr{Me~x46u>8C4Dw1wax_Rw^FE6@T zOQ~$`(zc9@qJ2ocjJzt8P;Sr)JfF?F(s^0hSMKTCc+Mv z5g~L;aH~<@MCRo00-as&A~j2YcR?u3l*($(h73^b%u(dwEMT&Em+qz|W6V_6>P5(S^fmEvDdLpdt@RXft`jZLC& z$2VZh7~@0YlD$}Qw}rk67(J&Q7S@Y`Lk2;YG=9Rv#ua_fdChn2Cse3$j+)Vh?6t_C zr$IS&IklUNyE-Q5;+c$>tUPhftOh3zd70FkXLz2EAiMr@Ym*idwT&Ll-v4Uu(T;;X zwbzp=IN1HXh>;=3X}owe@3y!`gbCacK%QIp$@%eNzEnogvJq4u_3E^5OUjZYXkF4p z9(>sNfR?FL9*iQMg8FjY7{k_Au9J9h78xur@bRH=I^O`1Uz?n;HmquIjcA|zRX94} zw7#w+J3k}xYmyUchM3!`8esB$;a5UJ1e0=sYb;HNpzSn-+Z&V!yuBOGh##J#A<2U@ zh|TySPeqI={kq$s;Eo3~A5JE97eWre?6gb1b>`*Pccs9YqnO)nz}DiXh0MKwDyYT0 zu2^4$9b~gsD52D~X^L5UDyC0dU$3y}B6eJ4P^R_0$!6_Gk4tXSn^-J#Z z&84G|TlnRKho3j=zj?tDaYZ;brU-*-J)XhhFp`AKzovoA51EbYPM(IAZaR!O@T!o* z20#A}el~?b_W5J}7-+E(!->CzgZ%s(dPG*81y}lu%m)KSCt)58Z_AzUtV#_K=`CfepTLR`Jd62GeL z0m$Z_XySL0F_a*W_n3aFueikr?Ad1U^3|%;ukNss*#shkR8-G$AUYKY%g+rk zfff)G>%%owjah%Cha|HcF7j#-{Xk2i7$UNeAcq(R12SAn_WhmBDoW6RMjokB{FJ`g zi(o(NA}@6D>LzGuJBkRxFGTw@C?}M?puk^86h`z4j8Wq4$*O|rpog>&Zk^MWp{0Ox z3ydj{N5)XRbr*IKy>kQ_i=5z}xpxf^1nD5A*_PODb`c`@2DZmU#;(GaM+ijN!TcuU zb>oB6^w5|Vr$97I`4sUUksIvLLpQ(xF8oguMar8w>rEbYob`+Ys6l5mEk zX)5j)GnuFlLH3WzDcYXx01C%mA#~_m=AINMgU(pR-k{lrZ8eMoQUBM5>8UG6p|L_i z?&ybyV0|8=BMrEfyxPop0U~HuF{BV-K!4xA1hc~}OZ}_W3D`yBDo?;zQeb;!}MPL(kt;^1L91SF_KXL;ZJD{`Bbbi1*5_2wuAL_ke=+3?!}4uNzHVXa%T ztknQ08W@PSTc^N`%|{sP_F7iRo*@l5A&oC-sn@w+|LOGt;nbT4LBQL#1c(&%z7A17 z42B4iAU&as*Y7(Bq19vKLb!P>t-z2aDMS~wUQVlMK+u5pR9KLc7`VT23PI~|lXhlM zGz8&!nXMZpf?>b$nB;6ASQEX>&@ z#gw(9;GLJJ)ivKBR_}#85lDD?69w2I&O;nA&baLBdIn(ocO+Xnn*w|w;e4IOLGvC{ zIEs@Z+!915!-qHuo%q%tW{9&}@xe$25J3D@C28e;0y0$)D9u!!A-ms@2mhY?mI2c~NoAXb97=ju%EErMVWQ$Ga%Y08Bg6j)J-O4*1nTsdk!LML}wgnrE z-7EqZ2Ev-$E-NqQ+NfavZ!e2bU~S!(6MlCppUWOVGH{M+wc4&xH|pgE!zE9^B#dQp zn(3tf>Vexm?W0;9T8CeL1_J+&=J63`BBy->K+<=@@DaaM+%^a7hHfLAq&>Ot(ETDa z5%hj0xxX;IGMY4pVD=cs%wG2Z%-8<3@bIm3H~^o(fsA@2Tz^d?3Cw-XoY#s8G2T7} z1eeYm(Rbn*dp;1r=&Bb*lj_77(W9B_0Gk36gdCHYDHCDMYfYei2NmBMRr$IzlO0~4 z%y-Z1?aLELLGWbP}P1-)gE}H0uxad$IQ#Hdo785L6HwUrKLoGAj=ce-4;4mN&s#8Pi&<<(&XfH5GzM#?9Wj z!B)iU3fK}xw_v&J^>O$Sk}l0Z!BhhZw8!x^pQd#h;c zl_zw-g)GTBtauI8JBrh}U3}>7cdo*mP&aZ~Nl@GR>RfPewhVbKeZbYZ^!ot>pQwajG?v4(>b#+86 zKL)VZz?cgMv;s1XfuWiG~l0{9ka}`$BO>nMmMxOl6SC zc+6hRx?Fq$l&j#ju$u^TTWmW3UO*44NCCM;bO+{i@i{PmeO<)u-`hi^MEc=CLwN36>p^k0LTUQ^}pW*Na5-c zq9{U;={?)M#HAMjW{LNa$%P9y9*}`GSty6C?ALlb0I}@?tl51p(J~?)pkJs3zmx{z z$8c+~F%T#|U+$c%8Y2nXe!}CdtumbgpoWx!w3S`fm=OzG1t9EiI>^0Lhh1G8Vz_8M zn)q%y89-)x2%Tc5AHYpf31&~??ecJDxIS0*VmSu&3h)|@#Ane914jj!Vf{5>GU9{b zAPE=x+HXd~8+lluh*0f`7RwY2e8r5!1ezE1MK;fl0X;jMf&tk7$L%t)cq<|BRo*%_ zpW`!_6VgNSUr|MnPC`qi6GyHhh9ZXWDiBVuArm@@!Uw%4LEjws)uWJ3D#(+ejVyAXhC?uszxAh4VG25VmjHviySv>9Qj5}Z&sON;lr!ql+=h$sn zbYo=c?vE|IE`b(NQ>zEA-e3e_7hz(Y#!7zg>o@m-(JS(C;-;A4M8gxoO@>8a7K{ja zfeBYfGM1l6?EHz2z0vsQ2jFHKc<>>?xupPIgZiG7VO24p9a={;#3URf1p%;p2Zf2f!WKx1 zHHJZmq2_c<7ly|qmqj?Rz?q2&lEazU3)`NA&AKe)e4Z7!JywMDf0N9e$OQ67V2_5K zOts*GV2RMq^Z9^Ai6Y?dJfSWG&V9U)1&P;3NqRWN!5IZ$V%l4f2E?9s($KP)=ehdVdMsdeCCF*7cf#bcpMzsB`>9Fs zA{9`WHf@-AZRtD=a3CB;a5_u{6RlP-*!E&LoGl{YwXEl0|2Sr;u8!w}>199^ zUo-gSX@OMmb*CpSd~@I{1p6mMn1_XJoj&-1Axj1hU!6&;Kv-&LM#hZ+89B6(a#=bzQms!_DuG^|Gago>1_Y-2Ix!cz$^6vUe3)Y!12dlRO8L_<6xe{FXjXg zS+Bu`37pagN|+!$L_oMb9-`bvlRcIyX2K60+wffj!AHkf8GG;sJ*|0zt5L%B1TEOAz z;b(f(L3pLtCl2>@wF@+fhGS0j37YP@Vo;zUq{Ac?cv{@>fbTOufGv_x^7qY)U_RX1 z=WdiZY!s%5ujwmhDvt_r0DM9BNS52ecw9taV?W@)%{Ey?3MH@~#ThxR%L3fCCmOM$ z2m~jX>b_!9Iflw%jl2*W;W;;{gJV1;!J&C|YYLhr@;F^f8Gk}0_!ZdP-n-=iUNZ3at66AG%mp>{~ z!J-K=9jwnRD+Dno(E(=h{A)4+cxH(RIO?GzVFjx^St#-du0h(ED7UI2v_->f3&PKv ztBjzRrzy-a#YzN$I5Rj%BA#9JS0dy^pDOWz& zvIwNR_HG5f;-} z-$cbF7T6S)?joSTbb_Bj@a2I!h9P1a8*v4rIb9zj3cLdQsRHVsHh|`{;hS3pWvYN! zw<8EXe|-R)ha}9u=A8uN@0qA2sFj8Q^ z!?(OwExF^i<*S`PttMzRsiEY_y*`7NK&~szBKH0ht}fzQiiRkm0^i6x9eo-zU0{i@ zwIy}4v%|0CS(j)E*}g!%U3~r(B$Oe=KY+tC%4j1qXXA@AU9@09F<^SCb_?_B_BUeV z-PwR@XPPv!q0g94$Md-mP522{?7<}Ql#o5Y#hzQpvb#~FrqRAqz_}XcDPM8J{dTPE z^zSt(vcnR@e0EF3dXPbYhQ3tFh-ytK8oH}<+XJ|@BFgl-+UtuS(dD7D{HXS^L{0*8 zJ~9pmXMW54GD>LuonI&g1EU2D93V%^e?p19|L`ICTjKC*` zvAmG-&9_)m(3$jJbs-SIvFgE z4@05a{Q}|zuxRb9D|pTqB`gl2%0Dg*W~8Qx6(%&ARKu})3CRb6xj$;eKdX0?NOQs` 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

#8WN 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 z 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 Vs1}$?`APDXE5BG=WEeZg{u8&AaIpXY literal 0 HcmV?d00001 diff --git a/static/css/styles.css b/static/css/styles.css new file mode 100644 index 0000000..575fa7c --- /dev/null +++ b/static/css/styles.css @@ -0,0 +1,199 @@ +@font-face { + font-family: "nazaninb"; + src: local("nazaninb"), url("/static/assets/fonts/BNaznnBd.ttf") format("truetype"); +} +@font-face { + font-family: "btitr"; + src: local("btitr"), url("/static/assets/fonts/btitrb.ttf") format("truetype"); +} +@font-face { + font-family: "nazanin"; + src: local("nazanin"), url("/static/assets/fonts/nazanin.ttf") format("truetype"); +} + +@page { + margin: 3mm; +} + +p { + font-size: 15px; + font-weight: 700; + font-family: nazanin; + +} +.nazanin-bold { + font-size: 16px; + font-weight: 700; + line-height: 23px !important; + font-family: nazaninb; + +} +.nazanin-bold-justify { + font-size: 16px; + font-weight: 700; + font-family: nazaninb; + line-height:8mm !important; + size:20pt; + text-align: justify !important; + +} + +body { + display: grid; + justify-content: center; + font-family: nazaninb; + margin: 0; + padding: 0; + background-color: #f0f0f0; + line-height: 15px; + +} + +.a4-container { + margin: 0; + width: 203.55mm; + height: 291mm; + background-image: url("/static/assets/img/bg.png"); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + position: relative; +} + +.text-overlay { + position: absolute; + top: 17mm; + right: 14mm; + left: 14mm; + font-size: 9pt; + color: #000; + padding: 10px; + border-radius: 5px; + text-align: center; + direction: rtl; + + +} + +.pagination { + position: absolute; + bottom: 7px; + left: 50%; + text-align: center; + padding: 5px; + border-radius: 50%; +} + +.page-number { + font-size: 14px; + text-align: center; +} + +.titles { + display: grid; + position: absolute; + left: 12mm; + color: #000; + font-size: 14px; + border-radius: 5px; + padding: 5px; + gap: 10px; +} + +.title { + font-size: 17px; + font-weight: 900; + text-align: center !important; +} + +.inner-title-titr { + font-size: 16px; + font-weight: 600; + text-align: right !important; + line-height: 13px; + margin-top: 30px; + font-family: btitr; + + +} +.inner-title { + font-size: 16px; + font-weight: 600; + text-align: right !important; + line-height: 13px; + margin-top: 30px; + font-family: nazaninb; + + +} + +.a4-container p { + text-align: right; + line-height: 10px; + + + +} + +.right-signature { + text-align: right !important; +} + +.left-signature { + text-align: left !important; +} + + +.highlight { + background-color: #ffeaa7; + font-weight: bold; +} + +table { + width: 100%; + border-collapse: collapse; + margin-top: 25px; + background: transparent; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + +th, td { + border: 1px solid #ddd; + padding: 8px 10px; + text-align: center; + font-size: 12px; + background-color: transparent; +} + +th { + background-color: #38b589; + color: white; + font-weight: normal; + text-align: center; +} +.custom-h1 { + background-color: #4665AE; + color: white; + font-weight: normal; + text-align: center; +} + +.confirm-box { + display: inline-block; + padding: 15px; + margin: 30px; + text-align: center; + font-family: nazaninb; + min-height: 150px; + vertical-align: top; + position: relative; +} + +.resize-image { + width: 140px; +} + +.header_nazar { + line-height: 20px !important; + +} diff --git a/static/css/styles_for_hatching_detail.css b/static/css/styles_for_hatching_detail.css new file mode 100644 index 0000000..09520e1 --- /dev/null +++ b/static/css/styles_for_hatching_detail.css @@ -0,0 +1,284 @@ +@font-face { + font-family: "nazaninb"; + src: local("nazaninb"), url("/static/assets/fonts/BNaznnBd.ttf") format("truetype"); +} + +@font-face { + font-family: "btitr"; + src: local("btitr"), url("/static/assets/fonts/btitrb.ttf") format("truetype"); +} + +@font-face { + font-family: "nazanin"; + src: local("nazanin"), url("/static/assets/fonts/nazanin.ttf") format("truetype"); +} + +@page { + margin: 3mm; +} + +p { + font-size: 15px; + font-weight: 700; + font-family: nazanin; + +} + +.nazanin-bold { + font-size: 16px; + font-weight: 700; + line-height: 23px !important; + font-family: nazaninb; + +} + +.nazanin-bold-justify { + font-size: 16px; + font-weight: 700; + font-family: nazaninb; + line-height: 8mm !important; + size: 20pt; + text-align: justify !important; + +} + +body { + display: grid; + justify-content: center; + font-family: nazaninb; + margin: 0; + padding: 0; + background-color: #f0f0f0; + line-height: 15px; + +} + +.a4-container { + margin: 0; + width: 203.55mm; + height: 292mm; + background-image: url('/static/assets/img/blue_bg.png'); + background-size: contain; + background-repeat: no-repeat; + background-position: center; + position: relative; +} + +.text-overlay { + position: absolute; + top: 17mm; + right: 14mm; + left: 14mm; + font-size: 9pt; + color: #000; + padding: 10px; + border-radius: 5px; + text-align: center; + direction: rtl; + + +} + +.pagination { + position: absolute; + bottom: 7px; + left: 50%; + text-align: center; + padding: 5px; + border-radius: 50%; +} + +.page-number { + font-size: 14px; + text-align: center; +} + +.titles { + display: grid; + position: absolute; + left: 12mm; + color: #000; + font-size: 14px; + border-radius: 5px; + padding: 5px; + gap: 10px; +} + +.title { + font-size: 17px; + font-weight: 900; + text-align: center !important; +} + +.inner-title-titr { + font-size: 16px; + font-weight: 600; + text-align: right !important; + line-height: 13px; + margin-top: 30px; + font-family: btitr; + + +} + +.inner-title { + font-size: 16px; + font-weight: 600; + text-align: right !important; + line-height: 13px; + margin-top: 30px; + font-family: nazaninb; + + +} + +.a4-container p { + text-align: right; + line-height: 10px; + + +} + +.right-signature { + text-align: right !important; +} + +.left-signature { + text-align: left !important; +} + + +.highlight { + background-color: #ffeaa7; + font-weight: bold; +} + +table { + width: 100%; + border-collapse: collapse; + margin-top: 25px; + background: transparent; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); +} + +th, td { + border: 1px solid #ddd; + padding: 4px 5px; + text-align: center; + font-size: 12px; + background-color: transparent; +} + +.chain-table-cell { + border: 1px solid #ddd; + padding: 1px 1px !important; + text-align: center; + font-size: 8px !important; + background-color: transparent; +} + +th { + background-color: #38b589; + color: white; + font-weight: normal; + text-align: center; +} + +.custom-h1 { + background-color: #4665AE; + color: white; + font-weight: normal; + text-align: center; +} + +.confirm-box { + display: inline-block; + padding: 15px; + margin: 30px; + text-align: center; + font-family: nazaninb; + min-height: 150px; + vertical-align: top; + position: relative; +} + +.resize-image { + width: 140px; +} + +.header_nazar { + line-height: 20px !important; + +} + + +.container { + display: flex; + align-items: flex-end; + position: relative; + margin: 10px; +} + +.text-element { + color: #2D5FFF; + background-color: #E0E7FF; + padding: 8px 16px; + border-radius: 4px 0 0 4px; + position: relative; + z-index: 2; + font-size: 0.9rem; + font-weight: 500; + margin-right: -3px; +} + +.line { + flex-grow: 1; + height: 2px; + background-color: #2D5FFF; + position: absolute; + bottom: 8px; + left: 0; + right: 0; +} + +.items-list { + display: flex; + flex-wrap: wrap; + direction: rtl; + justify-content: space-between; + +} + +.item { + width: 25%; + font-size: 14px; + text-align: right; + height: 60px; +} + +.item strong { + display: block; + margin-bottom: 5px; + color: #333; +} + +.item span { + display: block; +} + +@page { + @bottom-center { + content: "صفحه " counter(page) " از " counter(pages); + margin-top: -30px; + font-family: nazaninb; + } +} + + +.chain-table-cell2 { + border: 1px solid #ddd; + padding: 1px 1px !important; + text-align: center; + font-size: 6px !important; + background-color: transparent; +} \ No newline at end of file diff --git a/temp_functions.py b/temp_functions.py new file mode 100644 index 0000000..97322ae --- /dev/null +++ b/temp_functions.py @@ -0,0 +1,382 @@ + + +# ============ توابع جدید برای گزارشات پیامکی ============ + +def send_daily_slaughter_statistics_sms(): + # دریافت شماره های تلفن از دیتابیس + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + + # # شماره های hardcoded (اکنون از دیتابیس استفاده می شود) + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).aggregate( + total_orders=Sum('id'), + total_quantity=Sum('total_killed_quantity'), + total_live_weight=Sum('total_killed_weight'), + ) + + orders_count = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).count() + + total_quantity = province_kill_requests['total_quantity'] or 0 + total_live_weight = province_kill_requests['total_live_weight'] or 0 + total_carcass_weight = int(total_live_weight * 0.75) + average_weight = round(total_live_weight / total_quantity, 1) if total_quantity > 0 else 0 + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).aggregate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight') + ) + + loads_count = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).count() + + loads_quantity = kill_house_requests['total_quantity'] or 0 + loads_weight = kill_house_requests['total_weight'] or 0 + + formatted_quantity = to_locale_str(int(total_quantity)) + formatted_live_weight = to_locale_str(int(total_live_weight)) + formatted_carcass_weight = to_locale_str(int(total_carcass_weight)) + formatted_loads_quantity = to_locale_str(int(loads_quantity)) + formatted_loads_weight = to_locale_str(int(loads_weight)) + + message = f'اطلاعات کشتار مرغ گوشتی مورخ {date_shamsi} استان {province_name}\n' \ + f'تعداد سفارشات: {orders_count}\n' \ + f'حجم سفارش کشتار: {formatted_quantity} قطعه\n' \ + f'وزن تقریبی زنده: {formatted_live_weight} کیلوگرم\n' \ + f'وزن تقریبی لاشه: {formatted_carcass_weight} کیلوگرم\n' \ + f'میانگین وزن زنده: {average_weight} کیلوگرم\n' \ + f'اطلاعات بارایجاد شده:\n' \ + f'تعداد بار: {loads_count}\n' \ + f'حجم بارها: {formatted_loads_quantity} قطعه\n' \ + f'وزن بارها(زنده): {formatted_loads_weight} کیلوگرم\n' \ + f'سامانه رصدیار' + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}" + f"&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +def send_daily_distribution_report_sms(): + # دریافت شماره های تلفن از دیتابیس + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + + # # شماره های hardcoded (اکنون از دیتابیس استفاده می شود) + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).order_by('name') + + distribution_data = [] + total_distribution_weight = 0 + + for kill_house in kill_houses: + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + trash=False, + receiver_state__in=('pending', 'accepted'), + to_cold_house__isnull=True, + date__date=target_date, + warehouse=True + ).aggregate( + total_weight=Sum('real_weight_of_carcasses') + ) + + allocation_weight = kill_house_allocations['total_weight'] + + if allocation_weight and allocation_weight > 0: + distribution_data.append({ + 'name': kill_house.name, + 'weight': allocation_weight + }) + total_distribution_weight += allocation_weight + + if not distribution_data: + return + + message_lines = [f'گزارش توزیع گوشت مرغ داخل استان'] + message_lines.append(f'مورخ {date_shamsi} استان {province_name}') + + for item in distribution_data: + formatted_weight = to_locale_str(int(item['weight'])) + message_lines.append(f"{item['name']}: {formatted_weight} کیلوگرم") + + message_lines.append('-------------------------') + formatted_total = to_locale_str(int(total_distribution_weight)) + message_lines.append(f'مجموع کل توزیع: {formatted_total} کیلوگرم') + message_lines.append('سامانه رصدیار') + + message = '\n'.join(message_lines) + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}" + f"&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_daily_distribution_report_sms_manual(request): + # دریافت شماره های تلفن از دیتابیس + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + + # # شماره های hardcoded (اکنون از دیتابیس استفاده می شود) + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).order_by('name') + + distribution_data = [] + total_distribution_weight = 0 + + for kill_house in kill_houses: + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + trash=False, + receiver_state__in=('pending', 'accepted'), + to_cold_house__isnull=True, + date__date=target_date, + warehouse=True + ).aggregate( + total_weight=Sum('real_weight_of_carcasses') + ) + + allocation_weight = kill_house_allocations['total_weight'] + + if allocation_weight and allocation_weight > 0: + distribution_data.append({ + 'name': kill_house.name, + 'weight': allocation_weight + }) + total_distribution_weight += allocation_weight + + if not distribution_data: + return HttpResponse('هیچ توزیعی برای امروز ثبت نشده است', status=status.HTTP_200_OK) + + message_lines = [f'گزارش توزیع گوشت مرغ داخل استان'] + message_lines.append(f'مورخ {date_shamsi} استان {province_name}') + + for item in distribution_data: + formatted_weight = to_locale_str(int(item['weight'])) + message_lines.append(f"{item['name']}: {formatted_weight} کیلوگرم") + + message_lines.append('-------------------------') + formatted_total = to_locale_str(int(total_distribution_weight)) + message_lines.append(f'مجموع کل توزیع: {formatted_total} کیلوگرم') + message_lines.append('سامانه رصدیار') + + message = '\n'.join(message_lines) + + success_count = 0 + failed_numbers = [] + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}" + f"&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + success_count += 1 + except Exception as e: + failed_numbers.append(mobile) + print(f"Error sending SMS to {mobile}: {str(e)}") + else: + failed_numbers.append(mobile) + + return HttpResponse(f'گزارش توزیع با موفقیت برای {success_count} شماره ارسال شد. تعداد کشتارگاه: {len(distribution_data)}. شماره های ناموفق: {failed_numbers if failed_numbers else "ندارد"}', status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_daily_slaughter_statistics_sms_manual(request): + # دریافت شماره های تلفن از دیتابیس + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + + # # شماره های hardcoded (اکنون از دیتابیس استفاده می شود) + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).aggregate( + total_orders=Sum('id'), + total_quantity=Sum('total_killed_quantity'), + total_live_weight=Sum('total_killed_weight'), + ) + + orders_count = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).count() + + total_quantity = province_kill_requests['total_quantity'] or 0 + total_live_weight = province_kill_requests['total_live_weight'] or 0 + total_carcass_weight = int(total_live_weight * 0.75) + average_weight = round(total_live_weight / total_quantity, 1) if total_quantity > 0 else 0 + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).aggregate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight') + ) + + loads_count = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).count() + + loads_quantity = kill_house_requests['total_quantity'] or 0 + loads_weight = kill_house_requests['total_weight'] or 0 + + formatted_quantity = to_locale_str(int(total_quantity)) + formatted_live_weight = to_locale_str(int(total_live_weight)) + formatted_carcass_weight = to_locale_str(int(total_carcass_weight)) + formatted_loads_quantity = to_locale_str(int(loads_quantity)) + formatted_loads_weight = to_locale_str(int(loads_weight)) + + message = f'اطلاعات کشتار مرغ گوشتی مورخ {date_shamsi} استان {province_name}\n' \ + f'تعداد سفارشات: {orders_count}\n' \ + f'حجم سفارش کشتار: {formatted_quantity} قطعه\n' \ + f'وزن تقریبی زنده: {formatted_live_weight} کیلوگرم\n' \ + f'وزن تقریبی لاشه: {formatted_carcass_weight} کیلوگرم\n' \ + f'میانگین وزن زنده: {average_weight} کیلوگرم\n' \ + f'اطلاعات بارایجاد شده:\n' \ + f'تعداد بار: {loads_count}\n' \ + f'حجم بارها: {formatted_loads_quantity} قطعه\n' \ + f'وزن بارها(زنده): {formatted_loads_weight} کیلوگرم\n' \ + f'سامانه رصدیار' + + success_count = 0 + failed_numbers = [] + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}" + f"&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + success_count += 1 + except Exception as e: + failed_numbers.append(mobile) + print(f"Error sending SMS to {mobile}: {str(e)}") + else: + failed_numbers.append(mobile) + + return HttpResponse(f'پیامک با موفقیت برای {success_count} شماره ارسال شد. شماره های ناموفق: {failed_numbers if failed_numbers else "ندارد"}', status=status.HTTP_200_OK) \ No newline at end of file diff --git a/temp_model.txt b/temp_model.txt new file mode 100644 index 0000000..93d7351 --- /dev/null +++ b/temp_model.txt @@ -0,0 +1,17 @@ + + +class SmsRecipient(BaseModel): + """مدل برای ذخیره شماره های تلفن دریافت کننده پیامک""" + phone_number = models.CharField(max_length=11, unique=True) + name = models.CharField(max_length=100) + is_active = models.BooleanField(default=True) + + def __str__(self): + return f"{self.name} - {self.phone_number}" + + def save(self, *args, **kwargs): + super(SmsRecipient, self).save(*args, **kwargs) + + class Meta: + verbose_name = "پیگیر پیامک" + verbose_name_plural = "پیگیران پیامک" \ No newline at end of file diff --git a/templates/Digital_agreement_for_buying_and_selling.html b/templates/Digital_agreement_for_buying_and_selling.html new file mode 100644 index 0000000..360d5d3 --- /dev/null +++ b/templates/Digital_agreement_for_buying_and_selling.html @@ -0,0 +1,259 @@ +{% extends "base.html" %} +{% block title %} + توافق‌نامه دیجیتال خرید و فروش مرغ زنده در سامانه رصدیار +{% endblock %} +{% block body %} +

+
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ این توافق‌نامه با استناد به قوانین جاری جمهوری اسلامی ایران، از جمله قانون تجارت، قانون مدنی، قانون + جرایم رایانه‌ای، و با توجه به الزامات اجرایی سامانه ملی رصد و پایش زنجیره تأمین کالاهای اساسی (رصدیار)، + به صورت الکترونیکی و رسمی، میان طرفین ذیل منعقد می‌گردد: + +

+

+ ماده ۱ - طرفین قرارداد +

+

+ الف) مرغدار (فروشنده): +

+

+ نام و نام خانوادگی / مرغداری: {{ fullname }} / {{ unit_name }}({{ mobile }}) +

+ کد ملی / شناسه ملی: {{ national_code }} +

+

+ شناسه یکتای واحد: {{ breeding_unique_id }} +

+

+ شماره جواز جوجه ریزی: {{ licence_number }} +

+

+ آدرس فارم / مرغداری: {{ poultry_address }} +

+ {% if direct_buying_intermediary_mobile %} +

+ شماره واسط(دریافت کننده کد احراز): {{ direct_buying_intermediary_mobile }} +

+ + {% endif %} +

+ ب) کشتارگاه (خریدار): +

+

+ کشتارگاه: {{ kill_house_fullname }} +

+

+ نام کشتارگاه: {{ kill_house_name }}({{ kill_house_mobile }}) +

+

+ شناسه ملی: {{ kill_house_national_code }} +

+

+ آدرس کشتارگاه: {{ kill_house_address }} +

+ +

+ +

+ +

+ ماده ۲ - موضوع توافق‌نامه +

+

+ خرید و فروش مرغ زنده مطابق با اطلاعات ثبت‌شده در سامانه «رصدیار»، شامل: +

+

+ تاریخ خرید : {{ date_in_value }} +

+
+

حجم: {{ kill_capacity }} (قطعه)

+

وزن تقریبی: {{ weight }} (کیلوگرم)

+

میانگین وزنی: {{ Index_weight }} (کیلوگرم)

+

سن مرغ: {{ chicken_age }} روز

+
+

+ قیمت توافقی ثبت‌شده در سامانه: {{ amount }} ریال +

+

+ حداکثر زمان تسویه قرارداد: {{ max_time }} +

+

+ اطلاعات نهایی در کشتارگاه: +

+
+

حجم: {{ total_killed_quantity }} (قطعه)

+

وزن: {{ total_killed_weight }} (کیلوگرم)

+

میانگین وزنی: {{ avg_killed_weight }} (کیلوگرم)

+
+

+ ماده ۳ - تعهدات طرفین +

+

+ تعهدات مرغدار: +

+ الف) ارسال به‌موقع بار مطابق زمان، تعداد و وزن ثبت‌شده در سامانه. +

+

+ ب) اعلام دقیق وضعیت بهداشتی گله؛ در صورت وجود بیماری یا احتمال آلودگی، اطلاع‌رسانی فوری به کشتارگاه + الزامی است. +

+

+ ج) همکاری با مسئول فنی فارم و دامپزشکی در دریافت کد قرنطینه و تأییدیه حمل. +

+ +

+ تعهدات کشتارگاه: +

+

+ الف) ارسال وسیله نقلیه مجاز و تأییدشده برای حمل بار در موعد مقرر. +

+

+ ب) پرداخت وجه بار به شماره حساب اعلام‌شده توسط مرغدار ظرف مدت تعیین شده حداکثر {{ payment_deadline_days }} روز پس از تحویل بار. +

+

+ ج) ثبت اطلاعات بار (خودرو، باسکول، تحویل، پرداخت) در سامانه حداکثر تا 12 ساعت پس از کشتار. +

+ + +
+ + +
+ + +
+
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ ماده ۴ - تخلفات و مسئولیت‌ها +

+

+ در صورت بروز تخلف از سوی هر یک از طرفین، شرایط زیر اعمال خواهد شد: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
نوع تخلفمسئولشرح پیامدجریمه / اقدام قانونی
عدم ارسال بار پس از ثبت در سامانهمرغدارایجاد اختلال در زنجیره تأمینتعلیق دسترسی به سامانه برای 7 روز / ارجاع به شورای حل اختلاف/ جریمه مالی
عدم ارسال وسیله نقلیه برای بارکشتارگاهتأخیر در حمل و کشتارلغو سفارش/ جریمه مالی/ ثبت در سابقه تخلفات
عدم پرداخت به‌موقع وجه بارمرغدارنقض تعهد مالیجریمه روزانه 1٪ از مبلغ فاکتور از روز تأخیر تا تسویه کامل / توقف خرید بعدی
ارسال مرغ بیمار یا آلوده بدون اعلامکشتارگاهتهدید سلامت عمومیارجاع پرونده به دامپزشکی و تعزیرات / مسدودسازی موقت در سامانه
ثبت اطلاعات خلاف واقع در سامانههریک از طرفیناختلال در راستی‌آزماییارجاع به شورای حل اختلاف سامانه در استان / حذف دسترسی موقت یا دائم/ارجاع پرونده به تعزیرات
+

+ ماده ۵ - اعتبار حقوقی و اجرایی +

+

+ این توافق‌نامه پس از ثبت الکترونیکی در سامانه «رصدیار» و تأیید دیجیتال هر دو طرف، دارای اعتبار رسمی، + اجرایی و قابل استناد در مراجع قانونی خواهد بود. + +
+

+ کلیه سوابق تراکنش، مکاتبات، زمان‌بندی‌ها و امضای دیجیتال در سامانه محفوظ و ملاک داوری می‌باشد. +

+
+

+ ماده ۶ - حل اختلاف +

+

+ در صورت بروز اختلاف، مرجع داوری اولیه اتحادیه مرغداران گوشتی استان بوده و در صورت عدم حل، موضوع به شورای + حل اختلاف صنفی یا مراجع قضایی ذی‌ربط ارجاع خواهد شد. +

+
+
+ +
+

تایید الکترونیکی مرغدار

+ {% if input_direct_buying_code is True %} + + {% endif %} + +
+
+

تایید الکترونیکی خریدار

+ {% if direct_buying_state is True %} + + {% endif %} +
+
+ {% if payment_deadline_state == 'accepted' %} +

+ اطلاعات تسویه حساب: +

+
+
+

مبلغ تسویه: {{ total_paid_amount }} (ریال)

+

بررسی کننده: {{ payment_deadline_checker_fullname }}

+

تاریخ بررسی: {{ payment_deadline_check_date }}

+

گزارش: {{ payment_deadline_archive_message }}

+
+ {% endif %} +
+ + +
+{% endblock %} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..b9200f0 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,17 @@ + + + + + + {% block title %}{% endblock %} + + + + + +{% block body %} + +{% endblock %} + + + \ No newline at end of file diff --git a/templates/management_all_poultry_and_warehouse.html b/templates/management_all_poultry_and_warehouse.html new file mode 100644 index 0000000..0bce510 --- /dev/null +++ b/templates/management_all_poultry_and_warehouse.html @@ -0,0 +1,500 @@ +{% extends "base.html" %} +{% block title %} + سامانه رصدیار +{% endblock title %} +{% block body %} +
+ +
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ از تاریخ {{ from_date }} تا تاریخ {{ to_date }} استان {{ province}} +

+

+ گزارش فارم‌های فعال در بازه زمانی +

+ +

+ • تعداد فارم‌های فعال بر اساس جوجه‌ریزی: {{ poultry_count }} فارم +

+ • تعداد فارم‌های دارای زنجیره فعال: {{ chain_count }} فارم

+

+ • مجموع جوجه‌ریزی: {{ poultry_hatching_quantity }} قطعه

+

+ • مجموع تلفات دامپزشکی: {{ poultry_hatching_losses_vet }} قطعه

+

+ • مجموع تلفات اتحادیه: {{ poultry_hatching_losses_union }} قطعه

+

+ • مجموع تلفات کل: {{ poultry_hatching_total_losses }} قطعه +

+

+ • مجموع قطعه کشتار شده: {{ poultry_hatching_killed_quantity }}۰ قطعه +

+

+ • مجموع وزن کشتارشده: {{ poultry_hatching_total_killed_weight }} کیلوگرم +

+

+ • مانده در سالن: {{ poultry_hatching_left_over }} قطعه +

+

+ فارم‌های با سن بیشتر از ۶۰ روز +

+

+ • تعداد فارم‌های با سن بیش از 60 روز: {{ poultry_hatching_gt_60 }} مورد

+

+ • مجموع حجم فارم‌ها: {{ poultry_hatching_gt_60_quantity }}۰ قطعه

+

+ • مجموع مانده در سالن: {{ poultry_hatching_gt_60_left_over }} قطعه

+

+ بیشترین سن کشتار: {{ max_age_poultry }}روز

+

+ {{ max_age_poultry_name }} - {{ max_age_poultry_city }} - ( حجم جوجه ریزی: {{ max_age_poultry_quantity }} (قطعه) - حجم کشتار شده: {{ max_age_poultry_killed_quantity }} (قطعه) - حجم مانده در سالن: {{ max_age_poultry_left_over }} (قطعه) ) + +

+

+ کمترین سن کشتار: {{ min_age_poultry }} روز

+

+ {{ min_age_poultry_name }} - {{ min_age_poultry_city }} - ( حجم جوجه ریزی: {{ min_age_poultry_quantity }} (قطعه) - حجم کشتار شده: {{ min_age_poultry_killed_quantity }} (قطعه) - حجم مانده در سالن: {{ min_age_poultry_left_over }} (قطعه) ) +

+
+

+ بارهای کشتار شده داخل استان:

+ +

+ تعداد بارهای داخل استان {{ kill_house_request_count }} بار

+

+ مجموع کشتار داخل استان {{ kill_house_request_quantity }} قطعه +

+

+ مجموع وزن کشتار داخل استان {{ kill_house_request_weight }} کیلوگرم +

+

+ میانگین وزن هر قطعه {{ kill_house_request_average_weight }} کیلوگرم +

+

+ * نکته: بیشترین حجم کشتار داخل استان در {{ persian_date_req }} با {{ daily_quantity_req }} قطعه رخ داده است. +

+

+ بارهای خریداری شده خارج از استان

+

+ تعداد بارهای خریداری خارج از استان {{ free_bars_count }} بار +

+

+ مجموع قطعه کشتار خارج از استان {{ free_bars_quantity }} قطعه +

+

+ مجموع وزن کشتار خارج از استان {{ free_bars_live_weight }} کیلوگرم +

+

+ بیشترین خریدار:{{ kill_house_name }}({{ transaction_count }} بار) +

+

+ * نکته: بیشترین حجم کشتار خارج از استان در {{ persian_date }} با {{ daily_quantity }} قطعه رخ داده است. +

+ + +
+ + +
+
+
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ عملکرد خریداران (بر اساس خرید زنده داخل/خارج استان) +

+ + + + + + + + + + + + + + + {% for kh in kill_houses_data %} + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
نام کشتارگاهتعداد بارحجم داخل استان(قطعه)وزن داخل استان(کیلوگرم)حجم خارج استان(قطعه)وزن خارج استان(کیلوگرم)حجم کل بارها(قطعه)وزن کل بارها(کیلوگرم)
{{ kh.name }}{{ kh.load_count }}{{ kh.in_province_quantity }}{{ kh.in_province_wight }}{{ kh.out_province_quantity }}{{ kh.out_province_weight }}{{ kh.total_quantity }}{{ kh.total_weight }}
هیچ داده‌ای یافت نشد
+

+ بیشترین خرید داخل استان: {{ kill_house_name_req}} +

+

+ بیشترین خرید خارج از استان: {{ kill_house_name }} +

+

+ بیشترین بار ارسالی مرغدار : +

+

+ داخل استان :مرغداری {{ poultry_req_name_req }} با {{ top_poultry_req_stats_total_quantity }} قطعه شهرستان + {{poultry_city_req_name_req}} +

+

+ خارج استان :مرغداری {{ out_poultry_req_name_req }} {{ out_top_poultry_req_stats_total_quantity }} قطعه استان {{ out_poultry_province_req_name_req }} شهر{{ out_poultry_city_req_name_req }} +

+

+ عملکرد کشتارگاه‌ها و توزیع لاشه در داخل استان +

+ + + + + + + + + + + + + + {% for kh in management_kill_house_data %} + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
نام کشتارگاهوزن بار زنده(کیلوگرم)وزن وارد شده به انبار(کیلوگرم)وزن توزیع داخل استان(کیلوگرم)وزن توزیع خارج استان(کیلوگرم)وزن کل وزن توزیع شده(کیلوگرم)وزن مانده در انبار فعلی(کیلوگرم)درصد توزیع
{{ kh.name }}{{ kh.in_province_quantity }}{{ kh.in_ware_house_quantity }}{{ kh.steward_allocation_quantity }}{{ kh.kill_house_free_bar_quantity }}{{ kh.all_quantity }}{{ kh.product }}%{{ kh.percent }}
هیچ داده‌ای یافت نشد
+

+ ! توجه اطلاعات توزیع لاشه از تاریخ {{ tomorrow_of_date1 }} تا تاریخ {{ tomorrow_of_date2 }} میباشد. +

+

+ * نکته: درصد توزیع نسبت به وزن ورودی به انبار در بازه مذکور محاسبه شده است. +

+
+ +
+
+
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ گزارش بررسی اسناد و قبوض باسکول +

+ + + + + + + + + + + + + + {% for kh in duc_kill_house_data %} + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
نام کشتارگاهتعداد کل بارهاتعداد بار دارای سندتعداد بار بدون سندتعداد اسناد تایید شدهتعداد اسناد دارای مغایرتدرصد اسناد تایید شدهدرصد اسناد دارای مغایرت
{{ kh.name }}{{ kh.kill_house_request1_count }}{{ kh.bar_assigment_true_count }}{{ kh.bar_assigment_pending_count }}{{ kh.bar_document_status_accepted }}{{ kh.bar_document_status_rejected }}{{ kh.percent_bar_document_status_accepted }}%{{ kh.percent_bar_document_status_rejected }}%
هیچ داده‌ای یافت نشد
+

+ هشدار: بیش از ۵۰٪ بارها دارای سند مشکوک یا دست‌نویس هستند. +

+
+

+ اطلاعات بارهای دارای استعلام قرنطینه +

+
+

تعداد بارها: {{ total_count_has_quarantine }}

+

حجم بارهای رصدیار : {{ total_quarantine_quantity }} (قطعه)

+

حجم بارهای قرنطینه : {{ total_quantity_has_quarantine }} (قطعه)

+

+ اختلاف قطعه: + + {{ different }} + + (%{{ different_bar_percent }}) +

+
+ +
+

+ اطلاعات بارهای فاقد قرنطینه +

+
+

تعداد بارها: {{ total_id_hasnt_code }}

+

حجم بارها: {{ total_quantity_hasnt_code }} (قطعه)

+

وزن بارها: {{ total_weight_hasnt_code }} (کیلوگرم)

+ +
+
+

+ اطلاعات بارهای وارد نشده به انبار +

+
+

تعداد بارها: {{ total_id_hasnt_warehouse }}

+

حجم بارها: {{ total_quantity_hasnt_warehouse }} (قطعه)

+

وزن بارها: {{ total_weight_hasnt_warehouse }} (کیلوگرم)

+ +
+ +
+

+ اطلاعات بارهای تعیین تکلیف نشده(عدم تخلیه توسط کشتارگاه) +

+
+

تعداد بارها: {{ total_id_hasnt_assignment_state_archive }}

+

حجم بارها: {{ total_quantity_hasnt_assignment_state_archive }} (قطعه)

+

وزن بارها: {{ total_weight_hasnt_assignment_state_archive }} (کیلوگرم)

+ +
+
+

+ اطلاعات بارهای با سن کشتار بیش از 60 روز +

+
+

تعداد بارها: {{ total_id_hasnt_killing_age }}

+

حجم بارها: {{ total_quantity_hasnt_killing_age }} (قطعه)

+

وزن بارها: {{ total_weight_hasnt_killing_age }} (کیلوگرم)

+ +
+ +
+ + +
+
+
+
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ جمع‌بندی و نتیجه‌گیری

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
تعداد فارم فعال{{poultry_count}} مورد
میانگین تلفات{{avg_losses}} قطعه
میانگین سن کشتار{{total_killing_ave_age}} روز
میانگین وزن کشتار{{ avg_total_killed_weight }} کیلوگرم
بیشترین کشتار{{top_total_killed_weight}} کیلوگرم
بیشترین خرید داخلی{{total_quantity_top_inner}}قطعه
بیشترین خرید خارجی{{total_quantity_top_out}} قطعه
تعداد سند‌های مشکوک{{bar_assigment_pending_count1}} مورد
+
+
+

+ جزییات گزارش عملکرد: + دانلود اکسل +

+
+ + +
+{% endblock body %} \ No newline at end of file diff --git a/templates/poultry_datail.html b/templates/poultry_datail.html new file mode 100644 index 0000000..5c288f3 --- /dev/null +++ b/templates/poultry_datail.html @@ -0,0 +1,1485 @@ +{% load jalali_filters %} + + + + + + + + + + + +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات واحد گله
+
+
+ +
+
+ نام فارم: + {{ poultry.unit_name }} +
+
+ مرغدار: + {{ poultry.user.fullname }}({{ poultry.user.mobile }}) +
+
+ بهره برداری: + {{ InteractTypeName }} +
+
+ تاریخ جوجه ریزی: + {{ hatching_date }} +
+ +
+ حجم جوجه ریزی: + {{ quantity | toLocaleStr }} +
+
+ سن: + {{ chicken_age }} +
+
+ نژاد: + {{ chicken_breed }} +
+
+ وضعیت: + {% if violation %} + پیگیری + {% else %} + عادی + {% endif %} +
+ +
+ شماره مجوز جوجه ریزی: + {{ licence_number }} +
+
+ شناسه یکتا: + {{ poultry.breeding_unique_id }} +
+
+ مجوز بهداشتی جوجه ریزی: + {% if CertId %} + {{ CertId }} + {% else %} + - + {% endif %} +
+
+ ارتباط: + {% if UnionTypeName %} + {{ UnionTypeName }} + {% else %} + - + {% endif %} +
+ +
+ استان: + {{ poultry.address.province.name }} +
+
+ شهر: + {{ poultry.address.city.name }} +
+
+ دامپزشک فارم: + {{ vet_farm.vet_farm_full_name }}({{ vet_farm.vet_farm_mobile }}) +
+
+ سالن: + {{ hall }} +
+
+ دوره جوجه ریزی: + {{ period }} +
+ +
+ تاریخ ثبت جوجه ریزی: + {{ create_date_hatching }} +
+
+ میانگین سن کشتار: + {{ killing_ave_age }} +
+
+ پیش بینی تاریخ کشتار: + {{ predicate_date_hatching }} +
+
+ مالکیت: + {% if PersonTypeName %} + {{ PersonTypeName }} + {% else %} + - + {% endif %} +
+
+ حجم اختلاف کشتار: + {{ bar_difference_request_quantity|toLocaleStr }} +
+
+ وزن اختلاف کشتار + {{ bar_difference_request_weight|toLocaleStr }} +
+
+
+
اطلاعات کشتار و تلفات
+
+
+ +
+
+ تایید تخلیه در رصدیار: + %{{ percent_rasadyar1 }} +
+
+ تایید تخلیه در سماصط: + %{{ samasat_discharge_percentage }} +
+
+ حجم کشتار شده: + {{ killed_quantity|toLocaleStr}} +
+
+ حجم تخصیص بازگشتی: + {{ killing_info.return_province_kill_requests_quantity|toLocaleStr}} +
+
+ وزن تخصیص بازگشتی: + {{ killing_info.return_province_kill_requests_weight|toLocaleStr}} +
+
+ حجم بار بازگشتی: + {{ killing_info.return_kill_house_quantity|toLocaleStr}} +
+
+ وزن بارهای بازگشتی: + {{ killing_info.return_kill_house_weight|toLocaleStr}} +
+
+ حجم مانده در سالن: + {{ left_over|toLocaleStr }} +
+{#
#} +{# حجم بارهای عدم وصول:#} +{# {{ killing_info.non_receipt_kill_house_quantity|toLocaleStr}}#} +{#
#} +{#
#} +{# وزن بارهای عدم وصول:#} +{# {{ killing_info.non_receipt_kill_house_weight|toLocaleStr}}#} +{#
#} +
+ تلفات کل: + {{ total_losses|toLocaleStr}} +
+ +
+ تعداد بارها: + {{ killing_info.kill_house_requests|toLocaleStr }} +
+
+ حجم بارها: + {{ killing_info.kill_house_requests_first_quantity|toLocaleStr}} +
+
+ وزن بارها: + {{ killing_info.kill_house_requests_first_weight|toLocaleStr}} +
+
+ افت بارها: + {{ killing_info.ware_house_bars_weight_lose|toLocaleStr }}% +
+ +
+ حجم فروش به خارج استان: + {{ out_province_killed_quantity|int|toLocaleStr}} +
+
+ وزن فروش به خارج استان: + {{ out_province_killed_weight|toLocaleStr}} +
+
+ حجم بارهای تحویلی: + {{ killing_info.bar_complete_with_kill_house|toLocaleStr}} +
+
+ وزن بارهای تحویلی: + {{ killing_info.accepted_real_wight_final|toLocaleStr}} +
+ +
+ بارهای ورودی به انبار: + {{ killing_info.ware_house_bars|toLocaleStr }} +
+
+ حجم لاشه های انبار: + {{ killing_info.ware_house_bars_quantity|toLocaleStr }} +
+
+ وزن لاشه های انبار: + {{ killing_info.ware_house_bars_weight|toLocaleStr }} +
+
+ حجم افزایشی: + {{ increase_quantity|toLocaleStr }} +
+ +
+ تلفات دامپزشک: + {{ losses|toLocaleStr }} +
+
+ تلفات اتحادیه: + {{ direct_losses|toLocaleStr}} +
+
+ حجم تعهد دولتی: + {{ total_commitment_quantity|toLocaleStr }} +
+
+ حجم تعهد آزاد: + {{ total_free_commitment_quantity|toLocaleStr}} +
+ +
+ حجم کشتار دولتی: + {{ governmental_quantity|toLocaleStr}} +
+
+ حجم کشتار آزاد: + {{ free_quantity|toLocaleStr}} +
+
+ تخصیصات بدون بار: + {{ killing_info.province_kill_requests|toLocaleStr }} +
+
+ حجم تخصیصات بدون بار: + {{ killing_info.province_kill_requests_quantity|toLocaleStr }} +
+ +
+ وزن تخصیصات بدون بار: + {{ killing_info.province_kill_requests_weight|toLocaleStr }} +
+ +
+ وزن تعهد دولتی: + {{ total_commitment|toLocaleStr }} +
+
+ میانگین وزن کشتار: + {{ total_average_killed_weight|toLocaleStr }} +
+ +
+ وزن کل کشتار: + {{ total_killed_weight|toLocaleStr}} +
+
+ تعداد کشتار فعال: + {{ active_kill1 }} +
+
+ تعداد درخواست کشتار: + {{ active_kill.count_of_request|toLocaleStr }} +
+
+ آخرین تغییر: + {{ latest_hatching_change.full_name }} +
+
+
+ + + +
+
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای داخل استان
+
+
+ + + + + + + + + + + + + + + + + + + + + + {% for bar in bars %} + + + + {% if bar.poultry_request.free_sale_in_province == True %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
کدباروضعیتنوع فروشتاریخ کشتارخریدارتلفنکشتارکنسن مرغمحصولشهرکدقرنطینهاستعلام قرنطینهحجم زندهوزن زنده (کیلوگرم)حجم ورود به انباروزن ورود به انبار (کیلوگرم)
{{ bar.bar_code }}{{ bar.status }}آزاددولتی{{ bar.date|jalali }}{{ bar.buyer.name }}{{ bar.buyer.kill_house_operator.user.mobile }}{{ bar.killer_info.name }}({{ bar.killer_info.kill_house_operator.user.mobile }}){{ bar.poultry_request.age }}{{ bar.product }}{{ bar.buyer.kill_house_operator.address.city.name }}{{ bar.clearance_code|isNone }}{{ bar.quarantine_quantity|isNone }}{{ bar.accepted_real_quantity |int|toLocaleStr }}{{ bar.accepted_real_weight |int|toLocaleStr }}{{ bar.ware_house_accepted_real_quantity |int|toLocaleStr }}{{ bar.ware_house_accepted_real_weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% if bars2 %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای داخل استان
+
+
+ + + + + + + + + + + + + + + + + + + + + + {% for bar in bars %} + + + + {% if bar.poultry_request.free_sale_in_province == True %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
کدباروضعیتنوع فروشتاریخ کشتارخریدارتلفنکشتارکنسن مرغمحصولشهرکدقرنطینهاستعلام قرنطینهحجم زندهوزن زنده (کیلوگرم)حجم ورود به انباروزن ورود به انبار (کیلوگرم)
{{ bar.bar_code }}{{ bar.status }}آزاددولتی{{ bar.date|jalali }}{{ bar.buyer.name }}{{ bar.buyer.kill_house_operator.user.mobile }}{{ bar.killer_info.name }}({{ bar.killer_info.kill_house_operator.user.mobile }}){{ bar.poultry_request.age }}{{ bar.product }}{{ bar.buyer.kill_house_operator.address.city.name }}{{ bar.clearance_code|isNone }}{{ bar.quarantine_quantity|isNone }}{{ bar.accepted_real_quantity |int|toLocaleStr }}{{ bar.accepted_real_weight |int|toLocaleStr }}{{ bar.ware_house_accepted_real_quantity |int|toLocaleStr }}{{ bar.ware_house_accepted_real_weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% endif %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای خارج استان
+
+
+ + + + + + + + + + + + + + + {% for bar in outBars %} + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
کدسفارشتاریخخریدارتلفناستان/شهرکدقرنطینهاستعلام قرنطینهحجم زندهوزن زنده (کیلوگرم)
{{ bar.order_code }}{{ bar.send_date|jalali }}{{ bar.buyer_fullname }}{{ bar.buyer_mobile }}{{ bar.buyer_province }}/{{ bar.buyer_city }}{{ bar.quarantine_code|isNone }}{{ bar.quarantine_quantity|int|toLocaleStr }}{{ bar.quantity |int|toLocaleStr }}{{ bar.weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% if outBars2 %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای خارج استان
+
+
+ + + + + + + + + + + + + + + {% for bar in outBars2 %} + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
کدسفارشتاریخخریدارتلفناستان/شهرکدقرنطینهاستعلام قرنطینهحجم زندهوزن زنده (کیلوگرم)
{{ bar.order_code }}{{ bar.send_date|jalali }}{{ bar.buyer_fullname }}{{ bar.buyer_mobile }}{{ bar.buyer_province }}/{{ bar.buyer_city }}{{ bar.quarantine_code|isNone }}{{ bar.quarantine_quantity|int|toLocaleStr }}{{ bar.quantity |int|toLocaleStr }}{{ bar.weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+ +{% endif %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
مدیریت بار زنجیره
+
+
+ + + + + + + + + + + + + + + + + + + + {% for bar in chainAllocation %} + + {% if bar.state == 'accepted' %} + + {% elif bar.state == 'pending' %} + + {% else %} + + {% endif %} + + {% if bar.out_province == True %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
وضعیتتاریخ سفارشنوع فروشثبت کننده سفارشخریدارشرکت زنجیرهکد بهداشتیکد قرنطینهرانندهنوع خودروپلاکحجممیانگین وزنوزن
تایید شده در انتظار تایید رد شده {{ bar.date|jalali }} خارج استان داخل استان {{ bar.registerer.fullname }}({{ bar.registerer.mobile }}) {{ bar.buyer_name }}({{ bar.buyer_mobile }}) {{ bar.chain_company.name }}({{ bar.chain_company.user.mobile }}) {{ bar.health_code|isNone }} {{ bar.quarantine_code|isNone }} {{ bar.driver_name }}({{ bar.driver_mobile }}) {{ bar.type_car }} {{ bar.pelak }} {{ bar.quantity |int|toLocaleStr }} {{ bar.index_weight }} {{ bar.weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% if chainAllocation2 %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
مدیریت بار زنجیره
+
+
+ + + + + + + + + + + + + + + + + + + + {% for bar in chainAllocation2 %} + + {% if bar.state == 'accepted' %} + + {% elif bar.state == 'pending' %} + + {% else %} + + {% endif %} + + {% if bar.out_province == True %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
وضعیتتاریخ سفارشنوع فروشثبت کننده سفارشخریدارشرکت زنجیرهکد بهداشتیکد قرنطینهرانندهنوع خودروپلاکحجممیانگین وزنوزن
تایید شده در انتظار تایید رد شده {{ bar.date|jalali }} خارج استان داخل استان {{ bar.registerer.fullname }}({{ bar.registerer.mobile }}) {{ bar.buyer_name }}({{ bar.buyer_mobile }}) {{ bar.chain_company.name }}({{ bar.chain_company.user.mobile }}) {{ bar.health_code|isNone }} {{ bar.quarantine_code|isNone }} {{ bar.driver_name }}({{ bar.driver_mobile }}) {{ bar.type_car }} {{ bar.pelak }} {{ bar.quantity |int|toLocaleStr }} {{ bar.index_weight }} {{ bar.weight |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+ +{% endif %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
بارهای عدم وصول
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for item in returnKillHouseRequest %} + + + + {% if item.return_trash == True %} + + {% else %} + + {% endif %} + {% if item.poultry_request.market %} + + {% elif item.poultry_request.direct_buying %} + + + {% elif item.warehouse %} + + {% else %} + + {% endif %} + {% if item.poultry_request.freezing %} + + + {% elif item.poultry_request.export %} + + + {% else %} + + + {% endif %} + + + + + + + {% if item.killer %} + + {% else %} + + {% endif %} + + + + + + + + {% if item.state == 'pending' %} + + {% elif item.state == 'accepted' %} + + {% else %} + + {% endif %} + + + {% if item.non_receipt %} + + {% else %} + + + {% endif %} + + {% if item.non_receipt and item.main_non_receipt %} + + {% else %} + + + {% endif %} + + + {% empty %} + + + + {% endfor %} + +
کد بارکدسفارشنوع بارنوع درخواستنوع کشتارنام فارمنام مرغدارشهر مرغدارتاریخ درخواست کشتارتعداد بارتاریخ ثبت بارنام کشتارگاهشهر کشتارگاهوزنمیانگین وزنیتعداد نهاییوزن نهاییقیمت مرغدارقیمت کشتارگاهوضعیت تاییدپلاک خودرونام رانندهعدم دریافتپیام عدم دریافت
{{ item.bar_code }}{{ item.poultry_request.order_code}}برگشتیعدم وصولپنل معاملاتخرید مستقیمانباراتحادیهانجمادصادراتعادی{{ item.poultry_request.poultry.unit_name }}{{ item.poultry_request.poultry.user.fullname }} ({{ item.poultry_request.poultry.user.mobile }}){{ item.poultry_request.poultry.address.city.name}}{{ item.kill_request.receive_date|jalali }}{{ item.quantity|toLocaleStr }}{{ item.create_date|jalali }}{{ item.killer.name}}{{ item.killhouse_user.name}}{{ item.killhouse_user.kill_house_operator.user.city.name }}{{ item.weight_info.weight|toLocaleStr }}{{ item.weight_info.index_weight|toLocaleStr}}{{ item.accepted_real_quantity|toLocaleStr }}{{ item.accepted_real_weight|toLocaleStr }}{{ item.poultry_request.amount|toLocaleStr }}{{ item.weight_info.kill_house_price|toLocaleStr }}در انتظار تاییدتایید شدهرد شده{{ item.car.pelak }}{{ item.car.driver_name }}داردندارد{{ item.non_receipt_message }} کاربر (item.modify_date|jalali)سیستم (item.modify_date|jalali)
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% if nonReceipt2 %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
بارهای عدم وصول
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {% for item in returnKillHouseRequest %} + + + + {% if item.return_trash == True %} + + {% else %} + + {% endif %} + {% if item.poultry_request.market %} + + {% elif item.poultry_request.direct_buying %} + + + {% elif item.warehouse %} + + {% else %} + + {% endif %} + {% if item.poultry_request.freezing %} + + + {% elif item.poultry_request.export %} + + + {% else %} + + + {% endif %} + + + + + + + {% if item.killer %} + + {% else %} + + {% endif %} + + + + + + + + {% if item.state == 'pending' %} + + {% elif item.state == 'accepted' %} + + {% else %} + + {% endif %} + + + {% if item.non_receipt %} + + {% else %} + + + {% endif %} + + {% if item.non_receipt and item.main_non_receipt %} + + {% else %} + + + {% endif %} + + + {% empty %} + + + + {% endfor %} + +
کد بارکدسفارشنوع بارنوع درخواستنوع کشتارنام فارمنام مرغدارشهر مرغدارتاریخ درخواست کشتارتعداد بارتاریخ ثبت بارنام کشتارگاهشهر کشتارگاهوزنمیانگین وزنیتعداد نهاییوزن نهاییقیمت مرغدارقیمت کشتارگاهوضعیت تاییدپلاک خودرونام رانندهعدم دریافتپیام عدم دریافت
{{ item.bar_code }}{{ item.poultry_request.order_code}}برگشتیعدم وصولپنل معاملاتخرید مستقیمانباراتحادیهانجمادصادراتعادی{{ item.poultry_request.poultry.unit_name }}{{ item.poultry_request.poultry.user.fullname }} ({{ item.poultry_request.poultry.user.mobile }}){{ item.poultry_request.poultry.address.city.name}}{{ item.kill_request.receive_date|jalali }}{{ item.quantity|toLocaleStr }}{{ item.create_date|jalali }}{{ item.killer.name}}{{ item.killhouse_user.name}}{{ item.killhouse_user.kill_house_operator.user.city.name }}{{ item.weight_info.weight|toLocaleStr }}{{ item.weight_info.index_weight|toLocaleStr}}{{ item.accepted_real_quantity|toLocaleStr }}{{ item.accepted_real_weight|toLocaleStr }}{{ item.poultry_request.amount|toLocaleStr }}{{ item.weight_info.kill_house_price|toLocaleStr }}در انتظار تاییدتایید شدهرد شده{{ item.car.pelak }}{{ item.car.driver_name }}داردندارد{{ item.non_receipt_message }} کاربر (item.modify_date|jalali)سیستم (item.modify_date|jalali)
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% endif %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای قرنطینه
+
+
+ + + + + + + + + + + + + + + {% for bar in differentBars %} + + + {% if bar.Out == True %} + + {% else %} + + {% endif %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
تاریخ کشتارنوع بارسن مرغوضعیتخریدارمحصولشهرکدقرنطینهحجم
{{ bar.Date|jalali }}خارج استانداخل استان{{ bar.Age }}{{ bar.TrackingStatusDescription }}{{ bar.DesUnitName }}{{ bar.GoodName }}{{ bar.City }}{{ bar.TrackingCode|isNone }}{{ bar.GoodAmount |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + + +
+{% if differentBars2 %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اطلاعات بارهای قرنطینه
+
+
+ + + + + + + + + + + + + + + {% for bar in differentBars %} + + + {% if bar.Out == True %} + + {% else %} + + {% endif %} + + + + + + + + + + {% empty %} + + + + {% endfor %} + +
تاریخ کشتارنوع بارسن مرغوضعیتخریدارمحصولشهرکدقرنطینهحجم
{{ bar.Date|jalali }}خارج استانداخل استان{{ bar.Age }}{{ bar.TrackingStatusDescription }}{{ bar.DesUnitName }}{{ bar.GoodName }}{{ bar.City }}{{ bar.TrackingCode|isNone }}{{ bar.GoodAmount |int|toLocaleStr }}
هیچ داده‌ای یافت نشد
+ +
+ + +
+ +{% endif %} +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
تخصیص‌های بازگشتی
+
+
+ + + + + + + + + + + + + + + + + + + + + + + {% for item in return_province_request %} + + + + {% if item.market %} + + {% elif item.direct_buying %} + + {% elif item.warehouse %} + + {% else %} + + {% endif %} + + + + + + + + + + + + + + {% if item.state == "pending" %} + + {% elif item.state == "accepted" %} + + {% else %} + + {% endif %} + + {% if item.first_car_allocated_quantity > 0 %} + + {% else %} + + {% endif %} + + + {% with diff=item.quantity|add:item.total_killed_quantity|floatformat:-1 %} + + {% endwith %} + + + + {% empty %} + + + + {% endfor %} + +
کدسفارشنوع درخواستنام فارمنام مرغدارشهر مرغدارتاریخ کشتارتعداد درخواستتاریخ ثبت تخصیصنام کشتارگاهشهر کشتارگاهقیمت مرغدارقیمت کشتارگاهتعداد تخصیصوضعیت تاییدوضعیت تخصیص ماشینمانده قابل تخصیصبرگشت دهنده
{{ item.order_code|default:"-" }}پنل معاملاتخرید مستقیمانباراتحادیه{{ item.poultry_unit_name }} + {{ item.poultry_fullname }} ({{ item.poultry_mobile }}) + {{ item.poultry_city }}{{ item.killing_date|jalali }}{{ item.poultry_request_quantity|toLocaleStr }}{{ item.create_date|jalali }}{{ item.killhouse_user.name|default:"-" }}{{ item.killhouse_user.city|default:"-" }}{{ item.poultry_amount|toLocaleStr }} ﷼{{ item.kill_house_price|toLocaleStr }} ﷼{{ item.quantity|toLocaleStr }}در انتظار تاییدتایید شدهرد شدهداردندارد + {{ diff|floatformat:0|toLocaleStr }} + + {% if item.returner %} + {{ item.returner.fullname }} ({{ item.returner.mobile }}) + {% else %} + سیستم + {% endif %} + {{ item.modify_date|jalali }} +
هیچ داده‌ای یافت نشد
+ +
+ + + +
+ +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
اختلاف کشتار
+
+
+ + + + + + + + + + + + + + + + + {% for item in killingDifference %} + + + + + + + + + + + + + {% if item.state == "pending" %} + + {% elif item.state == "accepted" %} + + {% else %} + + {% endif %} + + {% endfor %} + +
ثبت کنندهتاریخ ثبتمرغدارکشتارگاهحجم کم شده از سالن مرغداروزن تقریبی کشتار (کیلوگرم)حجم سفارشات دریافتی توسط کشتارگاهاختلاف کشتار(حجم)اختلاف حجماختلاف وزنوضعیت
{{ item.register_fullname|default:"-" }}{{ item.create_date|jalali }}{{ item.hatching.poultry.unit_name|default:"-" }}{{ item.kill_house.name|default:"-" }}{{ item.quantity|toLocaleStr }}{{ item.weight|toLocaleStr }}{{ item.real_quantity|toLocaleStr }}{{ item.bar_info.difference_quantity|toLocaleStr }}{{ item.quantity|toLocaleStr }}{{ item.weight|toLocaleStr }}در انتظار تاییدتایید شدهرد شده
+ +
+ + + +
+ +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
افزایش حجم جوجه ریزی
+
+
+ + + + + + + + + + + + + + + + + + {% for item in hatchingIncrease %} + + + + + + + + + + + + + + {% endfor %} + +
مرغدارشماره مجوز جوجه ریزیشناسه یکتا فارمحجم جوجه ریزیحجم کشتارحجم تلفاتمانده در سالنحجم افزایشیثبت کنندهتاریخ ثبتپیغام
{{ item.hatching.poultry.unit_name|default:"-" }}{{ item.hatching.licence_number|default:"-" }}{{ item.hatching.breeding_unique_id|default:"-" }}{{ item.hatching_quantity|toLocaleStr }}{{ item.hatching_kill_quantity|toLocaleStr }}{{ item.hatching_losses|toLocaleStr }}{{ item.hatching_left_over|toLocaleStr }}{{ item.quantity|toLocaleStr }}{{ item.registerer_name|default:"-" }}{{ item.date|jalali }}{{ item.message|default:"-" }}
+ +
+ + + +
+ + +
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
گزارشات تلفات
+
+
+ + + + + + + + + + + + {% if evacuation_reports %} + {% for report in evacuation_reports %} + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} + +
شماره گزارشنوع گزارشتاریخ معدوم‌سازیتعدادتاریخ ثبت
{{ report.MoReportId|default:"-" }}{{ report.ReportTypeString|default:"-" }}{{ report.MoDateShamsi|default:"-" }}{{ report.GoodCount|default_if_none:0|int|toLocaleStr }}{{ report.RegDateShamsiWithTime }}
گزارشی ثبت نشده است
+
+ + +
+
+
+ +
+ {{ licence_number }} +
+
+ {{ shamsi_date }} +
+
+ - +
+
+
+
+
گزارشات تلفات
+
+
+ + + + + + + + + + + + {% if evacuation_reports %} + {% for report in evacuation_reports %} + + + + + + + + {% endfor %} + {% else %} + + + + {% endif %} + +
شماره گزارشنوع گزارشتاریخ معدوم‌سازیتعدادتاریخ ثبت
{{ report.MoReportId|default:"-" }}{{ report.ReportTypeString|default:"-" }}{{ report.MoDateShamsi|default:"-" }}{{ report.GoodCount|default_if_none:0|int|toLocaleStr }}{{ report.RegDateShamsiWithTime|default:report.RegDateShamsi|default:"-" }}
گزارشی ثبت نشده است
+
+ + +
+ diff --git a/templates/poultry_science_report.html b/templates/poultry_science_report.html new file mode 100644 index 0000000..96a327e --- /dev/null +++ b/templates/poultry_science_report.html @@ -0,0 +1,440 @@ +{% extends "base.html" %} +{% block title %} +گزارش بازرسی مرغداری - سامانه رصدیار +{% endblock %} +{% block body %} +
+
+
{{ report_id }}
+
{{ inspection_date }}
+
-
+
+
+

+ گزارش بازرسی مرغداری +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
تاریخ بازرسیشناسه بازرسینام فارمشناسه یکتاشناسه جوجه ریزیشهرستانتاریخ جوجه ریزیتعداد جوجه ریزیوضعیت بازرسی
{{ inspection_date }}{{ report_id }}{{ unit_name }}{{ breeding_unique_id }}{{ licence_number }}{{ city }}{{ hatching_date }}{{ initial_quantity }}{{ inspection_status }}
+ + +

اطلاعات

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
نام واحد + مرغداری{{ unit_name }}کد یکتا / + شناسه واحد{{ breeding_unique_id }}
پروانه بهداشتی + {{ health_permit }}مجوز جوجه ریزی + {{ hatching_licence }}
کد اپیدمیولوژیک + {{ epidemiological_code }}اعتبار پروانه بهره + برداری{{ permit_validity }}
وضعیت مستاجر + {{ tenant_status }}نام مالک / بهره + بردار{{ owner_name }}
نوع مالکیت{{ ownership_type }}کد ملی بهره + بردار{{ owner_national_code }}
استان{{ province }}شهر{{ city }}
مختصات جغرافیایی + {{ coordinates }}شماره تماس بهره + بردار{{ owner_mobile }}
ظرفیت اسمی + واحدها{{ nominal_capacity }}تاریخ جوجه ریزی + {{ hatching_date }}
تاریخ بازدید + {{ inspection_date }}تعداد جوجه ریزی + اولیه{{ initial_quantity }}
تعداد جوجه ریزی توسط + دامپزشکی{{ vet_quantity }}تعداد جوجه طبق خود اظهاری + مرغدار{{ self_declared_quantity }}
منبع تهیه جوجه + {{ chick_source }}سن جوجه در زمان + بازدید{{ chicken_age }}
نوع نژاد{{ breed_type }}
+ + +

پایش سلامت

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
وضعیت بهداشتی + سالن{{ health_status }}وضعیت + تهویه{{ ventilation_status }}
وضعیت بستر{{ bedding_status }}دما و رطوبت سالن با توجه + به سن جوجه{{ temperature_humidity }}
کیفیت آب مصرفی + {{ water_quality }}منبع آب مصرفی + {{ water_source }}
تعداد تلفات عادی + دوره{{ normal_losses }}تلفات غیر عادی + {{ abnormal_losses }}
علت تلفات غیر + عادی{{ abnormal_losses_reason }}نوع بیماری + تشخیصی{{ disease_type }}
نمونه برداری انجام + شده{{ sampling_done }}نوع نمونه{{ sample_type }}
نام مسئول فنی + بهداشتی{{ health_responsible }}نام مسئول فنی نظام + مهندسی{{ engineering_responsible }}
+ +
+ +
+ + +
+
+
{{ report_id }}
+
{{ inspection_date }}
+
-
+
+
+ + +

زیرساخت

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
وضعیت + نهاده{{ input_status }}نوع + دان{{ feed_type }}
کیفیت دانه{{ feed_quality }}موجودی تا روز + بازدید{{ inventory_until_visit }}
موجودی در انبار + {{ warehouse_inventory }}کد رهگیری{{ tracking_code }}
نام شرکت{{ company_name }}نوع ژنراتور{{ generator_type }}
مدل ژنراتور{{ generator_model }}تعداد ژنراتور + {{ generator_count }}
نوع سوخت{{ fuel_type }}ظرفیت ژنراتور + {{ generator_capacity }}
میزان موجودی سوخت اضطراری + (لیتر){{ emergency_fuel }}سابقه قطعی برق دوره + جاری{{ power_cut_history }}
مدت زمان قطعی + {{ power_cut_duration }}ساعت قطعی{{ power_cut_hour }}
عملکرد ژنراتور + {{ generator_status }}توضیحات تکمیلی + {{ additional_notes }}
+ + +

نیروی انسانی و تسهیلات

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
تعداد افراد + شاغل{{ employee_count }}تعداد افراد + بومی{{ local_employee_count }}
تعداد افراد غیر + بومی{{ non_local_employee_count }}وضعیت قرارداد + کارگران{{ worker_contract_status }}
آموزش دیده در حوزه بهداشت + و امنیت زیستی{{ health_training }}تسهیلات دریافتی + فعال{{ active_facilities }}
نوع تسهیلات{{ facility_type }}مبلغ تسهیلات + {{ facility_amount }}
وضعیت بازپرداخت + {{ repayment_status }}درخواست جدید بهره + بردار{{ new_request }}
تاریخ تسهیلات + {{ facility_date }}
+ + +

مستندات

+ + + + + + + + + + + + + + + + + +
+ وضعیت کلی سالن + {% if hall_images %} + {% for img in hall_images %} + + {% endfor %} + {% else %} + تصویری موجود نیست + {% endif %} +
+ انبار نهاده ها + {% if warehouse_images %} + {% for img in warehouse_images %} + + {% endfor %} + {% else %} + تصویری موجود نیست + {% endif %} +
+ تلفات + {% if losses_images %} + {% for img in losses_images %} + + {% endfor %} + {% else %} + تصویری موجود نیست + {% endif %} +
+ تصاویر تخلف + {% if violation_images %} + {% for img in violation_images %} + + {% endfor %} + {% else %} + تصویری موجود نیست + {% endif %} +
+ + +

توصیه ها / اخطارها / اقدامات اصلاحی +

+
+

وضعیت: {{ inspection_status_text }}

+

{{ recommendations }}

+
+ + +

احراز مسئول سالن

+ + + + + + + + + + + +
مسئول سالن + حضور دارد؟{{ hall_responsible_present }}نام مسئول + سالن در زمان بازدید{{ hall_responsible_name }}
تلفن مسئول سالن + {{ hall_responsible_phone }}
+ +
+ +
+ +{% endblock %} \ No newline at end of file diff --git a/templates/summary_report.html b/templates/summary_report.html new file mode 100644 index 0000000..b070c33 --- /dev/null +++ b/templates/summary_report.html @@ -0,0 +1,91 @@ +{% extends "base.html" %} +{% block title %} + سامانه رصدیار +{% endblock title %} +{% block body %} +
+ +
+ +
+ {{ number }} +
+
+ {{ date }} +
+
+ - +
+
+
+

+ از تاریخ {{ from_date }} تا تاریخ {{ to_date }} استان {{ province }} +

+ +

+ به اطلاع می‌رساند : +

+

+ تعداد {{ poultry_count }} فارم فعال در سطح استان شناسایی شده که از این تعداد {{ chain_count }} فارم + دارای زنجیره هستند. مجموع جوجه‌ریزی + در این بازه زمانی به بیش از {{ poultry_hatching_quantity }} قطعه رسیده که با احتساب تلفات دامپزشکی و + اتحادیه({{ poultry_hatching_total_losses }} قطعه)، + حدود {{ poultry_hatching_killed_quantity }} قطعه کشتار شده و بیش از{{ poultry_hatching_left_over }} قطعه + نیز همچنان در سالن‌ها باقی مانده‌اند. تعداد + {{ poultry_hatching_gt_60 }} + فارم با سن بیش از ۶۰ روز شناسایی شده که حجم کلی آن‌ها حدود {{ poultry_hatching_gt_60_quantity }} قطعه + بوده و میانگین مانده در سالن + آن‌ها حدود {{ poultry_hatching_gt_60_left_over }} درصد است. بیشترین سن کشتار به + فارم {{ max_age_poultry_name }} در + {{ max_age_poultry_city }} با + {{ max_age_poultry }} روز و کمترین سن + کشتار به فارم {{ min_age_poultry_name }} در {{ min_age_poultry_city }} با {{ min_age_poultry }} روز تعلق + دارد. +

+

+ در مجموع {{ kill_house_request_count }} بار کشتار در داخل استان ثبت شده که منجر به کشتار بیش + از {{ kill_house_request_quantity }} قطعه با وزنی حدود + {{ kill_house_request_weight }} + کیلوگرم شده است. همچنین {{ free_bars_count }} بار خریداری از خارج استان انجام شده که + شامل {{ free_bars_quantity }} قطعه با وزن + {{ free_bars_live_weight }} کیلوگرم بوده که بیشترین خریدار در این حوزه، {{ kill_house_name }} + با {{ transaction_count }} بار بوده است. +

+

+ از نظر عملکرد خریداران، {{ kill_house_name_req }} با {{ transaction_count_req }} بار + و {{ total_quantity_top_inner }} قطعه بیشترین خرید داخل استان را داشته و + {{ kill_house_name }} + با {{ total_quantity_top_out }} قطعه بیشترین حجم خرید از خارج استان را انجام داده است. بیشترین بار + ارسالی از داخل + استان مربوط به مرغداری {{ poultry_req_name_req }} {{ poultry_city_req_name_req }} + با {{ top_poultry_req_stats_total_quantity }} قطعه و از خارج استان مربوط به + مرغداری {{ out_poultry_req_name_req }} + در {{ out_poultry_province_req_name_req }} شهر {{ out_poultry_city_req_name_req }} + با {{ out_top_poultry_req_stats_total_quantity }} قطعه است. +

+

+ در خصوص توزیع لاشه، مجموع وزن لاشه فروش رفته از انبارها به میزان {{ steward_sum_weight_sale }} کیلوگرم به داخل استان و + {{ free_bar_sum_weight_sale }} کیلوگرم به خارج از استان صورت گرفته است. مهم‌ترین واحد‌ توزیع‌کننده لاشه درون استان + {{ out_kill_house_top }} + با وزن {{ out_weight_top }} کیلوگرم که بخش عمده‌ای از فروش داخلی را بر عهده داشته‌است. + و {{ free_bars_kill_house_top }} با وزن {{ free_bars_weight_top }} کیلوگرم توزیع به خارج استان بیشترین گوشت را از استان خارج کرده است. +

+

+ از نظر اسناد و قبوض باسکول، {{percent_bar_document_status_rejected_all}} درصد از بارها دارای سند مشکوک یا عدم احراز اصالت می باشند. +

+

+ جزییات گزارش عملکرد: + دانلود اکسل +

+ +
+ + +
+ +{% endblock body %} \ No newline at end of file diff --git a/templatetags/__init__.py b/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/templatetags/jalali_filters.py b/templatetags/jalali_filters.py new file mode 100644 index 0000000..5098a0c --- /dev/null +++ b/templatetags/jalali_filters.py @@ -0,0 +1,47 @@ +from django import template +from datetime import datetime + +from panel.helper_excel import shamsi_date, to_locale_str + +register = template.Library() + + +@register.filter(name='jalali') +def jalali(value): + if not value: + return "" + + try: + if isinstance(value, str): + try: + value = datetime.fromisoformat(value) + except: + return '-' + + if hasattr(value, 'date'): + value = value.date() + + return shamsi_date(value,in_value=True) + except: + return '-' + + +@register.filter(name='isNone') +def is_none(value): + if value is None: + return "-" + return value + + +@register.filter(name='toLocaleStr') +def to_locale_string(value): + if value is None: + return "-" + return to_locale_str(value) + + +@register.filter(name='int') +def to_int(value): + if value is None: + return "-" + return int(value) diff --git a/ticket/__init__.py b/ticket/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ticket/admin.py b/ticket/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/ticket/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/ticket/apps.py b/ticket/apps.py new file mode 100644 index 0000000..1b423f8 --- /dev/null +++ b/ticket/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class TicketConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'ticket' diff --git a/ticket/bucket.py b/ticket/bucket.py new file mode 100644 index 0000000..262f1c2 --- /dev/null +++ b/ticket/bucket.py @@ -0,0 +1,97 @@ +from botocore.exceptions import NoCredentialsError +import boto3 +import logging +from PIL import Image +import io +import base64 + +LIARA_ENDPOINT = 'https://storage.c2.liara.space' +LIARA_BUCKET_NAME = 'ticket-rasadyar' +LIARA_ACCESS_KEY = "gvqohestrakmqi6n" +LIARA_SECRET_KEY = '7240fdd8-59bc-4f02-b5e6-4a124e37fa0e' + +RASADYAR_ENDPOINT = 'https://s3.rasadyar.com' +RASADYAR_BUCKET_NAME = 'rasadyar' +RASADYAR_ACCESS_KEY = "zG3ewsbYsTqCmuws" +RASADYAR_SECRET_KEY = 'RInUMB78zlQZp6CNf8+sRoSh2cNDHcGQhXrLnTJ1AuI=' + + +def upload_to_liara(image, name): + s3 = boto3.client( + 's3', + endpoint_url=RASADYAR_ENDPOINT, + aws_access_key_id=RASADYAR_ACCESS_KEY, + aws_secret_access_key=RASADYAR_SECRET_KEY + ) + + s3.upload_fileobj( + image, + RASADYAR_BUCKET_NAME, + name, + ExtraArgs={'ACL': 'public-read'} # دسترسی عمومی + ) + + return f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{name}" + +def connect(): + logging.basicConfig(level=logging.INFO) + + try: + s3 = boto3.client( + 's3', + endpoint_url=LIARA_ENDPOINT, + aws_access_key_id=LIARA_ACCESS_KEY, + aws_secret_access_key=LIARA_SECRET_KEY + ) + except Exception as exc: + logging.info(exc) + return s3 + + +def upload_object_resize_to_liara(image_data, object_name): + try: + imgdata = base64.b64decode(image_data) + img = Image.open(io.BytesIO(imgdata)) + + img.thumbnail((500, 500)) + + buffer = io.BytesIO() + img.save(buffer, format="PNG") + buffer.seek(0) + + s3_resource = boto3.resource( + 's3', + endpoint_url=LIARA_ENDPOINT, + aws_access_key_id=LIARA_ACCESS_KEY, + aws_secret_access_key=LIARA_SECRET_KEY + ) + + bucket = s3_resource.Bucket(LIARA_BUCKET_NAME) + bucket.put_object( + ACL='public-read', + Body=buffer, + Key=object_name, + ContentType='image/png' + ) + + return f"{LIARA_ENDPOINT}/{LIARA_BUCKET_NAME}/{object_name}" + + except Exception as e: + raise Exception(f"خطا در آپلود فایل: {e}") + + +def delete_file_from_liara(file_name): + try: + s3 = boto3.client( + 's3', + endpoint_url=LIARA_ENDPOINT, + aws_access_key_id=LIARA_ACCESS_KEY, + aws_secret_access_key=LIARA_SECRET_KEY + ) + + s3.delete_object(Bucket=LIARA_BUCKET_NAME, Key=file_name) + + except NoCredentialsError: + raise Exception("اعتبارنامه‌های AWS معتبر نیستند") + except Exception as e: + raise Exception(f"خطا در آپلود فایل: {e}") diff --git a/ticket/customer_views.py b/ticket/customer_views.py new file mode 100644 index 0000000..a8a7323 --- /dev/null +++ b/ticket/customer_views.py @@ -0,0 +1,127 @@ +import random + +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from .models import ( + Ticket, + TicketContent, + Answer, + Question, + SupportUnit, + Group, + SystemUserProfile +) +from .serializers import ( + TicketSerializer, + TicketContentSerializer, + TicketAnswerSerializer, + TicketQuestionSerializer, + SupportUnitSerializer +) +from rest_framework.response import Response +from .helper import upload_listed_image +from rest_framework import status +from datetime import datetime + + +class CustomerTicketViewSet(viewsets.ModelViewSet): + queryset = Ticket.objects.all() + serializer_class = TicketSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # get user object + user = SystemUserProfile.objects.get(user=request.user) + + # different style of ticket information + if 'pending' in request.GET: + ticket = self.queryset.filter(customer=user, state='pending') + serializer = self.serializer_class(ticket, many=True) + elif 'responded' in request.GET: + ticket = self.queryset.filter(customer=user, state='responded') + serializer = self.serializer_class(ticket, many=True) + elif 'closed' in request.GET: + ticket = self.queryset.filter(customer=user, state='closed') + serializer = self.serializer_class(ticket, many=True) + elif 'all' in request.GET: + ticket = self.queryset.filter(customer=user) + serializer = self.serializer_class(ticket, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def retrieve(self, request, *args, **kwargs): + ticket = self.queryset.get(key=request.data['key']) + serializer = self.serializer_class(ticket) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + + if 'ticket_key' in request.data.keys(): + ticket_key = request.data['ticket_key'] + request.data.pop('ticket_key') + else: + ticket_key = None + + # get group unit information + group = Group.objects.get( + name__exact=request.data['support_unit'] + ) + request.data.pop('support_unit') # pop this block from body data + + # get support unit object information + support_unit = SupportUnit.objects.get( + unit=group + ) + + # ticket number + ticket_id = random.randint(1000000, 9999999) + + # process list of images + req = upload_listed_image(req=request, field='image') + + # create ticket content + content_serializer = TicketContentSerializer(data=req.data) + if content_serializer.is_valid(): + content_obj = content_serializer.create(validated_data=req.data) + + # create question from customer + question = Question( + questioner=SystemUserProfile.objects.get(user=request.user), + content=content_obj + ) + question.save() + + if ticket_key is not None: + ticket = Ticket.objects.get(key=ticket_key) + ticket.question.add(question) + ticket.state = 'pending' + ticket.save() + else: + # create final ticket + ticket = Ticket( + customer=SystemUserProfile.objects.get(user=request.user), + support_unit=support_unit, + state='pending', + ticket_id=ticket_id + ) + ticket.save() + ticket.question.add(question) + + serializer = self.serializer_class(ticket) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object + request.data.pop('ticket_key') + + # send ticket object to serializer for update + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + ticket_updated = serializer.update(validated_data=request.data, instance=ticket) + serializer = self.serializer_class(ticket_updated) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors) + + def destroy(self, request, *args, **kwargs): + pass diff --git a/ticket/helper.py b/ticket/helper.py new file mode 100644 index 0000000..5a7b566 --- /dev/null +++ b/ticket/helper.py @@ -0,0 +1,75 @@ +import base64 +import io +import os +import random +import string + +import boto3 +from PIL import Image + +from ticket.bucket import RASADYAR_ENDPOINT, RASADYAR_BUCKET_NAME, RASADYAR_ACCESS_KEY, RASADYAR_SECRET_KEY + +ARVAN_TICKET_GALLERY = "https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/" +# ARVAN_TICKET_GALLERY = "https://ticketgallery.s3.ir-thr-at1.arvanstorage.com/" +ARVAN_User_Image_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' + + +def send_image_to_server(image): + ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + imgdata = base64.b64decode(image) + img = Image.open(io.BytesIO(imgdata)) + + img.thumbnail((500, 500)) + + buffer = io.BytesIO() + img.save(buffer, format="PNG") + buffer.seek(0) + + s3_resource = boto3.resource( + 's3', + endpoint_url=RASADYAR_ENDPOINT, + aws_access_key_id=RASADYAR_ACCESS_KEY, + aws_secret_access_key=RASADYAR_SECRET_KEY + ) + + bucket = s3_resource.Bucket(RASADYAR_BUCKET_NAME) + bucket.put_object( + ACL='public-read', + Body=buffer, + Key=ran + '.jpg', + ContentType='image/png' + ) + + image_url = f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{ran + '.jpg'}" + + return image_url + + +def upload_listed_image(req=None, field=None): + image_list = [] + if req.data[field] != []: + for item in req.data[field]: + image_list.append(send_image_to_server(item)) + req.data.pop(field) + req.data[field] = image_list + elif req.data[field] == "": + req.data[field] = "empty" + return req + + +def send_image_to_server_for_poultry_science(image, name): + s3 = boto3.client( + 's3', + endpoint_url=RASADYAR_ENDPOINT, + aws_access_key_id=RASADYAR_ACCESS_KEY, + aws_secret_access_key=RASADYAR_SECRET_KEY + ) + + s3.upload_fileobj( + image, + RASADYAR_BUCKET_NAME, + name, + ExtraArgs={'ACL': 'public-read'} # دسترسی عمومی + ) + + return f"{RASADYAR_ENDPOINT}/{RASADYAR_BUCKET_NAME}/{name}" diff --git a/ticket/migrations/0001_initial.py b/ticket/migrations/0001_initial.py new file mode 100644 index 0000000..49f2f7f --- /dev/null +++ b/ticket/migrations/0001_initial.py @@ -0,0 +1,150 @@ +# Generated by Django 3.2.13 on 2023-09-18 19:32 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('authentication', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Answer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(max_length=100, null=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Question', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(max_length=100, null=True)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SupportUnit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supportunit_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supportunit_modifiedby', to=settings.AUTH_USER_MODEL)), + ('unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='support_unit', to='auth.group')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TicketContent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=200, null=True)), + ('content', models.TextField(max_length=2000, null=True)), + ('image', models.JSONField(default=dict)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketcontent_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketcontent_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Ticket', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('ticket_id', models.BigIntegerField(default=0)), + ('state', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_createdby', to=settings.AUTH_USER_MODEL)), + ('customer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_customer', to='authentication.systemuserprofile')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_modifiedby', to=settings.AUTH_USER_MODEL)), + ('operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_operator', to='authentication.systemuserprofile')), + ('question', models.ManyToManyField(related_name='ticket_question', to='ticket.Question')), + ('respond', models.ManyToManyField(related_name='ticket_respond', to='ticket.Answer')), + ('support_unit', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_unit', to='ticket.supportunit')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='question', + name='content', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='questioner_content', to='ticket.ticketcontent'), + ), + migrations.AddField( + model_name='question', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='question_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='question', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='question_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='question', + name='questioner', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='questioner', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='answer', + name='content', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_content', to='ticket.ticketcontent'), + ), + migrations.AddField( + model_name='answer', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='answer', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='answer', + name='question', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer_question', to='ticket.question'), + ), + migrations.AddField( + model_name='answer', + name='responder', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answer', to='authentication.systemuserprofile'), + ), + ] diff --git a/ticket/migrations/0002_auto_20240612_0954.py b/ticket/migrations/0002_auto_20240612_0954.py new file mode 100644 index 0000000..793e16d --- /dev/null +++ b/ticket/migrations/0002_auto_20240612_0954.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2024-06-12 09:54 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0035_auto_20240612_0954'), + ('ticket', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='answer', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='question', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='supportunit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='ticket', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='ticketcontent', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.CreateModel( + name='TicketSupport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('userlocation', models.CharField(max_length=250, null=True)), + ('title', models.CharField(max_length=100, null=True)), + ('picture', models.CharField(max_length=250, null=True)), + ('text', models.TextField(null=True)), + ('ticket_id', models.BigIntegerField(default=0)), + ('state', models.CharField(default='open', max_length=100)), + ('type', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_support', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/ticket/migrations/0003_alter_ticketsupport_ticket_id.py b/ticket/migrations/0003_alter_ticketsupport_ticket_id.py new file mode 100644 index 0000000..e124ece --- /dev/null +++ b/ticket/migrations/0003_alter_ticketsupport_ticket_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-06-12 09:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0002_auto_20240612_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='ticketsupport', + name='ticket_id', + field=models.BigIntegerField(default=1), + ), + ] diff --git a/ticket/migrations/0004_auto_20240612_1936.py b/ticket/migrations/0004_auto_20240612_1936.py new file mode 100644 index 0000000..d9a52b8 --- /dev/null +++ b/ticket/migrations/0004_auto_20240612_1936.py @@ -0,0 +1,31 @@ +# Generated by Django 3.2.13 on 2024-06-12 19:36 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0037_auto_20240612_1936'), + ('ticket', '0003_alter_ticketsupport_ticket_id'), + ] + + operations = [ + migrations.RenameField( + model_name='ticketsupport', + old_name='state', + new_name='status', + ), + migrations.CreateModel( + name='MessageSupport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('message', models.TextField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='authentication.systemuserprofile')), + ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='replies', to='ticket.messagesupport')), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticketsupport')), + ], + ), + ] diff --git a/ticket/migrations/0005_messagesupport_sender.py b/ticket/migrations/0005_messagesupport_sender.py new file mode 100644 index 0000000..fbd3dea --- /dev/null +++ b/ticket/migrations/0005_messagesupport_sender.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-06-15 14:07 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0004_auto_20240612_1936'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='sender', + field=models.CharField(default='user', max_length=50), + ), + ] diff --git a/ticket/migrations/0006_auto_20240615_1418.py b/ticket/migrations/0006_auto_20240615_1418.py new file mode 100644 index 0000000..8c49756 --- /dev/null +++ b/ticket/migrations/0006_auto_20240615_1418.py @@ -0,0 +1,35 @@ +# Generated by Django 3.2.13 on 2024-06-15 14:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0005_messagesupport_sender'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketsupport', + name='picture', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='text', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='userlocation', + ), + migrations.AddField( + model_name='messagesupport', + name='picture', + field=models.CharField(max_length=250, null=True), + ), + migrations.AddField( + model_name='messagesupport', + name='user_location', + field=models.CharField(max_length=250, null=True), + ), + ] diff --git a/ticket/migrations/0007_ticketsupport_to_user.py b/ticket/migrations/0007_ticketsupport_to_user.py new file mode 100644 index 0000000..df5189c --- /dev/null +++ b/ticket/migrations/0007_ticketsupport_to_user.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.13 on 2024-08-30 10:34 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0045_auto_20240830_1034'), + ('ticket', '0006_auto_20240615_1418'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='to_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='to_user_ticket', to='authentication.systemuserprofile'), + ), + ] diff --git a/ticket/migrations/0008_messagesupport_send_message.py b/ticket/migrations/0008_messagesupport_send_message.py new file mode 100644 index 0000000..1d72e85 --- /dev/null +++ b/ticket/migrations/0008_messagesupport_send_message.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-08-31 08:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0007_ticketsupport_to_user'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='send_message', + field=models.BooleanField(default=False), + ), + ] diff --git a/ticket/migrations/0009_ticketsupport_is_read.py b/ticket/migrations/0009_ticketsupport_is_read.py new file mode 100644 index 0000000..0be9a5a --- /dev/null +++ b/ticket/migrations/0009_ticketsupport_is_read.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-09-07 10:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0008_messagesupport_send_message'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='is_read', + field=models.BooleanField(default=False), + ), + ] diff --git a/ticket/migrations/0010_remove_ticketsupport_is_read.py b/ticket/migrations/0010_remove_ticketsupport_is_read.py new file mode 100644 index 0000000..31fba7f --- /dev/null +++ b/ticket/migrations/0010_remove_ticketsupport_is_read.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.13 on 2024-09-07 13:47 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0009_ticketsupport_is_read'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketsupport', + name='is_read', + ), + ] diff --git a/ticket/migrations/0011_ticketsupport_last_message.py b/ticket/migrations/0011_ticketsupport_last_message.py new file mode 100644 index 0000000..0efd1bf --- /dev/null +++ b/ticket/migrations/0011_ticketsupport_last_message.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-09-07 13:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0010_remove_ticketsupport_is_read'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='last_message', + field=models.CharField(max_length=100, null=True), + ), + ] diff --git a/ticket/migrations/0012_auto_20240907_1417.py b/ticket/migrations/0012_auto_20240907_1417.py new file mode 100644 index 0000000..f3bbc0a --- /dev/null +++ b/ticket/migrations/0012_auto_20240907_1417.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.13 on 2024-09-07 14:17 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0011_ticketsupport_last_message'), + ] + + operations = [ + migrations.RemoveField( + model_name='messagesupport', + name='user_location', + ), + migrations.RemoveField( + model_name='ticketsupport', + name='type', + ), + ] diff --git a/ticket/migrations/0013_ticketpermission.py b/ticket/migrations/0013_ticketpermission.py new file mode 100644 index 0000000..c5f9bd6 --- /dev/null +++ b/ticket/migrations/0013_ticketpermission.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.13 on 2024-09-10 13:12 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('ticket', '0012_auto_20240907_1417'), + ] + + operations = [ + migrations.CreateModel( + name='TicketPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('from_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='from_role', to='auth.group')), + ('to_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='to_role', to='auth.group')), + ], + ), + ] diff --git a/ticket/migrations/0014_auto_20240911_0853.py b/ticket/migrations/0014_auto_20240911_0853.py new file mode 100644 index 0000000..573ed01 --- /dev/null +++ b/ticket/migrations/0014_auto_20240911_0853.py @@ -0,0 +1,32 @@ +# Generated by Django 3.2.13 on 2024-09-11 08:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('ticket', '0013_ticketpermission'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketpermission', + name='from_role', + ), + migrations.RemoveField( + model_name='ticketpermission', + name='to_role', + ), + migrations.AddField( + model_name='ticketpermission', + name='role', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='ticketpermission', + name='roles', + field=models.ManyToManyField(null=True, related_name='to_role', to='auth.Group'), + ), + ] diff --git a/ticket/migrations/0015_auto_20240912_1105.py b/ticket/migrations/0015_auto_20240912_1105.py new file mode 100644 index 0000000..ff85c6a --- /dev/null +++ b/ticket/migrations/0015_auto_20240912_1105.py @@ -0,0 +1,34 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('authentication', '0047_auto_20240912_1105'), + ('ticket', '0014_auto_20240911_0853'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='to_role', + field=models.ManyToManyField(null=True, related_name='to_role_ticket', to='auth.Group'), + ), + migrations.AddField( + model_name='ticketsupport', + name='type_ticket', + field=models.CharField(default='single', max_length=100), + ), + migrations.RemoveField( + model_name='ticketsupport', + name='to_user', + ), + migrations.AddField( + model_name='ticketsupport', + name='to_user', + field=models.ManyToManyField(null=True, related_name='to_user_ticket', to='authentication.SystemUserProfile'), + ), + ] diff --git a/ticket/migrations/0016_ticketsupport_picture.py b/ticket/migrations/0016_ticketsupport_picture.py new file mode 100644 index 0000000..4aeea4d --- /dev/null +++ b/ticket/migrations/0016_ticketsupport_picture.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0015_auto_20240912_1105'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='picture', + field=models.CharField(max_length=250, null=True), + ), + ] diff --git a/ticket/migrations/0017_auto_20240912_1118.py b/ticket/migrations/0017_auto_20240912_1118.py new file mode 100644 index 0000000..21fab76 --- /dev/null +++ b/ticket/migrations/0017_auto_20240912_1118.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0048_auto_20240912_1118'), + ('auth', '0012_alter_user_first_name_max_length'), + ('ticket', '0016_ticketsupport_picture'), + ] + + operations = [ + migrations.AlterField( + model_name='ticketpermission', + name='roles', + field=models.ManyToManyField(related_name='to_role', to='auth.Group'), + ), + migrations.AlterField( + model_name='ticketsupport', + name='to_role', + field=models.ManyToManyField(related_name='to_role_ticket', to='auth.Group'), + ), + migrations.AlterField( + model_name='ticketsupport', + name='to_user', + field=models.ManyToManyField(related_name='to_user_ticket', to='authentication.SystemUserProfile'), + ), + ] diff --git a/ticket/migrations/0018_auto_20240912_1258.py b/ticket/migrations/0018_auto_20240912_1258.py new file mode 100644 index 0000000..ea654d0 --- /dev/null +++ b/ticket/migrations/0018_auto_20240912_1258.py @@ -0,0 +1,24 @@ +# Generated by Django 3.2.13 on 2024-09-12 12:58 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0017_auto_20240912_1118'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='parent', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='ticket.ticketsupport'), + ), + migrations.AddField( + model_name='ticketsupport', + name='read_only', + field=models.BooleanField(default=True), + ), + ] diff --git a/ticket/migrations/0019_remove_ticketsupport_picture.py b/ticket/migrations/0019_remove_ticketsupport_picture.py new file mode 100644 index 0000000..0fc190c --- /dev/null +++ b/ticket/migrations/0019_remove_ticketsupport_picture.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.13 on 2024-09-14 09:26 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0018_auto_20240912_1258'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketsupport', + name='picture', + ), + ] diff --git a/ticket/migrations/0020_ticketsupport_role.py b/ticket/migrations/0020_ticketsupport_role.py new file mode 100644 index 0000000..ed27f1a --- /dev/null +++ b/ticket/migrations/0020_ticketsupport_role.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-09-14 09:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0019_remove_ticketsupport_picture'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='role', + field=models.CharField(max_length=100, null=True), + ), + ] diff --git a/ticket/migrations/0021_messagesupport_last_seen.py b/ticket/migrations/0021_messagesupport_last_seen.py new file mode 100644 index 0000000..5cdc4dc --- /dev/null +++ b/ticket/migrations/0021_messagesupport_last_seen.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-09-14 10:56 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0020_ticketsupport_role'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='last_seen', + field=models.DateTimeField(null=True), + ), + ] diff --git a/ticket/migrations/0022_auto_20240917_0951.py b/ticket/migrations/0022_auto_20240917_0951.py new file mode 100644 index 0000000..50c9ac9 --- /dev/null +++ b/ticket/migrations/0022_auto_20240917_0951.py @@ -0,0 +1,22 @@ +# Generated by Django 3.2.13 on 2024-09-17 09:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0021_messagesupport_last_seen'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketsupport', + name='id', + ), + migrations.AlterField( + model_name='ticketsupport', + name='ticket_id', + field=models.AutoField(primary_key=True, serialize=False), + ), + ] \ No newline at end of file diff --git a/ticket/migrations/0023_auto_20241228_0919.py b/ticket/migrations/0023_auto_20241228_0919.py new file mode 100644 index 0000000..443c45c --- /dev/null +++ b/ticket/migrations/0023_auto_20241228_0919.py @@ -0,0 +1,20 @@ +# Generated by Django 3.2.13 on 2024-12-28 09:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0022_auto_20240917_0951'), + ] + + operations = [ + migrations.RemoveField( + model_name='messagesupport', + name='ticket', + ), + migrations.DeleteModel( + name='TicketSupport', + ), + ] diff --git a/ticket/migrations/0024_ticketsupport.py b/ticket/migrations/0024_ticketsupport.py new file mode 100644 index 0000000..dd95db4 --- /dev/null +++ b/ticket/migrations/0024_ticketsupport.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2024-12-28 09:26 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('auth', '0012_alter_user_first_name_max_length'), + ('authentication', '0054_auto_20241228_0926'), + ('ticket', '0023_auto_20241228_0919'), + ] + + operations = [ + migrations.CreateModel( + name='TicketSupport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=100, null=True)), + ('ticket_id', models.IntegerField(null=True, unique=True)), + ('status', models.CharField(default='open', max_length=100)), + ('last_message', models.CharField(max_length=100, null=True)), + ('type_ticket', models.CharField(default='single', max_length=100)), + ('read_only', models.BooleanField(default=True)), + ('role', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticketsupport_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='ticket.ticketsupport')), + ('to_role', models.ManyToManyField(related_name='to_role_ticket', to='auth.Group')), + ('to_user', models.ManyToManyField(related_name='to_user_ticket', to='authentication.SystemUserProfile')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_support', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/ticket/migrations/0025_messagesupport_ticket.py b/ticket/migrations/0025_messagesupport_ticket.py new file mode 100644 index 0000000..602efaa --- /dev/null +++ b/ticket/migrations/0025_messagesupport_ticket.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2024-12-28 09:31 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0024_ticketsupport'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='ticket', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='ticket.ticketsupport'), + ), + ] diff --git a/ticket/migrations/0026_messagesupport_file.py b/ticket/migrations/0026_messagesupport_file.py new file mode 100644 index 0000000..582a85c --- /dev/null +++ b/ticket/migrations/0026_messagesupport_file.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-12-29 21:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0025_messagesupport_ticket'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='file', + field=models.TextField(null=True), + ), + ] diff --git a/ticket/migrations/0027_ticketsupport_unread_message.py b/ticket/migrations/0027_ticketsupport_unread_message.py new file mode 100644 index 0000000..ce514d6 --- /dev/null +++ b/ticket/migrations/0027_ticketsupport_unread_message.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2024-12-31 21:32 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0026_messagesupport_file'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='unread_message', + field=models.BooleanField(default=False), + ), + ] diff --git a/ticket/migrations/0028_messagesupport_read_by.py b/ticket/migrations/0028_messagesupport_read_by.py new file mode 100644 index 0000000..d96394d --- /dev/null +++ b/ticket/migrations/0028_messagesupport_read_by.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2025-01-18 14:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0056_auto_20250118_1418'), + ('ticket', '0027_ticketsupport_unread_message'), + ] + + operations = [ + migrations.AddField( + model_name='messagesupport', + name='read_by', + field=models.ManyToManyField(blank=True, related_name='read_messages', to='authentication.SystemUserProfile'), + ), + ] diff --git a/ticket/migrations/0029_auto_20250126_2046.py b/ticket/migrations/0029_auto_20250126_2046.py new file mode 100644 index 0000000..175a168 --- /dev/null +++ b/ticket/migrations/0029_auto_20250126_2046.py @@ -0,0 +1,30 @@ +# Generated by Django 3.2.13 on 2025-01-26 20:46 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0058_auto_20250126_2046'), + ('ticket', '0028_messagesupport_read_by'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='is_referred', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='ticketsupport', + name='referred_by', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='referred_by_me', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='ticketsupport', + name='referred_to', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='referred_tickets', to='authentication.systemuserprofile'), + ), + ] diff --git a/ticket/migrations/0030_auto_20250126_2122.py b/ticket/migrations/0030_auto_20250126_2122.py new file mode 100644 index 0000000..ea5c9bd --- /dev/null +++ b/ticket/migrations/0030_auto_20250126_2122.py @@ -0,0 +1,29 @@ +# Generated by Django 3.2.13 on 2025-01-26 21:22 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0059_auto_20250126_2122'), + ('ticket', '0029_auto_20250126_2046'), + ] + + operations = [ + migrations.RemoveField( + model_name='ticketsupport', + name='referred_to', + ), + migrations.AddField( + model_name='ticketsupport', + name='referred_to', + field=models.ManyToManyField(related_name='referred_tickets', to='authentication.SystemUserProfile'), + ), + migrations.AlterField( + model_name='ticketsupport', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_support', to='authentication.systemuserprofile'), + ), + ] diff --git a/ticket/migrations/0031_ticketsupport_referred_date.py b/ticket/migrations/0031_ticketsupport_referred_date.py new file mode 100644 index 0000000..49a58e9 --- /dev/null +++ b/ticket/migrations/0031_ticketsupport_referred_date.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-02-01 12:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0030_auto_20250126_2122'), + ] + + operations = [ + migrations.AddField( + model_name='ticketsupport', + name='referred_date', + field=models.DateTimeField(auto_now=True, null=True), + ), + ] diff --git a/ticket/migrations/0032_ticketclosepermission.py b/ticket/migrations/0032_ticketclosepermission.py new file mode 100644 index 0000000..28e7bc9 --- /dev/null +++ b/ticket/migrations/0032_ticketclosepermission.py @@ -0,0 +1,21 @@ +# Generated by Django 3.2.13 on 2025-05-25 09:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ticket', '0031_ticketsupport_referred_date'), + ] + + operations = [ + migrations.CreateModel( + name='TicketClosePermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('active', models.BooleanField(default=False)), + ('day', models.SmallIntegerField(default=1)), + ], + ), + ] diff --git a/ticket/migrations/__init__.py b/ticket/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/ticket/models.py b/ticket/models.py new file mode 100644 index 0000000..e0cf9c2 --- /dev/null +++ b/ticket/models.py @@ -0,0 +1,190 @@ +from django.db import models +from authentication.models import ( + SystemUserProfile, + BaseModel, + Group +) +from panel.models import ProvinceOperator + + +# Create your models here. + +class Ticket(BaseModel): + customer = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name='ticket_customer', + null=True + ) + operator = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name='ticket_operator', + null=True + ) + question = models.ManyToManyField( + 'Question', + related_name="ticket_question", + ) + respond = models.ManyToManyField( + 'Answer', + related_name="ticket_respond" + ) + support_unit = models.ForeignKey( + 'SupportUnit', + on_delete=models.CASCADE, + related_name="ticket_unit", + null=True + ) + ticket_id = models.BigIntegerField(default=0) + state = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Ticket, self).save(*args, **kwargs) + + +class TicketContent(BaseModel): + title = models.CharField(max_length=200, null=True) + content = models.TextField(max_length=2000, null=True) + image = models.JSONField(default=dict) + + def save(self, *args, **kwargs): + super(TicketContent, self).save(*args, **kwargs) + + +class Question(BaseModel): + questioner = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="questioner", + null=True + ) + content = models.ForeignKey( + TicketContent, + on_delete=models.CASCADE, + related_name="questioner_content" + ) + state = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Question, self).save(*args, **kwargs) + + +class Answer(BaseModel): + responder = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="answer", + null=True + ) + question = models.ForeignKey( + Question, + on_delete=models.CASCADE, + related_name='answer_question', + null=True + ) + content = models.ForeignKey( + TicketContent, + on_delete=models.CASCADE, + related_name='answer_content', + null=True + ) + state = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Answer, self).save(*args, **kwargs) + + +class SupportUnit(BaseModel): + name = models.CharField(max_length=100, null=True) + unit = models.ForeignKey( + Group, + on_delete=models.CASCADE, + related_name="support_unit", + null=True + ) + + def save(self, *args, **kwargs): + super(SupportUnit, self).save(*args, **kwargs) + + +class TicketSupport(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.SET_NULL, + related_name='ticket_support', + null=True + ) + referred_to = models.ManyToManyField( + SystemUserProfile, + related_name='referred_tickets', + ) + referred_by = models.ForeignKey( + SystemUserProfile, + on_delete=models.SET_NULL, + related_name='referred_by_me', + null=True, + ) + to_user=models.ManyToManyField( + SystemUserProfile, + related_name='to_user_ticket', + ) + + to_role = models.ManyToManyField( + Group, + related_name='to_role_ticket', + ) + + parent=models.ForeignKey('TicketSupport',on_delete=models.CASCADE,null=True) + title = models.CharField(max_length=100, null=True) + ticket_id = models.IntegerField(unique=True, null=True) + status = models.CharField(max_length=100, default='open') + last_message = models.CharField(max_length=100, null=True) + type_ticket = models.CharField(default='single',max_length=100) + read_only = models.BooleanField(default=True) + role = models.CharField(max_length=100, null=True) + unread_message=models.BooleanField(default=False) + is_referred = models.BooleanField(default=False) + referred_date = models.DateTimeField(auto_now=True,null=True) + + + def save(self, *args, **kwargs): + if not self.ticket_id: + last_ticket = TicketSupport.objects.order_by('-ticket_id').first() + self.ticket_id = last_ticket.ticket_id + 1 if last_ticket else 1 + super(TicketSupport, self).save(*args, **kwargs) + + +class MessageSupport(models.Model): + ticket = models.ForeignKey(TicketSupport, related_name='messages', on_delete=models.CASCADE,null=True) + created_by = models.ForeignKey(SystemUserProfile, on_delete=models.CASCADE) + parent = models.ForeignKey('self', null=True, blank=True, related_name='replies', on_delete=models.CASCADE) + message = models.TextField() + created_at = models.DateTimeField(auto_now_add=True) + sender = models.CharField(max_length=50,default='user') + picture = models.CharField(max_length=250, null=True) + send_message = models.BooleanField(default=False) + last_seen=models.DateTimeField(null=True) + file=models.TextField( null=True) + read_by = models.ManyToManyField(SystemUserProfile, related_name='read_messages', blank=True) + + + + def save(self, *args, **kwargs): + super(MessageSupport,self).save(*args, **kwargs) + + +class TicketPermission(models.Model): + role=models.CharField(max_length=200,null=True) + roles=models.ManyToManyField(Group,related_name='to_role') + + def save(self, *args, **kwargs): + super(TicketPermission,self).save(*args, **kwargs) + + +class TicketClosePermission(models.Model): + active = models.BooleanField(default=False) + day = models.SmallIntegerField(default=1) + + def save(self, *args, **kwargs): + super(TicketClosePermission, self).save(*args, **kwargs) diff --git a/ticket/operator_views.py b/ticket/operator_views.py new file mode 100644 index 0000000..e993040 --- /dev/null +++ b/ticket/operator_views.py @@ -0,0 +1,117 @@ +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from .models import ( + Ticket, + TicketContent, + Answer, + Question, + SupportUnit, + Group, + SystemUserProfile +) +from .serializers import ( + TicketSerializer, + TicketContentSerializer, + TicketAnswerSerializer, + TicketQuestionSerializer, + SupportUnitSerializer +) +from rest_framework.response import Response +from .helper import upload_listed_image +from rest_framework import status +from datetime import datetime + + +class OperatorTicketViewSet(viewsets.ModelViewSet): + queryset = Ticket.objects.all() + serializer_class = TicketSerializer + permission_classes = [TokenHasReadWriteScope] + + def ticket_by_flag(self, request, state): + ticket_list = [] + roles = SystemUserProfile.objects.get(user=request.user).role.all() + if state is not None: + ticket = self.queryset.filter(state=state) + else: + ticket = self.queryset.all() + for item in ticket: + for role in roles: + if item.support_unit.unit == role: + ticket_list.append(item) + return ticket_list + + def list(self, request, *args, **kwargs): + # get user object + user = SystemUserProfile.objects.get(user=request.user) + + # different style of ticket information + if 'pending' in request.GET: + ticket_list = self.ticket_by_flag(request=request, state='pending') + serializer = self.serializer_class(ticket_list, many=True) + elif 'responded' in request.GET: + ticket = self.queryset.filter(operator=user, state='responded') + serializer = self.serializer_class(ticket, many=True) + elif 'closed' in request.GET: + ticket = self.queryset.filter(operator=user, state='closed') + serializer = self.serializer_class(ticket, many=True) + elif 'all' in request.GET: + ticket_list = self.ticket_by_flag(request=request, state=None) + serializer = self.serializer_class(ticket_list, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + def retrieve(self, request, *args, **kwargs): + ticket = self.queryset.get(key=request.data['key']) + serializer = self.serializer_class(ticket) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object + request.data.pop('ticket_key') + + # get question object + # question = Question.objects.get(key=request.data['question_key']) + # request.data.pop('question_key') + question = ticket.question.all().last() + + # create list of images + req = upload_listed_image(req=request, field='image') + + # create content object information + content_serializer = TicketContentSerializer(data=req.data) + if content_serializer.is_valid(): + content_obj = content_serializer.create(validated_data=req.data) + + # create responder object information + answer = Answer( + responder=SystemUserProfile.objects.get(user=request.user), + content=content_obj, + question=question + ) + answer.save() + + # set respond for ticket questioner + ticket.operator = SystemUserProfile.objects.get(user=request.user) + ticket.state = 'responded' + ticket.save() + ticket.respond.add(answer) + + serializer = self.serializer_class(ticket) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + ticket = self.queryset.get(key=request.data['ticket_key']) # contains ticket object + request.data.pop('ticket_key') + + # send ticket object to serializer for update + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + ticket_updated = serializer.update(validated_data=request.data, instance=ticket) + serializer = self.serializer_class(ticket_updated) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors) + + def destroy(self, request, *args, **kwargs): + pass diff --git a/ticket/serializers.py b/ticket/serializers.py new file mode 100644 index 0000000..894d0cc --- /dev/null +++ b/ticket/serializers.py @@ -0,0 +1,163 @@ +from rest_framework import serializers + +from authentication.models import SystemUserProfile +from .models import ( + Ticket, + TicketContent, + Question, + Answer, + SupportUnit, TicketSupport, MessageSupport, TicketPermission, TicketClosePermission +) +from authentication.serializer.serializer import ( + SystemUserProfileSerializer, + GroupSerializer, SystemUserProfileBaseInfoForTicketSerializer +) + + +class TicketContentSerializer(serializers.ModelSerializer): + class Meta: + model = TicketContent + exclude = ( + 'id', + 'modify_date', + 'created_by', + 'modified_by', + 'trash', + ) + + +class TicketQuestionSerializer(serializers.ModelSerializer): + content = TicketContentSerializer(required=False) + + class Meta: + model = Question + fields = ( + 'key', + 'content' + ) + + +class TicketAnswerSerializer(serializers.ModelSerializer): + content = TicketContentSerializer(required=False) + + # question = TicketQuestionSerializer(required=False) + + class Meta: + model = Answer + fields = ( + 'key', + 'content', + # 'question' + ) + + +class SupportUnitSerializer(serializers.ModelSerializer): + unit = GroupSerializer(required=False) + + class Meta: + model = SupportUnit + fields = ( + 'unit', + ) + + +class TicketSerializer(serializers.ModelSerializer): + customer = SystemUserProfileSerializer(required=False) + operator = SystemUserProfileSerializer(required=False) + support_unit = SupportUnitSerializer(required=False) + # question = TicketQuestionSerializer(required=False, many=True) + # respond = TicketAnswerSerializer(required=False, many=True) + title = serializers.SerializerMethodField('get_title') + data = serializers.SerializerMethodField('get_responds') + + class Meta: + model = Ticket + exclude = ( + 'id', + 'created_by', + 'modified_by', + 'trash', + 'question', + 'respond', + ) + + def get_title(self, instance): + title = instance.question.all() + title = title[0].content.title + return title + + def get_responds(self, instance): + data = [] + for i in instance.question.all(): + question = TicketQuestionSerializer(i).data + question['type'] = 'customer' + data.append(question) + for j in instance.respond.filter(question=i): + answer = TicketAnswerSerializer(j).data + answer['type'] = 'operator' + data.append(answer) + return data + + def update(self, instance, validated_data): + instance.state = validated_data.get('state', instance.state) + instance.save() + return instance + + +class SystemUserProfileForTicketPermissionSerializer(serializers.ModelSerializer): + class Meta: + model = SystemUserProfile + fields=['key','fullname','mobile'] + + +class TicketClosePermissionSerializer(serializers.ModelSerializer): + class Meta: + model = TicketClosePermission + fields = '__all__' + + +class TicketSupportSerializer(serializers.ModelSerializer): + user = SystemUserProfileForTicketPermissionSerializer(read_only=True) + to_user = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True) + referred_by = SystemUserProfileForTicketPermissionSerializer(read_only=True) + referred_to = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True) + to_role = GroupSerializer(read_only=True,many=True) + + class Meta: + model = TicketSupport + fields = '__all__' + + +class MessageSupportSerializer(serializers.ModelSerializer): + created_by = SystemUserProfileForTicketPermissionSerializer(read_only=True) + parent = SystemUserProfileForTicketPermissionSerializer(read_only=True) + read_by = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True) + ticket= TicketSupportSerializer(read_only=True) + + class Meta: + model = MessageSupport + fields = '__all__' + + +class MessageSupportWithoutReadBySerializer(serializers.ModelSerializer): + created_by = SystemUserProfileForTicketPermissionSerializer(read_only=True) + parent = SystemUserProfileForTicketPermissionSerializer(read_only=True) + # read_by = SystemUserProfileForTicketPermissionSerializer(read_only=True,many=True) + + class Meta: + model = MessageSupport + exclude = ('read_by',) + depth=1 + +class TicketPermissionSerializer(serializers.ModelSerializer): + roles=serializers.SerializerMethodField() + + class Meta: + model = TicketPermission + fields = ['id','role','roles'] + + def get_roles(self,obj): + permissions = TicketPermission.objects.filter(role=obj.role).prefetch_related('roles') + roles = [role.name for permission in permissions for role in permission.roles.all()] + return roles + diff --git a/ticket/tests.py b/ticket/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/ticket/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/ticket/urls.py b/ticket/urls.py new file mode 100644 index 0000000..a36aad4 --- /dev/null +++ b/ticket/urls.py @@ -0,0 +1,22 @@ +from django.urls import include, path +from rest_framework.routers import DefaultRouter +from . import customer_views, operator_views,views +from .views import get_num_message, closed_unread_ticket, get_unread_ticket_for_dashboard + +router = DefaultRouter() +router.register('create_ticket', customer_views.CustomerTicketViewSet, basename='create_ticket') +router.register('respond', operator_views.OperatorTicketViewSet, basename='respond') +router.register(r'ticket', views.TicketSupportViewSet, basename='ticket') +router.register(r'message', views.MessageSupportViewSet, basename='message') +router.register(r'message-for-role', views.MessageForRoleViewSet, basename='message_for_role') +router.register(r'ticket-permission', views.TicketPermissionViewSet, basename='ticket-permission') +router.register(r'get-user-from-role', views.GetUserFromRoleViewSet, basename='get_user_from_role') +router.register(r'ticket-close-permission', views.TicketClosePermissionViewSet, basename='ticket-close-permission') + + +urlpatterns = [ + path('', include(router.urls)), + path('get_num_message/', get_num_message), + path('closed_unread_ticket/', closed_unread_ticket), + path('get_unread_ticket_for_dashboard/', get_unread_ticket_for_dashboard), +] diff --git a/ticket/views.py b/ticket/views.py new file mode 100644 index 0000000..b6f740d --- /dev/null +++ b/ticket/views.py @@ -0,0 +1,512 @@ +import datetime +import random +import string + +import requests +from django.db.models import Q, Count +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework import status +from rest_framework import viewsets +from rest_framework.decorators import api_view, permission_classes +from rest_framework.pagination import PageNumberPagination +from rest_framework.permissions import AllowAny +from rest_framework.response import Response + +from authentication.models import SystemUserProfile, Group +from authentication.sms_management import ticket_answered +from helper_eata import token, chat_id +from panel.filterset import TicketsFilterSet +from panel.helper import build_query +from ticket.models import TicketSupport, MessageSupport, TicketPermission, TicketClosePermission +from ticket.serializers import TicketSupportSerializer, MessageSupportSerializer, TicketPermissionSerializer, \ + SystemUserProfileForTicketPermissionSerializer, MessageSupportWithoutReadBySerializer, \ + TicketClosePermissionSerializer +from .bucket import upload_to_liara +from .helper import send_image_to_server + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +def update_unread_ticket(tickets, user): + user_roles = list(user.role.all()) + + unread_ticket_ids = MessageSupport.objects.filter( + Q(ticket__user=user) | + Q(ticket__to_user=user) | + Q(ticket__to_role__in=user_roles) | + Q(ticket__referred_by=user) | + Q(ticket__referred_to=user.id), + ~Q(created_by=user), + ~Q(read_by=user.id), + ticket__in=tickets + ).values_list('ticket_id', flat=True).distinct() + + unread_set = set(unread_ticket_ids) + + for ticket in tickets: + ticket.unread_message = ticket.id in unread_set + + TicketSupport.objects.bulk_update(tickets, ['unread_message']) + + +class TicketSupportViewSet(viewsets.ModelViewSet): + queryset = TicketSupport.objects.filter(trash=False).select_related( + 'user', 'referred_by' + ).prefetch_related( + 'to_role', 'referred_to', 'to_user').order_by('-unread_message', '-create_date') + serializer_class = TicketSupportSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filterset_class = TicketsFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + role_list = list(user.role.values_list('id', flat=True).distinct()) + role_check = any(role in ['AdminX', 'SuperAdmin'] for role in user.role.values_list('name', flat=True)) + type_param = request.GET.get('type', None) + status = request.GET.get('status', 'open') + base_filter = Q(user=user) | Q(to_user=user.id) | Q(to_role__in=role_list) | Q(referred_to=user.id) | Q( + referred_by=user) + + if role_check: + if type_param: + query = self.queryset.filter(type_ticket=type_param, + status=status).distinct() if type_param else self.queryset + else: + query = self.queryset.filter(status=status).distinct() + + else: + if type_param: + query = self.queryset.filter(base_filter, type_ticket=type_param, status=status).distinct() + else: + query = self.queryset.filter(base_filter, status=status) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + query = query.filter( + build_query(self.filterset_class, value) + ) + update_unread_ticket(query, user) + query = query.order_by('-unread_message', '-create_date') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + page = self.paginate_queryset(query) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = self.serializer_class(query, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + type_ticket = request.data.get('type_ticket') + read_only = request.data.get('read_only') + to_user_data = request.data.get('to_user') + if request.data.get('image') is not None: + image = send_image_to_server(request.data['image']) + else: + image = None + if request.FILES.get('file'): + file_obj = request.FILES.get('file') + file_url = upload_to_liara(file_obj, file_obj.name) + else: + file_url = None + if to_user_data: + to_users = SystemUserProfile.objects.filter(key__in=request.data['to_user']) + ticket = TicketSupport( + user=user, + title=request.data['title'], + status='open', + read_only=read_only, + type_ticket=type_ticket, + role=request.data.get('role'), + ) + ticket.save() + ticket.to_user.set(to_users) + + else: + to_role = Group.objects.filter(name__in=request.data.get('to_role')) + if ((SystemUserProfile.objects.filter(trash=False, role__in=to_role).count() < 2)): + return Response({'result': 'برای نقش انتخابی، لطفاً تیکت شخصی ثبت کنید!'}, + status=status.HTTP_403_FORBIDDEN) + ticket = TicketSupport( + user=user, + title=request.data['title'], + status='open', + read_only=read_only, + type_ticket=type_ticket, + role=request.data.get('role'), + ) + ticket.save() + ticket.to_role.set(to_role) + msg = MessageSupport( + ticket=ticket, + message=request.data['message'], + created_by=user, + sender=request.data.get('sender'), + picture=image, + file=file_url) + msg.save() + return Response({'msg': 'با موفقیت انجام شد.'}, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + ticket_id = request.data.get('ticket') + ticket = self.queryset.filter(ticket_id=int(ticket_id)).first() + + if ticket: + if 'referred_to' in request.data: + referred_to = SystemUserProfile.objects.filter(key__in=request.data['referred_to']) + ticket.referred_by = SystemUserProfile.objects.get(user=request.user) + ticket.status = 'open' + ticket.is_referred = True + ticket.save() + referrer_name = [] + for user in referred_to: + if not ticket.referred_to.filter(id=user.id).exists(): + ticket.referred_to.add(user) + referrer_name.append(user.fullname) + if len(referrer_name) > 1: + names = ' و '.join(referrer_name) + else: + names = referrer_name[0] if referrer_name else '' + if referrer_name: + MessageSupport.objects.create( + ticket=ticket, + message=f"تیکت شماره {ticket.ticket_id} به ({names}) ارجاع داده شد.", + created_by=SystemUserProfile.objects.get(user=request.user), + sender='Admin' + ) + return Response({'message': 'تیکت با موفقیت ارجاع داده شد.'}, status=200) + + else: + ticket.status = 'closed' + ticket.save() + return Response({'result': 'تیکت با موفقیت پایان یافت.'}, status=status.HTTP_200_OK) + return Response({'result': 'تیکت وجود ندارد!'}, status=status.HTTP_400_BAD_REQUEST) + + +class MessageSupportViewSet(viewsets.ModelViewSet): + queryset = MessageSupport.objects.all().select_related('ticket').order_by('created_at') + serializer_class = MessageSupportSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + ticket_id = request.GET.get('ticket') + role_list = list(user.role.values_list('id', flat=True).distinct()) + role_check = any( + role in ['AdminX', 'SuperAdmin', 'ProvinceOperator'] for role in user.role.values_list('name', flat=True)) + query = self.queryset.filter(ticket__ticket_id=int(ticket_id)).order_by('-created_at') + if query.filter(Q(ticket__user=user) | Q(ticket__to_user=user.id) | Q(ticket__to_role__in=role_list) | Q( + ticket__referred_by=user) | Q(ticket__referred_to=user.id)).exists(): + unseen_messages = query.filter(~Q(created_by=user), last_seen__isnull=True) + unseen_messages.update(last_seen=datetime.datetime.now()) + + for message in query.filter(~Q(created_by=user)): + if not message.read_by.filter(id=user.id).exists(): + message.read_by.add(user) + + query = query.defer('message') + if role_check: + srz_data = self.serializer_class(query, many=True).data + else: + srz_data = MessageSupportWithoutReadBySerializer(query, many=True).data + return Response(srz_data) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.select_related('user').filter(user=request.user).first() + ticket_id = request.data.get('ticket') + ticket = TicketSupport.objects.get(ticket_id=int(ticket_id)) + + if ticket.status == 'closed': + return Response({'result': 'این تیکت بسته شده است!'}, status=status.HTTP_403_FORBIDDEN) + + if ticket.read_only == False and ticket.type_ticket == 'public' and ticket.parent is None \ + and ticket.user != user: + new_ticket = TicketSupport( + user=user, + title=ticket.title, + status='open', + read_only=False, + type_ticket='single', + parent=ticket, + last_message=request.data.get('sender'), + role=request.data.get('role'), + ) + new_ticket.save() + new_ticket.to_user.add(ticket.user) + + msg = MessageSupport( + ticket=new_ticket, + message=request.data.get('message'), + created_by=user, + sender=request.data.get('sender') + ) + else: + msg = MessageSupport( + ticket=ticket, + message=request.data.get('message'), + created_by=user, + sender=request.data.get('sender') + ) + ticket.last_message = request.data.get('sender') + ticket.save() + if request.data['send_message'] == True: + ticket_answered(ticket.user.mobile) + msg.send_message = True + if request.data.get('image') is not None: + # ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + # upload_object_resize(image_data=request.data['image'], bucket_name="profileimagedefault", + # object_name="{0}.jpg".format(str(ran))) + msg.picture = send_image_to_server(request.data['image']) + if request.FILES.get('file'): + file_obj = request.FILES.get('file') + file_url = upload_to_liara(file_obj, file_obj.name) + msg.file = file_url + msg.save() + ser_data = self.serializer_class(msg) + return Response(ser_data.data, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + msg_id = request.data.get('message_id') + instance = self.get_queryset().get(id=msg_id) + request.data.pop('message_id') + serializer = self.get_serializer(instance, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response({'result': "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class MessageForRoleViewSet(viewsets.ModelViewSet): + queryset = MessageSupport.objects.all() + serializer_class = MessageSupportSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + user_sender = SystemUserProfile.objects.get(user=request.user) + if 'role' in request.data.keys(): + to_user = SystemUserProfile.objects.filter(trash=False, role__name__in=request.data['role']) + relations = [ + TicketSupport( + user=user_sender, + title=request.data['title'], + status='open', + to_user=user + ) + for user in to_user + ] + TicketSupport.objects.bulk_create(relations) + + return Response({'msg': 'با موفقیت ارسال شد'}, status=status.HTTP_201_CREATED) + + +class TicketPermissionViewSet(viewsets.ModelViewSet): + queryset = TicketPermission.objects.all() + serializer_class = TicketPermissionSerializer + permission_classes = [AllowAny] + + def create(self, request, *args, **kwargs): + role = request.data['role'] + group = request.data['roles'] + roles = Group.objects.filter(name__in=group) + ticket = TicketPermission.objects.get(role=role) + ticket.roles.set(roles) + ser_data = self.serializer_class(ticket) + return Response(ser_data.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + if 'role' in request.GET: + role = request.GET['role'] + query = self.queryset.get(role=role) + ser_data = self.serializer_class(query).data + return Response(ser_data, status=status.HTTP_200_OK) + else: + query = self.queryset + ser_data = self.serializer_class(query, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class GetUserFromRoleViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileForTicketPermissionSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + role = request.GET['role'] + user = SystemUserProfile.objects.filter(~Q(user=request.user), trash=False, role__name=role, ) + ser_data = self.serializer_class(user, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) + + +class TicketClosePermissionViewSet(viewsets.ModelViewSet): + queryset = TicketClosePermission.objects.all().first() + serializer_class = TicketClosePermissionSerializer + permission_classes = [TokenHasReadWriteScope] + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def get_num_message(request): + user = SystemUserProfile.objects.get(user=request.user) + message = MessageSupport.objects.filter( + Q(ticket__user=user) | Q(ticket__to_user=user) | Q(ticket__to_role__in=user.role.all()) | Q( + ticket__referred_by=user) | Q(ticket__referred_to=user.id) + , ~Q(created_by=user)).exclude(read_by=user.id).values('ticket').annotate( + ticket_count=Count('ticket', distinct=True) + ).distinct() + state = True if message.count() > 0 else False + return Response({ + 'state': state, + 'num': message.count(), + }) + + +# @api_view(["PUT"]) +# @csrf_exempt +# @permission_classes([AllowAny]) +# def FileUploadView(request): +# # queryset = TicketSupport.objects.all() +# # permission_classes = [AllowAny] +# # serializer_class = TicketSupportSerializer +# # +# # def create(self, request, *args, **kwargs): +# file_obj = request.FILES.get('file') +# if not file_obj: +# return Response({"error": "فایلی ارسال نشده است"}, status=status.HTTP_400_BAD_REQUEST) +# +# try: +# file_url = upload_to_liara(file_obj, file_obj.name) +# return Response({"file_url": file_url}, status=status.HTTP_201_CREATED) +# except Exception as e: +# return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +def bot_eitaa_for_bar(): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + data = { + "cookie": "ASP.NET_SessionId=w1jadrzcqgznxugnjee1xrkj; .ASPXAUTH=4CC27FD1BAB0CA729584056577AA51209F731F22CDF4B95F9FEE33AD12F1DFFF960C77B0A237D5733E336195A2CA6DB1C1F2CA2EDCD079EC0B3C3092A2BF1BA8811D7C44263B1E5EB84430C0906024A55D51AF1FE5852F406C358A051715BB9270475D58228F44380D12FA075A4DF0E029220F0C809AEDDDF58FFE9568064DD9D397B038D19DC1757232A92EA63571EA7B47E1706F677528E539301417093B523B6C2BFD340AA33DC32D50E7853E3D14D93924313B9B1EB36320C90A2303BB852841EE0DE1D844B281B4CD6D7E95D593CF2E2F0C3816687C529B7702863F75CD6549F49D346C7C88F22F033C75C357BE9E91AD170A2502731BC03AE2DF09F594417646FE332B8BAB70673E584A23AD45CADC285C554B66FD29DD989F85962891A11C06FC84832DD8FB03933CF26E190601D493B0430A742544B8BC0A8639E4E5788432AA401FAFFD3A1C6793FB24909A992405D07E53B81DF546AB07ED90314735518C37E9291F10E2B723B795B8BB838C2810CE103A4EF893211BFDBB605ADBE0E3B9B35438A5FE3506937D020EC2EF061B6D1E3AAFB3A9A138CC219A4A556CEB6A2E44C18D53C85666A5C0C9663F8314EFD97FFF5C1844C0FEB4362A781E2138785D832EEFD1AEDAD1271C2513A6F4EC1174EF107AC2E9FEFF8A9A111CC6D6189CCC66E93224EE4D30813AAD9DCDE1CFC530B08CB67827C351DCE4C2AFD4E3FB12E85EA0CD6E2D3D4CC8753D74E863A37C5675D82C9977518A942786EF055F0DBFC809B9F9B6A45B269526FC9D8B5E888B1C6E40C6ACE8EB37ED7E1F9F266A018936F3228A3C8E20C1BD869CC657D1CE19FFEA8C8B979DE5077E17AE5FA1F085B3A424C91DA19D3743871A2A9440937B2C4E076EC99AE4DEE1A7AF601448F2F763FC2DF85ED8902287DDD0ED5B9E649A4490900B4BF64F639CDD761326AC08D1B540CBD853B42F556FFB8FD5BC33A54E68125CD20278B191A1896BF955FFA1B4CC5308E12A84003B64B0EE532079563DC334FB9AEB9B742803EBE35C82CA14E5D0D84CA736AB9A2E07EECFF98657561C029ECE3C1249DA843B4236E41BD745E54B1A86ED2CE4EA0FDDBB3B4B2B97A87548B23298283F6D09094F7BC709FAABE59CC84138F83B083EAB15BE0B032481; leggedOut=-" + } + r = requests.post(url='https://pay.rasadyar.net/transporting-chickens/', data=data) + + data = { + 'chat_id': chat_id, + 'text': r.status_code, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse(response.status_code) + + +# def close_ticket_cron_job(): +# ticket=TicketSupport.objects.filter(Q(unread_message=False,read_only=True)|Q(unread_message=True,read_only=False),trash=False,status='open') +# for t in ticket: +# two_day_ago =datetime.datetime.now().date() - datetime.timedelta(days=2) +# if (t.create_date.date() - datetime.datetime.now().date()).days > 2: +# t.status='closed' +# t.to_role=None +# t.title=None +# t.trash=False +# t.create_date=datetime.datetime.now() +# t.save() +# else: +# continue + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def closed_unread_ticket(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + two_day_ago = datetime.datetime.now() - datetime.timedelta(days=2) + ten_day_ago = datetime.datetime.now() - datetime.timedelta(days=10) + tickets = TicketSupport.objects.filter( + trash=False, + status='open', + type_ticket='single' + ) + text_two_day_ago_message = 'به دلیل عدم دریافت پیام جدید در مدت 48 ساعت، این تیکت توسط سامانه به صورت خودکار بسته شد.' + text_ten_day_ago_message = 'به دلیل خوانده نشدن پیام در مدت 10 روز، این تیکت توسط سامانه به صورت خودکار بسته شد.' + for ticket in tickets: + message = MessageSupport.objects.filter(ticket=ticket).last() + if not message: + continue + if message.read_by.exists() and message.last_seen.date() <= two_day_ago.date(): + msg = MessageSupport( + ticket=ticket, + message=text_two_day_ago_message, + created_by=user) + msg.save() + ticket.status = 'closed' + ticket.save() + + if not message.read_by.exists() and message.created_at.date() <= ten_day_ago.date(): + msg = MessageSupport( + ticket=ticket, + message=text_ten_day_ago_message, + created_by=user) + msg.save() + ticket.status = 'closed' + ticket.save() + + return HttpResponse('ok') + + +def closed_unread_ticket_cron(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + two_day_ago = datetime.datetime.now() - datetime.timedelta(days=2) + ten_day_ago = datetime.datetime.now() - datetime.timedelta(days=10) + tickets = TicketSupport.objects.filter( + trash=False, + status='open', + type_ticket='single' + ) + text_two_day_ago_message = 'به دلیل عدم دریافت پیام جدید در مدت 48 ساعت، این تیکت توسط سامانه به صورت خودکار بسته شد.' + # text_ten_day_ago_message = 'به دلیل خوانده نشدن پیام در مدت 10 روز، این تیکت توسط سامانه به صورت خودکار بسته شد.' + for ticket in tickets: + message = MessageSupport.objects.filter(ticket=ticket).last() + if not message: + continue + if message.read_by.exists() and message.last_seen.date() <= two_day_ago.date(): + msg = MessageSupport( + ticket=ticket, + message=text_two_day_ago_message, + created_by=user) + msg.save() + ticket.status = 'closed' + ticket.save() + + # if not message.read_by.exists() and message.created_at.date() <= ten_day_ago.date(): + # msg = MessageSupport( + # ticket=ticket, + # message=text_ten_day_ago_message, + # created_by=user) + # msg.save() + # ticket.status = 'closed' + # ticket.save() + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def get_unread_ticket_for_dashboard(request): + user = SystemUserProfile.objects.get(user=request.user) + role_list = list(user.role.values_list('id', flat=True).distinct()) + base_filter = Q(user=user) | Q(to_user=user.id) | Q(to_role__in=role_list) | Q(referred_to=user.id) | Q( + referred_by=user) + query = TicketSupport.objects.filter(base_filter, status='open',trash=False).select_related( + 'user', 'referred_by' + ).prefetch_related( + 'to_role', 'referred_to', 'to_user').order_by('-create_date') + update_unread_ticket(query, user) + query1 = query.filter(unread_message=True) + ser_data = TicketSupportSerializer(query1, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) \ No newline at end of file

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%0DyrD%_q@6ocGh_p0BUs?{Az| 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 U)(w+L`~cc#XkemWt?L~3Z>SiAG5`Po literal 0 HcmV?d00001 diff --git a/authentication/__init__.py b/authentication/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/admin.py b/authentication/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/authentication/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/authentication/apps.py b/authentication/apps.py new file mode 100644 index 0000000..8bab8df --- /dev/null +++ b/authentication/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class AuthenticationConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'authentication' diff --git a/authentication/arvan_image/arvan_storage.py b/authentication/arvan_image/arvan_storage.py new file mode 100644 index 0000000..6b2f9da --- /dev/null +++ b/authentication/arvan_image/arvan_storage.py @@ -0,0 +1,169 @@ +# توابع مورد نیاز برای اتصال به ای پی آی استوریج آروان +# test +import boto3 +import logging +from botocore.exceptions import ClientError +from django.http import HttpResponse +from PIL import Image +import io +import base64 + +ARVAN_STORAGE_URL = "https://dmstore.s3.ir-thr-at1.arvanstorage.ir/36bba98f-a813-4667-bd60-33aef708bcba.jpg?AWSAccessKeyId=d5739a44-e663-4f43-99f3-13121a62a9e6&Signature=KpBpHBtAS77Y3hHx53g6bmjlGpc%3D&Expires=1651552380" + + +def connect(): + logging.basicConfig(level=logging.INFO) + + try: + s3_resource = boto3.resource( + 's3', + endpoint_url='https://s3.ir-thr-at1.arvanstorage.ir', + aws_access_key_id='b0b563b2-bb60-4faf-b09a-660982e70b00', + aws_secret_access_key='abdcccaadbd3d897b5432f72bc91048940e012ffa4f308ba0fe16f28e3c80e57' + ) + except Exception as exc: + logging.info(exc) + return s3_resource + + +def get_bucket_list(): + s3_resource = connect() + li = [] + try: + for bucket in s3_resource.buckets.all(): + logging.info(f'bucket_name: {bucket.name}') + li.append(bucket.name) + except ClientError as exc: + logging.error(exc) + return li[0] + + +# این تابع رو درتمامی قسمت های سیستم میتونیم برای ذخیره عکس بر روی استوریج آروان استفاده کنیم + +# def upload_object(image_data, bucket_name, object_name): +# resource_connect = connect() +# s3_resource = resource_connect +# bucket = s3_resource.Bucket(bucket_name) +# with open(object_name, "wb") as fh: +# fh.write(base64.standard_b64decode(image_data)) +# with open(object_name, "rb") as fh: +# bucket.put_object( +# ACL='public-read', +# Body=fh, +# Key=object_name +# ) + +def upload_object(image_data, bucket_name, object_name): + resource_connect = connect() + s3_resource = resource_connect + bucket = s3_resource.Bucket(bucket_name) + buffer = io.BytesIO() + imgdata = base64.b64decode(image_data) + img = Image.open(io.BytesIO(imgdata)) + new_img = img.resize((500, 500)) # x, y + new_img.save(buffer, format="PNG") + img_b64 = base64.b64encode(buffer.getvalue()) + with open(object_name, "wb") as fh: + fh.write(base64.standard_b64decode(img_b64)) + # base64.standard_b64decode(image_data) + with open(object_name, "rb") as fh: + bucket.put_object( + ACL='public-read', + Body=fh, + Key=object_name + ) + + + + +def compress_image(image_data, quality): + imgdata = base64.b64decode(image_data) + img = Image.open(io.BytesIO(imgdata)) + buffer = io.BytesIO() + img.save(buffer, format='JPEG', quality=quality) + compressed_data = buffer.getvalue() + img_b64 = base64.b64encode(compressed_data) + return img_b64 + + +def upload_object_resize(image_data, bucket_name, object_name): + resource_connect = connect() + s3_resource = resource_connect + bucket = s3_resource.Bucket(bucket_name) + # compressed_img = compress_image(image_data, quality=200) # تغییر دهید quality به مقدار دلخواه خود + decoded_image_data = base64.b64decode(image_data) + image_stream = io.BytesIO(decoded_image_data) + bucket.put_object( + ACL='public-read', + Body=image_stream, + Key=object_name + ) + + # with open(object_name, "wb") as fh: + # fh.write(base64.standard_b64decode(compressed_img)) + # + # with open(object_name, "rb") as fh: + # bucket.put_object( + # ACL='public-read', + # Body=fh, + # Key=object_name + # ) + + +# def upload_object_resize(image_data, bucket_name, object_name): +# resource_connect = connect() +# s3_resource = resource_connect +# bucket = s3_resource.Bucket(bucket_name) +# buffer = io.BytesIO() +# imgdata = base64.b64decode(image_data) +# img = Image.open(io.BytesIO(imgdata)) +# img.save(buffer, format="PNG") +# img_b64 = base64.b64encode(buffer.getvalue()) +# with open(object_name, "wb") as fh: +# fh.write(base64.standard_b64decode(img_b64)) +# # base64.standard_b64decode(image_data) +# with open(object_name, "rb") as fh: +# bucket.put_object( +# ACL='public-read', +# Body=fh, +# Key=object_name +# ) + +def upload_object_less_size(image_data, bucket_name, object_name): + resource_connect = connect() + s3_resource = resource_connect + bucket = s3_resource.Bucket(bucket_name) + buffer = io.BytesIO() + imgdata = base64.b64decode(image_data) + img = Image.open(io.BytesIO(imgdata)) + # new_img = img.resize((500, 500)) # x, y + img.save(buffer, format="PNG") + img_b64 = base64.b64encode(buffer.getvalue()) + with open(object_name, "wb") as fh: + fh.write(base64.standard_b64decode(img_b64)) + # base64.standard_b64decode(image_data) + with open(object_name, "rb") as fh: + bucket.put_object( + ACL='public-read', + Body=fh, + Key=object_name + ) + + +def upload_object_for_poultry_science(image_data, bucket_name, object_name): + resource_connect = connect() + s3_resource = resource_connect + bucket = s3_resource.Bucket(bucket_name) + buffer = io.BytesIO() + imgdata = base64.b64decode(image_data) + new_img = Image.open(io.BytesIO(imgdata)) + new_img.save(buffer, format="JPEG") + img_b64 = base64.b64encode(buffer.getvalue()) + with open(object_name, "wb") as fh: + fh.write(base64.standard_b64decode(img_b64)) + with open(object_name, "rb") as fh: + bucket.put_object( + ACL='public-read', + Body=fh, + Key=object_name + ) diff --git a/authentication/filterset.py b/authentication/filterset.py new file mode 100644 index 0000000..0bc12d5 --- /dev/null +++ b/authentication/filterset.py @@ -0,0 +1,29 @@ +from url_filter.filtersets import ModelFilterSet +# from url_filter.filtersets import ModelFilterSet +from authentication.models import ( + UserProfile, + SystemUserProfile, ExternalTransaction +) +from panel.models import PoultryRequestExchange + + +# فیلترست مریوط به مدل کاربر (برای قسمت جستجو اطلاعات کاربراستفاده میشود) +class UserProfileFilterSet(ModelFilterSet): + class Meta: + model = UserProfile + + +# فیلترست مریوط به مدل درخواست مرغدار (برای قسمت جستجو درخواست مرغدار استفاده میشود) +class PoultryRequestExchangeFilterSet(ModelFilterSet): + class Meta: + model = PoultryRequestExchange + + +class SystemUserProfileFilteSet(ModelFilterSet): + class Meta: + model = SystemUserProfile + + +class ExternalTransactionFilterSet(ModelFilterSet): + class Meta: + model = ExternalTransaction diff --git a/authentication/healthcheck.py b/authentication/healthcheck.py new file mode 100644 index 0000000..4c079a2 --- /dev/null +++ b/authentication/healthcheck.py @@ -0,0 +1,5 @@ +from django.http import JsonResponse + + +def health_check(request): + return JsonResponse({"status": "ok"}) diff --git a/authentication/helper/__init__.py b/authentication/helper/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/helper/helper.py b/authentication/helper/helper.py new file mode 100644 index 0000000..48a3957 --- /dev/null +++ b/authentication/helper/helper.py @@ -0,0 +1,78 @@ +from django.contrib.auth.models import User +from rest_framework import status +from rest_framework.response import Response +from authentication.models import City, SystemUserProfile, SystemAddress +from authentication.views import ARTA_URL_REGISTER +from panel.admin import PROJECT_API_KEY +from panel.models import Guilds, Wallet +import requests + + +def register_user(group, city_name, mobile, first_name, last_name, national_id, postal_code, address_text): + try: + # Fetch city and related province + city = City.objects.select_related('province').get(name=city_name) + province = city.province + except City.DoesNotExist: + return Response({"result": "شهر یافت نشد"}, status=status.HTTP_400_BAD_REQUEST) + + # Check if user profile exists and if they are associated with a guild + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).last() + if system_profile and Guilds.objects.filter(user=system_profile, trash=False).exists(): + return 'exist' + + # Register a new user if system profile does not exist + if not system_profile: + password = "123456" + registration_data = { + "username": mobile, + "password": password, + "api_key": PROJECT_API_KEY + } + + # Attempt to register the user via ARTA + response = requests.post(ARTA_URL_REGISTER, data=registration_data, verify=False) + if response.status_code != 200: + return None + + + # Create Django user + user = User.objects.create(username=mobile, first_name=first_name, last_name=last_name) + + # Generate base order ID + last_profile = SystemUserProfile.objects.order_by('-base_order').first() + base_order = (last_profile.base_order + 1) if last_profile else 1000 + + # Create system profile + system_profile = SystemUserProfile.objects.create( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=f"{first_name} {last_name}", + user=user, + base_order=base_order, + password=password, + national_id=national_id, + city=city, + province=province + ) + + # Create address for the user + address = SystemAddress.objects.create( + city=city, + province=province, + address=address_text, + postal_code=postal_code + ) + + # Assign role to the user + system_profile.role.add(group) + + # Create wallet for the user + wallet = Wallet.objects.create() + + return { + "system_profile": system_profile, + "address": address, + "wallet": wallet + } diff --git a/authentication/helper/image_services.py b/authentication/helper/image_services.py new file mode 100644 index 0000000..aec5c13 --- /dev/null +++ b/authentication/helper/image_services.py @@ -0,0 +1,21 @@ +from ticket.helper import send_image_to_server + + +def upload_image(req=None, field=None): + if req.data[field] != "": + req.data[field] = send_image_to_server(req.data[field]) + elif req.data[field] == "": + req.data[field] = "empty" + return req + + +def upload_listed_image(req=None, field=None): + image_list = [] + if req.data[field] != []: + for item in req.data[field]: + image_list.append(send_image_to_server(item)) + req.data.pop(field) + req.data[field] = image_list + elif req.data[field] == "": + req.data[field] = "empty" + return req diff --git a/authentication/helper/make_user_gate_way_id.py b/authentication/helper/make_user_gate_way_id.py new file mode 100644 index 0000000..d728fad --- /dev/null +++ b/authentication/helper/make_user_gate_way_id.py @@ -0,0 +1,12 @@ +import string +import random + +from authentication.models import SystemUserProfile +from general_urls import base_user_gate_way_id + +while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)) + res = base_user_gate_way_id + res + if not SystemUserProfile.objects.filter(user_gate_way_id=res).exists(): + break + diff --git a/authentication/helper/refresh.py b/authentication/helper/refresh.py new file mode 100644 index 0000000..13b45fa --- /dev/null +++ b/authentication/helper/refresh.py @@ -0,0 +1,12 @@ +from django.contrib.auth.models import User +from oauth2_provider.models import AccessToken +from datetime import timedelta +from datetime import datetime + + +def refresh(id): + user = User.objects.get(id=id) + # access = AccessToken.objects.filter(user=user).last() + # access.expires = datetime.now() + timedelta(minutes=30) + # access.save() + diff --git a/authentication/log.py b/authentication/log.py new file mode 100644 index 0000000..5d82b71 --- /dev/null +++ b/authentication/log.py @@ -0,0 +1,82 @@ +import time +from functools import wraps + +from authentication.models import Log, SystemUserProfile +import requests + + +def log_function_info(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + start_time = time.time() + response = func(request, *args, **kwargs) + duration = time.time() - start_time + log = Log( + user=request.user, + function_name=func.__name__, + request=request, + response=response, + request_body=request.data, + response_body=response.data, + duration=duration, + status=response.status_code + ) + log.save() + return response + + return wrapper + + +def log_viewset_info(func): + @wraps(func) + def wrapper(viewset, request, *args, **kwargs): + start_time = time.time() + response = func(viewset, request, *args, **kwargs) + duration = time.time() - start_time + log = Log( + user=request.user, + function_name=func.__name__, + request=request, + response=response, + request_body=request.data, + response_body=response.data, + duration=duration, + status=response.status_code + ) + log.save() + return response + + return wrapper + + +def log_sms(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + response = func(request, *args, **kwargs) + operator = SystemUserProfile.objects.get(user=request.user) + roles = None + users = None + message = request.data['message'] + if 'role' in request.data.keys(): + roles = request.data['role'] + if 'user' in request.data.keys(): + users = request.data['user'] + + if roles != None and users != None: + users = SystemUserProfile.objects.filter(role__name__in=roles, key__in=users, + province=operator.province).order_by('id') + elif roles != None: + users = SystemUserProfile.objects.filter(role__name__in=roles, province=operator.province).order_by('id') + else: + users = SystemUserProfile.objects.filter(key__in=users, province=operator.province).order_by('id') + + for user in users: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + r = requests.request("GET", url, headers=headers, data=payload) + return response + + return wrapper diff --git a/authentication/message/__init__.py b/authentication/message/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/message/serializers.py b/authentication/message/serializers.py new file mode 100644 index 0000000..b63815d --- /dev/null +++ b/authentication/message/serializers.py @@ -0,0 +1,28 @@ +from rest_framework import serializers +from authentication.models import UserMessage +from ..serializer.serializer import ( + GroupSerializer, + SystemUserProfileSerializer +) + + +# سریالایزر مربوط به سیستم پیام کاربر +class UserMessageSerializer(serializers.ModelSerializer): + users = SystemUserProfileSerializer(required=False, many=True) + roles = GroupSerializer(required=False, many=True) + sender = SystemUserProfileSerializer(required=False) + + class Meta: + model = UserMessage + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'created_by', + 'modified_by', + ) + extra_kwargs = { + 'link_text': {'required': False}, + 'link': {'required': False} + } diff --git a/authentication/message/views.py b/authentication/message/views.py new file mode 100644 index 0000000..94cf2c9 --- /dev/null +++ b/authentication/message/views.py @@ -0,0 +1,195 @@ +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from authentication.message.serializers import UserMessageSerializer +from panel.models import CheckState, OperatorLastTimeEnter +from authentication.sahandsms.sms import sms_reminder +from authentication.models import ( + UserMessage, + UserProfile, + SendingMessageMethod, + UserMessageType, SystemUserProfile +) +from django.contrib.auth.models import Group +from rest_framework.response import Response +from notification.models import ( + NotificationToken, + NotificationType, + Notification +) +from notification.najva import ( + get_segments_detail, + send_notif_to_segments +) +from rest_framework import viewsets +from rest_framework import status +import random +import string +import os + +from ticket.helper import send_image_to_server + +# آدرس پایه ذخیره عکس مربوط به سیستم پیام کاربر در استوریج آروان +ARVAN_user_message_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' + + +# ویو ست کلی برای سیستم پیام کاربر که شامل ساخت و ویرایش و حذف می باشد +# برای ساخت چند حالت دارد که یا برای یک شخص ارسال میشه یا جند شخص یا یک نقش خاص +class UserMessageViewSet(viewsets.ModelViewSet): + queryset = UserMessage.objects.all() + serializer_class = UserMessageSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + try: + images = request.data['image'] + request.data.pop('image') + except: + images = None + + try: + roles = request.data['roles'] + request.data.pop('roles') + except: + roles = None + + try: + users = request.data['users'] + request.data.pop('users') + except: + users = None + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + user_message = serializer.create(validated_data=request.data) + user_message.sender = SystemUserProfile.objects.get(user=request.user) + if roles == None: + pass + else: + for role in roles: + rol = Group.objects.get(name=role) + user_message.roles.add(rol) + if users == None and roles == None: + for user in SystemUserProfile.objects.all(): + user_message.users.add(user) + elif users == None: + user_list = [] + for rol in roles: + persons = SystemUserProfile.objects.filter(role__name=rol) + for user in persons: + user_list.append(user.key) + for user in user_list: + user = SystemUserProfile.objects.get(key__exact=user) + user_message.users.add(user) + else: + for user in users: + user = SystemUserProfile.objects.get(key__exact=user) + user_message.users.add(user) + if images == None: + pass + else: + pic = [] + for image in images: + pic.append(send_image_to_server(image)) + user_message.image = pic + user_message.save() + serializer = self.serializer_class(user_message) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + if 'sender' in request.GET: + queryset = UserMessage.objects.filter( + sender=SystemUserProfile.objects.get(user=request.user) + ) + if 'receiver' in request.GET: + user_id = SystemUserProfile.objects.get(user_id__exact=request.user.id) + queryset = UserMessage.objects.filter(users=user_id) + + serializer = UserMessageSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user_id=request.user.id) + key = request.data['key'] + queryset = UserMessage.objects.get(key__exact=key) + queryset.users.remove(user) + queryset.save() + return Response(status=status.HTTP_200_OK) + + +class SendingMessageMethodViewSet(viewsets.ModelViewSet): + queryset = SendingMessageMethod.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = UserMessageViewSet + + def create(self, request, *args, **kwargs): + if not SendingMessageMethod.objects.filter(level=request.data['level']): + SendingMessageMethod( + level=request.data['level'], + methods='/'.join(request.data['methods']) + ).save() + return Response({'msg': 'Done'}, status=status.HTTP_200_OK) + return Response({'msg': 'Method Exist'}, status=status.HTTP_403_FORBIDDEN) + + def update(self, request, *args, **kwargs): + method = SendingMessageMethod.objects.get(key__exact=request.data['key']) + method.level = request.data['level'] + method.methods = '/'.join(request.data['methods']) + method.save() + return Response({'msg': 'Done'}, status=status.HTTP_200_OK) + + +class SendSMSViewSet(viewsets.ModelViewSet): + queryset = UserMessage.objects.all() + serializer_class = UserMessageSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + segments = [] + usermessage = UserMessage() + usermessage.message_level = "sms" + if 'value' in request.data.keys(): + for key in request.data['value']: + if UserProfile.objects.filter(key__exact=key): + segments.append(UserProfile.objects.get(key__exact=key)) + if Group.objects.filter(name__exact=key): + for item in UserProfile.objects.filter(role__name__exact=key): + segments.append(item) + usermessage.message_type = UserMessageType.objects.get(name__exact=request.data['request_type']) + for i in segments: + sms_reminder( + receptor=i.mobile, + title=request.data['heading'], + content=request.data['message'], + link_text=request.data['link_text'], + link=request.data['link'], + time=request.data['time'] + ) + if not request.data['value']: + for item in UserProfile.objects.filter(role__name__exact="Poultry"): + sms_reminder( + receptor=item.mobile, + title=request.data['heading'], + content=request.data['message'], + link_text=request.data['link_text'], + link=request.data['link'], + time=request.data['time'] + ) + usermessage.heading = request.data['heading'] + usermessage.message = request.data['message'] + usermessage.link_text = request.data['link_text'] + usermessage.link = request.data['link'] + usermessage.time = request.data['time'] + usermessage.save() + if 'value' in request.data.keys(): + for key in request.data['value']: + if UserProfile.objects.filter(key__exact=key): + usermessage.users.add(UserProfile.objects.get(key__exact=key)) + if Group.objects.filter(name__exact=key): + usermessage.roles.add(Group.objects.get(name__exact=key)) + request.data.pop('value') + request.data.pop('request_type') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + serializer.create(validated_data=request.data) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) diff --git a/authentication/migrations/0001_initial.py b/authentication/migrations/0001_initial.py new file mode 100644 index 0000000..90c7688 --- /dev/null +++ b/authentication/migrations/0001_initial.py @@ -0,0 +1,431 @@ +# Generated by Django 3.2.13 on 2023-09-18 19:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Address', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(default='', max_length=200, null=True)), + ('country', models.CharField(default='', max_length=100, null=True)), + ('province', models.CharField(default='', max_length=50, null=True)), + ('city', models.CharField(default='', max_length=50, null=True)), + ('address', models.CharField(max_length=300, null=True)), + ('postal_code', models.CharField(default='', max_length=20, null=True)), + ('breeding_unique_id', models.CharField(max_length=50, null=True)), + ('phone', models.CharField(default='', max_length=20, null=True)), + ('phone_type', models.CharField(default='', max_length=20, null=True)), + ('no', models.CharField(default='', max_length=5, null=True)), + ('floor', models.IntegerField(default=0, null=True)), + ('unit', models.IntegerField(default=0, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='address_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='address_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='BankCard', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name_of_bank_user', models.CharField(max_length=200, null=True)), + ('bank_name', models.CharField(max_length=30, null=True)), + ('card', models.CharField(max_length=16, null=True)), + ('shaba', models.CharField(max_length=100, null=True)), + ('account', models.CharField(max_length=50, null=True)), + ('user_bank_id_key', models.IntegerField(null=True)), + ('province_name', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bankcard_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bankcard_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='City', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_id_foreign_key', models.IntegerField(null=True)), + ('city_id_key', models.IntegerField(null=True)), + ('name', models.CharField(max_length=200, null=True)), + ('province_center', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PermissionLevel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='permissionlevel_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='permissionlevel_modifiedby', to=settings.AUTH_USER_MODEL)), + ('role', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='group_permission', to='auth.group')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Province', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('province_id_key', models.IntegerField(null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SystemUserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('token', models.CharField(max_length=36, null=True)), + ('user_django_id_foreign_key', models.IntegerField(null=True)), + ('province_id_foreign_key', models.IntegerField(null=True)), + ('city_id_foreign_key', models.IntegerField(null=True)), + ('system_user_profile_id_key', models.IntegerField(null=True)), + ('fullname', models.CharField(max_length=150, null=True)), + ('first_name', models.CharField(max_length=200, null=True)), + ('last_name', models.CharField(max_length=200, null=True)), + ('national_code', models.CharField(max_length=20, null=True)), + ('national_code_image', models.CharField(max_length=500, null=True)), + ('national_id', models.CharField(max_length=20, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('birthday', models.CharField(max_length=20, null=True)), + ('image', models.CharField(max_length=500, null=True)), + ('password', models.CharField(max_length=100, null=True)), + ('active', models.BooleanField(default=True)), + ('state', models.JSONField(default={'birthday': '', 'city': '', 'first_name': '', 'image': '', 'last_name': '', 'mobile': '', 'national_code': '', 'national_id': '', 'province': ''})), + ('base_order', models.BigIntegerField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('access_level', models.ManyToManyField(related_name='user_permission_level', to='authentication.PermissionLevel')), + ('city', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_city', to='authentication.city')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemuserprofile_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemuserprofile_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_province', to='authentication.province')), + ('role', models.ManyToManyField(related_name='user_system_roles', to='auth.Group')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_user_profile_user', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='UserProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('key', models.UUIDField(default=uuid.uuid4, null=True)), + ('token', models.CharField(default='', max_length=36)), + ('app_token', models.CharField(max_length=36, null=True)), + ('company', models.CharField(max_length=30, null=True)), + ('fullname', models.CharField(default='', max_length=150, null=True)), + ('first_name', models.CharField(default='', max_length=200, null=True)), + ('last_name', models.CharField(default='', max_length=200, null=True)), + ('natinal_id', models.CharField(default='', max_length=10, null=True)), + ('mobile', models.CharField(default='', max_length=11, null=True)), + ('birthday', models.CharField(default='', max_length=20, null=True)), + ('image', models.CharField(max_length=500, null=True)), + ('state', models.CharField(default='register', max_length=20)), + ('unit_name', models.CharField(max_length=100, null=True)), + ('password', models.CharField(max_length=100, null=True)), + ('gis_code', models.CharField(max_length=30, null=True)), + ('operating_licence_capacity', models.BigIntegerField(default=0)), + ('number_of_halls', models.IntegerField(default=0)), + ('tenant', models.BooleanField(null=True)), + ('person_type', models.CharField(max_length=10, null=True)), + ('economic_code', models.CharField(max_length=30, null=True)), + ('system_code', models.CharField(max_length=20, null=True)), + ('epidemiological_code', models.CharField(max_length=20, null=True)), + ('breeding_unique_id', models.CharField(max_length=20, null=True)), + ('total_capacity', models.BigIntegerField(default=0)), + ('licence_number', models.CharField(max_length=20, null=True)), + ('health_certificate_number', models.CharField(max_length=20, null=True)), + ('number_of_requests', models.BigIntegerField(default=0)), + ('hatching_date', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 566242))), + ('last_party_date', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 566242))), + ('number_of_incubators', models.BigIntegerField(default=0)), + ('herd_age_by_day', models.IntegerField(default=0)), + ('herd_age_by_week', models.IntegerField(default=0)), + ('number_of_party', models.IntegerField(default=0)), + ('communication_type', models.CharField(max_length=30, null=True)), + ('cooperative', models.CharField(max_length=50, null=True)), + ('date_of_register', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 566242))), + ('unit_status', models.CharField(max_length=20, null=True)), + ('samasat_user_code', models.CharField(max_length=20, null=True)), + ('base_order', models.BigIntegerField(null=True)), + ('incubation_date', models.DateTimeField(null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_address', to='authentication.address')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userprofile_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userprofile_modifiedby', to=settings.AUTH_USER_MODEL)), + ('role', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_role', to='auth.group')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='users', to=settings.AUTH_USER_MODEL)), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bank_user', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='UserMessageType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(choices=[('user', 'USER'), ('alluser', 'AllUSER'), ('group', 'GROUP'), ('allgroup', 'AllGROUP'), ('usergroup', 'UserGroup'), ('province_accept', 'ProvinceAccept'), ('province_rejected', 'ProvinceRejected'), ('city_operator_accept', 'CityOperatorAccept'), ('city_operator_rejected', 'CityOperatorRejected'), ('assignment_accepted', 'AssignmentAccepted'), ('assignment_rejected', 'AssignmentRejected')], default='', max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessagetype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessagetype_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='UserMessage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('heading', models.CharField(default='', max_length=100, null=True)), + ('message', models.TextField(default='', max_length=500, null=True)), + ('link_text', models.CharField(max_length=150, null=True)), + ('link', models.CharField(max_length=100, null=True)), + ('image', models.JSONField(default=dict, null=True)), + ('expire', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 32, 12, 570238))), + ('time', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 570238))), + ('state', models.CharField(default='pending', max_length=20)), + ('message_level', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessage_createdby', to=settings.AUTH_USER_MODEL)), + ('message_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_type', to='authentication.usermessagetype')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessage_modifiedby', to=settings.AUTH_USER_MODEL)), + ('roles', models.ManyToManyField(blank=True, related_name='user_roles', to='auth.Group')), + ('sender', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_sender', to='authentication.systemuserprofile')), + ('users', models.ManyToManyField(blank=True, related_name='user_message', to='authentication.SystemUserProfile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Tenant', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fullname', models.CharField(max_length=50, null=True)), + ('national_code', models.CharField(max_length=20, null=True)), + ('birthday', models.CharField(max_length=50, null=True)), + ('rental', models.CharField(max_length=30, null=True)), + ('tracking_code', models.CharField(max_length=30, null=True)), + ('rent_date_from', models.CharField(max_length=30, null=True)), + ('rent_date_to', models.CharField(max_length=30, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tenant_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='tenant_modifiedby', to=settings.AUTH_USER_MODEL)), + ('userprofile', models.ManyToManyField(related_name='tenant_user', to='authentication.UserProfile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SystemAddress', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_id_foreign_key', models.IntegerField(null=True)), + ('city_id_foreign_key', models.IntegerField(null=True)), + ('address_id_key', models.IntegerField(null=True)), + ('address', models.CharField(max_length=300, null=True)), + ('postal_code', models.CharField(default='', max_length=20, null=True)), + ('breeding_unique_id', models.CharField(max_length=50, null=True)), + ('phone', models.CharField(default='', max_length=20, null=True)), + ('phone_type', models.CharField(default='', max_length=20, null=True)), + ('no', models.CharField(default='', max_length=5, null=True)), + ('floor', models.IntegerField(default=0, null=True)), + ('unit', models.IntegerField(default=0, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('city', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_address', to='authentication.city')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemaddress_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemaddress_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_address', to='authentication.province')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SendingMessageMethod', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('level', models.CharField(max_length=50, null=True)), + ('methods', models.CharField(max_length=150, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sendingmessagemethod_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sendingmessagemethod_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='MultiRole', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='multi_role_address', to='authentication.address')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='multirole_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='multirole_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='multi_role_users', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Log', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('function_name', models.CharField(max_length=200, null=True)), + ('duration', models.FloatField(null=True)), + ('status', models.IntegerField(null=True)), + ('response', models.TextField(null=True)), + ('request', models.TextField(null=True)), + ('request_body', models.TextField(null=True)), + ('response_body', models.TextField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='log_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='log_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='log_user', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='GeoPoint', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('lang', models.CharField(max_length=50, null=True)), + ('lat', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='geopoint_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='geopoint_modifiedby', to=settings.AUTH_USER_MODEL)), + ('userprofile', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='geo_user', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CityUnit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('city_id_foreign_key', models.IntegerField(null=True)), + ('city_unit_id_key', models.IntegerField(null=True)), + ('name', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('city', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_province', to='authentication.city')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityunit_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityunit_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='city', + name='province', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_province', to='authentication.province'), + ), + ] diff --git a/authentication/migrations/0002_auto_20231005_0439.py b/authentication/migrations/0002_auto_20231005_0439.py new file mode 100644 index 0000000..8f4ac51 --- /dev/null +++ b/authentication/migrations/0002_auto_20231005_0439.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-10-05 04:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 5, 39, 40, 819402)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 819402)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 819402)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 819402)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 819402)), + ), + ] diff --git a/authentication/migrations/0003_auto_20231112_1026.py b/authentication/migrations/0003_auto_20231112_1026.py new file mode 100644 index 0000000..31ff740 --- /dev/null +++ b/authentication/migrations/0003_auto_20231112_1026.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2023-11-12 10:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0002_auto_20231005_0439'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 11, 25, 58, 984672)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 10, 25, 58, 984672)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 10, 25, 58, 984672)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 10, 25, 58, 984672)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 10, 25, 58, 984672)), + ), + migrations.CreateModel( + name='ExternalTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(auto_now_add=True)), + ('amount', models.BigIntegerField(default=0)), + ('status', models.CharField(default='pending', max_length=100)), + ('transaction_type', models.CharField(max_length=100, null=True)), + ('description', models.CharField(default=False, max_length=200)), + ('is_complete', models.BooleanField(default=False)), + ('message', models.TextField(null=True)), + ('saleReferenceId', models.CharField(max_length=100, null=True)), + ('refId', models.CharField(max_length=100, null=True)), + ('orderId', models.CharField(max_length=100, null=True)), + ('cardHolderPan', models.CharField(max_length=100, null=True)), + ('receiver_role', models.CharField(max_length=100, null=True)), + ('creator_role', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='externaltransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('creator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='creator_user', to='authentication.systemuserprofile')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='externaltransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('receiver', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='receiver_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/authentication/migrations/0004_auto_20231112_1223.py b/authentication/migrations/0004_auto_20231112_1223.py new file mode 100644 index 0000000..b0f3987 --- /dev/null +++ b/authentication/migrations/0004_auto_20231112_1223.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2023-11-12 12:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0003_auto_20231112_1026'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='payer', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 13, 23, 6, 109087)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 12, 23, 6, 109087)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 12, 23, 6, 105091)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 12, 23, 6, 105091)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 12, 23, 6, 105091)), + ), + ] diff --git a/authentication/migrations/0005_auto_20231112_1544.py b/authentication/migrations/0005_auto_20231112_1544.py new file mode 100644 index 0000000..bb7df8f --- /dev/null +++ b/authentication/migrations/0005_auto_20231112_1544.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-11-12 15:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0004_auto_20231112_1223'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 16, 44, 52, 32224)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 44, 52, 32224)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 44, 52, 28223)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 44, 52, 28223)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 15, 44, 52, 28223)), + ), + ] diff --git a/authentication/migrations/0006_auto_20231114_0931.py b/authentication/migrations/0006_auto_20231114_0931.py new file mode 100644 index 0000000..5c4923f --- /dev/null +++ b/authentication/migrations/0006_auto_20231114_0931.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-11-14 09:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0005_auto_20231112_1544'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 10, 30, 58, 605133)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 58, 605133)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 58, 605133)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 58, 605133)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 58, 605133)), + ), + ] diff --git a/authentication/migrations/0007_auto_20231120_1913.py b/authentication/migrations/0007_auto_20231120_1913.py new file mode 100644 index 0000000..955d14e --- /dev/null +++ b/authentication/migrations/0007_auto_20231120_1913.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2023-11-20 19:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0006_auto_20231114_0931'), + ] + + operations = [ + migrations.AddField( + model_name='usermessage', + name='receive_code', + field=models.CharField(max_length=400, null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 20, 12, 55, 673532)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 19, 12, 55, 673532)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 19, 12, 55, 670532)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 19, 12, 55, 669532)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 19, 12, 55, 669532)), + ), + ] diff --git a/authentication/migrations/0008_auto_20231120_2009.py b/authentication/migrations/0008_auto_20231120_2009.py new file mode 100644 index 0000000..ca5ab1d --- /dev/null +++ b/authentication/migrations/0008_auto_20231120_2009.py @@ -0,0 +1,61 @@ +# Generated by Django 3.2.13 on 2023-11-20 20:09 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0007_auto_20231120_1913'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 21, 9, 35, 153161)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 20, 9, 35, 153161)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 20, 9, 35, 150161)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 20, 9, 35, 150161)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 20, 9, 35, 150161)), + ), + migrations.CreateModel( + name='UserMessageSend', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('message', models.TextField(max_length=500, null=True)), + ('receive_code', models.CharField(max_length=400, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessagesend_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usermessagesend_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/authentication/migrations/0009_auto_20231120_2134.py b/authentication/migrations/0009_auto_20231120_2134.py new file mode 100644 index 0000000..45778e6 --- /dev/null +++ b/authentication/migrations/0009_auto_20231120_2134.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.13 on 2023-11-20 21:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0008_auto_20231120_2009'), + ] + + operations = [ + migrations.RemoveField( + model_name='usermessage', + name='receive_code', + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 22, 34, 29, 248210)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 21, 34, 29, 248210)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 21, 34, 29, 245208)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 21, 34, 29, 244207)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 20, 21, 34, 29, 244207)), + ), + ] diff --git a/authentication/migrations/0010_auto_20231202_1108.py b/authentication/migrations/0010_auto_20231202_1108.py new file mode 100644 index 0000000..6f92b5f --- /dev/null +++ b/authentication/migrations/0010_auto_20231202_1108.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-02 11:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0009_auto_20231120_2134'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 12, 8, 44, 239211)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 239211)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 235210)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 235210)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 235210)), + ), + ] diff --git a/authentication/migrations/0011_auto_20231205_1256.py b/authentication/migrations/0011_auto_20231205_1256.py new file mode 100644 index 0000000..b6c0c08 --- /dev/null +++ b/authentication/migrations/0011_auto_20231205_1256.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-05 12:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0010_auto_20231202_1108'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 13, 56, 11, 857259)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 857259)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 853262)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 853262)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 853262)), + ), + ] diff --git a/authentication/migrations/0012_auto_20231211_1102.py b/authentication/migrations/0012_auto_20231211_1102.py new file mode 100644 index 0000000..431672d --- /dev/null +++ b/authentication/migrations/0012_auto_20231211_1102.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-11 11:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0011_auto_20231205_1256'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 2, 7, 786317)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 786317)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 780322)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 780322)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 780322)), + ), + ] diff --git a/authentication/migrations/0013_auto_20231214_1418.py b/authentication/migrations/0013_auto_20231214_1418.py new file mode 100644 index 0000000..7b4f1d9 --- /dev/null +++ b/authentication/migrations/0013_auto_20231214_1418.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2023-12-14 14:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0012_auto_20231211_1102'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 15, 18, 27, 572252)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 572252)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 563261)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 563261)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 563261)), + ), + ] diff --git a/authentication/migrations/0014_auto_20240107_1133.py b/authentication/migrations/0014_auto_20240107_1133.py new file mode 100644 index 0000000..8aca747 --- /dev/null +++ b/authentication/migrations/0014_auto_20240107_1133.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-01-07 11:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0013_auto_20231214_1418'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 12, 32, 59, 193761)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 193761)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 188761)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 187761)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 187761)), + ), + ] diff --git a/authentication/migrations/0015_auto_20240107_2228.py b/authentication/migrations/0015_auto_20240107_2228.py new file mode 100644 index 0000000..a4cf51c --- /dev/null +++ b/authentication/migrations/0015_auto_20240107_2228.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-01-07 22:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0014_auto_20240107_1133'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 23, 28, 10, 522399)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 522399)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 518403)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 518403)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 518403)), + ), + ] diff --git a/authentication/migrations/0016_auto_20240110_0238.py b/authentication/migrations/0016_auto_20240110_0238.py new file mode 100644 index 0000000..8e4ae23 --- /dev/null +++ b/authentication/migrations/0016_auto_20240110_0238.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-01-10 02:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0015_auto_20240107_2228'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 3, 38, 17, 869472)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 869472)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 864477)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 864477)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 864477)), + ), + ] diff --git a/authentication/migrations/0017_auto_20240131_1351.py b/authentication/migrations/0017_auto_20240131_1351.py new file mode 100644 index 0000000..c54e232 --- /dev/null +++ b/authentication/migrations/0017_auto_20240131_1351.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-01-31 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0016_auto_20240110_0238'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='kill_house_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 51, 24, 623765)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 13, 51, 24, 623765)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 13, 51, 24, 619768)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 13, 51, 24, 619768)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 13, 51, 24, 619768)), + ), + ] diff --git a/authentication/migrations/0018_auto_20240131_1405.py b/authentication/migrations/0018_auto_20240131_1405.py new file mode 100644 index 0000000..e56a13c --- /dev/null +++ b/authentication/migrations/0018_auto_20240131_1405.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2024-01-31 14:05 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0017_auto_20240131_1351'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='kill_house_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_kill_house_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 5, 12, 182042)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 5, 12, 182042)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 5, 12, 178046)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 5, 12, 177046)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 5, 12, 178046)), + ), + ] diff --git a/authentication/migrations/0019_auto_20240131_1429.py b/authentication/migrations/0019_auto_20240131_1429.py new file mode 100644 index 0000000..e5fd537 --- /dev/null +++ b/authentication/migrations/0019_auto_20240131_1429.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.13 on 2024-01-31 14:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0018_auto_20240131_1405'), + ] + + operations = [ + migrations.RemoveField( + model_name='externaltransaction', + name='kill_house_id_foreign_key', + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 15, 29, 49, 130976)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 29, 49, 130976)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 29, 49, 126982)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 29, 49, 126982)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 31, 14, 29, 49, 126982)), + ), + ] diff --git a/authentication/migrations/0020_auto_20240220_1341.py b/authentication/migrations/0020_auto_20240220_1341.py new file mode 100644 index 0000000..4042f41 --- /dev/null +++ b/authentication/migrations/0020_auto_20240220_1341.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-02-20 13:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0019_auto_20240131_1429'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 14, 41, 7, 8616)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 8616)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 3621)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 3621)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 3621)), + ), + ] diff --git a/authentication/migrations/0021_auto_20240326_1330.py b/authentication/migrations/0021_auto_20240326_1330.py new file mode 100644 index 0000000..2e17393 --- /dev/null +++ b/authentication/migrations/0021_auto_20240326_1330.py @@ -0,0 +1,305 @@ +# Generated by Django 3.2.13 on 2024-03-26 13:30 + +import datetime +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0020_auto_20240220_1341'), + ] + + operations = [ + migrations.AlterField( + model_name='address', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='address', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='address', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='bankcard', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='bankcard', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='bankcard', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='city', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='city', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='city', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='cityunit', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='cityunit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityunit', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='externaltransaction', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='externaltransaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='externaltransaction', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='geopoint', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='geopoint', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='geopoint', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='log', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='log', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='log', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='multirole', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='multirole', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='multirole', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='permissionlevel', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='permissionlevel', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='permissionlevel', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='province', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='province', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='province', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='systemaddress', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='systemaddress', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='systemaddress', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='tenant', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='tenant', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='tenant', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessage', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 14, 30, 27, 97658)), + ), + migrations.AlterField( + model_name='usermessage', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessage', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 13, 30, 27, 97658)), + ), + migrations.AlterField( + model_name='usermessagesend', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessagesend', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessagesend', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessagetype', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='usermessagetype', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='usermessagetype', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='userprofile', + name='create_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 13, 30, 27, 93663)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 13, 30, 27, 93663)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 13, 30, 27, 93663)), + ), + migrations.AlterField( + model_name='userprofile', + name='modify_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + ] diff --git a/authentication/migrations/0022_auto_20240326_1425.py b/authentication/migrations/0022_auto_20240326_1425.py new file mode 100644 index 0000000..48b07e0 --- /dev/null +++ b/authentication/migrations/0022_auto_20240326_1425.py @@ -0,0 +1,219 @@ +# Generated by Django 3.2.13 on 2024-03-26 14:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0021_auto_20240326_1330'), + ] + + operations = [ + migrations.AlterField( + model_name='address', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='address', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='bankcard', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='bankcard', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='city', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='city', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='cityunit', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='cityunit', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='externaltransaction', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='externaltransaction', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='geopoint', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='geopoint', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='log', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='log', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='multirole', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='multirole', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='permissionlevel', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='permissionlevel', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='province', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='province', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='sendingmessagemethod', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='systemaddress', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='systemaddress', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='systemuserprofile', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='tenant', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='tenant', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='usermessage', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 15, 25, 26, 958154)), + ), + migrations.AlterField( + model_name='usermessage', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 14, 25, 26, 958154)), + ), + migrations.AlterField( + model_name='usermessagesend', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='usermessagesend', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='usermessagetype', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='usermessagetype', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='userprofile', + name='create_date', + field=models.DateTimeField(auto_now_add=True), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 14, 25, 26, 953162)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 14, 25, 26, 953162)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 26, 14, 25, 26, 953162)), + ), + migrations.AlterField( + model_name='userprofile', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/authentication/migrations/0023_auto_20240408_1626.py b/authentication/migrations/0023_auto_20240408_1626.py new file mode 100644 index 0000000..625e74d --- /dev/null +++ b/authentication/migrations/0023_auto_20240408_1626.py @@ -0,0 +1,87 @@ +# Generated by Django 3.2.13 on 2024-04-08 16:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0022_auto_20240326_1425'), + ] + + operations = [ + migrations.CreateModel( + name='Notice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=1000, null=True)), + ('text', models.TextField(null=True)), + ('users', models.JSONField(null=True)), + ('read_users', models.JSONField(null=True)), + ('unread_users', models.JSONField(null=True)), + ('roles', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notice_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notice_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 17, 26, 21, 530567)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 26, 21, 530567)), + ), + migrations.AlterField( + model_name='usermessagesend', + name='message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 26, 21, 526571)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 26, 21, 526571)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 26, 21, 526571)), + ), + migrations.CreateModel( + name='UserNoticeInfo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('seen', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usernoticeinfo_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='usernoticeinfo_modifiedby', to=settings.AUTH_USER_MODEL)), + ('notice', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_notice', to='authentication.notice')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notice_users', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/authentication/migrations/0024_auto_20240408_1632.py b/authentication/migrations/0024_auto_20240408_1632.py new file mode 100644 index 0000000..3114921 --- /dev/null +++ b/authentication/migrations/0024_auto_20240408_1632.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-04-08 16:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0023_auto_20240408_1626'), + ] + + operations = [ + migrations.AddField( + model_name='notice', + name='images', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 17, 32, 52, 144178)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 32, 52, 144178)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 32, 52, 140182)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 32, 52, 140182)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 8, 16, 32, 52, 140182)), + ), + ] diff --git a/authentication/migrations/0025_auto_20240416_1440.py b/authentication/migrations/0025_auto_20240416_1440.py new file mode 100644 index 0000000..f1ee608 --- /dev/null +++ b/authentication/migrations/0025_auto_20240416_1440.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-04-16 14:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0024_auto_20240408_1632'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 15, 40, 32, 497347)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 497347)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 489346)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 489346)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 489346)), + ), + ] diff --git a/authentication/migrations/0026_auto_20240417_1103.py b/authentication/migrations/0026_auto_20240417_1103.py new file mode 100644 index 0000000..921e1ae --- /dev/null +++ b/authentication/migrations/0026_auto_20240417_1103.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-04-17 11:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0025_auto_20240416_1440'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 2, 49, 693622)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 693622)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 693622)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 677998)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 677998)), + ), + ] diff --git a/authentication/migrations/0027_auto_20240420_0033.py b/authentication/migrations/0027_auto_20240420_0033.py new file mode 100644 index 0000000..c48f184 --- /dev/null +++ b/authentication/migrations/0027_auto_20240420_0033.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-04-20 00:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0026_auto_20240417_1103'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 1, 33, 3, 837655)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 837655)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 833655)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 833655)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 833655)), + ), + ] diff --git a/authentication/migrations/0028_auto_20240427_1357.py b/authentication/migrations/0028_auto_20240427_1357.py new file mode 100644 index 0000000..737e5d6 --- /dev/null +++ b/authentication/migrations/0028_auto_20240427_1357.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-04-27 13:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0027_auto_20240420_0033'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='amount_with_tax', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 14, 56, 47, 586337)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 56, 47, 586337)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 56, 47, 577334)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 56, 47, 577334)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 56, 47, 577334)), + ), + ] diff --git a/authentication/migrations/0029_auto_20240511_1129.py b/authentication/migrations/0029_auto_20240511_1129.py new file mode 100644 index 0000000..f1459ce --- /dev/null +++ b/authentication/migrations/0029_auto_20240511_1129.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-05-11 11:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0028_auto_20240427_1357'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 12, 29, 47, 632167)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 632167)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 632167)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 632167)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 632167)), + ), + ] diff --git a/authentication/migrations/0030_auto_20240511_1312.py b/authentication/migrations/0030_auto_20240511_1312.py new file mode 100644 index 0000000..1fc5db4 --- /dev/null +++ b/authentication/migrations/0030_auto_20240511_1312.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-05-11 13:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0029_auto_20240511_1129'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 14, 11, 48, 448971)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 448971)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 442972)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 442972)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 442972)), + ), + ] diff --git a/authentication/migrations/0031_auto_20240516_1321.py b/authentication/migrations/0031_auto_20240516_1321.py new file mode 100644 index 0000000..3b75fd1 --- /dev/null +++ b/authentication/migrations/0031_auto_20240516_1321.py @@ -0,0 +1,45 @@ +# Generated by Django 3.2.13 on 2024-05-16 13:21 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0030_auto_20240511_1312'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='chain_company_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_chain_company_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 14, 21, 17, 757672)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 21, 17, 757672)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 21, 17, 748673)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 21, 17, 748673)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 21, 17, 748673)), + ), + ] diff --git a/authentication/migrations/0032_auto_20240517_1337.py b/authentication/migrations/0032_auto_20240517_1337.py new file mode 100644 index 0000000..26a7eae --- /dev/null +++ b/authentication/migrations/0032_auto_20240517_1337.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-17 13:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0031_auto_20240516_1321'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='externaltransaction', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='externaltransaction', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='externaltransaction', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='externaltransaction', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='externaltransaction', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 14, 36, 53, 296879)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 36, 53, 296879)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 36, 53, 292879)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 36, 53, 292879)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 36, 53, 292879)), + ), + ] diff --git a/authentication/migrations/0033_auto_20240517_1351.py b/authentication/migrations/0033_auto_20240517_1351.py new file mode 100644 index 0000000..799f6de --- /dev/null +++ b/authentication/migrations/0033_auto_20240517_1351.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-05-17 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0032_auto_20240517_1337'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='pay_type', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 14, 51, 41, 231332)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 51, 41, 231332)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 51, 41, 222333)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 51, 41, 222333)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 51, 41, 222333)), + ), + ] diff --git a/authentication/migrations/0034_auto_20240527_1506.py b/authentication/migrations/0034_auto_20240527_1506.py new file mode 100644 index 0000000..8fb5481 --- /dev/null +++ b/authentication/migrations/0034_auto_20240527_1506.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-05-27 15:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0033_auto_20240517_1351'), + ] + + operations = [ + migrations.AddField( + model_name='systemuserprofile', + name='user_gate_way_id', + field=models.CharField(max_length=6, null=True, unique=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 16, 6, 17, 530512)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 6, 17, 530512)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 6, 17, 526511)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 6, 17, 526511)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 27, 15, 6, 17, 526511)), + ), + ] diff --git a/authentication/migrations/0035_auto_20240612_0954.py b/authentication/migrations/0035_auto_20240612_0954.py new file mode 100644 index 0000000..01fe1ad --- /dev/null +++ b/authentication/migrations/0035_auto_20240612_0954.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-12 09:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0034_auto_20240527_1506'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 10, 54, 43, 323313)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 9, 54, 43, 323313)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 9, 54, 43, 320316)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 9, 54, 43, 320316)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 9, 54, 43, 320316)), + ), + ] diff --git a/authentication/migrations/0036_auto_20240612_1137.py b/authentication/migrations/0036_auto_20240612_1137.py new file mode 100644 index 0000000..c48b82f --- /dev/null +++ b/authentication/migrations/0036_auto_20240612_1137.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-12 11:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0035_auto_20240612_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 36, 51, 452143)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 452143)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 449142)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 449142)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 449142)), + ), + ] diff --git a/authentication/migrations/0037_auto_20240612_1936.py b/authentication/migrations/0037_auto_20240612_1936.py new file mode 100644 index 0000000..a6120c0 --- /dev/null +++ b/authentication/migrations/0037_auto_20240612_1936.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-12 19:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0036_auto_20240612_1137'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 20, 36, 32, 610011)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 19, 36, 32, 610011)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 19, 36, 32, 606011)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 19, 36, 32, 606011)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 19, 36, 32, 606011)), + ), + ] diff --git a/authentication/migrations/0038_auto_20240613_1101.py b/authentication/migrations/0038_auto_20240613_1101.py new file mode 100644 index 0000000..3fd7cac --- /dev/null +++ b/authentication/migrations/0038_auto_20240613_1101.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-13 11:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0037_auto_20240612_1936'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 12, 1, 44, 767799)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 767799)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 764798)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 764798)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 764798)), + ), + ] diff --git a/authentication/migrations/0039_auto_20240616_0956.py b/authentication/migrations/0039_auto_20240616_0956.py new file mode 100644 index 0000000..901e04b --- /dev/null +++ b/authentication/migrations/0039_auto_20240616_0956.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-16 09:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0038_auto_20240613_1101'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 10, 56, 22, 683195)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 683195)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 680170)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 680170)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 680170)), + ), + ] diff --git a/authentication/migrations/0040_auto_20240618_1451.py b/authentication/migrations/0040_auto_20240618_1451.py new file mode 100644 index 0000000..ce6108c --- /dev/null +++ b/authentication/migrations/0040_auto_20240618_1451.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-06-18 14:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0039_auto_20240616_0956'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 15, 51, 39, 156393)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 156393)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 148392)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 148392)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 148392)), + ), + ] diff --git a/authentication/migrations/0041_auto_20240713_0951.py b/authentication/migrations/0041_auto_20240713_0951.py new file mode 100644 index 0000000..5c8ab3e --- /dev/null +++ b/authentication/migrations/0041_auto_20240713_0951.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-07-13 09:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0040_auto_20240618_1451'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 51, 8, 10909)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 10909)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 6909)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 6909)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 6909)), + ), + ] diff --git a/authentication/migrations/0042_auto_20240713_1024.py b/authentication/migrations/0042_auto_20240713_1024.py new file mode 100644 index 0000000..0353f9d --- /dev/null +++ b/authentication/migrations/0042_auto_20240713_1024.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-07-13 10:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0041_auto_20240713_0951'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 24, 12, 652810)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 652810)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 648804)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 648804)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 648804)), + ), + ] diff --git a/authentication/migrations/0043_auto_20240803_1121.py b/authentication/migrations/0043_auto_20240803_1121.py new file mode 100644 index 0000000..5461c5f --- /dev/null +++ b/authentication/migrations/0043_auto_20240803_1121.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-08-03 11:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0042_auto_20240713_1024'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 12, 21, 40, 439193)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 439193)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 435193)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 435193)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 435193)), + ), + ] diff --git a/authentication/migrations/0044_auto_20240820_1038.py b/authentication/migrations/0044_auto_20240820_1038.py new file mode 100644 index 0000000..c9205d7 --- /dev/null +++ b/authentication/migrations/0044_auto_20240820_1038.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-08-20 10:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0043_auto_20240803_1121'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 11, 37, 50, 488910)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 488910)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 479908)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 479908)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 479908)), + ), + ] diff --git a/authentication/migrations/0045_auto_20240830_1034.py b/authentication/migrations/0045_auto_20240830_1034.py new file mode 100644 index 0000000..383b0e3 --- /dev/null +++ b/authentication/migrations/0045_auto_20240830_1034.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-08-30 10:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0044_auto_20240820_1038'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 11, 34, 3, 932129)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 34, 3, 932129)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 34, 3, 928091)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 34, 3, 928091)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 34, 3, 928091)), + ), + ] diff --git a/authentication/migrations/0046_auto_20240912_0926.py b/authentication/migrations/0046_auto_20240912_0926.py new file mode 100644 index 0000000..c6c5808 --- /dev/null +++ b/authentication/migrations/0046_auto_20240912_0926.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-09-12 09:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0045_auto_20240830_1034'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 10, 25, 52, 994361)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 52, 994361)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 52, 990361)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 52, 990361)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 52, 990361)), + ), + ] diff --git a/authentication/migrations/0047_auto_20240912_1105.py b/authentication/migrations/0047_auto_20240912_1105.py new file mode 100644 index 0000000..b9786e1 --- /dev/null +++ b/authentication/migrations/0047_auto_20240912_1105.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0046_auto_20240912_0926'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 5, 45, 59359)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 5, 45, 59359)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 5, 45, 56344)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 5, 45, 56344)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 5, 45, 56344)), + ), + ] diff --git a/authentication/migrations/0048_auto_20240912_1118.py b/authentication/migrations/0048_auto_20240912_1118.py new file mode 100644 index 0000000..b4d663e --- /dev/null +++ b/authentication/migrations/0048_auto_20240912_1118.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0047_auto_20240912_1105'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 18, 3, 954859)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 18, 3, 954859)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 18, 3, 951853)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 18, 3, 951853)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 18, 3, 951853)), + ), + ] diff --git a/authentication/migrations/0049_auto_20241005_1324.py b/authentication/migrations/0049_auto_20241005_1324.py new file mode 100644 index 0000000..2bde782 --- /dev/null +++ b/authentication/migrations/0049_auto_20241005_1324.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2024-10-05 13:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0048_auto_20240912_1118'), + ] + + operations = [ + migrations.AddField( + model_name='city', + name='product_price', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 14, 24, 2, 356280)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 24, 2, 356280)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 24, 2, 351281)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 24, 2, 351281)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 24, 2, 351281)), + ), + ] diff --git a/authentication/migrations/0050_auto_20241029_1116.py b/authentication/migrations/0050_auto_20241029_1116.py new file mode 100644 index 0000000..eea2db2 --- /dev/null +++ b/authentication/migrations/0050_auto_20241029_1116.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-10-29 11:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0049_auto_20241005_1324'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 12, 16, 42, 670857)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 670857)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 670857)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 654920)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 654920)), + ), + ] diff --git a/authentication/migrations/0051_auto_20241130_1837.py b/authentication/migrations/0051_auto_20241130_1837.py new file mode 100644 index 0000000..0c0e314 --- /dev/null +++ b/authentication/migrations/0051_auto_20241130_1837.py @@ -0,0 +1,49 @@ +# Generated by Django 3.2.13 on 2024-11-30 18:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0050_auto_20241029_1116'), + ] + + operations = [ + migrations.AddField( + model_name='externaltransaction', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='externaltransaction', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 37, 30, 803723)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 37, 30, 803723)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 37, 30, 799720)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 37, 30, 799720)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 37, 30, 799720)), + ), + ] diff --git a/authentication/migrations/0052_auto_20241208_1147.py b/authentication/migrations/0052_auto_20241208_1147.py new file mode 100644 index 0000000..e4d835d --- /dev/null +++ b/authentication/migrations/0052_auto_20241208_1147.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-08 11:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0051_auto_20241130_1837'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 12, 47, 31, 513277)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 513277)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 511274)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 511274)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 511274)), + ), + ] diff --git a/authentication/migrations/0053_auto_20241215_1031.py b/authentication/migrations/0053_auto_20241215_1031.py new file mode 100644 index 0000000..331dff9 --- /dev/null +++ b/authentication/migrations/0053_auto_20241215_1031.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-15 10:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0052_auto_20241208_1147'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 31, 13, 476768)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 476768)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 473020)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 473020)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 473020)), + ), + ] diff --git a/authentication/migrations/0054_auto_20241228_0926.py b/authentication/migrations/0054_auto_20241228_0926.py new file mode 100644 index 0000000..8074d63 --- /dev/null +++ b/authentication/migrations/0054_auto_20241228_0926.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2024-12-28 09:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0053_auto_20241215_1031'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 10, 26, 11, 380483)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 9, 26, 11, 380483)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 9, 26, 11, 378476)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 9, 26, 11, 378476)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 28, 9, 26, 11, 378476)), + ), + ] diff --git a/authentication/migrations/0055_auto_20250112_1550.py b/authentication/migrations/0055_auto_20250112_1550.py new file mode 100644 index 0000000..421958e --- /dev/null +++ b/authentication/migrations/0055_auto_20250112_1550.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-12 15:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0054_auto_20241228_0926'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 16, 50, 33, 128256)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 128256)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 124237)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 124237)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 124237)), + ), + ] diff --git a/authentication/migrations/0056_auto_20250118_1418.py b/authentication/migrations/0056_auto_20250118_1418.py new file mode 100644 index 0000000..310fdfe --- /dev/null +++ b/authentication/migrations/0056_auto_20250118_1418.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-18 14:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0055_auto_20250112_1550'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 15, 18, 21, 786785)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 14, 18, 21, 786785)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 14, 18, 21, 782787)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 14, 18, 21, 782787)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 18, 14, 18, 21, 782787)), + ), + ] diff --git a/authentication/migrations/0057_auto_20250121_0857.py b/authentication/migrations/0057_auto_20250121_0857.py new file mode 100644 index 0000000..bb09edb --- /dev/null +++ b/authentication/migrations/0057_auto_20250121_0857.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-01-21 08:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0056_auto_20250118_1418'), + ] + + operations = [ + migrations.AddField( + model_name='systemuserprofile', + name='unit_address', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_city', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_economical_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_national_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_postal_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_province', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='unit_registration_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 9, 57, 41, 955428)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 955428)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 955428)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 955428)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 955428)), + ), + ] diff --git a/authentication/migrations/0058_auto_20250126_2046.py b/authentication/migrations/0058_auto_20250126_2046.py new file mode 100644 index 0000000..191a791 --- /dev/null +++ b/authentication/migrations/0058_auto_20250126_2046.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-26 20:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0057_auto_20250121_0857'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 21, 45, 45, 347320)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 20, 45, 45, 347320)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 20, 45, 45, 344319)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 20, 45, 45, 344319)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 20, 45, 45, 344319)), + ), + ] diff --git a/authentication/migrations/0059_auto_20250126_2122.py b/authentication/migrations/0059_auto_20250126_2122.py new file mode 100644 index 0000000..d19a7ec --- /dev/null +++ b/authentication/migrations/0059_auto_20250126_2122.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-26 21:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0058_auto_20250126_2046'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 22, 22, 22, 642630)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 21, 22, 22, 642630)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 21, 22, 22, 638656)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 21, 22, 22, 638656)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 26, 21, 22, 22, 638656)), + ), + ] diff --git a/authentication/migrations/0060_auto_20250302_1203.py b/authentication/migrations/0060_auto_20250302_1203.py new file mode 100644 index 0000000..bf0f460 --- /dev/null +++ b/authentication/migrations/0060_auto_20250302_1203.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-02 12:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0059_auto_20250126_2122'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 2, 54, 212438)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 212438)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 210430)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 210430)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 210430)), + ), + ] diff --git a/authentication/migrations/0061_auto_20250302_1351.py b/authentication/migrations/0061_auto_20250302_1351.py new file mode 100644 index 0000000..2573109 --- /dev/null +++ b/authentication/migrations/0061_auto_20250302_1351.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-02 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0060_auto_20250302_1203'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 51, 24, 153713)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 153713)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 149697)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 149697)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 149697)), + ), + ] diff --git a/authentication/migrations/0062_auto_20250302_1458.py b/authentication/migrations/0062_auto_20250302_1458.py new file mode 100644 index 0000000..397dc8c --- /dev/null +++ b/authentication/migrations/0062_auto_20250302_1458.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-02 14:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0061_auto_20250302_1351'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 15, 58, 25, 437483)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 437483)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 433467)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 433467)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 433467)), + ), + ] diff --git a/authentication/migrations/0063_auto_20250303_1205.py b/authentication/migrations/0063_auto_20250303_1205.py new file mode 100644 index 0000000..b434ba3 --- /dev/null +++ b/authentication/migrations/0063_auto_20250303_1205.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 12:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0062_auto_20250302_1458'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 5, 3, 133575)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 133575)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 130344)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 129310)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 130344)), + ), + ] diff --git a/authentication/migrations/0064_auto_20250303_1315.py b/authentication/migrations/0064_auto_20250303_1315.py new file mode 100644 index 0000000..3de6e1f --- /dev/null +++ b/authentication/migrations/0064_auto_20250303_1315.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 13:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0063_auto_20250303_1205'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 15, 43, 962800)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 43, 962800)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 43, 958810)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 43, 958810)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 43, 958810)), + ), + ] diff --git a/authentication/migrations/0065_auto_20250303_1500.py b/authentication/migrations/0065_auto_20250303_1500.py new file mode 100644 index 0000000..56e14ad --- /dev/null +++ b/authentication/migrations/0065_auto_20250303_1500.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-03 15:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0064_auto_20250303_1315'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 15, 59, 55, 26833)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 26833)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 24825)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 24825)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 24825)), + ), + ] diff --git a/authentication/migrations/0066_auto_20250306_1106.py b/authentication/migrations/0066_auto_20250306_1106.py new file mode 100644 index 0000000..d6fe3b9 --- /dev/null +++ b/authentication/migrations/0066_auto_20250306_1106.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-03-06 11:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0065_auto_20250303_1500'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 12, 6, 39, 507190)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 11, 6, 39, 507190)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 11, 6, 39, 503181)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 11, 6, 39, 503181)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 6, 11, 6, 39, 503181)), + ), + ] diff --git a/authentication/migrations/0067_auto_20250525_1503.py b/authentication/migrations/0067_auto_20250525_1503.py new file mode 100644 index 0000000..96c8efd --- /dev/null +++ b/authentication/migrations/0067_auto_20250525_1503.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0066_auto_20250306_1106'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 16, 2, 53, 151705)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 151705)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 148412)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 148412)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 148412)), + ), + ] diff --git a/authentication/migrations/0068_auto_20250525_1504.py b/authentication/migrations/0068_auto_20250525_1504.py new file mode 100644 index 0000000..4edd59c --- /dev/null +++ b/authentication/migrations/0068_auto_20250525_1504.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0067_auto_20250525_1503'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 16, 4, 13, 29545)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 29545)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 26452)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 26452)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 26452)), + ), + ] diff --git a/authentication/migrations/0069_auto_20250525_1505.py b/authentication/migrations/0069_auto_20250525_1505.py new file mode 100644 index 0000000..520205e --- /dev/null +++ b/authentication/migrations/0069_auto_20250525_1505.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0068_auto_20250525_1504'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 16, 5, 28, 192717)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 192717)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 188592)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 188592)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 188592)), + ), + ] diff --git a/authentication/migrations/0070_auto_20250527_1154.py b/authentication/migrations/0070_auto_20250527_1154.py new file mode 100644 index 0000000..6b02235 --- /dev/null +++ b/authentication/migrations/0070_auto_20250527_1154.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-05-27 11:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0069_auto_20250525_1505'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 12, 54, 41, 955504)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 11, 54, 41, 955504)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 11, 54, 41, 955504)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 11, 54, 41, 955504)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 11, 54, 41, 955504)), + ), + ] diff --git a/authentication/migrations/0071_auto_20250601_1023.py b/authentication/migrations/0071_auto_20250601_1023.py new file mode 100644 index 0000000..56558b6 --- /dev/null +++ b/authentication/migrations/0071_auto_20250601_1023.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-06-01 10:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0070_auto_20250527_1154'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 11, 23, 19, 683163)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 683163)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 681156)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 681156)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 681156)), + ), + ] diff --git a/authentication/migrations/0072_auto_20250901_1207.py b/authentication/migrations/0072_auto_20250901_1207.py new file mode 100644 index 0000000..50fa25a --- /dev/null +++ b/authentication/migrations/0072_auto_20250901_1207.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-09-01 12:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0071_auto_20250601_1023'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 13, 6, 58, 640479)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 640479)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 636520)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 636520)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 636520)), + ), + ] diff --git a/authentication/migrations/0073_auto_20250920_1257.py b/authentication/migrations/0073_auto_20250920_1257.py new file mode 100644 index 0000000..e372a91 --- /dev/null +++ b/authentication/migrations/0073_auto_20250920_1257.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-09-20 12:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0072_auto_20250901_1207'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 13, 57, 40, 513826)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 513826)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 509834)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 508831)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 509834)), + ), + ] diff --git a/authentication/migrations/0074_auto_20251028_0856.py b/authentication/migrations/0074_auto_20251028_0856.py new file mode 100644 index 0000000..719c84c --- /dev/null +++ b/authentication/migrations/0074_auto_20251028_0856.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-10-28 08:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0073_auto_20250920_1257'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 55, 52, 569561)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 569561)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 565592)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 565592)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 565592)), + ), + ] diff --git a/authentication/migrations/0075_auto_20251029_1055.py b/authentication/migrations/0075_auto_20251029_1055.py new file mode 100644 index 0000000..bcef587 --- /dev/null +++ b/authentication/migrations/0075_auto_20251029_1055.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-10-29 10:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0074_auto_20251028_0856'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 11, 54, 57, 498118)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 498118)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 495117)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 495117)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 495117)), + ), + ] diff --git a/authentication/migrations/0076_auto_20251104_1340.py b/authentication/migrations/0076_auto_20251104_1340.py new file mode 100644 index 0000000..d71a47c --- /dev/null +++ b/authentication/migrations/0076_auto_20251104_1340.py @@ -0,0 +1,54 @@ +# Generated by Django 3.2.13 on 2025-11-04 13:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0075_auto_20251029_1055'), + ] + + operations = [ + migrations.AddField( + model_name='systemuserprofile', + name='father_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='gender', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='systemuserprofile', + name='is_alive', + field=models.BooleanField(null=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 14, 40, 24, 948077)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 40, 24, 948077)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 40, 24, 944573)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 40, 24, 944573)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 40, 24, 944573)), + ), + ] diff --git a/authentication/migrations/0077_auto_20251110_1100.py b/authentication/migrations/0077_auto_20251110_1100.py new file mode 100644 index 0000000..c1eccf7 --- /dev/null +++ b/authentication/migrations/0077_auto_20251110_1100.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-11-10 11:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0076_auto_20251104_1340'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 12, 0, 21, 824810)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 824810)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 821718)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 821718)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 821718)), + ), + ] diff --git a/authentication/migrations/0078_auto_20251208_1617.py b/authentication/migrations/0078_auto_20251208_1617.py new file mode 100644 index 0000000..9c32391 --- /dev/null +++ b/authentication/migrations/0078_auto_20251208_1617.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-08 16:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0077_auto_20251110_1100'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 17, 14, 44, 867599)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 44, 867599)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 44, 863841)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 44, 863841)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 44, 863841)), + ), + ] diff --git a/authentication/migrations/0079_auto_20251213_1632.py b/authentication/migrations/0079_auto_20251213_1632.py new file mode 100644 index 0000000..f23f4ee --- /dev/null +++ b/authentication/migrations/0079_auto_20251213_1632.py @@ -0,0 +1,44 @@ +# Generated by Django 3.2.13 on 2025-12-13 16:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0078_auto_20251208_1617'), + ] + + operations = [ + migrations.AddField( + model_name='systemuserprofile', + name='pos', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 17, 31, 59, 715230)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 715230)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 711672)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 710642)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 710642)), + ), + ] diff --git a/authentication/migrations/0080_auto_20251214_1635.py b/authentication/migrations/0080_auto_20251214_1635.py new file mode 100644 index 0000000..d3a5a7e --- /dev/null +++ b/authentication/migrations/0080_auto_20251214_1635.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-14 16:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0079_auto_20251213_1632'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 17, 35, 24, 669993)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 669993)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 666317)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 666317)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 666317)), + ), + ] diff --git a/authentication/migrations/0081_auto_20251217_1648.py b/authentication/migrations/0081_auto_20251217_1648.py new file mode 100644 index 0000000..20aef6d --- /dev/null +++ b/authentication/migrations/0081_auto_20251217_1648.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-12-17 16:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0080_auto_20251214_1635'), + ] + + operations = [ + migrations.AlterField( + model_name='usermessage', + name='expire', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 17, 47, 34, 370198)), + ), + migrations.AlterField( + model_name='usermessage', + name='time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 370198)), + ), + migrations.AlterField( + model_name='userprofile', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 366661)), + ), + migrations.AlterField( + model_name='userprofile', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 366661)), + ), + migrations.AlterField( + model_name='userprofile', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 366661)), + ), + ] diff --git a/authentication/migrations/__init__.py b/authentication/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/models.py b/authentication/models.py new file mode 100644 index 0000000..81781b5 --- /dev/null +++ b/authentication/models.py @@ -0,0 +1,548 @@ +import string +import random +from django.contrib.postgres.fields import ArrayField +from django.db import models +from django.contrib.auth.models import User, Group +from django.conf import settings +from datetime import datetime, timezone, time, timedelta +from django.utils import timezone + +import uuid + + +# مدل پایه که تمامی مدل ها در سیستم ازین مدل ارث بری می کنند +from general_urls import base_user_gate_way_id + + +class BaseModel(models.Model): + key = models.UUIDField(default=uuid.uuid4, editable=False, unique=True) + create_date = models.DateTimeField(auto_now_add=True) + modify_date = models.DateTimeField(auto_now=True) + created_by = models.ForeignKey( + settings.AUTH_USER_MODEL, + related_name="%(class)s_createdby", + on_delete=models.CASCADE, + null=True, + blank=True, + ) + modified_by = models.ForeignKey( + settings.AUTH_USER_MODEL, + on_delete=models.CASCADE, + related_name="%(class)s_modifiedby", + null=True, + blank=True, + ) + trash = models.BooleanField(default=False) + + class Meta: + abstract = True + + +# مدل استان برای ذخیره استان استفاده میشود +class Province(BaseModel): + name = models.CharField(max_length=200, null=True) + province_id_key = models.IntegerField(null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Province, self).save(*args, **kwargs) + + +# مدل شهرستان برای ذخیره شهرستان استفاده میشود +class City(BaseModel): + province = models.ForeignKey( + Province, on_delete=models.CASCADE, related_name="city_province", null=True + ) + province_id_foreign_key = models.IntegerField(null=True) + city_id_key = models.IntegerField(null=True) + name = models.CharField(max_length=200, null=True) + product_price = models.FloatField(default=0) + province_center = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(City, self).save(*args, **kwargs) + + +# مدل زیربخش شهرستان برای ذخیره زیربخش شهرستان استفاده میشود +class CityUnit(BaseModel): + city = models.ForeignKey( + City, on_delete=models.CASCADE, related_name="city_province", null=True + ) + city_id_foreign_key = models.IntegerField(null=True) + city_unit_id_key = models.IntegerField(null=True) + name = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(CityUnit, self).save(*args, **kwargs) + + +class PermissionLevel(BaseModel): + role = models.ForeignKey( + Group, + on_delete=models.CASCADE, + null=True, + related_name='group_permission' + ) + name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(PermissionLevel, self).save(*args, **kwargs) + + +# مدل آدرس برای ذخیره آدرس استفاده میشود +class SystemAddress(BaseModel): + province = models.ForeignKey( + Province, + on_delete=models.CASCADE, + related_name="province_address", + null=True + ) + city = models.ForeignKey( + City, + on_delete=models.CASCADE, + related_name="city_address", + null=True + ) + province_id_foreign_key = models.IntegerField(null=True) + city_id_foreign_key = models.IntegerField(null=True) + address_id_key = models.IntegerField(null=True) + address = models.CharField(max_length=300, null=True) + postal_code = models.CharField(max_length=20, default="", null=True) + breeding_unique_id = models.CharField(max_length=50, null=True) + phone = models.CharField(max_length=20, default="", null=True) + phone_type = models.CharField(max_length=20, default="", null=True) + no = models.CharField(max_length=5, default="", null=True) + floor = models.IntegerField(default=0, null=True) + unit = models.IntegerField(default=0, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(SystemAddress, self).save(*args, **kwargs) + + +# مدل آدرس برای ذخیره آدرس استفاده میشود +class Address(BaseModel): + title = models.CharField(max_length=200, default="", null=True) + country = models.CharField(max_length=100, default="", null=True) + province = models.CharField(max_length=50, default="", null=True) + city = models.CharField(max_length=50, default="", null=True) + address = models.CharField(max_length=300, null=True) + postal_code = models.CharField(max_length=20, default="", null=True) + breeding_unique_id = models.CharField(max_length=50, null=True) + phone = models.CharField(max_length=20, default="", null=True) + phone_type = models.CharField(max_length=20, default="", null=True) + no = models.CharField(max_length=5, default="", null=True) + floor = models.IntegerField(default=0, null=True) + unit = models.IntegerField(default=0, null=True) + + def save(self, *args, **kwargs): + super(Address, self).save(*args, **kwargs) + + +# مدل اطلاعات بانکی برای ذخیره اطلاعات جساب شخص استفاده میشود +class BankCard(BaseModel): + name_of_bank_user = models.CharField(max_length=200, null=True) + bank_name = models.CharField(max_length=30, null=True) + card = models.CharField(max_length=16, null=True) + shaba = models.CharField(max_length=100, null=True) + account = models.CharField(max_length=50, null=True) + user_bank_id_key = models.IntegerField(null=True) + province_name = models.CharField(max_length=50, null=True) + + # state = models.CharField(max_length=30, null=True) + + +class MultiRole(BaseModel): + user = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="multi_role_users", null=True + ) + address = models.ForeignKey( + Address, + on_delete=models.CASCADE, + related_name='multi_role_address', + null=True + ) + + def save(self, *args, **kwargs): + super(MultiRole, self).save(*args, **kwargs) + + +# مدل پروفایل کاربری برای ذخیره پروفایل کاربری شخص استفاده میشود +class SystemUserProfile(BaseModel): + token = models.CharField(max_length=36, null=True) + user_gate_way_id = models.CharField(max_length=6,null=True, unique=True) + + user = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="system_user_profile_user", null=True + ) + province = models.ForeignKey( + Province, + on_delete=models.CASCADE, + related_name='user_province', + null=True + ) + + city = models.ForeignKey( + City, + on_delete=models.CASCADE, + related_name='user_city', + null=True + ) + + user_django_id_foreign_key = models.IntegerField(null=True) + province_id_foreign_key = models.IntegerField(null=True) + city_id_foreign_key = models.IntegerField(null=True) + system_user_profile_id_key = models.IntegerField(null=True) + fullname = models.CharField(max_length=150, null=True) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + father_name = models.CharField(max_length=200, null=True) + gender = models.CharField(max_length=20, null=True) + is_alive = models.BooleanField(null=True) + national_code = models.CharField(max_length=20, null=True) + national_code_image = models.CharField(max_length=500, null=True) + national_id = models.CharField(max_length=20, null=True) + mobile = models.CharField(max_length=11, null=True) + birthday = models.CharField(max_length=20, null=True) + image = models.CharField(max_length=500, null=True) + password = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + state = models.JSONField( + default={ + "province": "", + "city": "", + "first_name": "", + "last_name": "", + "national_code": "", + "national_id": "", + "mobile": "", + "birthday": "", + "image": "" + } + ) + access_level = models.ManyToManyField( + PermissionLevel, + related_name="user_permission_level" + ) + role = models.ManyToManyField( + Group, + related_name='user_system_roles' + ) + base_order = models.BigIntegerField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + unit_name = models.CharField(max_length=500, null=True) + unit_national_id = models.CharField(max_length=100, null=True) + unit_registration_number = models.CharField(max_length=100, null=True) + unit_economical_number = models.CharField(max_length=100, null=True) + unit_province = models.CharField(max_length=100, null=True) + unit_city = models.CharField(max_length=100, null=True) + unit_postal_code = models.CharField(max_length=100, null=True) + unit_address = models.TextField(null=True) + pos = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + if self.user_gate_way_id is None: + while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)) + res = base_user_gate_way_id + res + if not SystemUserProfile.objects.filter(user_gate_way_id=res).exists(): + break + self.user_gate_way_id=res + super(SystemUserProfile, self).save(*args, **kwargs) + + +# مدل پروفایل کاربری برای ذخیره پروفایل کاربری شخص استفاده میشود +class UserProfile(BaseModel): + key = models.UUIDField(default=uuid.uuid4, editable=True, null=True) + token = models.CharField(max_length=36, default="") + app_token = models.CharField(max_length=36, null=True) + user = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="users", null=True + ) + company = models.CharField(max_length=30, null=True) + address = models.ForeignKey( + Address, + on_delete=models.CASCADE, + related_name='user_address', + null=True + ) + role = models.ForeignKey( + Group, + on_delete=models.CASCADE, + null=True, + related_name='user_role' + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="bank_user", + null=True + ) + fullname = models.CharField(max_length=150, null=True, default="") + first_name = models.CharField(max_length=200, null=True, default="") + last_name = models.CharField(max_length=200, null=True, default="") + natinal_id = models.CharField(max_length=10, null=True, default="") + mobile = models.CharField(max_length=11, null=True, default="") + birthday = models.CharField(max_length=20, null=True, default="") + image = models.CharField(max_length=500, null=True) + state = models.CharField(max_length=20, default="register") + unit_name = models.CharField(max_length=100, null=True) + password = models.CharField(max_length=100, null=True) + gis_code = models.CharField(max_length=30, null=True) + operating_licence_capacity = models.BigIntegerField(default=0) + number_of_halls = models.IntegerField(default=0) + tenant = models.BooleanField(null=True) + person_type = models.CharField(max_length=10, null=True) + economic_code = models.CharField(max_length=30, null=True) + system_code = models.CharField(max_length=20, null=True) + epidemiological_code = models.CharField(max_length=20, null=True) + breeding_unique_id = models.CharField(max_length=20, null=True) + total_capacity = models.BigIntegerField(default=0) + licence_number = models.CharField(max_length=20, null=True) + health_certificate_number = models.CharField(max_length=20, null=True) + number_of_requests = models.BigIntegerField(default=0) + hatching_date = models.DateTimeField(default=timezone.now()) + last_party_date = models.DateTimeField(default=timezone.now()) + number_of_incubators = models.BigIntegerField(default=0) + herd_age_by_day = models.IntegerField(default=0) + herd_age_by_week = models.IntegerField(default=0) + number_of_party = models.IntegerField(default=0) + communication_type = models.CharField(max_length=30, null=True) + cooperative = models.CharField(max_length=50, null=True) + date_of_register = models.DateTimeField(default=timezone.now()) + unit_status = models.CharField(max_length=20, null=True) + samasat_user_code = models.CharField(max_length=20, null=True) + base_order = models.BigIntegerField(null=True) + incubation_date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + # if self.first_name != None and self.last_name != None: + # self.fullname = self.first_name + " " + self.last_name + super(UserProfile, self).save(*args, **kwargs) + + +# مدل نقاط جغرافیایی برای ذخیره نقاط طولی و عرضی آدرس استفاده میشود +class GeoPoint(BaseModel): + userprofile = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + related_name="geo_user", + null=True + ) + name = models.CharField(max_length=100, null=True) + lang = models.CharField(max_length=50, null=True) + lat = models.CharField(max_length=50, null=True) + + +class Tenant(BaseModel): + userprofile = models.ManyToManyField( + UserProfile, + related_name="tenant_user", + ) + fullname = models.CharField(max_length=50, null=True) + national_code = models.CharField(max_length=20, null=True) + birthday = models.CharField(max_length=50, null=True) + rental = models.CharField(max_length=30, null=True) + tracking_code = models.CharField(max_length=30, null=True) + rent_date_from = models.CharField(max_length=30, null=True) + rent_date_to = models.CharField(max_length=30, null=True) + + +class UserMessageType(BaseModel): + message_types = ( + ("user", "USER"), + ("alluser", "AllUSER"), + ("group", "GROUP"), + ("allgroup", "AllGROUP"), + ("usergroup", "UserGroup"), + ("province_accept", "ProvinceAccept"), + ("province_rejected", "ProvinceRejected"), + ("city_operator_accept", "CityOperatorAccept"), + ("city_operator_rejected", "CityOperatorRejected"), + ("assignment_accepted", "AssignmentAccepted"), + ("assignment_rejected", "AssignmentRejected"), + ) + name = models.CharField(choices=message_types, max_length=50, default="", null=True) + + def __str__(self) -> str: + return self.name + + def save(self, *args, **kwargs): + super(UserMessageType, self).save(*args, **kwargs) + + pass + + +# مدل پیام کاربر برای ذخیره پیام کاربر استفاده میشود +class UserMessage(BaseModel): + roles = models.ManyToManyField( + Group, + blank=True, + related_name="user_roles" + ) + users = models.ManyToManyField( + SystemUserProfile, + blank=True, + related_name="user_message" + ) + sender = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="message_sender", + null=True + ) + heading = models.CharField(max_length=100, null=True, default="") + message = models.TextField(max_length=500, null=True, default="") + link_text = models.CharField(max_length=150, null=True) + link = models.CharField(max_length=100, null=True) + image = models.JSONField(default=dict, null=True) + expire = models.DateTimeField(default=datetime.now() + timedelta(hours=1)) + time = models.DateTimeField(default=datetime.now()) + state = models.CharField(max_length=20, default="pending") + message_type = models.ForeignKey( + UserMessageType, + on_delete=models.CASCADE, + null=True, + related_name="message_type" + ) + message_level = models.CharField(max_length=50, null=True) + + def save(self, *args, **kwargs): + super(UserMessage, self).save(*args, **kwargs) + + +class SendingMessageMethod(BaseModel): + level = models.CharField(max_length=50, null=True) + methods = models.CharField(max_length=150, null=True) + + def save(self, *args, **kwargs): + super(SendingMessageMethod, self).save(*args, **kwargs) + + +class Log(BaseModel): + user = models.ForeignKey( + User, on_delete=models.CASCADE, related_name="log_user", null=True + ) + function_name = models.CharField(max_length=200, null=True) + duration = models.FloatField(null=True) + status = models.IntegerField(null=True) + response = models.TextField(null=True) + request = models.TextField(null=True) + request_body = models.TextField(null=True) + response_body = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(Log, self).save(*args, **kwargs) + + +class ExternalTransaction(BaseModel): + date = models.DateTimeField(auto_now_add=True) + amount = models.BigIntegerField(default=0) + amount_with_tax = models.BigIntegerField(default=0) + status = models.CharField(max_length=100, default='pending') + transaction_type = models.CharField(max_length=100, null=True) + type = models.CharField(max_length=100, null=True) + payer = models.CharField(max_length=100, null=True) + description = models.CharField(max_length=200, default=False) + is_complete = models.BooleanField(default=False) + message = models.TextField(null=True) + saleReferenceId = models.CharField(max_length=100, null=True) + refId = models.CharField(max_length=100, null=True) + orderId = models.CharField(max_length=100, null=True) + cardHolderPan = models.CharField(max_length=100, null=True) + receiver_role = models.CharField(max_length=100, null=True) + creator_role = models.CharField(max_length=100, null=True) + kill_house_user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="transaction_kill_house_user" + ) + chain_company_user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="transaction_chain_company_user" + ) + receiver = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="receiver_user" + ) + creator = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="creator_user" + ) + union_share = models.BigIntegerField(default=0) + company_share = models.BigIntegerField(default=0) + guilds_share = models.BigIntegerField(default=0) + city_share = models.BigIntegerField(default=0) + wallet_share = models.BigIntegerField(default=0) + other_share = models.BigIntegerField(default=0) + pay_type = models.CharField(max_length=200, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + + def save(self, *args, **kwargs): + super(ExternalTransaction, self).save(*args, **kwargs) + + +class UserMessageSend(BaseModel): + user = models.ForeignKey(SystemUserProfile, on_delete=models.CASCADE, null=True) + message = models.TextField(null=True) + receive_code = models.CharField(max_length=400, null=True) + + def save(self, *args, **kwargs): + super(UserMessageSend, self).save(*args, **kwargs) + + +class Notice(BaseModel): + title = models.CharField(max_length=1000, null=True) + text = models.TextField(null=True) + users = models.JSONField(null=True) + read_users = models.JSONField(null=True) + unread_users = models.JSONField(null=True) + images = models.JSONField(null=True) + roles = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(Notice, self).save(*args, **kwargs) + + +class UserNoticeInfo(BaseModel): + notice = models.ForeignKey( + Notice, + related_name="user_notice", + + on_delete=models.CASCADE, + null=True + ) + user = models.ForeignKey( + SystemUserProfile, + related_name="notice_users", + on_delete=models.CASCADE, + null=True + ) + seen = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(UserNoticeInfo, self).save(*args, **kwargs) diff --git a/authentication/permission_views.py b/authentication/permission_views.py new file mode 100644 index 0000000..9c0ec92 --- /dev/null +++ b/authentication/permission_views.py @@ -0,0 +1,75 @@ + +# ویوست و توابعی که برای ایجاد سطج دستزسی جدید در سیستم استفاده میشوند + + +from django.contrib.auth.models import Group +from oauth2_provider.contrib.rest_framework import TokenHasScope, TokenHasReadWriteScope +from rest_framework import viewsets, serializers, status +from rest_framework.permissions import IsAuthenticated +from . import permissions +from rest_framework.response import Response +import logging + +log = logging.getLogger(__name__) + + +class GroupSerializer(serializers.ModelSerializer): + class Meta: + model = Group + fields = ['name'] + + +class GroupPermissionViewset(viewsets.ModelViewSet): + authentication_classes = [] + permission_classes = [TokenHasReadWriteScope] + queryset = Group.objects.all() + serializer_class = GroupSerializer + + def get_queryset(self): + queryset = super(GroupPermissionViewset, self).get_queryset() + log.error(f"here {self.request.user}") + + return queryset + + def list(self, request, *args, **kwargs): + queryset = super(GroupPermissionViewset, self).get_queryset() + log.error(f"here {request.user}") + + serializer = GroupSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + serializer.create(validated_data=request.data) + return Response(serializer.data) + return Response(serializer.errors) + + def retrieve(self, request, pk=None, *args, **kwargs): + key = request.GET['name'] + log.error(f"here {request.user}") + queryset = super(GroupPermissionViewset, self).get_queryset() + + queryset = queryset.get(name__exact=key) + serializer = self.serializer_class(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + key = request.GET['name'] + queryset = super(GroupPermissionViewset, self).get_queryset() + queryset = queryset.get(name__exact=key) + serializer = self.serializer_class(queryset) + serializer.update(instance=queryset, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def partial_update(self, request, pk=None, *args, **kwargs): + pass + + def destroy(self, request, pk=None, *args, **kwargs): + key = request.GET['name'] + queryset = super(GroupPermissionViewset, self).get_queryset() + + queryset = queryset.get(name__exact=key) + queryset.delete() + queryset.save() + return Response(status=status.HTTP_200_OK) diff --git a/authentication/permissions.py b/authentication/permissions.py new file mode 100644 index 0000000..72115a7 --- /dev/null +++ b/authentication/permissions.py @@ -0,0 +1,329 @@ + +# ویوست ها و توابعی که برای ایجاد سطج دستزسی جدید در سیستم استفاده میشوند + + +from rest_framework.permissions import BasePermission, DjangoModelPermissions +# from django.utils.datetime_safe import datetime +from authentication.models import UserProfile +from django.contrib.auth.models import Group +from datetime import timedelta, datetime +from rest_framework import permissions +from django.utils import timezone + + +class IsAuthenticatedOrCreate(permissions.IsAuthenticated): + def has_permission(self, request, view): + if request.method == 'POST': + return True + return super(IsAuthenticatedOrCreate, self).has_permission(request, view) + + +class IsOwner(permissions.BasePermission): + message = "Not an owner." + + def has_object_permission(self, request, view, obj): + if request.method in permissions.SAFE_METHODS: + return True + return request.user == obj.created_by + + +class AuthorOrReadOnly(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.is_authenticated: + return True + return False + + def has_object_permission(self, request, view, obj): + if obj.author == request.user: + return True + return False + + +class AuthenticatedOnly(permissions.BasePermission): + + def has_object_permission(self, request, view, obj): + if request.user.is_authenticated: + return True + return False + + +class AuthorAllStaffAllButEditOrReadOnly(permissions.BasePermission): + edit_methods = ("PUT", "PATCH") + + def has_permission(self, request, view): + if request.user.is_authenticated: + return True + + def has_object_permission(self, request, view, obj): + if request.user.is_superuser: + return True + + if request.method in permissions.SAFE_METHODS: + return True + + if obj.author == request.user: + return True + + if request.user.is_staff and request.method not in self.edit_methods: + return True + + return False + + +class ExpiredObjectSuperuserOnly(permissions.BasePermission): + message = "This object is expired." # custom error message + + def object_expired(self, obj): + expired_on = timezone.make_aware(datetime.now() - timedelta(minutes=10)) + return obj.created < expired_on + + def has_object_permission(self, request, view, obj): + + if self.object_expired(obj) and not request.user.is_superuser: + return False + else: + return True + + +class IsStaff(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.is_staff: + return True + return False + + def has_object_permission(self, request, view, obj): + if request.user.is_staff: + return True + return False + + +class IsOwner2(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.is_authenticated: + return True + return False + + def has_object_permission(self, request, view, obj): + if obj.author == request.user: + return True + return False + + +class IsFinancesMember(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Finances").exists(): + return True + + +class IsCustomer(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Customer").exists(): + return True + + +class IsOperator(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Operator").exists(): + return True + + +class IsSaler(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Saler").exists(): + return True + + +class IsSupervisor(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Supervisor").exists(): + return True + + +class IsStorekeeper(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Storekeeper").exists(): + return True + + +class IsDeliveryMember(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Delivery").exists(): + return True + + +class IsAdminMember(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="Admin").exists(): + return True + + +class IsChatRoomOperator(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="ChatRoomOperator").exists(): + return True + + +class IsInformationOperator(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="InformationOperator").exists(): + return True + + +class IsFinanceUnitOperator(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="FinancialUnitOperator").exists(): + return True + + +class IsFinanceUnitAdmin(permissions.BasePermission): + + def has_permission(self, request, view): + if request.user.groups.filter(name="FinancialUnitAdmin").exists(): + return True + + +class IsSuperUser(BasePermission): + + def has_permission(self, request, view): + return request.user and request.user.is_superuser + + +class CityOperator(BasePermission): + + def has_permission(self, request, view): + if UserProfile.objects.filter(user__exact=request.user, role__name__exact="CityOperator").exists(): + return True + else: + return False + + +class ProvinceOperator(BasePermission): + + def has_permission(self, request, view): + if UserProfile.objects.filter(user__exact=request.user, role__name__exact="ProvinceOperator").exists(): + return True + + +class Poultry(BasePermission): + + def has_permission(self, request, view): + if UserProfile.objects.filter(user__exact=request.user, role__exact="Poultry").exists(): + return True + + +class KillHouseOperator(BasePermission): + + def has_permission(self, request, view): + if UserProfile.objects.filter(user__exact=request.user, role__exact="KillHouseOperator").exists(): + return True + + +class OwnerOrModelPermission(DjangoModelPermissions): + + def __same_user(self, obj, request): + from django.contrib.auth.models import User + return isinstance(obj, User) and obj.id == request.user.id + + def __is_owner(self, obj, request): + return hasattr(obj, 'owner') and obj.owner is not None and self.__same_user(obj.owner, request) + + def has_permission(self, request, view): + return request.user.is_superuser or DjangoModelPermissions().has_permission(request, view) + + def has_object_permission(self, request, view, obj): + return request.user.is_superuser or self.__same_user( + obj, request) or self.__is_owner( + obj, request) or DjangoModelPermissions().has_object_permission(request, view, obj) + + +class PaymentRequiredPermission(DjangoModelPermissions): + def can_operate(self, request): + return request.user.has_paid() + + def has_permission(self, request, view): + return self.can_operate(request) + + def has_object_permission(self, request, view, obj): + return self.can_operate(request) + + +class IsUser(BasePermission): + def has_permission(self, request, view): + return request.user and request.user.is_superuser + + def has_object_permission(self, request, view, obj): + return request.user.is_superuser or obj.user.id == request.user.id + + +class APIPermission(permissions.BasePermission): + message = 'Only API user can access APIs' + + group_name = "api" + + def has_permission(self, request, view): + try: + group = request.user.groups.get(name=self.group_name) + except Group.DoesNotExist: + self.message = "Permission denied, user group '{}' does not exists".format(self.group_name) + return False + return group.name == self.group_name + + +def _is_in_group(user, group_name): + """ + Takes a user and a group name, and returns `True` if the user is in that group. + """ + try: + return Group.objects.get(name=group_name).user_set.filter(id=user.id).exists() + except Group.DoesNotExist: + return None + + +def _has_group_permission(user, required_groups): + return any([_is_in_group(user, group_name) for group_name in required_groups]) + + +class IsLoggedInUserOrAdmin(permissions.BasePermission): + # group_name for super admin + required_groups = ['admin'] + + def has_object_permission(self, request, view, obj): + has_group_permission = _has_group_permission(request.user, self.required_groups) + if self.required_groups is None: + return False + return obj == request.user or has_group_permission + + +class IsAdminUser(permissions.BasePermission): + # group_name for super admin + required_groups = ['admin'] + + def has_permission(self, request, view): + has_group_permission = _has_group_permission(request.user, self.required_groups) + return request.user and has_group_permission + + def has_object_permission(self, request, view, obj): + has_group_permission = _has_group_permission(request.user, self.required_groups) + return request.user and has_group_permission + + +class IsAdminOrAnonymousUser(permissions.BasePermission): + required_groups = ['admin', 'anonymous'] + + def has_permission(self, request, view): + has_group_permission = _has_group_permission(request.user, self.required_groups) + return request.user and has_group_permission diff --git a/authentication/register.py b/authentication/register.py new file mode 100644 index 0000000..9970710 --- /dev/null +++ b/authentication/register.py @@ -0,0 +1,4427 @@ +from datetime import datetime, timedelta +import utm +from django.contrib.auth.models import User, Group +from django.db.models.functions import Abs +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from rest_framework import status +import openpyxl +from openpyxl.styles import Font, Alignment, PatternFill, Border, Side +from openpyxl.worksheet.datavalidation import DataValidation +from openpyxl.utils import get_column_letter +from io import BytesIO + +from authentication.sahandsms.sms import USERNAME_SMS_FINANCIAL, PASSWORD_SMS_FINANCIAL, OUT_SMS_PASS, OUT_SMS_USER, \ + PASSWORD_SMS_HAMEDAN, USERNAME_SMS_HAMEDAN +from authentication.sms_management import send_sms_request +from authentication.views import ARTA_URL_CHANGE_MOBILE_NUMBER, ARTA_URL_CHANGE_PASSWORD +from general_urls import base_user_gate_way_id, base_url_for_sms_report +from panel.KillHouse.helpers import kill_house_free_sale_product_warehousing, kill_house_requests_product_warehousing, \ + kill_house_free_buying_product_warehousing, kill_house_allocations_product_warehousing +from panel.ProvinceOperator.helpers import guild_steward_allocations_product_warehousing, \ + guild_steward_free_buying_product_warehousing, guild_steward_free_sale_product_warehousing, \ + guild_steward_product_segmentation +from panel.admin import PROJECT_API_KEY +from panel.convert_date import convert_to_miladi +from panel.helper import UNION_NUMBER, check_mobile_number +from panel.helper_excel import percent_of_losses, shamsi_date, to_locale_str +from panel.models import KillHouseDriver, Poultry, PoultryRequest, Wallet, LastUpdate, \ + KillHouseAssignmentInformation, KillHouseRequest, KillHouse, InternalTransaction, Guilds, Steward, GuildSteward, \ + RolesProducts, StewardAllocation, NewProduct, KillHouseFreeBarInformation, KillHouseFreeSaleBarInformation, \ + ColdHouseAllocations, CityOperatorCheckRequest, KillRequest, StewardFreeBarInformation, \ + StewardFreeSaleBarInformation, ChainAllocation, KillHouseWareHouse, VetFarm, CityOperator, CityGuild, \ + BarDifferenceRequest, PosSegmentation, PosMachineTransactions, WarehouseArchive, ProductsTransactions +from authentication.models import SystemUserProfile, City, Province, ExternalTransaction +import requests +from rest_framework.decorators import permission_classes, api_view +from rest_framework.permissions import AllowAny +from django.db.models import Q, F, Count, Sum + +from panel.poultry.helpers import poultry_prediction +from ticket.models import TicketSupport, MessageSupport + +ARTA_REGISTER = "https://userbackend.rasadyar.com/api/register_all/" +from rest_framework.response import Response +import hashlib + + +# pk_assigment = [4990, 4991, 4992, 4385, 4386, 4387, 4447, 4448, 4449, 4839, 4840, 5084, 5109, 5111, 3875, 4895, 4897, +# 4899, 4900, 4901, 4902, 4530, 4531, 4532, 4533, 4534, 4583, 4585, 4630, 4632, 4635, 4034, 3130, 3132, +# 4707, 4708, 4709, 4710, 4711, 3173, 3174, 3176, 3177, 3178, 3179, 3180] +# +# pk_kill_house_request = [12291, 12289, 12288, 11568, 11569, 11567, 11669, 11667, 11671, 12053, 12055, 12368, 12401, +# 12421, 10918, 12124, 12136, 12135, 12137, 12132, 12134, 11734, 11731, 11732, 11733, 11735, +# 11779, 11782, 11875, 11873, 11871, 11142, 10104, 10106, 11886, 11887, 11889, 11891, 11893, +# 10084, 10085, 10080, 10082, 10075, 10077, 10116] +# +# pk_province_kill_request = [4289, 4275, 4275, 4041, 4041, 4038, 4076, 4076, 4055, 4195, 4195, 4316, 4334, 4335, 3811, 4215, +# 4217, 4217, 4217, 4218, 4218, 4104, +# 4104, 4104, 4104, 4104, 4114, 4114, 4136, 4136, 4148, 3877, 3546, 3545, 4151, 4151, 4151, 4151, +# 4151, 3530, 3530, 3542, 3542, 3535, 3535, 3542] +# +# pk_hatching = [1273, 1251, 1251, 1206, 1206, 1252, 1247, 1247, 1206, 1203, 1203, 1276, 1307, 1249, 1143, 1281, 1232, +# 1232, 1232, 1273, 1273, 1240, +# 1240, 1240, 1240, 1240, 1234, 1234, 1200, 1200, 1247, 1186, 1085, 1098, 1251, 1251, 1251, 1251, 1251, +# 1336, 1336, 1113, 1113, 1253, 1253, 1113] + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def create_driver_excel_template(request): + """ + ایجاد فایل اکسل قالب برای ثبت راننده‌ها + پارامتر: kill_house_ids - لیست id کشتارگاه‌ها (کاما جدا شده) + """ + # دریافت id های کشتارگاه از پارامترهای درخواست + kill_house_ids_param = request.GET.get('kill_house_ids', '') + + if kill_house_ids_param: + kill_house_ids = [int(x.strip()) for x in kill_house_ids_param.split(',') if x.strip()] + kill_houses = KillHouse.objects.filter(trash=False, id__in=kill_house_ids) + else: + kill_houses = KillHouse.objects.filter(trash=False) + + # ساخت workbook + workbook = openpyxl.Workbook() + worksheet = workbook.active + worksheet.title = "رانندگان" + worksheet.sheet_view.rightToLeft = True + + # تعریف هدرهای اکسل + headers = [ + 'کشتارگاه', + 'مدل خودرو', + 'نوع خودرو', + 'پلاک خودرو', + 'کد بهداشتی حمل', + 'تاریخ اعتبار بهداشتی', + 'ظرفیت خودرو(قفس)', + 'کد ملی راننده', + 'شماره تماس راننده', + 'ملاحظات' + ] + + # استایل‌ها + header_fill = PatternFill(start_color="1E487B", fill_type="solid") + header_font = Font(size=11, bold=True, color="FFFFFF") + header_alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + thin_border = Border( + left=Side(style='thin'), + right=Side(style='thin'), + top=Side(style='thin'), + bottom=Side(style='thin') + ) + + # نوشتن هدرها + for col_num, header in enumerate(headers, 1): + cell = worksheet.cell(row=1, column=col_num, value=header) + cell.fill = header_fill + cell.font = header_font + cell.alignment = header_alignment + cell.border = thin_border + worksheet.column_dimensions[get_column_letter(col_num)].width = 18 + + # تنظیم عرض ستون‌ها + worksheet.column_dimensions['A'].width = 30 # کشتارگاه + worksheet.column_dimensions['D'].width = 22 # پلاک خودرو + worksheet.column_dimensions['F'].width = 20 # تاریخ اعتبار بهداشتی + worksheet.column_dimensions['J'].width = 25 # ملاحظات + + # ارتفاع ردیف هدر + worksheet.row_dimensions[1].height = 25 + + # ایجاد شیت جدید برای لیست کشتارگاه‌ها + kill_house_sheet = workbook.create_sheet(title="لیست کشتارگاه‌ها") + kill_house_sheet.sheet_view.rightToLeft = True + + # هدر شیت کشتارگاه‌ها + kill_house_headers = ['شناسه (ID)', 'نام کشتارگاه'] + for col_num, header in enumerate(kill_house_headers, 1): + cell = kill_house_sheet.cell(row=1, column=col_num, value=header) + cell.fill = header_fill + cell.font = header_font + cell.alignment = header_alignment + cell.border = thin_border + + kill_house_sheet.column_dimensions['A'].width = 15 + kill_house_sheet.column_dimensions['B'].width = 35 + + # لیست برای dropdown + kill_house_list = [] + + # پر کردن لیست کشتارگاه‌ها + for row_num, kill_house in enumerate(kill_houses, 2): + # فرمت: "id - نام کشتارگاه" + display_value = f"{kill_house.id} - {kill_house.name or 'بدون نام'}" + kill_house_list.append(display_value) + + kill_house_sheet.cell(row=row_num, column=1, value=kill_house.id).border = thin_border + kill_house_sheet.cell(row=row_num, column=2, value=kill_house.name or 'بدون نام').border = thin_border + + # ایجاد dropdown برای ستون کشتارگاه + if kill_house_list: + # اگر تعداد کشتارگاه‌ها زیاد باشد، از reference به شیت دیگر استفاده می‌کنیم + if len(kill_house_list) <= 100: + # استفاده از لیست مستقیم + dv = DataValidation( + type="list", + formula1='"' + ','.join(kill_house_list) + '"', + allow_blank=True + ) + else: + # استفاده از reference به شیت کشتارگاه‌ها + dv = DataValidation( + type="list", + formula1=f"'لیست کشتارگاه‌ها'!$A$2:$A${len(kill_house_list) + 1}", + allow_blank=True + ) + + dv.error = 'لطفاً از لیست کشتارگاه‌ها انتخاب کنید' + dv.errorTitle = 'ورودی نامعتبر' + dv.prompt = 'یک کشتارگاه از لیست انتخاب کنید' + dv.promptTitle = 'انتخاب کشتارگاه' + + # اضافه کردن validation به ستون اول (کشتارگاه) برای 1000 ردیف + dv.add('A2:A1001') + worksheet.add_data_validation(dv) + + # ذخیره فایل در BytesIO + output = BytesIO() + workbook.save(output) + output.seek(0) + + # ارسال فایل به عنوان response + response = HttpResponse( + content=output.getvalue(), + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + ) + response['Content-Disposition'] = 'attachment; filename="driver_template.xlsx"' + + return response + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def upload_driver_excel(request): + from panel.models import KillHouseADDCAR + + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Driver") + + success_count = 0 + error_list = [] + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i == 1: + continue + + try: + kill_house_value = row[0] + type_car = row[2] # مدل خودرو + pelak = row[3] # پلاک خودرو + health_code = row[4] # کد بهداشتی حمل + health_code_expiry = row[5] # تاریخ اعتبار بهداشتی + capacity = row[6] # ظرفیت خودرو (قفس) + national_code = row[7] # کد ملی راننده + driver_mobile = row[8] # شماره تماس راننده + notes = row[9] if len(row) > 9 else None # ملاحظات + + kill_house_id = None + if kill_house_value: + if isinstance(kill_house_value, int): + kill_house_id = kill_house_value + elif isinstance(kill_house_value, str): + if ' - ' in str(kill_house_value): + kill_house_id = int(str(kill_house_value).split(' - ')[0].strip()) + else: + kill_house_id = int(kill_house_value) + + kill_house = None + if kill_house_id: + kill_house = KillHouse.objects.filter(trash=False, id=kill_house_id).first() + + driver_mobile = str(driver_mobile) if driver_mobile else None + if driver_mobile and len(driver_mobile) <= 10: + driver_mobile = '0' + driver_mobile + + if not driver_mobile: + error_list.append(f"ردیف {i + 1}: شماره تماس راننده خالی است") + continue + + driver_name = "" + if kill_house: + existing_drivers_count = KillHouseADDCAR.objects.filter( + trash=False, + kill_house=kill_house, + archive=False + ).count() + + kill_house_name = kill_house.name or f"کشتارگاه {kill_house.id}" + driver_number = existing_drivers_count + 1 + driver_name = f"راننده {kill_house_name} {driver_number}" + + system_profile = None + try: + system_profile = SystemUserProfile.objects.get(trash=False, mobile=driver_mobile) + if group not in system_profile.role.all(): + system_profile.role.add(group) + + if not system_profile.first_name and driver_name: + system_profile.first_name = driver_name + system_profile.fullname = driver_name + system_profile.save() + + except SystemUserProfile.DoesNotExist: + password = '123456' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + + data = { + "username": driver_mobile, + "first_name": driver_name, + "last_name": "", + "password": hashed_password, + "national_code": str(national_code) if national_code else "", + "role": "Driver", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=driver_mobile, first_name=driver_name, last_name="", password=hashed_password) + user.save() + + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + + province_obj = None + city_obj = None + if kill_house and kill_house.system_address: + province_obj = kill_house.system_address.province + city_obj = kill_house.system_address.city + + system_profile = SystemUserProfile( + mobile=driver_mobile, + first_name=driver_name, + last_name="", + fullname=driver_name, + user=user, + base_order=base_id, + password=password, + national_code=str(national_code) if national_code else None, + city=city_obj, + province=province_obj + ) + system_profile.save() + system_profile.role.add(group) + else: + error_list.append(f"ردیف {i + 1}: خطا در ثبت کاربر در سیستم مرکزی") + continue + + province_name = None + province_number = 0 + city_name = None + city_number = 0 + + if kill_house: + province_name = kill_house.province_name + province_number = kill_house.province_number or 0 + city_name = kill_house.city_name + city_number = kill_house.city_number or 0 + + driver = KillHouseDriver( + type_car=str(type_car) if type_car else None, + type='exclusive', + capocity=str(capacity) if capacity else None, + pelak=str(pelak) if pelak else None, + health_code=str(health_code) if health_code else None, + driver_name=driver_name, + driver_mobile=driver_mobile, + user=system_profile, + ) + driver.save() + + if kill_house: + if not KillHouseADDCAR.objects.filter( + trash=False, + kill_house=kill_house, + driver=driver, + archive=False + ).exists(): + add_car = KillHouseADDCAR( + kill_house=kill_house, + driver=driver, + kill_house_id_foreign_key=kill_house.id, + driver_id_foreign_key=driver.id, + province_name=province_name, + province_number=province_number, + city_name=city_name, + city_number=city_number + ) + add_car.save() + + success_count += 1 + + except Exception as e: + error_list.append(f"ردیف {i + 1}: {str(e)}") + continue + + return Response({ + "result": "عملیات با موفقیت انجام شد", + "success_count": success_count, + "errors": error_list + }, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_driver_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Driver") + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + first_name = row[1] + last_name = row[2] + mobile = row[3] + birthday = row[4] + province = row[5] + city = row[6] + password = row[7] + national_code = row[8] + car = row[9] + capacity = row[10] + plaque = row[11] + health_code = row[12] + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + + province = Province.objects.filter(name=province) + province = province.last() + city = City.objects.filter(name=city) + city = city.last() + + if i == 0: + continue + mobile = str(mobile) + if len(mobile) <= 10: + mobile = '0' + mobile + try: + system_profile = SystemUserProfile.objects.get(trash=False, mobile=mobile) + if 'Driver' not in system_profile.role.all(): + system_profile.role.add(group) + + except: + + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": national_code, + "role": "Driver", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + '' + last_name, + user=user, + base_order=base_id, + password=password, + birthday=birthday, + city=city, + province=province + ) + system_profile.save() + system_profile.role.add(group) + + else: + return Response({"result": "مشکلی پیش آمده!"}, status=status.HTTP_401_UNAUTHORIZED) + + if KillHouseDriver.objects.filter(trash=False, user=system_profile, health_code=health_code, + pelak=plaque).exists(): + continue + else: + driver = KillHouseDriver( + type_car=car, + capocity=capacity, + pelak=plaque, + health_code=health_code, + driver_name=first_name + '' + last_name, + driver_mobile=mobile, + user=system_profile, + ) + driver.save() + + return Response({"result": "register"}, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_poultry_hatching_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename='BytesIO(file)', data_only=True) + sheet = wb_obj.active + sheet.delete_rows(sheet.max_row) + + not_find_list = [] + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + breeding_uniq_id = row[4] + licence_number = row[7] + hatching_quantity = row[11] + poultry_name = row[5] + losses = row[22] + if i <= 6: + continue + + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).first() + + if not poultry: + not_find_list.append(breeding_uniq_id) + continue + poultry.unit_name = poultry_name + poultry.save() + hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + if hatch: + period = hatch.last().period + 1 + else: + period = 1 + + hatching_date = row[9].split('/') + date = convert_to_miladi( + year=int(hatching_date[0]), + month=int(hatching_date[1]), + day=int(hatching_date[2]) + ) + + poultry_hatching = hatch.filter(trash=False, archive=False, state='pending', + allow_hatching='pending').order_by('id') + + if not poultry_hatching.exists(): + if not hatch.filter(archive=True, state='complete', + allow_hatching="True", licence_number=licence_number).exists(): + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed='*ترکیبی', + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses + + ) + hatching.save() + + else: + previouse_hatching = poultry_hatching.last() + + hatchings = poultry_hatching.filter(licence_number=licence_number) + if not hatchings: + if previouse_hatching.left_over > (previouse_hatching.quantity * percent_of_losses): + previouse_hatching.violation = True + previouse_hatching.save() + + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed='*ترکیبی', + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses + + ) + hatching.save() + else: + last_hatchings = hatchings.first() + last_hatchings.date = date + last_hatchings.quantity = hatching_quantity + last_hatchings.losses = losses + last_hatchings.save() + + update = LastUpdate.objects.first() + update.update_date = datetime.now() + update.save() + return Response(not_find_list, status=status.HTTP_201_CREATED) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_poultry_hatching_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + inter = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + breeding_uniq_id = row[3] + + if i == 7: + continue + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id) + if poultry: + poultry = poultry.last() + else: + continue + poultry_hatching = PoultryHatching.objects.filter(trash=False, poultry=poultry, state='pending') + for poultry_hatchings in poultry_hatching: + dict_1 = { + "poultry": poultry_hatchings.poultry.unit_name, + "date": poultry_hatchings.date, + "quantity": poultry_hatchings.quantity, + "breed": poultry_hatchings.chicken_breed, + + } + inter.append(dict_1) + # dict_1.clear() + + return Response(inter, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_poultry_in_db(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + list1 = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + try: + poultry = Poultry.objects.get(breeding_unique_id=row[6]) + if poultry: + continue + except: + dict1 = { + 'نام مرغدار': row[0], + 'شناسه یکتا': row[6] + } + list1.append(dict1) + return Response(list1, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def reset_hatching_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + l = 0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 7: + continue + date = row[8].split('/') + miladi_date = convert_to_miladi( + year=int(date[0]), + month=int(date[1]), + day=int(date[2]) + ) + poultrys = Poultry.objects.filter(trash=False, breeding_unique_id=row[3]) + # return HttpResponse(poultrys.count()) + if poultrys: + for poultry in poultrys: + poultry_hatchings = PoultryHatching.objects.filter(poultry=poultry, date__year=miladi_date.year, + date__month=miladi_date.month, + date__day=miladi_date.day, + archive=False, trash=False, state='pending', + allow_hatching='pending') + if poultry_hatchings: + for poultry_hatching in poultry_hatchings: + l += 1 + if poultry_hatching.quantity - poultry_hatching.left_over == 0: + poultry_hatching.quantity = row[9] + poultry_hatching.left_over = row[9] + poultry_hatching.save() + else: + continue + + else: + continue + return Response(l) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def enter_driver_hamedan(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Driver") + l = 0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 2: + continue + mobile = str(row[2]) + if len(mobile) == 10: + mobile = '0' + str.zfill(mobile, 10) + health_code = 0 + if row[8] is not None: + health_code = row[8] + first_name = row[0] + last_name = [1] + password = '00100' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + province = Province.objects.filter(name='همدان') + province = province.last() + city = City.objects.filter(name='همدان') + city = city.last() + + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).last() + if not system_profile: + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": '0', + "role": "Driver", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + '' + last_name, + user=user, + base_order=base_id, + password=password, + birthday=str(datetime.now().date()), + city=city, + province=province + ) + system_profile.save() + system_profile.role.add(group) + l += 1 + kill_drivers = KillHouseDriver.objects.filter(trash=False, health_code=health_code, user__mobile=mobile, + driver_mobile=mobile) + if not kill_drivers: + wallet = Wallet() + wallet.save() + KillHouseDriver( + user=system_profile, + driver_name=first_name + ' ' + last_name, + driver_mobile=mobile, + type_car='کامیون', + type='exclusive', + pelak=row[9], + capocity=row[7], + health_code=health_code, + wallet=wallet, + ) + l += 1 + return Response(l) + + +def add_zero_for_user_mobile(request): + users = SystemUserProfile.objects.all() + l = 0 + for user in users: + if len(user.mobile) == 10: + user.mobile = '0' + user.mobile + user.save() + l += 1 + + return HttpResponse(l, status=status.HTTP_200_OK) + + +def integration_of_hatching(request): + poultry = Poultry.objects.filter(trash=False) + for user in poultry: + poultry_hatching = PoultryHatching.objects.filter(trash=False, poultry=user, archive=False, + allow_hatching='pending').order_by('id') + if poultry_hatching: + first_hatching = poultry_hatching.first() + for hatching in poultry_hatching: + if first_hatching != hatching: + first_hatching.quantity += hatching.quantity + first_hatching.left_over += hatching.left_over + first_hatching.killed_quantity += hatching.killed_quantity + p_requests = PoultryRequest.objects.filter(trash=False, hatching=hatching) + if p_requests: + for p_request in p_requests: + p_request.hatching = first_hatching + p_request.save() + hatching.trash = True + hatching.save() + first_hatching.save() + else: + pass + return HttpResponse('ok') + + +def period_to_fix(request): + poultries = Poultry.objects.filter(trash=False).order_by('id') + + for poultry in poultries: + hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + # if len(hatch) > 1: + # period = len(hatch) + 1 + # else: + period = 1 + for hatching in hatch: + hatching.period = period + hatching.save() + period += 1 + return HttpResponse('ok') + + +# from panel.models import KillHouseAssignmentInformation, KillHouseRequest +# +# +# def assignment_information_fix_bar_info(request): +# kill_request=KillHouseRequest.objects.filter(trash=False,accepted_real_quantity=0,accepted_real_weight=0).select_related('province_request__poultry_request').only('accepted_real_weight','accepted_real_quantity','province_request__poultry_request') +# for kill in kill_request: +# kill.accepted_real_quantity=kill.quantity +# kill.accepted_real_weight=int(kill.quantity * kill.province_request.poultry_request.Index_weight) +# kill.save() +# +# return HttpResponse('ok') + + +# from panel.models import ProvinceKillRequest, KillHouseRequest +# from django.db.models import Sum +# def assignment_information_fix_bar_info(request): +# province = ProvinceKillRequest.objects.filter(total_killed_quantity=0,trash=False,state__in=('pending','accepted')) +# +# for p in province: +# p.total_killed_quantity=p.main_quantity +# p.total_killed_weight=int(p.main_quantity * p.province_request.poultry_request.Index_weight) +# p.save() +# return HttpResponse('ok') + + +# from panel.models import KillHouseAssignmentInformation, KillHouseRequest +# +# +# def assignment_information_fix_bar_info(request): +# kill_request=KillHouseRequest.objects.filter(trash=False,accepted_real_quantity=0,accepted_real_weight=0).select_related('province_request__poultry_request') +# for kill in kill_request: +# kill.accepted_real_quantity=kill.quantity +# kill.accepted_real_weight=int(kill.quantity * kill.province_request.poultry_request.Index_weight) +# kill.save() +# +# return HttpResponse('ok') +# +# +# def assignment_information_fix_bar_info(request): +# bar_information = KillHouseAssignmentInformation.objects.filter(trash=False).only( +# 'net_weight', 'real_quantity', 'kill_house_request__key').values('net_weight', 'real_quantity', +# 'kill_house_request__key') +# +# for bar in bar_information: +# try: +# kill_request = KillHouseRequest.objects.get(trash=False, key=bar['kill_house_request__key']) +# +# kill_request.accepted_real_quantity = bar['real_quantity'] +# kill_request.accepted_real_weight = bar['net_weight'] +# kill_request.save() +# except: +# pass +# +# +# return HttpResponse('ok') + +# +# from panel.models import KillHouseAssignmentInformation, KillHouseRequest +# # +# # +# def assignment_information_fix_bar_info(request): +# bar_information = KillHouseAssignmentInformation.objects.filter(pk__in=pk_assigment,trash=False).select_related('kill_house_request') +# for bar in bar_information: +# try: +# kill_request = KillHouseRequest.objects.get(trash=False, key=bar.kill_house_request.key) +# +# kill_request.accepted_real_quantity = bar.real_quantity +# kill_request.accepted_real_weight = bar.net_weight +# kill_request.save() +# except: +# pass +# +# return HttpResponse(len(bar_information)) +# +# from panel.models import ProvinceKillRequest, KillHouseRequest +# from django.db.models import Sum +# +# +# def assignment_information_fix_bar_info(request): +# province = ProvinceKillRequest.objects.filter(trash=False,state__in=('pending','accepted')) +# +# for p in province: +# kill_request = KillHouseRequest.objects.filter(trash=False, province_kill_request=p).only( +# 'accepted_real_quantity', 'accepted_real_weight') +# total_killed_quantity = kill_request.aggregate(total=Sum('accepted_real_quantity'))[ +# 'total'] +# total_killed_weight = kill_request.aggregate(total=Sum('accepted_real_weight'))[ +# 'total'] +# +# total_first_car = kill_request.aggregate(total=Sum('quantity'))[ +# 'total'] +# +# p.total_killed_quantity = total_killed_quantity if total_killed_quantity != None else 0 +# p.total_killed_weight = total_killed_weight if total_killed_weight != None else 0 +# p.first_car_allocated_quantity= total_first_car if total_first_car != None else 0 +# +# if p.main_quantity < p.total_killed_quantity: +# p.extra_killed_quantity = p.total_killed_quantity - p.main_quantity +# +# p.save() +# +# p.quantity=p.main_quantity - p.first_car_allocated_quantity if(p.main_quantity - p.first_car_allocated_quantity) > 0 else 0 +# p.save() +# return HttpResponse('ok') + +# from panel.models import ProvinceKillRequest, PoultryHatching +# from django.db.models import Sum +# +# +# def assignment_information_fix_bar_info(request): +# hatchings = PoultryHatching.objects.filter(trash=False).order_by('id') +# +# for hatching in hatchings: +# province_kills = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), +# province_request__poultry_request__hatching=hatching).order_by( +# 'id') +# +# total_extra = province_kills.aggregate(total=Sum('extra_killed_quantity'))[ +# 'total'] +# +# total_killed_quantity = province_kills.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_weight = province_kills.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# +# hatching.killed_quantity = total_killed_quantity if total_killed_quantity != None else 0 +# hatching.total_killed_weight = total_killed_weight if total_killed_weight != None else 0 +# +# province_kill_free = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=True) +# total_killed_free_quantity = province_kill_free.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_free_weight = province_kill_free.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.free_quantity = total_killed_free_quantity if total_killed_free_quantity != None else 0 +# hatching.free_killed_quantity = total_killed_free_weight if total_killed_free_weight != None else 0 +# +# province_kill_goverment = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=False) +# +# total_killed_goverment_quantity = province_kill_goverment.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_goverment_weight = province_kill_goverment.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.governmental_quantity = total_killed_goverment_quantity if total_killed_goverment_quantity != None else 0 +# hatching.governmental_killed_quantity = total_killed_goverment_weight if total_killed_goverment_weight != None else 0 +# +# hatching.extra_killed_quantity = total_extra if total_extra != None else 0 +# +# hatching.save() +# return HttpResponse('ok') + + +# from panel.models import ProvinceKillRequest, PoultryHatching +# from django.db.models import Sum +# from panel.models import ProvinceKillRequest, KillHouseRequest +# +# +# def assignment_information_fix_bar_info(request): +# list1 = [1336,1146,1120,1253,1141,1098,1112,1145,1163,1155,1134,1087,1172,1072,1113,1089,1115,1072,1123,1085,1109] +# +# hatchings = PoultryHatching.objects.filter(trash=False, id__in=list1) +# +# province = ProvinceKillRequest.objects.filter(trash=False,state__in=('accepted','pending') ,province_request__poultry_request__hatching__in=hatchings) +# for p in province: +# kill_requests=KillHouseRequest.objects.filter(trash=False,province_kill_request=p) +# total_killed_quantity = kill_requests.aggregate(total=Sum('accepted_real_quantity'))[ +# 'total'] +# total_killed_weight = kill_requests.aggregate(total=Sum('accepted_real_weight'))[ +# 'total'] +# total_car = kill_requests.aggregate(total=Sum('quantity'))[ +# 'total'] +# p.total_killed_quantity=total_killed_quantity if total_killed_quantity !=None else 0 +# p.total_killed_weight=total_killed_weight if total_killed_weight !=None else 0 +# p.first_car_allocated_quantity=total_car if total_car != None else 0 +# +# if p.main_quantity < p.total_killed_quantity: +# p.extra_killed_quantity = p.total_killed_quantity - p.main_quantity +# +# p.save() +# for hatching in hatchings: +# province_kills = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), +# province_request__poultry_request__hatching=hatching).order_by( +# 'id') +# +# total_extra = province_kills.aggregate(total=Sum('extra_killed_quantity'))[ +# 'total'] +# +# total_killed_quantity = province_kills.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_weight = province_kills.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# +# hatching.killed_quantity = total_killed_quantity if total_killed_quantity != None else 0 +# hatching.total_killed_weight = total_killed_weight if total_killed_weight != None else 0 +# +# province_kill_free = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=True) +# total_killed_free_quantity = province_kill_free.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_free_weight = province_kill_free.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.free_quantity = total_killed_free_quantity if total_killed_free_quantity != None else 0 +# hatching.free_killed_quantity = total_killed_free_weight if total_killed_free_weight != None else 0 +# +# province_kill_goverment = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=False) +# +# total_killed_goverment_quantity = province_kill_goverment.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_goverment_weight = province_kill_goverment.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.governmental_quantity = total_killed_goverment_quantity if total_killed_goverment_quantity != None else 0 +# hatching.governmental_killed_quantity = total_killed_goverment_weight if total_killed_goverment_weight != None else 0 +# +# hatching.extra_killed_quantity = total_extra if total_extra != None else 0 +# +# hatching.save() +# +# +# return HttpResponse('ok') +# +# from panel.models import ProvinceKillRequest, PoultryHatching +# from django.db.models import Sum +# from panel.models import ProvinceKillRequest, KillHouseRequest +# def assignment_information_fix_bar_info_3_day_ago(request): +# date=datetime.now().date() - timedelta(days=3) +# kill_house_reqs = KillHouseRequest.objects.filter(Q(vet_state= 'pending')|Q(assignment_state_archive='pending') +# ,clearance_code__isnull=True,kill_request__recive_date__date__lte=date, trash=False) +# +# list1=[] +# for kill_house_req in kill_house_reqs: +# kill_house_req.trash = True +# kill_house_req.save() +# hatching = PoultryHatching.objects.get(key=kill_house_req.province_request.poultry_request.hatching.key, trash=False) +# if hatching.id not in list1: +# list1.append(hatching.id) +# +# hatchings = PoultryHatching.objects.filter(trash=False, id__in=list1) +# +# province = ProvinceKillRequest.objects.filter(trash=False,state__in=('accepted','pending') ,province_request__poultry_request__hatching__in=hatchings) +# for p in province: +# kill_requests=KillHouseRequest.objects.filter(trash=False,province_kill_request=p) +# total_killed_quantity = kill_requests.aggregate(total=Sum('accepted_real_quantity'))[ +# 'total'] +# total_killed_weight = kill_requests.aggregate(total=Sum('accepted_real_weight'))[ +# 'total'] +# total_car = kill_requests.aggregate(total=Sum('quantity'))[ +# 'total'] +# p.total_killed_quantity=total_killed_quantity if total_killed_quantity !=None else 0 +# p.total_killed_weight=total_killed_weight if total_killed_weight !=None else 0 +# p.first_car_allocated_quantity=total_car if total_car != None else 0 +# +# if p.main_quantity < p.total_killed_quantity: +# p.extra_killed_quantity = p.total_killed_quantity - p.main_quantity +# +# p.save() +# for hatching in hatchings: +# province_kills = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), +# province_request__poultry_request__hatching=hatching).order_by( +# 'id') +# +# total_extra = province_kills.aggregate(total=Sum('extra_killed_quantity'))[ +# 'total'] +# +# total_killed_quantity = province_kills.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_weight = province_kills.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# +# hatching.killed_quantity = total_killed_quantity if total_killed_quantity != None else 0 +# hatching.total_killed_weight = total_killed_weight if total_killed_weight != None else 0 +# +# province_kill_free = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=True) +# total_killed_free_quantity = province_kill_free.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_free_weight = province_kill_free.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.free_quantity = total_killed_free_quantity if total_killed_free_quantity != None else 0 +# hatching.free_killed_quantity = total_killed_free_weight if total_killed_free_weight != None else 0 +# +# province_kill_goverment = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=False) +# +# total_killed_goverment_quantity = province_kill_goverment.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_goverment_weight = province_kill_goverment.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.governmental_quantity = total_killed_goverment_quantity if total_killed_goverment_quantity != None else 0 +# hatching.governmental_killed_quantity = total_killed_goverment_weight if total_killed_goverment_weight != None else 0 +# +# hatching.extra_killed_quantity = total_extra if total_extra != None else 0 +# +# hatching.save() +# +# +# return HttpResponse('ok') + +# def assignment_information_fix_bar_info(request): +# kill_house_requests=(KillHouseRequest.objects.filter(trash=True,clearance_code__isnull=True,message__isnull=False, +# bar_remover__isnull=False)).only('message') +# for kill_house_request in kill_house_requests: +# kill_house_request.message='عدم دریافت کد قرنطینه' +# # kill_house_request.bar_remover={ +# # "date": str(kill_house_request.create_date.date()), +# # "role":"KillHouse", +# # "mobile": kill_house_request.killhouse_user.kill_house_operator.user.mobile, +# # "full_name": kill_house_request.killhouse_user.kill_house_operator.user.fullname, +# # } +# kill_house_request.save() +# return HttpResponse('ok') +# +from panel.models import ProvinceKillRequest, PoultryHatching + + +# def assignment_information_fix_bar_info(request): +# today = datetime.now().date() - timedelta(days=2) +# province_kill_requests = (ProvinceKillRequest.objects.filter(kill_request__recive_date__date__lte=today, +# first_car_allocated_quantity=0, trash=False) +# .select_related('province_request__poultry_request')) +# if province_kill_requests: +# for province_kill_request in province_kill_requests: +# poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, +# trash=False) +# hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) +# +# if province_kill_request.main_quantity - province_kill_request.quantity == 0: +# province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) +# province_check.quantity += province_kill_request.main_quantity +# province_check.save() +# poultry_request.remain_quantity += province_kill_request.main_quantity +# poultry_request.save() +# +# if poultry_request.free_sale_in_province == True: +# hatching.free_killed_quantity -= province_kill_request.total_killed_weight +# hatching.free_quantity -= province_kill_request.total_killed_quantity +# else: +# hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight +# hatching.governmental_quantity -= province_kill_request.total_killed_quantity +# +# hatching.save() +# province_kill_request.quantity = 0 +# province_kill_request.total_killed_quantity = 0 +# province_kill_request.total_killed_weight = 0 +# province_kill_request.return_to_province = True +# province_kill_request.save() +# return HttpResponse({'msg': 'all done'}) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def register_guilds(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Guilds") + l = 0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 1: + continue + mobile = str(row[2]) + if len(mobile) == 10: + mobile = '0' + str.zfill(mobile, 10) + # postal_code = row[4] + national_code = row[5] + first_name = row[0] + last_name = row[1] + guild_id = row[4] + license_num = 0 + password = '00100' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + province = Province.objects.get(id=2) + city = City.objects.get(id=8) + area = 'گوشت و مرغ' + type_act = 'خرده فروش' + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).first() + if system_profile: + pass + # data = { + # "username": mobile, + # "first_name": first_name, + # "last_name": last_name, + # "password": hashed_password, + # "national_id": national_code, + # "role": "Guilds", + # "api_key": PROJECT_API_KEY + # } + # req = requests.post( + # url=ARTA_REGISTER, + # data=data, + # verify=False + # ) + # + # if req.status_code == 200: + # user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + # user.save() + # base_id = SystemUserProfile.objects.all() + # if base_id.count() > 0: + # base_id = int(base_id.last().base_order) + 1 + # else: + # base_id = 1000 + # system_profile = SystemUserProfile( + # mobile=mobile, + # first_name=first_name, + # last_name=last_name, + # fullname=first_name + '' + last_name, + # user=user, + # base_order=base_id, + # password=password, + # birthday=str(datetime.now().date()), + # city=city, + # province=province + # ) + # system_profile.save() + # system_profile.role.add(group) + # l += 1 + # address = SystemAddress(city=city, province=province, address=row[3]) + # address.save() + # wallet = Wallet() + # wallet.save() + # guildss=Guilds( + # user=system_profile, + # license_number=license_num, + # guilds_name=first_name + '' + last_name, + # guilds_id=guild_id, + # area_activity=area, + # type_activity=type_act, + # address=address, + # wallet=wallet, + # ) + # guildss.save() + # l+=1 + # guild = Guilds.objects.filter(trash=False, user=system_profile).first() + # if guild: + + # if not Product.objects.filter(guild__exact=guild): + # l+=1 + # + # additional_products = AdditionalProducts.objects.filter(trash=False).exclude( + # name='سایر محصولات').order_by('id') + # if additional_products: + # for additional_product in additional_products: + # show = True if additional_product.name == 'مرغ گرم' else False + # product = Product( + # name=additional_product.name, + # image=additional_product.image, + # unit_of_measurement=additional_product.unit_of_measurement, + # priority=additional_product.priority, + # guild=guild, + # selling_free_price=additional_product.selling_free_price, + # selling_approved_price=additional_product.selling_approved_price, + # selling_more_than_inventory=additional_product.selling_more_than_inventory, + # selling_other_products=additional_product.selling_other_products, + # price=additional_product.price, + # show=show, + # ) + # product.save() + # company = PosCompany.objects.get(id=1) + # pos_machine=POSMachine.objects.filter(guild__exact=guild).first() + # if not pos_machine: + # while (True): + # res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + # res = base_pos_id + res + # if not POSMachine.objects.filter(pos_id=res).exists(): + # break + # pos_machine=POSMachine( + # pos_id=res, + # user=guild.user, + # guild=guild, + # pos_company=company + # ) + # pos_machine.save() + # guild.has_pos = True + # guild.save() + # l+=1 + # return Response(l) + + +# from panel.models import ProvinceKillRequest, PoultryHatching +# from django.db.models import Sum +# from panel.models import ProvinceKillRequest, KillHouseRequest +# def assignment_information_fix_bar_info(request): +# hatchings = PoultryHatching.objects.filter(trash=False, pk__in=pk_hatching) +# +# province = ProvinceKillRequest.objects.filter(trash=False ,pk__in=pk_province_kill_request ) +# for p in province: +# kill_requests=KillHouseRequest.objects.filter(trash=False,province_kill_request=p) +# total_killed_quantity = kill_requests.aggregate(total=Sum('accepted_real_quantity'))[ +# 'total'] +# total_killed_weight = kill_requests.aggregate(total=Sum('accepted_real_weight'))[ +# 'total'] +# total_car = kill_requests.aggregate(total=Sum('quantity'))[ +# 'total'] +# p.total_killed_quantity=total_killed_quantity if total_killed_quantity !=None else 0 +# p.total_killed_weight=total_killed_weight if total_killed_weight !=None else 0 +# p.first_car_allocated_quantity=total_car if total_car != None else 0 +# +# if p.main_quantity < p.total_killed_quantity: +# p.extra_killed_quantity = p.total_killed_quantity - p.main_quantity +# +# p.save() +# for hatching in hatchings: +# province_kills = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), +# province_request__poultry_request__hatching=hatching).order_by( +# 'id') +# +# total_extra = province_kills.aggregate(total=Sum('extra_killed_quantity'))[ +# 'total'] +# +# total_killed_quantity = province_kills.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_weight = province_kills.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# +# hatching.killed_quantity = total_killed_quantity if total_killed_quantity != None else 0 +# hatching.total_killed_weight = total_killed_weight if total_killed_weight != None else 0 +# +# province_kill_free = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=True) +# total_killed_free_quantity = province_kill_free.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_free_weight = province_kill_free.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.free_quantity = total_killed_free_quantity if total_killed_free_quantity != None else 0 +# hatching.free_killed_quantity = total_killed_free_weight if total_killed_free_weight != None else 0 +# +# province_kill_goverment = province_kills.filter( +# province_request__poultry_request__free_sale_in_province=False) +# +# total_killed_goverment_quantity = province_kill_goverment.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] +# total_killed_goverment_weight = province_kill_goverment.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] +# hatching.governmental_quantity = total_killed_goverment_quantity if total_killed_goverment_quantity != None else 0 +# hatching.governmental_killed_quantity = total_killed_goverment_weight if total_killed_goverment_weight != None else 0 +# +# hatching.extra_killed_quantity = total_extra if total_extra != None else 0 +# +# hatching.save() +# +# +# return HttpResponse('ok') + + +def update_chicken_age_from_login(): + poultry_hatching = PoultryHatching.objects.filter(trash=False).only('date', 'chicken_age', 'last_change').order_by( + '-id') + now = datetime.now().date() + for hatching in poultry_hatching: + now_age = (now - hatching.date.date()).days + 1 + if hatching.archive == False and hatching.allow_hatching == 'pending': + hatching.chicken_age = now_age + hatching.save() + elif hatching.archive == True and hatching.allow_hatching == 'True': + if hatching.last_change: + date = datetime.strptime((hatching.last_change['date'].split(' ')[0]), '%Y-%m-%d').date() + age = (date - hatching.date.date()).days + 1 + if age < 80: + hatching.chicken_age = (date - hatching.date.date()).days + 1 + hatching.save() + else: + continue + if now_age <= 120: + hatching.now_age = now_age + hatching.save() + + +def violation_archive_true(request): + poultry_haching = PoultryHatching.objects.filter(allow_hatching='True', archive=True, + trash=False, left_over__gt=F('quantity') * percent_of_losses, + violation=False).only('quantity', 'left_over', 'violation') + l = 0 + for hatching in poultry_haching: + hatching.violation = True + hatching.save() + l += 1 + return HttpResponse(l) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def update_chicken_breed_from_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file), data_only=True) + sheet = wb_obj.active + + sheet.delete_rows(sheet.max_row) + done = 0 + not_done = 0 + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 7: + continue + breeding_uniq_id = row[3] + breed = row[10] + licence_number = row[5] + try: + poultry_hatching = PoultryHatching.objects.filter(violation=False, trash=False, allow_hatching='pending', + state='pending', + poultry__breeding_unique_id=breeding_uniq_id, + licence_number=licence_number).order_by( + 'id').last() + + if poultry_hatching: + if poultry_hatching.chicken_breed == '*ترکیبی': + poultry_hatching.chicken_breed = breed + elif poultry_hatching.chicken_breed != breed and poultry_hatching.chicken_breed != '*ترکیبی': + poultry_hatching.chicken_breed = 'ترکیبی' + else: + continue + + poultry_hatching.save() + done += 1 + except: + not_done += 1 + continue + # hatching.save() + return Response(f'موفق:{done}\n ناموفق ها:{not_done}', status=status.HTTP_201_CREATED) + + +def ye_chee_bani(request): + kill_assigment = KillHouseAssignmentInformation.objects.filter( + ~Q(real_quantity=F('kill_house_request__accepted_real_quantity'))).select_related('kill_house_request') + + list1 = kill_assigment.values_list('kill_house_request__province_request__poultry_request__hatching__pk', flat=True) + # print(list(list1)) + return HttpResponse(list(list1)) + + +def dedicated_killer(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + l = 0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 1: + continue + bar_code = row[1] + mobile = str(row[12]) + if len(mobile) == 10: + mobile = '0' + str.zfill(mobile, 10) + try: + kill_req = KillHouseRequest.objects.get(bar_code=bar_code) + killer = KillHouse.objects.get(kill_house_operator__user__mobile=mobile) + kill_req.killer = killer + kill_req.save() + except: + l += 1 + continue + return HttpResponse(l) + + +def valem_kin2(request): + kill_req = KillHouseRequest.objects.filter(archive_wage=True, create_date__date__gte='2024-03-20').only( + 'archive_wage').order_by('id') + m = kill_req.values_list('pk', flat=True) + print(len(m)) + for i in kill_req: + i.archive_wage = False + i.save() + # kill_req = ProvinceKillRequest.objects.filter(archive_wage=True, create_date__date__gte='2024-03-20').only( + # 'archive_wage').order_by('id') + # for i in kill_req: + # i.archive_wage = False + # i.save() + + # kill_req = KillHouseFreeBarInformation.objects.filter(archive_wage=False, create_date__date__lte='2024-04-19').only( + # 'archive_wage').order_by('id') + # for i in kill_req: + # i.archive_wage = True + # i.save() + + return HttpResponse('ok') + + +def transaction_company_for_freezing(request): + poultry_request = PoultryRequest.objects.filter(trash=False, freezing=True).order_by('id') + province_request = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted') + , archive_wage=False, + province_request__poultry_request__in=poultry_request).only( + 'total_killed_weight', 'total_wage_amount', 'company_share', 'wage', 'company_share_percent' + ) + for p in province_request: + amount = int(p.total_killed_weight * 500) + p.total_wage_amount = amount + p.wage = 500 + p.company_share = amount + p.guilds_share = 0 + p.union_share = 0 + p.company_share_percent = 100 + p.union_share_percent = 0 + p.guilds_share_percent = 0 + p.save() + + return HttpResponse('ok') + + +import string +import random + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def make_gate_way_id(request): + users = SystemUserProfile.objects.filter(user_gate_way_id__isnull=True).order_by('id') + for user in users: + while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)) + res = base_user_gate_way_id + res + if not SystemUserProfile.objects.filter(user_gate_way_id=res).exists(): + break + user.user_gate_way_id = res + user.save() + return HttpResponse('done!') + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_server_time(request): + date = datetime.now() + return Response(date) + + +def transaction_fix(request): + province_request = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted') + , archive_wage=False, + ).only( + 'total_killed_weight', 'total_wage_amount', 'company_share', 'wage', 'company_share_percent', 'other_share', + 'other_share_percent' + ).exclude(id=3868) + for p in province_request: + amount = p.total_wage_amount + + p.guilds_share = amount - (p.company_share + p.union_share) + p.save() + + return HttpResponse('ok') + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def internal_transaction_fix(request): + internals = InternalTransaction.objects.filter(trash=False, status='completed', date__date__gt='2024-06-01' + , transaction_type='wage-gateway-auto') \ + .order_by('date') + for internal in internals: + if internal.amount != ( + internal.company_share + internal.guilds_share + internal.union_share + internal.other_share): + internal.company_share = internal.company_share + ((internal.amount * 1) / 100) + internal.save() + + return Response('ok') + + +def utm_to_loc(easting, northing): + zone_number = 39 + zone_letter = 'N' + lat, lon = utm.to_latlon(easting, northing, zone_number, zone_letter) + zone_number = int((lon + 180) // 6) + 1 + zone_letter = 'CDEFGHJKLMNPQRSTUVWXX'[(int(lat) + 80) // 8] + lat, lon = utm.to_latlon(easting, northing, zone_number, zone_letter) + + return lat, lon + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def convert_utm_to_location(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + list1 = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 1: + continue + else: + utm = row[14] + breeding_uniq_id = row[5] + utm = utm.split('/') + easting = int(utm[0]) + northing = int(utm[1]) + lat, long = utm_to_loc(easting, northing) + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).first() + if poultry: + poultry.lat = lat + poultry.long = long + poultry.save() + else: + list1.append(breeding_uniq_id) + + return HttpResponse('ok') + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fix_internal_transactions(request): + internal = InternalTransaction.objects.filter(trash=False, kill_house__isnull=False) + for i in internal: + i.payer_fullname = i.kill_house.kill_house_operator.user.fullname + i.payer_mobile = i.kill_house.kill_house_operator.user.mobile + i.save() + return Response('ok') + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_hatching(request): + poultryes = Poultry.objects.filter(trash=False) + list1 = [] + + for p in poultryes: + # پیدا کردن تاریخ‌هایی که دوبار یا بیشتر تکرار شده‌اند + repeated_dates = PoultryHatching.objects.values('date__year', 'date__month').annotate( + date_count=Count('id') + ).filter(trash=False, poultry=p, date_count__gt=1) + + # فیلتر کردن رکوردهایی که سال و ماه آنها در لیست تکراری‌ها قرار دارند + query = Q() + for date in repeated_dates: + query |= Q(date__year=date['date__year'], date__month=date['date__month']) + + poultry_hatchings = PoultryHatching.objects.filter(query, trash=False, poultry=p, killed_quantity=0) + # for p in poultry_hatchings: + # p.trash=True + # p.save() + + return Response(list1) + + +def change_last_digit_to_six(request): + user_profile = SystemUserProfile.objects.filter(trash=False, mobile='09216919296').order_by('id') + for u in user_profile: + first_mobile_number = u.mobile + second_mobile_number = '09011110911' + data = { + "first_mobile_number": str(first_mobile_number), + "second_mobile_number": '09011110911', + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + # return Response(req.status_code) + if req.status_code == 200: + print('ok') + second_mobile_number = second_mobile_number + + user = User.objects.filter(id=u.user.id).first() + user.username = second_mobile_number + user.save() + u.mobile = second_mobile_number + u.save() + return HttpResponse('ok') + + +def canceled_out_province_request(): + province_requests = PoultryRequest.objects.filter(state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending'), trash=False, + archive=False, + out_province_request_cancel=False, out=True, wage_pay=False, + has_wage=True) + data = {"date": str(datetime.now()), "role": "SuperAdmin", "mobile": "-", + "fullname": "کنسل شده توسط سیستم به دلیل عدم پرداخت"} + for province_request in province_requests: + if province_request.state_process == 'accepted' and province_request.province_state == 'accepted': + hatching = PoultryHatching.objects.get(key=province_request.hatching.key, trash=False) + hatching.out_province_killed_weight -= int(province_request.quantity * province_request.Index_weight) + hatching.out_province_killed_quantity -= province_request.quantity + hatching.save() + province_request.out_province_request_cancel = True + province_request.out_province_request_canceller = data + province_request.archive = True + province_request.state_process = 'rejected' + province_request.province_state = 'rejected' + province_request.save() + + message = f'بار خارج از استان به شماره {province_request.order_code} به علت عدم پرداخت کنسل شد.' \ + f'\n' \ + f'(سامانه رصدیار)' + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={UNION_NUMBER}&message={message}") + + +def fix_guild_kill_house(request): + guilds = Guilds.objects.filter(trash=False, kill_house_centers_allocation__isnull=False) + for guild in guilds: + list1 = [] + for i in guild.kill_house_centers_allocation: + list1.append(i['value']) + kill_house1 = KillHouse.objects.filter(key__in=list1) + guild.kill_house.set(kill_house1) + + return HttpResponse('ok') + + +def fix_guild_steward_kill_house(request): + stewards = Steward.objects.filter(trash=False, centers_allocation__isnull=False) + for steward in stewards: + guild = Guilds.objects.get(trash=False, id=steward.guilds.id) + list1 = [] + for i in steward.centers_allocation: + list1.append(i['value']) + kill_house1 = KillHouse.objects.filter(key__in=list1) + guild.steward_kill_house.set(kill_house1) + + return HttpResponse('ok') + + +def fix_guild_steward(request): + guild = Guilds.objects.get(id=26, trash=False) + stewards = guild.stewards.all() + list1 = [i['value'] for i in guild.centers_allocation] + + # واکشی مباشرین مرتبط + stewardss = Guilds.objects.filter( + pk__in=Steward.objects.filter(key__in=list1).values_list('guilds', flat=True), + trash=False + ) + + # حذف رابطه‌های قبلی در مدل میانی + GuildSteward.objects.filter(guild=guild).delete() + + # اضافه کردن روابط جدید در مدل میانی + guild_stewards = [GuildSteward(guild=guild, steward=steward) for steward in stewardss] + GuildSteward.objects.bulk_create(guild_stewards) + + return HttpResponse('done!') + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def check_product(request): + product = RolesProducts.objects.get(id=1) + return Response(kill_house_free_sale_product_warehousing(product)) + + +def add_to_steward_temp_key(request): + stewards_allocations = StewardAllocation.objects.filter(steward__isnull=False).order_by('id') + for stewards_allocation in stewards_allocations: + stewards_allocation.steward_temp_key = stewards_allocation.steward.guilds.id + stewards_allocation.save() + return HttpResponse('ok') + + +def add_to_steward(request): + stewards_allocations = StewardAllocation.objects.filter(steward_temp_key__isnull=False).order_by('id') + for stewards_allocation in stewards_allocations: + guild = Guilds.objects.get(id=stewards_allocation.steward_temp_key) + stewards_allocation.steward = guild + stewards_allocation.save() + return HttpResponse('ok') + + +def make_role_prodoct(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + guilds = Guilds.objects.filter(trash=False) + product = NewProduct.objects.all().first() + for kill_house in kill_houses: + role_product = RolesProducts( + kill_house=kill_house, + parent_product=product, + name='مرغ گرم', + ) + role_product.save() + for guild in guilds: + role_product = RolesProducts( + guild=guild, + parent_product=product, + name='مرغ گرم', + ) + role_product.save() + + return HttpResponse('ok') + + +def fix_steward_allocation(request): + steward_allocations = StewardAllocation.objects.filter(kill_house__isnull=False).order_by('id') + for steward_allocation in steward_allocations: + product = RolesProducts.objects.filter(kill_house=steward_allocation.kill_house).first() + if steward_allocation.guilds is not None: + steward_allocation.to_guilds = steward_allocation.guilds + steward_allocation.allocation_type = 'killhouse_guild' + steward_allocation.guilds = None + elif steward_allocation.steward is not None: + steward_allocation.to_steward = steward_allocation.steward + steward_allocation.allocation_type = 'killhouse_steward' + steward_allocation.steward = None + else: + continue + steward_allocation.product = product + + steward_allocation.save() + return HttpResponse('ok') + + +def fix_KillHouseFreeSaleBarInformation(request): + free_kills = KillHouseFreeSaleBarInformation.objects.filter(trash=False, kill_house__isnull=False).order_by('id') + for free_kill in free_kills: + product = RolesProducts.objects.filter(kill_house=free_kill.kill_house).first() + free_kill.product = product + free_kill.save() + return HttpResponse('ok') + + +def fix_KillHouseFreeBarInformation(request): + free_kills = KillHouseFreeBarInformation.objects.filter(trash=False, kill_house__isnull=False).order_by('id') + for free_kill in free_kills: + product = RolesProducts.objects.filter(kill_house=free_kill.kill_house).first() + free_kill.product = product + free_kill.save() + return HttpResponse('ok') + + +# @api_view(["GET"]) +# @permission_classes([AllowAny]) +# @csrf_exempt +# def kill_house_requests_product_warehousing(request): +# kill_house=KillHouse.objects.get(id=int(request.GET['id'])) +# product=RolesProducts.objects.get(kill_house=kill_house) +# kill_house_requests = KillHouseRequest.objects.filter(killhouse_user=product.kill_house, +# ware_house_confirmation=True, trash=False,calculate_status=True) +# +# governmental_kill_house_requests = kill_house_requests.filter(province_request__poultry_request__free_sale_in_province=False) +# free_kill_house_requests = kill_house_requests.filter(province_request__poultry_request__free_sale_in_province=True) +# # governmental_kill_house_requests = kill_house_requests.filter( +# # province_request__poultry_request__free_sale_in_province=False, +# # province_request__poultry_request__direct_buying=False) +# # free_kill_house_requests = kill_house_requests.filter( +# # Q(province_request__poultry_request__free_sale_in_province=True) | Q( +# # province_request__poultry_request__direct_buying=True)) +# product.province_governmental_carcasses_quantity = \ +# governmental_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_quantity'))['total'] or 0 +# product.province_governmental_carcasses_weight = \ +# governmental_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ +# 'total'] or 0 +# product.province_free_carcasses_quantity = \ +# free_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_quantity'))['total'] or 0 +# product.province_free_carcasses_weight = \ +# free_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ +# 'total'] or 0 +# +# product.save() +# return Response("done!") + + +# @api_view(["GET"]) +# @permission_classes([AllowAny]) +# @csrf_exempt +# def kill_house_free_buying_product_warehousing(request): +# kill_house=KillHouse.objects.get(id=int(request.GET['id'])) +# product=RolesProducts.objects.get(kill_house=kill_house) +# kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(kill_house=product.kill_house, trash=False,calculate_status=True) +# product.free_buying_carcasses_quantity = \ +# kill_house_free_buying_bars.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 +# product.free_buying_carcasses_weight = \ +# kill_house_free_buying_bars.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# product.save() +# return Response("done!") + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def kill_house_cold_house_allocations_product_warehousing(request): + kill_house = KillHouse.objects.get(id=int(request.GET['id'])) + product = RolesProducts.objects.get(kill_house=kill_house) + cold_house_allocations = ColdHouseAllocations.objects.filter(kill_house=product.kill_house, + state__in=('pending', 'accepted'), + trash=False) + + product.freezing_quantity = cold_house_allocations.aggregate(total=Sum('real_quantity'))[ + 'total'] or 0 + product.freezing_weight = cold_house_allocations.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + product.save() + return Response("done!") + + +# @api_view(["GET"]) +# @permission_classes([AllowAny]) +# @csrf_exempt +# def kill_house_allocations_product_warehousing(request): +# kill_house=KillHouse.objects.get(id=int(request.GET['id'])) +# product=RolesProducts.objects.get(kill_house=kill_house) +# kill_house_allocations = StewardAllocation.objects.filter( +# Q(kill_house=product.kill_house) | Q(to_kill_house=product.kill_house), trash=False,calculate_status=True) +# kill_house_allocated = kill_house_allocations.filter(kill_house__isnull=False) +# kill_house_allocated_from = kill_house_allocations.filter(kill_house__isnull=True) +# governmental_kill_house_allocated_from = kill_house_allocated_from.filter(approved_price_status=True) +# free_kill_house_allocated_from = kill_house_allocated_from.filter(approved_price_status=False) +# +# +# product.province_allocated_quantity = kill_house_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( +# total=Sum('real_number_of_carcasses'))[ +# 'total'] or 0 +# product.province_allocated_weight = kill_house_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( +# total=Sum('real_weight_of_carcasses'))[ +# 'total'] or 0 +# +# product.receive_governmental_carcasses_quantity = \ +# governmental_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( +# total=Sum('receiver_real_number_of_carcasses'))[ +# 'total'] or 0 +# product.receive_governmental_carcasses_weight = \ +# governmental_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( +# total=Sum('receiver_real_weight_of_carcasses'))[ +# 'total'] or 0 +# +# +# product.receive_free_carcasses_quantity = \ +# free_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( +# total=Sum('receiver_real_number_of_carcasses'))[ +# 'total'] or 0 +# product.receive_free_carcasses_weight = \ +# free_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( +# total=Sum('receiver_real_weight_of_carcasses'))[ +# 'total'] or 0 +# +# product.save() +# return Response("done!") +# + + +# @api_view(["GET"]) +# @permission_classes([AllowAny]) +# @csrf_exempt +# def kill_house_free_sale_product_warehousing(request): +# kill_house=KillHouse.objects.get(id=int(request.GET['id'])) +# product=RolesProducts.objects.get(kill_house=kill_house) +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=product.kill_house, +# +# trash=False,calculate_status=True) +# +# product.out_province_allocated_quantity = kill_house_free_sale_bars.aggregate(total=Sum('real_number_of_carcasses'))[ +# 'total'] or 0 +# product.out_province_allocated_weight = kill_house_free_sale_bars.aggregate(total=Sum('real_weight_of_carcasses'))[ +# 'total'] or 0 +# # return ({"len(1)":product.out_province_allocated_quantity,"2":product.out_province_allocated_weight}) +# product.save() +# return Response("done!") +# + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_kill_house_request_calculate(request): + check_date = '2024-06-01' + check_date = datetime.strptime(check_date, '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__lt=check_date, trash=False) + for kill_house_request in kill_house_requests: + kill_house_request.calculate_status = False + kill_house_request.save() + return Response("done!") + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_kill_house_free_bar_information_calculate(request): + check_date = '2024-06-01' + check_date = datetime.strptime(check_date, '%Y-%m-%d').date() + kill_house_free_bars = KillHouseFreeBarInformation.objects.filter(date__date__lt=check_date, trash=False) + for kill_house_free_bar in kill_house_free_bars: + kill_house_free_bar.calculate_status = False + kill_house_free_bar.save() + return Response("done!") + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_kill_house_free_sale_bar_information_calculate(request): + check_date = '2024-06-01' + check_date = datetime.strptime(check_date, '%Y-%m-%d').date() + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(date__date__lt=check_date, trash=False) + for kill_house_free_sale_bar in kill_house_free_sale_bars: + kill_house_free_sale_bar.calculate_status = False + kill_house_free_sale_bar.save() + return Response("done!") + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_steward_allocations_calculate(request): + check_date = '2024-06-01' + check_date = datetime.strptime(check_date, '%Y-%m-%d').date() + steward_allocations = StewardAllocation.objects.filter(date__date__lt=check_date, trash=False) + for steward_allocation in steward_allocations: + steward_allocation.calculate_status = False + steward_allocation.save() + return Response("done!") + + +def update_trash_status(model, filter_kwargs): + """ + به‌روزرسانی فیلدهای `trash`, `temporary_trash` و `temporary_deleted` برای یک مدل مشخص. + """ + queryset = model.objects.filter(**filter_kwargs).only('temporary_deleted', 'trash', 'temporary_trash') + for item in queryset: + if item.trash == True: + item.temporary_deleted = True + item.trash = True + item.temporary_trash = True + item.save() + + +def temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (PoultryRequest, {"send_date__date__lt": check_date}), + (CityOperatorCheckRequest, {"poultry_request__send_date__date__lt": check_date}), + (KillRequest, {"recive_date__date__lt": check_date}), + (ProvinceKillRequest, {"kill_request__recive_date__date__lt": check_date}), + (KillHouseRequest, {"kill_request__recive_date__date__lt": check_date}), + (KillHouseAssignmentInformation, {"kill_house_request__kill_request__recive_date__date__lt": check_date}), + (KillHouseFreeBarInformation, {"date__date__lt": check_date}), + (KillHouseFreeSaleBarInformation, {"date__date__lt": check_date}), + (StewardAllocation, {"date__date__lt": check_date}), + (ColdHouseAllocations, {"date__date__lt": check_date}), + (StewardFreeBarInformation, {"date__date__lt": check_date}), + (StewardFreeSaleBarInformation, {"date__date__lt": check_date}), + (InternalTransaction, {"date__date__lt": check_date}), + (ExternalTransaction, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def PoultryRequest_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (PoultryRequest, {"send_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def CityOperatorCheckRequest_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (CityOperatorCheckRequest, {"poultry_request__send_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def KillRequest_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (KillRequest, {"recive_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def ProvinceKillRequest_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (ProvinceKillRequest, {"kill_request__recive_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def KillHouseRequest_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (KillHouseRequest, {"kill_request__recive_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def KillHouseAssignmentInformation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (KillHouseAssignmentInformation, {"kill_house_request__kill_request__recive_date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def KillHouseFreeBarInformation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (KillHouseFreeBarInformation, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def StewardAllocation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (StewardAllocation, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def ColdHouseAllocations_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (ColdHouseAllocations, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def StewardFreeBarInformation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (StewardFreeBarInformation, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def StewardFreeSaleBarInformation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (StewardFreeSaleBarInformation, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def InternalTransaction_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (InternalTransaction, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def ExternalTransaction_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (ExternalTransaction, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def ChainAllocation_temporary_trash_true(request): + check_date = datetime.strptime('2024-11-10', '%Y-%m-%d').date() + + models_and_filters = [ + (ChainAllocation, {"date__date__lt": check_date}), + ] + + for model, filter_kwargs in models_and_filters: + update_trash_status(model, filter_kwargs) + + return HttpResponse('ok') + + +def archive_hatching_temporary_true(request): + filtered_poultry_hatch = PoultryHatching.objects.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True)) + for filtered_poultry in filtered_poultry_hatch: + if filtered_poultry.trash == True: + filtered_poultry.temporary_deleted = True + filtered_poultry.trash = True + filtered_poultry.temporary_trash = True + filtered_poultry.save() + return HttpResponse('ok') + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def duplicate_order_code(request): + from django.db.models import Count + + duplicate_order_codes = PoultryRequest.objects.values('order_code').annotate(count=Count('id')).filter(count__gt=1, + trash=False).values_list( + 'order_code', flat=True) + + return Response(duplicate_order_codes) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_duplicate_order_code(request): + duplicate_order_codes = ( + PoultryRequest.objects + .values('order_code') + .annotate(count=Count('id')) + .filter(count__gt=1, trash=False) + .values_list('order_code', flat=True) + ) + + # استخراج شناسه‌های مرغ‌های مرتبط با کدهای تکراری + poultry_ids = ( + PoultryRequest.objects + .filter(order_code__in=duplicate_order_codes, trash=False) + .values_list('poultry__id', flat=True) + .distinct() + ) + + # مرتب‌سازی مرغ‌ها بر اساس شناسه + poultries = Poultry.objects.filter(trash=False, id__in=poultry_ids).order_by('id') + list1 = [] + # بررسی درخواست‌های مرتبط با هر مرغ + for poultry in poultries: + requests = PoultryRequest.objects.filter(trash=False, poultry=poultry).order_by('order_code') + base_order_code = str(poultry.user.base_order) # فرض بر این است که "user" به درستی تعریف شده است + last_order = [] + for req in requests: + if str(req.order_code)[:4] == base_order_code: + last_order.clear() + last_order.append(req.order_code) + # if str(req.order_code)[:4] != base_order_code: + # list1.append(req.id) + if last_order: + last_num = last_order[0] + 1 + for req in requests: + if str(req.order_code)[:4] != base_order_code: + base_order_code = last_num + req.order_code = base_order_code + req.save() + last_num += 1 + last_order.clear() + + return Response(list1) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_duplicate_order_code_new(request): + duplicate_order_codes = ( + PoultryRequest.objects + .values('order_code') + .annotate(count=Count('id')) + .filter(count__gt=1, trash=False) + .values_list('order_code', flat=True) + ) + + # استخراج شناسه‌های مرغ‌های مرتبط با کدهای تکراری + poultry_ids = ( + PoultryRequest.objects + .filter(order_code__in=duplicate_order_codes, trash=False) + .values_list('poultry__user__id', flat=True) + .distinct() + ) + + # مرتب‌سازی مرغ‌ها بر اساس شناسه + poultries = SystemUserProfile.objects.filter(trash=False, id__in=poultry_ids).order_by('id') + list1 = [] + for user in poultries: + print(user.id) + order_code = int(str(user.base_order) + '0001') + requests = PoultryRequest.objects.filter(trash=False, poultry__user=user).order_by('id') + for req in requests: + req.order_code = order_code + req.save() + order_code += 1 + # # بررسی درخواست‌های مرتبط با هر مرغ + # for poultry in poultries: + # requests = PoultryRequest.objects.filter(trash=False,poultry=poultry).order_by('order_code') + # base_order_code = str(poultry.user.base_order) # فرض بر این است که "user" به درستی تعریف شده است + # last_order=[] + # for req in requests: + # if str(req.order_code)[:4] == base_order_code: + # last_order.clear() + # last_order.append(req.order_code) + # # if str(req.order_code)[:4] != base_order_code: + # # list1.append(req.id) + # if last_order: + # last_num=last_order[0] + 1 + # for req in requests: + # if str(req.order_code)[:4] != base_order_code: + # base_order_code = last_num + # req.order_code=base_order_code + # req.save() + # last_num+=1 + # last_order.clear() + + return Response(list1) + + +def add_free_bar_to_warehouse(): + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + date = datetime.now().date() - timedelta(days=3) + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter(buy_type='live', trash=False, weight_of_carcasses=0, + create_date__date__lt=date, kill_house=kill_house, + ware_house=False) + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + for free_bar in free_bars: + product = free_bar.product + real_weight = round((free_bar.live_weight * 75) / 100) + free_bar.number_of_carcasses = int(real_weight / 1.5) + free_bar.weight_of_carcasses = real_weight + free_bar.weight_loss = 25 + free_bar.ware_house = True + free_bar.date = str(datetime.now()) + free_bar.entered_message = 'ورود به انبار توسط سیستم' + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int( + free_bar.weight_of_carcasses) + + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + kill_house_free_buying_product_warehousing(product) + + mobile = kill_house.kill_house_operator.user.mobile + if kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتارکن' + message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + f'\n' \ + f'تعداد {len(free_bars)} بار (خارج استان) با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") + + +def change_password_poultry(request): + poultries = SystemUserProfile.objects.filter(role__name='Poultry') + for poultry in poultries: + password = random.randint(1000, 9999) + print(password) + data = { + 'username': poultry.mobile, + 'password': str(password) + } + req_change_pass = requests.post( + url=ARTA_URL_CHANGE_PASSWORD, + data=data, + verify=False + ) + if req_change_pass.status_code == 200: + poultry.password = str(password) + poultry.save() + + +def add_vet_farm_to_poultry_request(request): + from django.db.models import F, ExpressionWrapper, DurationField + + requests = PoultryRequest.objects.filter(trash=False, vet_farm__isnull=True).order_by('id') + for r in requests: + vet_farms = VetFarm.objects.filter(poultry=r.poultry).order_by('id') + if len(vet_farms) == 1: + + r.vet_farm = vet_farms.first().vet + r.save() + elif len(vet_farms) > 1: + # محاسبه اختلاف زمان و مرتب‌سازی بر اساس آن + vet_farms_with_diff = vet_farms.annotate( + date_diff=ExpressionWrapper( + F('create_date') - r.send_date, + output_field=DurationField() + ) + ).order_by('-date_diff') + closest_vet_farm = vet_farms_with_diff.first() + if closest_vet_farm: + r.vet_farm = closest_vet_farm.vet + r.save() + return HttpResponse("ok") + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fix_kill_req_njsndb(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 6 or row is None: + continue + poultry = row[3] + date = row[6] + quantity = row[13] + wieght = row[14] + accepterde = row[19] + date = date.split('-') + + date = convert_to_miladi( + year=int(date[0]), + month=int(date[1]), + day=int(date[2]) + ) + kill_req = KillHouseFreeBarInformation.objects.get(trash=False, kill_house=5, + poultry_name=poultry, quantity=int(quantity), + live_weight=int(wieght), date__date=date, + acceptor_rejector=accepterde, + + ) + + kill_house = KillHouse.objects.get(id=int(row[21])) + if kill_house: + print(kill_req.id) + kill_req.exclusive_killer = kill_house + kill_req.save() + + # print(date.date()) + # for kill in kill_req: + # if kill.poultry_name == poultry and kill.quantity== quantity and \ + # kill.live_weight== wieght and kill.date.date() ==date and kill.acceptor_rejector == accepterde: + # print(kill.id) + return HttpResponse('ok') + + +def create_city_guild(request): + city_operator = CityOperator.objects.filter(trash=False, id=1) + prefix = "0918000" # قسمت ثابت شماره موبایل + random_part = random.randint(0, 9999) # تولید یک عدد تصادفی بین ۰ تا ۹۹۹۹ + random_part_str = f"{random_part:04d}" # اطمینان از چهار رقمی بودن (مثلاً ۰۱۲۳ به جای ۱۲۳) + phone_number = prefix + random_part_str + list1 = [] + group = Group.objects.get(name__exact="CityGuild") + for i in city_operator: + first_name = 'شرکت' + last_name = str(i.unit_name.strip().split()[-1]) + password = '2025' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + province = Province.objects.filter(id=i.user.province.id).last() + city = City.objects.filter(id=i.user.city.id).last() + data = { + "username": phone_number, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": '0', + "role": "CityGuild", + "api_key": PROJECT_API_KEY + } + while True: + system_profile = SystemUserProfile.objects.filter(mobile=phone_number, trash=False).last() + if not system_profile: + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + if req.status_code == 200: + break + else: + phone_number = str(int(phone_number) + 1) + else: + phone_number = str(int(phone_number) + 1) + + user = User(username=phone_number, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=phone_number, + first_name=first_name, + last_name=last_name, + fullname=first_name + '' + last_name, + user=user, + base_order=base_id, + password=password, + birthday=str(datetime.now().date()), + city=city, + province=province + ) + system_profile.save() + system_profile.role.add(group) + wallet = Wallet() + wallet.save() + guild = CityGuild( + user=system_profile, + address=i.address, + unit_name=f'شرکت پروتئین {last_name}', + wallet=wallet, + wallet_amount=0, + ) + guild.save() + + return HttpResponse('ok') + + +def add_killing_age_to_poultry_request(request): + poultry_requests = PoultryRequest.objects.filter(trash=False, out_province_request_cancel=False).order_by('id') + for poultry_request in poultry_requests: + age = (poultry_request.send_date.date() - poultry_request.hatching.date.date()).days + 1 + poultry_request.killing_age = age + poultry_request.save() + return HttpResponse('ok') + + +def add_poultry_prediction(request): + poultry_hatching = PoultryHatching.objects.filter(trash=False, temporary_trash=False, + temporary_deleted=False).values_list('poultry__id', + flat=True).distinct() + poultrys = Poultry.objects.filter(id__in=poultry_hatching, trash=False) + for poultry in poultrys: + poultry_prediction(poultry) + return HttpResponse('ok') + + +def fix_out_quantity_hatching(request): + hatchings = PoultryHatching.objects.filter(trash=False, allow_hatching='pending', + state='pending') + l = 0 + for hatching in hatchings: + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending'), + out_province_request_cancel=False, + hatching=hatching) + + total_killed_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] + total_killed_weight = out_poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] + total_killed_weight = total_killed_weight / len(out_poultry_requests) + if total_killed_quantity != hatching.out_province_killed_quantity: + hatching.out_province_killed_quantity = total_killed_quantity + hatching.out_province_killed_weight = int(total_killed_weight * total_killed_quantity) + hatching.save() + return HttpResponse(l) + + +def accept_bar_difference_request_pending_cron_job(): + date = datetime.now().date() - timedelta(days=2) + bar_requests = BarDifferenceRequest.objects.filter(trash=False, + state='pending', create_date__date__lt=date).order_by('id') + for bar_request in bar_requests: + bar_request.state = 'accepted' + bar_request.acceptor_fullname = 'سیستمی' + bar_request.acceptor_mobile = '00000000000' + bar_request.acceptor_date = datetime.now() + bar_request.hatching.bar_difference_request_quantity += bar_request.quantity + bar_request.hatching.bar_difference_request_weight += bar_request.weight + bar_request.hatching.save() + bar_request.save() + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def live_chicken_transportation(request): + import requests + + url = "https://www.samasat.ir/Report/BroilerCarryChickenAccordingToCarriage/_AjaxBinding" + headers = { + "authority": "www.samasat.ir", + "accept": "*/*", + "accept-encoding": "gzip, deflate, br, zstd", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/x-www-form-urlencoded; charset=UTF-8" + } + + cookies = { + "ASP.NET_SessionId": "dl1fj1ad2m4ys1doyjr0gi1c", + ".ASPXAUTH": "01BF39FE4507AAA7C63455A5B32B87A86145C672877A8ACAB074E87A89F13CDA40489ECD2E6732763758CD61528A0AE6BB390A8B3603BDAAA31CDD3AE7509F7885088F9CB51F56128C497F58ADEEFB54791C2F08ACF11AC1662DC1052430AA26E3EF29C1390FEC77C0C27908CC7A7AC9B62D7809419BE9639C848D10EB00022DCEE2B53039E8C13A59E7D50F3BC45D8C2328368285EF992B6FCF076CECFE8EFBE570F3A1FD0831D0B64EB8C9BBD326E088A40BCF3602C565FD00E78309AF4A4B75BA4E99A5A968F2FE666CCB4F176CAD2D9AC75D100EB69EBE4EA832C23C6EC8442B501BE3A014B50B711167292D3934C86843AC8CF151913575473BFE6003332B0DE69FDEAF78993B986CF8766682AC35E7B8A0492CBD59859E94DDABCC0FE6696C4703772CCEA19B05BE641B3F2DB636D79E8AEDB97E81792D9F357E8C8B3A843364032098683E90B61E90A3C2E647AD68BC067624EEB5328D0A22B8D38F9BC2A032C654DEE193580793A0CB0EDA4C65123EF59FC27D44E304FCCD8DB1548A944BEC5D1EE489C95EDBC406E61C603FC479D004DD705AAFE5FC1D10883E416D30AA11A1FF048DC92F41613B54E04F25D63D951F89380518D71CEC42C0E4207B66F0E0A940DF387782BD54A10E84A4F1E0266AB096538577CFA49A64092BC6CEBFED30B4E4F29D1D16EFB78BBF9B54D8047DD8919555906C98D0BFA11D81EDB0C938EAC11561EF3BB403D07A67C32D5F2202FC21881356CC3F954291FCF3C80653C46102A9C45C417D8241569D6D5ABEA8BB26DDA2E8A1E1D2A406A7EBD94F5E2349B5A18FB7C6CFE4E4FAD6C40201EC27F64DB539B964B18BEEA6A1DC188E3981053C0C1572325E54218AB20E663A194C78CEF2716D126456346B8323CCA4387D827AF775C055F7DF1D6131B2AB4B8C4CCC2B5AE7C025A4F6726B42E6BDCB99B8D695E091766B4C61BD16FE16DC8BF096010C6F1C077B12BD702B71C96D46D37670E40056337F971E3B2B8A72E50A64334B0DD480CC2B4E3F658255DF7C5880D6A5B673AE17EDECB65FDB34EF71E378DC1971389FEA8C89F01F96E75E30C4E5B3F42C07823C5AE78A720F71F15BA90FDEE9EE5D22920EB0F9052D083992D3430FCA0D327B365D734E7BBDCACEAAB6C8", + "leggedOut": "-" + } + + payload = { + "sort": "RemoveDateMax-desc", + "page": "1", + "pageSize": "25", + "group": "", + "aggregate": "HatchingCount-sum~RemoveCount-sum", + "filter": "", + "searchVm.ProvinceLocationId": "65550", + "searchVm.UnitName": "", + "searchVm.PersonFullName": "", + "searchVm.PartIdCode": "", + "searchVm.PostalCode": "", + "searchVm.EpidemiologicCode": "", + "searchVm.CapacityFemale": "", + "searchVm.BfrCode": "", + "searchVm.SourceCertId": "", + "searchVm.HatchingCount": "", + "searchVm.RemoveCount": "", + "searchVm.HatchingDateFrom": "", + "searchVm.HatchingDateTo": "", + "searchVm.PercentRemoveTakhlieFromHatchingFrom": "", + "searchVm.PercentRemoveTakhlieFromHatchingTo": "", + "searchVm.RemoveDateMinFrom": "", + "searchVm.RemoveDateMinTo": "", + "searchVm.RemoveDateMaxFrom": "1403/11/24", + "searchVm.RemoveDateMaxTo": "1403/12/04", + "searchVm.RemoveAgeAvgFrom": "", + "searchVm.RemoveAgeAvgTo": "", + "searchVm.RemoveAgeAvgSamasatFrom": "", + "searchVm.RemoveAgeAvgSamasatTo": "", + "searchVm.RemovePartyCountFrom": "", + "searchVm.RemovePartyCountTo": "" + } + + response = requests.post(url, headers=headers, cookies=cookies, data=payload) + + return Response(response.json()) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def heards_meat_flow(request): + import requests + url = "https://www.samasat.ir/Report/BroilerOnFlowFlocksHealthPermitReport/_AjaxBinding" + headers = { + "authority": "www.samasat.ir", + "accept": "*/*", + "accept-encoding": "gzip, deflate, br, zstd", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/x-www-form-urlencoded; charset=UTF-8" + } + + cookies = { + "ASP.NET_SessionId": "dl1fj1ad2m4ys1doyjr0gi1c", + ".ASPXAUTH": "01BF39FE4507AAA7C63455A5B32B87A86145C672877A8ACAB074E87A89F13CDA40489ECD2E6732763758CD61528A0AE6BB390A8B3603BDAAA31CDD3AE7509F7885088F9CB51F56128C497F58ADEEFB54791C2F08ACF11AC1662DC1052430AA26E3EF29C1390FEC77C0C27908CC7A7AC9B62D7809419BE9639C848D10EB00022DCEE2B53039E8C13A59E7D50F3BC45D8C2328368285EF992B6FCF076CECFE8EFBE570F3A1FD0831D0B64EB8C9BBD326E088A40BCF3602C565FD00E78309AF4A4B75BA4E99A5A968F2FE666CCB4F176CAD2D9AC75D100EB69EBE4EA832C23C6EC8442B501BE3A014B50B711167292D3934C86843AC8CF151913575473BFE6003332B0DE69FDEAF78993B986CF8766682AC35E7B8A0492CBD59859E94DDABCC0FE6696C4703772CCEA19B05BE641B3F2DB636D79E8AEDB97E81792D9F357E8C8B3A843364032098683E90B61E90A3C2E647AD68BC067624EEB5328D0A22B8D38F9BC2A032C654DEE193580793A0CB0EDA4C65123EF59FC27D44E304FCCD8DB1548A944BEC5D1EE489C95EDBC406E61C603FC479D004DD705AAFE5FC1D10883E416D30AA11A1FF048DC92F41613B54E04F25D63D951F89380518D71CEC42C0E4207B66F0E0A940DF387782BD54A10E84A4F1E0266AB096538577CFA49A64092BC6CEBFED30B4E4F29D1D16EFB78BBF9B54D8047DD8919555906C98D0BFA11D81EDB0C938EAC11561EF3BB403D07A67C32D5F2202FC21881356CC3F954291FCF3C80653C46102A9C45C417D8241569D6D5ABEA8BB26DDA2E8A1E1D2A406A7EBD94F5E2349B5A18FB7C6CFE4E4FAD6C40201EC27F64DB539B964B18BEEA6A1DC188E3981053C0C1572325E54218AB20E663A194C78CEF2716D126456346B8323CCA4387D827AF775C055F7DF1D6131B2AB4B8C4CCC2B5AE7c025A4F6726B42E6BDCB99B8D695E091766B4C61BD16FE16DC8BF096010C6F1C077B12BD702B71C96D46D37670E40056337F971E3B2B8A72E50A64334B0DD480CC2B4E3F658255DF7C5880D6A5B673AE17EDECB65FDB34EF71E378DC1971389FEA8C89F01F96E75E30C4E5B3F42C07823C5AE78A720F71F15BA90FDEE9EE5D22920EB0F9052D083992D3430FCA0D327B365D734E7BBDCACEAAB6C8", + "leggedOut": "-" + } + + payload = { + "sort": "HatchingDate-desc", + "page": "1", + "pageSize": "25", + "group": "", + "aggregate": "HatchingCount-sum~HatchingCountInBargiri-sum~HatchingCountInTakhlie-sum~TrackingBargiriCount-sum~DiffHamlThanTakhlieCount-sum~DiffTakhlieThanHamlCount-sum~HamlMorghTotalCount-sum~HamlMorghTakhlieCount-sum~EvacuationCount-sum", + "filter": "", + "searchVm.FromDate": "01/09/1403 12:00:00 ق.ظ", + "searchVm.ToDate": "04/12/1403 12:00:00 ق.ظ", + "searchVm.TableName": "Z_002_ReportTempTable_5a2f0974ec3542d4b92ac87e75ef5549", + "searchVm.ProvinceLocationId": "65550", + "searchVm.PartIdCode": "", + "searchVm.UnitName": "", + "searchVm.PostalCode": "", + "searchVm.EpidemiologicCode": "", + "searchVm.PersonFullName": "", + "searchVm.CapacityFemaleFrom": "", + "searchVm.CapacityFemaleTo": "", + "searchVm.RequestCode": "", + "searchVm.DesCertId": "", + "searchVm.FlockAgeDayFrom": "1", + "searchVm.FlockAgeDayTo": "60", + "searchVm.HatchingDateFromPersian": "", + "searchVm.HatchingDateToPersian": "", + "searchVm.MaxHatchingDateFromPersian": "", + "searchVm.MaxHatchingDateToPersian": "", + "searchVm.TrackingStatusId": "", + "searchVm.PercentMorghToJoojeTotalFrom": "", + "searchVm.PercentMorghToJoojeTotalTo": "", + "searchVm.PercentMorghToJoojeTakhlieFrom": "", + "searchVm.PercentMorghToJoojeTakhlieTo": "" + } + + # Send the POST request + response = requests.post(url, headers=headers, cookies=cookies, data=payload) + + return Response(response.json()) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def detail_heards_meat_flow(request): + import requests + + url = "https://www.samasat.ir/WinBroilerFlockRequest/WinBroilerFlockRequestHatchingTrackingRep/_AjaxBindingWinBroilerFlockRequestHatchingTrackingRepVw" + headers = { + "authority": "www.samasat.ir", + "accept": "*/*", + "accept-encoding": "gzip, deflate, br, zstd", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/x-www-form-urlencoded; charset=UTF-8" + } + + cookies = { + "ASP.NET_SessionId": "i2l4rxgagljnsecfg4smvbwg", + ".ASPXAUTH": "681FA227EBBFA8AFFA02E6C23A8B52159139B3D2E6AB49D18E71D6E568273F013CC434A01E2E9B27F6594D01A3B5FBC3923AA876642555D6FDD209306CB9336FE1CC172797B46B72274BDEBFCCD7EAD1EC6C69A30A871BE40FF5C9EDC025E10569533963A92F00B03A3495622A962FBE0FFDAF4B4EC513AF1458BF6282C2C7D2618DCA2A1394D5E1BF34EA50FED6490AD29AA63749DC0EA8849792A6834139F6EDA2C5C938AC36A92371B542C576FEA94A81F3D7274F6EFFCD8FD08820B871D4BD588CB415DCC3D86B5408577D50C1C36B00D6032BE82D85BD80453D5C1FF719C186000C379CB43FB794AE9C91838A0D04D744BEC9E7ADDCCB0668B0326F1B1F50EAE3128537F4ECB07A5453AFBCDD22A5509A1DDE5AA7EF25CBAFBEB06182E468E80BB28C7DEE72D1990FCDE24C6B4E1621E77BCF221A25783CD87D15777C1698052EA6193725C5CB0B3DF1788D1C15DF2AB14357A6051DA5810B948EEDC7697E701EED1D1A69E268742EB63A133F5667D23D2191ABC60C8A0C828A61CBF8432DD6F49DA32B7D9FAE4DA4AF0D7A175A6CCAFDB2DAB13DA6A5AD802945F0A9DB3E9FE8D4694449600109EF2656993993C14F269C8E61747696480B0079765B99386F7A218E38C37A32E9D14C97B246E3102FCFD5E298C11A1955D88FC2D94F5795B7245B62611965C2A46B3E9B0E906D5879B6D3AFF76401E7F5F1CE6E7215CF6AF52D313A3A57853E23F0E2402B9101F482BA857A987EAC5B2895FB29C49840EA2AB0F4A316A3223F8E67967A2ADFB43CFE47109A70A98725EFAB57F68A57E42F5E0DB306339BE841861A094399A8BA9CD98ED065A20CFB30C5ECC46A3CBD9C7B03DFDD603C0C143D353EC1A8A2CE0AB9ADB69A3EFB0B6B953520B133026355CC4FAAFD9D380FE436CD8B87471ED0B507663192A4B35A2D085BAD0A47C9DBC5E813EFF7BE2BB64A2A10A5A8EFE0D80CBE2EE81E2DC0F86DAD4A5D9F2A1F7E32EAFF8669E95616DB93CCF5FD801B293D47AEFAB1EE5C2801D2E916868687226315BAF13A971ED0382D75EF0EA69271962959DD05AB22B2A6397980B026B59A8A38A1385689258D7BB05E0DFAF7E4DF9868A50088D044003FB55A6D20E8EBAF92F457C1BBCD7BFB5E15A0795445A11ECA", + "leggedOut": "-" + } + + payload = { + "sort": "IssueDate-desc", + "page": "1", + "pageSize": "25", + "group": "", + "filter": "", + "certId": "140313016425" + } + + response = requests.post(url, headers=headers, cookies=cookies, data=payload) + + return Response(response.json()) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def breed(request): + import requests + + url = "https://www.samasat.ir/Report/BroilerFlockRequestDetailReport/_AjaxBinding" + headers = { + "authority": "www.samasat.ir", + "accept": "*/*", + "accept-encoding": "gzip, deflate, br, zstd", + "accept-language": "en-US,en;q=0.9", + "content-type": "application/x-www-form-urlencoded; charset=UTF-8" + } + + cookies = { + "ASP.NET_SessionId": "i2l4rxgagljnsecfg4smvbwg", + ".ASPXAUTH": "681FA227EBBFA8AFFA02E6C23A8B52159139B3D2E6AB49D18E71D6E568273F013CC434A01E2E9B27F6594D01A3B5FBC3923AA876642555D6FDD209306CB9336FE1CC172797B46B72274BDEBFCCD7EAD1EC6C69A30A871BE40FF5C9EDC025E10569533963A92F00B03A3495622A962FBE0FFDAF4B4EC513AF1458BF6282C2C7D2618DCA2A1394D5E1BF34EA50FED6490AD29AA63749DC0EA8849792A6834139F6EDA2C5C938AC36A92371B542C576FEA94A81F3D7274F6EFFCD8FD08820B871D4BD588CB415DCC3D86B5408577D50C1C36B00D6032BE82D85BD80453D5C1FF719C186000C379CB43FB794AE9C91838A0D04D744BEC9E7ADDCCB0668B0326F1B1F50EAE3128537F4ECB07A5453AFBCDD22A5509A1DDE5AA7EF25CBAFBEB06182E468E80BB28C7DEE72D1990FCDE24C6B4E1621E77BCF221A25783CD87D15777C1698052EA6193725C5CB0B3DF1788D1C15DF2AB14357A6051DA5810B948EEDC7697E701EED1D1A69E268742EB63A133F5667D23D2191ABC60C8A0C828A61CBF8432DD6F49DA32B7D9FAE4DA4AF0D7A175A6CCAFDB2DAB13DA6A5AD802945F0A9DB3E9FE8D4694449600109EF2656993993C14F269C8E61747696480B0079765B99386F7A218E38C37A32E9D14C97B246E3102FCFD5E298C11A1955D88FC2D94F5795B7245B62611965C2A46B3E9B0E906D5879B6D3AFF76401E7F5F1CE6E7215CF6AF52D313A3A57853E23F0E2402B9101F482BA857A987EAC5B2895FB29C49840EA2AB0F4A316A3223F8E67967A2ADFB43CFE47109A70A98725EFAB57F68A57E42F5E0DB306339BE841861A094399A8BA9CD98ED065A20CFB30C5ECC46A3CBD9C7B03DFDD603C0C143D353EC1A8A2CE0AB9ADB69A3EFB0B6B953520B133026355CC4FAAFD9D380FE436CD8B87471ED0B507663192A4B35A2D085BAD0A47C9DBC5E813EFF7BE2BB64A2A10A5A8EFE0D80CBE2EE81E2DC0F86DAD4A5D9F2A1F7E32EAFF8669E95616DB93CCF5FD801B293D47AEFAB1EE5C2801D2E916868687226315BAF13A971ED0382D75EF0EA69271962959DD05AB22B2A6397980B026B59A8A38A1385689258D7BB05E0DFAF7E4DF9868A50088D044003FB55A6D20E8EBAF92F457C1BBCD7BFB5E15A0795445A11ECA", + "leggedOut": "-" + } + + payload = { + "sort": "SendDate-desc", + "page": "1", + "pageSize": "25", + "group": "", + "aggregate": "RequestCountLong-sum~ChickCountLong-sum", + "filter": "", + "searchVm.FlockRequestId": "", + "searchVm.Islegal": "True", + "searchVm.HatcheryId": "", + "searchVm.ProvinceLocationId": "65550", + "searchVm.PartIdCode": "", + "searchVm.UnitName": "", + "searchVm.BfrRequestCode": "", + "searchVm.CertId": "", + "searchVm.BroilerPedigreeTypeId": "", + "searchVm.SendDateFrom": "1403/11/28", + "searchVm.SendDateTo": "1403/12/05", + "searchVm.ChickCountFrom": "", + "searchVm.ChickCountTo": "", + "searchVm.PedigreeType": "", + "searchVm.SenderUnitName": "", + "searchVm.StartDateFrom": "", + "searchVm.StartDateTo": "", + "searchVm.EndDateFrom": "", + "searchVm.EndDateTo": "", + "searchVm.RequestCountFrom": "", + "searchVm.RequestCountTo": "", + "searchVm.SystemCode": "", + "searchVm.EpidemiologicCode": "", + "searchVm.PostalCode": "", + "searchVm.CapacityFemaleFrom": "", + "searchVm.CapacityFemaleTo": "", + "searchVm.PersonNationalCodeOrId": "", + "searchVm.PersonName": "", + "searchVm.RegDateFrom": "", + "searchVm.RegDateTo": "" + } + + response = requests.post(url, headers=headers, cookies=cookies, data=payload) + + return Response(response.json()) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def chat_bot_info(request): + hatchings = PoultryHatching.objects.filter(trash=False, archive=False, state='pending').order_by('date') + poultry = Poultry.objects.filter(pk__in=hatchings.values_list('poultry', flat=True)) + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), + return_to_province=False, + province_request__poultry_request__hatching__in=hatchings) + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=hatchings) + + result = { + "number_of_hatchings": len(hatchings), + "number_of_poultry": len(poultry), + "hatching_quantity": hatchings.aggregate(total=Sum('quantity'))['total'] or 0, + "number_province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0, + "number_of_kill_house_requests": len(kill_house_requests), + "kill_house_requests_quantity": kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0, + } + + return Response(result, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def add_interest_license_id_to_poultry(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + list1 = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 6 or row is None: + continue + breeding = row[5] + licenc = row[13] + try: + poultry = Poultry.objects.get(breeding_unique_id=breeding, trash=False) + poultry.interest_license_id = licenc + poultry.save() + except: + list1.append(breeding) + # print(date.date()) + # for kill in kill_req: + # if kill.poultry_name == poultry and kill.quantity== quantity and \ + # kill.live_weight== wieght and kill.date.date() ==date and kill.acceptor_rejector == accepterde: + # print(kill.id) + return HttpResponse(list1) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def add_asddasasd(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + list1 = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i < 1 or row is None: + continue + + east = row[16] + west = row[17] + licenc = row[3] + poultry = Poultry.objects.filter(Lat__isnull=True, interest_license_id=licenc).first() + if poultry: + if east and west is not None: + lon, lat = utm_to_loc(east, west) + poultry.Lat = lon + poultry.Long = lat + poultry.save() + # تبدیل مختصات + # breeding=row[5] + # licenc=row[13] + # try: + # poultry=Poultry.objects.get(breeding_unique_id=breeding,trash=False) + # poultry.interest_license_id=licenc + # poultry.save() + # except: + # list1.append(breeding) + # # print(date.date()) + # for kill in kill_req: + # if kill.poultry_name == poultry and kill.quantity== quantity and \ + # kill.live_weight== wieght and kill.date.date() ==date and kill.acceptor_rejector == accepterde: + # print(kill.id) + return HttpResponse(list1) + + +# def add_to_warehouse_manual(request): +# kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( +# 'system_address__province') +# for kill_house in kill_houses: +# kill_house_requests = KillHouseRequest.objects.filter( +# Q(killhouse_user=kill_house) | Q(killer=kill_house), +# ware_house_confirmation=False, trash=False, calculate_status=True) +# if kill_house_requests: +# # wieght = \ +# # kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ +# # 'total'] or 0 +# for kill_house_request in kill_house_requests: +# kill_house = kill_house_request.killhouse_user +# product = RolesProducts.objects.filter(parent_product__product_id=2, kill_house=kill_house).first() +# +# +# +# kill_house_request.ware_house_accepted_real_quantity = kill_house_request.accepted_real_quantity +# kill_house_request.ware_house_accepted_real_weight = int(kill_house_request.accepted_real_weight - ( +# (kill_house_request.accepted_real_weight * 25) / 100)) +# kill_house_request.weight_loss = 25 +# kill_house_request.ware_house_input_type = 'loss_weight' +# kill_house_request.ware_house_confirmation = True +# kill_house_request.date_of_ware_house = str(datetime.now()) +# kill_house_request.entered_message='ورود به انبار توسط سیستم' +# kill_house_request.save() +# kill_house_requests_product_warehousing(product) +# +# # mobile=kill_house.kill_house_operator.user.mobile +# # if kill_house.killer == False: +# # killer = 'کشتارگاه' +# # else: +# # killer = 'کشتارکن' +# # message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ +# # f'\n' \ +# # f'تعداد {len(kill_house_requests)} بار با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ +# # f'\n' \ +# # f'(سامانه رصدیار)' +# # check_mobile = check_mobile_number(mobile) +# # if check_mobile: +# # req = requests.get( +# # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") +# return HttpResponse('ok') + +def add_free_bar_to_warehouse_automatic_type_manual(request): + if base_url_for_sms_report == 'ha' or base_url_for_sms_report == 'ku': + send_day = 2 + send_time = 48 + else: + send_day = 1 + send_time = 24 + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter( + create_date__date__lt=datetime.now().date() - timedelta(days=send_day), buy_type='live', trash=False, + weight_of_carcasses=0, kill_house=kill_house, ware_house=False, register_type='automatic') + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for free_bar in free_bars: + product = free_bar.product + real_weight = round((free_bar.live_weight * 75) / 100) + free_bar.number_of_carcasses = int(real_weight / 1.5) + free_bar.weight_of_carcasses = real_weight + free_bar.weight_loss = 25 + free_bar.ware_house = True + free_bar.date = str(datetime.now()) + # free_bar.entered_message = 'ورود به انبار توسط سیستم' + # free_bar.entered_message = 'ورود به انبار مجازی' + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int( + free_bar.weight_of_carcasses) + + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + kill_house_free_buying_product_warehousing(product) + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + to_locale_str(int(real_weight)), + shamsi_date(free_bar.create_date) + )) + # mobile=kill_house.kill_house_operator.user.mobile + # if kill_house.killer == False: + # killer = 'کشتارگاه' + # else: + # killer = 'کشتارکن' + # message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + # f'\n' \ + # f'تعداد {len(free_bars)} بار (خارج استان) با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ + # f'\n' \ + # f'(سامانه رصدیار)' + # check_mobile = check_mobile_number(mobile) + # if check_mobile: + # req = requests.get( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار مجازی به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به شما، به دلیل گذشت مهلت {send_time} ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار مجازی منتقل گردید.*** ' \ + '\n' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return HttpResponse('ok') + + +def add_free_bar_to_warehouse_automatic_type_cron(): + # if base_url_for_sms_report == 'ha': + send_day = 2 + send_time = 48 + # else: + # send_day = 1 + # send_time = 24 + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter( + register_date__date__lt=datetime.now().date() - timedelta(days=send_day), buy_type='live', trash=False, + weight_of_carcasses=0, kill_house=kill_house, ware_house=False, register_type='automatic') + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for free_bar in free_bars: + product = free_bar.product + real_weight = round((free_bar.live_weight * 75) / 100) + free_bar.number_of_carcasses = int(real_weight / 1.5) + free_bar.weight_of_carcasses = real_weight + free_bar.weight_loss = 25 + free_bar.ware_house = True + free_bar.date = str(datetime.now()) + # free_bar.entered_message = 'ورود به انبار توسط سیستم' + # free_bar.entered_message = 'ورود به انبار مجازی' + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int( + free_bar.weight_of_carcasses) + + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + kill_house_free_buying_product_warehousing(product) + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + to_locale_str(int(real_weight)), + shamsi_date(free_bar.create_date) + )) + # mobile=kill_house.kill_house_operator.user.mobile + # if kill_house.killer == False: + # killer = 'کشتارگاه' + # else: + # killer = 'کشتارکن' + # message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + # f'\n' \ + # f'تعداد {len(free_bars)} بار (خارج استان) با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ + # f'\n' \ + # f'(سامانه رصدیار)' + # check_mobile = check_mobile_number(mobile) + # if check_mobile: + # req = requests.get( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار مجازی به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به شما، به دلیل گذشت مهلت {send_time} ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار مجازی منتقل گردید.*** ' \ + '\n' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def add_free_bar_to_warehouse_manual(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter( + create_date__date__lt=datetime.now().date() - timedelta(days=2), buy_type='live', trash=False, + weight_of_carcasses=0, kill_house=kill_house, ware_house=False, register_type='manual') + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for free_bar in free_bars: + product = free_bar.product + real_weight = round((free_bar.live_weight * 75) / 100) + free_bar.number_of_carcasses = int(real_weight / 1.5) + free_bar.weight_of_carcasses = real_weight + free_bar.weight_loss = 25 + free_bar.ware_house = True + free_bar.date = str(datetime.now()) + free_bar.entered_message = 'ورود به انبار توسط سیستم' + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int( + free_bar.weight_of_carcasses) + + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + kill_house_free_buying_product_warehousing(product) + + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + to_locale_str(int(real_weight)), + shamsi_date(free_bar.date) + )) + # mobile=kill_house.kill_house_operator.user.mobile + # if kill_house.killer == False: + # killer = 'کشتارگاه' + # else: + # killer = 'کشتارکن' + # message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + # f'\n' \ + # f'تعداد {len(free_bars)} بار (خارج استان) با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ + # f'\n' \ + # f'(سامانه رصدیار)' + # check_mobile = check_mobile_number(mobile) + # if check_mobile: + # req = requests.get( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به شما، به دلیل گذشت مهلت ۴۸ ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار منتقل گردید.*** ' \ + '***' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + return HttpResponse('ok') + + +def add_free_bar_to_warehouse_cron(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter(create_date__date__lt=datetime.now().date() - + timedelta(days=2), buy_type='live', + trash=False, + weight_of_carcasses=0, kill_house=kill_house, + ware_house=False + , register_type='manual') + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for free_bar in free_bars: + product = free_bar.product + real_weight = round((free_bar.live_weight * 75) / 100) + free_bar.number_of_carcasses = int(real_weight / 1.5) + free_bar.weight_of_carcasses = real_weight + free_bar.weight_loss = 25 + free_bar.ware_house = True + free_bar.date = str(datetime.now()) + free_bar.entered_message = 'ورود به انبار توسط سیستم' + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int( + free_bar.weight_of_carcasses) + + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + kill_house_free_buying_product_warehousing(product) + + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + to_locale_str(int(real_weight)), + shamsi_date(free_bar.date) + )) + # mobile=kill_house.kill_house_operator.user.mobile + # if kill_house.killer == False: + # killer = 'کشتارگاه' + # else: + # killer = 'کشتارکن' + # message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + # f'\n' \ + # f'تعداد {len(free_bars)} بار (خارج استان) با حجم {wieght} به علت گذشتن زمان لازم برای ورود به انبار توسط سیستم وارد انبار شدند.' \ + # f'\n' \ + # f'(سامانه رصدیار)' + # check_mobile = check_mobile_number(mobile) + # if check_mobile: + # req = requests.get( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to={mobile}&message={message}") + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به شما، به دلیل گذشت مهلت ۴۸ ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار منتقل گردید.*** ' \ + '***' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def fix_poultry_request_script(request): + hatchings = PoultryHatching.objects.filter(trash=False, archive=False, + allow_hatching='pending') + for hatching in hatchings: + + province_requests = PoultryRequest.objects.filter( + Q(wage_pay=False, has_wage=False) | Q(wage_pay=True, has_wage=True), hatching=hatching + , state_process='accepted', province_state='accepted', trash=False, archive=False, + out_province_request_cancel=False, out=True) + if province_requests: + hatching.out_province_killed_quantity = province_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + hatching.out_province_killed_weight = province_requests.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + hatching.save() + + return HttpResponse('ok') + + +def add_to_warehouse(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + date = datetime.now().date() - timedelta(days=2) + for kill_house in kill_houses: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__lt=date, + ware_house_confirmation=False, trash=False, calculate_status=True) + if kill_house_requests: + wieght = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + len_kill_house_requests = len(kill_house_requests) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for kill_house_request in kill_house_requests: + kill_house = kill_house_request.killhouse_user + kill_house_request.ware_house_accepted_real_quantity = kill_house_request.accepted_real_quantity + kill_house_request.ware_house_accepted_real_weight = int( + (kill_house_request.accepted_real_weight * 75) / 100) + kill_house_request.weight_loss = 25 + kill_house_request.ware_house_input_type = 'loss_weight' + kill_house_request.ware_house_confirmation = True + kill_house_request.date_of_ware_house = str(datetime.now()) + kill_house_request.entered_message = 'ورود به انبار توسط سیستم' + kill_house_request.save() + + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + kill_house_request.clearance_code, + to_locale_str(int(kill_house_request.accepted_real_weight)), + to_locale_str(int(kill_house_request.ware_house_accepted_real_weight)), + shamsi_date(kill_house_request.kill_request.recive_date) + )) + product = RolesProducts.objects.filter(kill_house=kill_house).first() + kill_house_requests_product_warehousing(product) + + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار داخل استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به جنابعالی، به دلیل گذشت مهلت ۴۸ ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار منتقل گردید.' \ + f'***' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def add_to_warehouse_manual(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + date = datetime.now().date() - timedelta(days=2) + for kill_house in kill_houses: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__lt=date, + ware_house_confirmation=False, trash=False, calculate_status=True) + if kill_house_requests: + wieght = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + len_kill_house_requests = len(kill_house_requests) + ware_house_accepted_real_weight = int((wieght * 75) / 100) + bars_info = [] + for kill_house_request in kill_house_requests: + kill_house = kill_house_request.killhouse_user + kill_house_request.ware_house_accepted_real_quantity = kill_house_request.accepted_real_quantity + kill_house_request.ware_house_accepted_real_weight = int( + (kill_house_request.accepted_real_weight * 75) / 100) + kill_house_request.weight_loss = 25 + kill_house_request.ware_house_input_type = 'loss_weight' + kill_house_request.ware_house_confirmation = True + kill_house_request.date_of_ware_house = str(datetime.now()) + kill_house_request.entered_message = 'ورود به انبار توسط سیستم' + kill_house_request.save() + + bars_info.append( + 'کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - وزن لاشه: {2} کیلوگرم - تاریخ بار: ({3})'.format( + kill_house_request.clearance_code, + to_locale_str(int(kill_house_request.accepted_real_weight)), + to_locale_str(int(kill_house_request.ware_house_accepted_real_weight)), + shamsi_date(kill_house_request.kill_request.recive_date) + ) + ) + + product = RolesProducts.objects.filter(kill_house=kill_house).first() + kill_house_requests_product_warehousing(product) + + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:اعلام ورود بار به انبار به دلیل انقضای مهلت زمانی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار داخل استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم و وزن لاشه {to_locale_str(int(ware_house_accepted_real_weight))} کیلوگرم متعلق به جنابعالی، به دلیل گذشت مهلت ۴۸ ساعته و عدم اقدام به موقع، به‌صورت خودکار به انبار منتقل گردید.' \ + f'***' \ + f' جزئیات بارهای منتقل شده:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f' جهت مشاهده بارها به بخش انبار و توزیع مراجعه نمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return HttpResponse('ok') + + +def return_from_archive_poultry_hatching_with_cron_job(): + now_date = datetime.now().date() + hatching = PoultryHatching.objects.filter(trash=False, + allow_hatching='True', input_archiver__isnull=True, + last_change__role="automatic-archive", + state='complete', archive=True, last_change__isnull=False).only( + 'allow_hatching', + 'left_over', 'quantity', 'state', + 'archive') + for hatch in hatching: + archive_date = hatch.last_change['date'] + date1 = datetime.strptime(archive_date, '%Y-%m-%d %H:%M:%S.%f').date() + if now_date == date1: + if hatch.left_over > (hatch.quantity * percent_of_losses): + hatch.violation = False + hatch.allow_hatching = 'pending' + hatch.state = 'pending' + hatch.archive = False + if hatch.first_date_input_archive is not None: + hatch.first_date_input_archive = None + + hatch.last_change = None + hatch.save() + + +def warning_free_bar_to_warehouse_manual(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter(buy_type='live', trash=False, + weight_of_carcasses=0, kill_house=kill_house, + ware_house=False) + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + bars_info = ['کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - تاریخ بار: ({2})'.format + (free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + shamsi_date(free_bar.date)) + for free_bar in free_bars] + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری بارهای وارد نشده به انبار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم وارد انبار نگردیده است.' \ + '\n' \ + f' جزئیات بارهای وارد نشده به انبار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return HttpResponse('ok') + + +def warning_free_bar_to_warehouse_cron(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).select_related( + 'system_address__province') + for kill_house in kill_houses: + free_bars = KillHouseFreeBarInformation.objects.filter(buy_type='live', trash=False, + weight_of_carcasses=0, kill_house=kill_house, + ware_house=False) + + if free_bars: + wieght = \ + free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + + len_kill_house_requests = len(free_bars) + bars_info = ['کد قرنطینه: {0} - وزن زنده: {1} کیلوگرم - تاریخ بار: ({2})'.format + (free_bar.bar_clearance_code, + to_locale_str(int(free_bar.live_weight)), + shamsi_date(free_bar.date)) + for free_bar in free_bars] + + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری بارهای وارد نشده به انبار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد. ***' \ + '\n' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار خارج استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم وارد انبار نگردیده است.' \ + '\n' \ + f' جزئیات بارهای وارد نشده به انبار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def warning_to_warehouse_cron(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + for kill_house in kill_houses: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True) + if kill_house_requests: + wieght = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + len_kill_house_requests = len(kill_house_requests) + bars_info = ['کد بار: {0} - وزن زنده: {1} کیلوگرم - تاریخ بار: {2}'.format( + bar.bar_code, + to_locale_str(int(bar.accepted_real_weight)), + shamsi_date(bar.kill_request.recive_date)) + for bar in kill_house_requests] + + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری بارهای وارد نشده به انبار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار داخل استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم وارد انبار نگردیده است.' \ + f'***' \ + f' جزئیات بارهای وارد نشده به انبار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def warning_to_warehouse_manual(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + for kill_house in kill_houses: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True) + if kill_house_requests: + wieght = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + len_kill_house_requests = len(kill_house_requests) + bars_info = ['کد بار: {0} - وزن زنده: {1} کیلوگرم - تاریخ بار: ({2})'.format( + bar.bar_code, + to_locale_str(int(bar.accepted_real_weight)), + shamsi_date(bar.kill_request.recive_date)) + for bar in kill_house_requests] + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری بارهای وارد نشده به انبار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، محموله بار داخل استانی به تعداد {to_locale_str(len_kill_house_requests)} بار و وزن زنده {to_locale_str(int(wieght))} کیلوگرم وارد انبار نگردیده است.' \ + f'***' \ + f' جزئیات بارهای وارد نشده به انبار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return HttpResponse('ok') + + +def warning_province_kill_request_without_bar_manual(request): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + for kill_house in kill_houses: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), + archive_wage=False, + return_to_province=False, + trash=False, first_car_allocated_quantity=0) + if province_kill_request: + wieght = \ + province_kill_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + len_province_kill_request = len(province_kill_request) + bars_info = ['کد سفارش: {0} - وزن: {1} کیلوگرم - تاریخ تخصیص: ({2})'.format + (bar.province_request.poultry_request.order_code, + to_locale_str(int(bar.quantity)), + shamsi_date(bar.kill_request.recive_date)) + for bar in province_kill_request] + + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری تخصیصات بدون بار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، تخصیصات بدون بار به تعداد {to_locale_str(len_province_kill_request)} تخصیص و وزن {to_locale_str(int(wieght))} کیلوگرم فاقد تخصیص ماشین میباشد.' \ + f'***' \ + f' جزئیات تخصیصات بدون بار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return HttpResponse('ok') + + +def warning_province_kill_request_without_bar_cron(): + user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + for kill_house in kill_houses: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), + archive_wage=False, + return_to_province=False, + trash=False, first_car_allocated_quantity=0) + if province_kill_request: + wieght = \ + province_kill_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + len_province_kill_request = len(province_kill_request) + bars_info = ['کد سفارش:{0} - وزن:{1} کیلوگرم - تاریخ تخصیص:{2}'.format + (bar.province_request.poultry_request.order_code, + to_locale_str(int(bar.quantity)), + shamsi_date(bar.province_request.kill_request.recive_date)) + for bar in province_kill_request] + new_ticket = TicketSupport( + user=kill_house.kill_house_operator.user, + title="پیام سیستمی:یادآوری تخصیصات بدون بار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house.kill_house_operator.user) + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '***' \ + f'به استحضار می‌رساند مطابق سیستم‌مانیتورینگ سامانه، تخصیصات بدون بار به تعداد {to_locale_str(len_province_kill_request)} تخصیص و وزن {to_locale_str(int(wieght))} کیلوگرم فاقد تخصیص ماشین میباشد.' \ + f'***' \ + f' جزئیات تخصیصات بدون بار:' \ + f'***' \ + f'{bars_details}' \ + f'***' \ + f'لطفاً در اسرع وقت نسبت به تعیین تکلیف بارهای مربوطه در سامانه اقدام فرمایید.' \ + f'***' \ + f'با تشکر -ربات هوشمند سامانه رصدیار' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def update_chicken_age_from_login_manual(request): + poultry_hatching = PoultryHatching.objects.filter(trash=False).only('date', 'chicken_age', 'last_change').order_by( + '-id') + now = datetime.now().date() + for hatching in poultry_hatching: + now_age = (now - hatching.date.date()).days + 1 + if hatching.archive == False and hatching.allow_hatching == 'pending': + hatching.chicken_age = now_age + hatching.save() + elif hatching.archive == True and hatching.allow_hatching == 'True': + if hatching.last_change: + date = datetime.strptime((hatching.last_change['date'].split(' ')[0]), '%Y-%m-%d').date() + age = (date - hatching.date.date()).days + 1 + if age < 80: + hatching.chicken_age = (date - hatching.date.date()).days + 1 + hatching.save() + else: + continue + if now_age <= 120: + hatching.now_age = now_age + hatching.save() + + return HttpResponse('ok') + + +def fix_duplicate_order_code_cron(): + duplicate_order_codes = ( + PoultryRequest.objects + .values('order_code') + .annotate(count=Count('id')) + .filter(count__gt=1, trash=False) + .values_list('order_code', flat=True) + ) + + # استخراج شناسه‌های مرغ‌های مرتبط با کدهای تکراری + poultry_ids = ( + PoultryRequest.objects + .filter(order_code__in=duplicate_order_codes, trash=False) + .values_list('poultry__id', flat=True) + .distinct() + ) + + # مرتب‌سازی مرغ‌ها بر اساس شناسه + poultries = Poultry.objects.filter(trash=False, id__in=poultry_ids).order_by('id') + list1 = [] + # بررسی درخواست‌های مرتبط با هر مرغ + for poultry in poultries: + requests = PoultryRequest.objects.filter(trash=False, poultry=poultry).order_by('order_code') + base_order_code = str(poultry.user.base_order) # فرض بر این است که "user" به درستی تعریف شده است + last_order = [] + for req in requests: + if str(req.order_code)[:4] == base_order_code: + last_order.clear() + last_order.append(req.order_code) + # if str(req.order_code)[:4] != base_order_code: + # list1.append(req.id) + if last_order: + last_num = last_order[0] + 1 + for req in requests: + if str(req.order_code)[:4] != base_order_code: + base_order_code = last_num + req.order_code = base_order_code + req.save() + last_num += 1 + last_order.clear() + + +def fix_duplicate_order_code_new_cron(): + duplicate_order_codes = ( + PoultryRequest.objects + .values('order_code') + .annotate(count=Count('id')) + .filter(count__gt=1, trash=False) + .values_list('order_code', flat=True) + ) + + # استخراج شناسه‌های مرغ‌های مرتبط با کدهای تکراری + poultry_ids = ( + PoultryRequest.objects + .filter(order_code__in=duplicate_order_codes, trash=False) + .values_list('poultry__user__id', flat=True) + .distinct() + ) + + # مرتب‌سازی مرغ‌ها بر اساس شناسه + poultries = SystemUserProfile.objects.filter(trash=False, id__in=poultry_ids).order_by('id') + list1 = [] + for user in poultries: + print(user.id) + order_code = int(str(user.base_order) + '0001') + requests = PoultryRequest.objects.filter(trash=False, poultry__user=user).order_by('id') + for req in requests: + req.order_code = order_code + req.save() + order_code += 1 + # # بررسی درخواست‌های مرتبط با هر مرغ + # for poultry in poultries: + # requests = PoultryRequest.objects.filter(trash=False,poultry=poultry).order_by('order_code') + # base_order_code = str(poultry.user.base_order) # فرض بر این است که "user" به درستی تعریف شده است + # last_order=[] + # for req in requests: + # if str(req.order_code)[:4] == base_order_code: + # last_order.clear() + # last_order.append(req.order_code) + # # if str(req.order_code)[:4] != base_order_code: + # # list1.append(req.id) + # if last_order: + # last_num=last_order[0] + 1 + # for req in requests: + # if str(req.order_code)[:4] != base_order_code: + # base_order_code = last_num + # req.order_code=base_order_code + # req.save() + # last_num+=1 + # last_order.clear() + + +# def fine_cron(): +# now = datetime.now().date() +# province_kill_requests = ProvinceKillRequest.objects.filter(tarsh=False, return_to_province=False, +# kill_request__recive_date__date=now, +# state__in=('pending', 'accepted'), +# first_car_allocated_quantity=0).select_related( +# 'kill_request', 'province_request', 'province_request__poultry_request', +# 'province_request__poultry_request__hatching') +# for province_kill_request in province_kill_requests: +# poultry_request = province_kill_request.province_request.poultry_request +# hatching = province_kill_request.province_request.poultry_request.hatching +# province_check = province_kill_request.province_request +# province_check.quantity += province_kill_request.main_quantity +# province_check.save() +# poultry_request.remain_quantity += province_kill_request.main_quantity +# poultry_request.save() +# kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) +# kill_request.remain_quantity += province_kill_request.main_quantity +# kill_request.save() +# if poultry_request.export == True: +# hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) +# hatching.export_killed_quantity -= int(request.data['quantity']) +# elif poultry_request.free_sale_in_province == True: +# hatching.free_killed_quantity -= province_kill_request.total_killed_weight +# # hatching.free_killed_quantity -= int(amount * poultry_request.Index_weight) +# hatching.free_quantity -= province_kill_request.total_killed_quantity +# # hatching.free_quantity -= amount +# else: +# hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight +# hatching.governmental_quantity -= province_kill_request.total_killed_quantity +# hatching.save() +# province_kill_request.quantity = 0 +# province_kill_request.total_killed_quantity = 0 +# province_kill_request.total_killed_weight = 0 +# province_kill_request.return_to_province = True +# province_kill_request.returner = {"fullname": user.fullname, "mobile": user.mobile, +# "date": str(datetime.now())} +# province_kill_request.save() + +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status +import requests +from concurrent.futures import ThreadPoolExecutor + + +class KillHouseStressTestView(APIView): + """ + اندپوینتی برای تست فشار (concurrent requests) روی KillHouseMarketInfoViewSet + """ + + def get(self, request): + # آدرس ویوست اصلی (اینجا تغییر بده به آدرس واقعی خودت) + target_url = "http://127.0.0.1:8000/kill-house-market-info/?role=KillHouse" + headers = { + "Authorization": f"Bearer {request.auth}", # یا توکن ثابت بذار + } + + def fetch(i): + try: + resp = requests.get(target_url, headers=headers, timeout=10) + return {"req": i, "status": resp.status_code, "len": len(resp.text)} + except Exception as e: + return {"req": i, "error": str(e)} + + results = [] + with ThreadPoolExecutor(max_workers=10) as executor: # چند تا ریکوست همزمان + futures = [executor.submit(fetch, i) for i in range(20)] # 20 بار + for f in futures: + results.append(f.result()) + + return Response(results, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False) + province_kill_requests.update(warehouse=False) + kill_house_requests = KillHouseRequest.objects.filter(killhouse_user__in=kill_houses, trash=False) + kill_house_requests.update(warehouse=False) + steward_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, trash=False) + steward_allocations.update(warehouse=False) + kill_house_free_bars = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, trash=False) + kill_house_free_bars.update(warehouse=False) + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house__in=kill_houses, trash=False) + kill_house_free_sale_bars.update(warehouse=False) + segmentations = PosSegmentation.objects.filter(kill_house__in=kill_houses, trash=False) + segmentations.update(warehouse=False) + archives = WarehouseArchive.objects.filter(trash=False, kill_house__in=kill_houses) + archives.update(warehouse=False) + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_input_province_bars_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + kill_house_requests_product_warehousing(product) + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_out_buying_bars_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + kill_house_free_buying_product_warehousing(product) + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_in_province_allocations_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + kill_house_allocations_product_warehousing(product) + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_free_sale_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + kill_house_free_sale_product_warehousing(product) + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_cold_house_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + cold_house_allocations = StewardAllocation.objects.filter(kill_house=kill_house, to_cold_house__isnull=False, + receiver_state='accepted', warehouse=True) + kill_house.total_cold_house_governmental_weight = \ + cold_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + kill_house.total_cold_house_free_weight = \ + cold_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + kill_house.save() + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_warehouse_segmentation_for_limitation(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(parent_product__name='مرغ گرم', kill_house=kill_house).first() + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, trash=False, warehouse=True) + product.segmentation_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.save() + kill_house.total_segmentation_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + kill_house.total_segmentation_free_weight = segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + kill_house.save() + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_kill_house_archive_warehousing(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False, warehouse=True) + + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + product.ware_house_archive_weight = archives_weight + product.save() + kill_house.ware_house_archive_governmental_weight = archives_governmental_weight + kill_house.ware_house_archive_free_weight = archives_free_weight + kill_house.save() + return Response("ok") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_steward_free_buying_product_warehousing_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.get(parent_product__name='مرغ گرم', guild=steward) + guild_steward_free_buying_product_warehousing(product) + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_steward_guild_steward_allocations_warehousing_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.get(parent_product__name='مرغ گرم', guild=steward) + guild_steward_allocations_product_warehousing(product) + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_guild_steward_free_sale_warehousing_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.get(parent_product__name='مرغ گرم', guild=steward) + guild_steward_free_sale_product_warehousing(product) + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_guild_steward_product_segmentation_warehousing_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.get(parent_product__name='مرغ گرم', guild=steward) + guild_steward_product_segmentation(product) + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_steward_guild_pos_allocations_warehousing_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.get(parent_product__name='مرغ گرم', guild=steward) + product.pos_allocated_weight = 0 + product.save() + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_guild_steward_archive_warehousing(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + + archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, warehouse=True) + + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + product.ware_house_archive_weight = archives_weight + product.save() + steward.ware_house_archive_governmental_weight = archives_governmental_weight + steward.ware_house_archive_free_weight = archives_free_weight + steward.save() + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_guild_steward_pos_allocation_weight_for_product(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + for steward in stewards: + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + product.pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + product.save() + pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + pos_governmental_allocated_weight = transactions.filter(price_approved=True).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + pos_free_allocated_weight = transactions.filter(price_approved=False).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + product.guild.pos_allocated_weight = int(pos_allocated_weight / 1000) + product.guild.pos_governmental_allocated_weight = int(pos_governmental_allocated_weight / 1000) + product.guild.pos_free_allocated_weight = int(pos_free_allocated_weight / 1000) + product.guild.save() + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_steward_warehouse_for_limitation(request): + stewards = Guilds.objects.filter(trash=False, steward=True, active=True) + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds__in=stewards) | Q(to_guilds__in=stewards) | Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) + guild_steward_allocations.update(steward_warehouse=False) + guild_steward_free_buying_bars = StewardFreeBarInformation.objects.filter( + Q(guild__in=stewards) | Q(steward__in=stewards), trash=False, warehouse=True) + guild_steward_free_buying_bars.update(warehouse=False) + + guild_steward_free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + Q(guild__in=stewards) | Q(steward__in=stewards), trash=False, warehouse=True) + guild_steward_free_sale_bars.update(warehouse=False) + segmentations = PosSegmentation.objects.filter(guild__in=stewards, trash=False) + segmentations.update(warehouse=False) + archives = WarehouseArchive.objects.filter(trash=False, steward__in=stewards) + archives.update(warehouse=False) + transactions = PosMachineTransactions.objects.filter(pos__guild__in=stewards, paid=True, trash=False) + transactions.update(warehouse=False) + product_transactions = ProductsTransactions.objects.filter(transaction__pos__guild__in=stewards, + transaction__paid=True, trash=False) + product_transactions.update(warehouse=False) + return Response("done!") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_time_error(request): + return Response(datetime.now()) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def fix_pos_owner(request): + transactions = PosMachineTransactions.objects.filter(live_stock=False, trash=False) + for transaction in transactions: + if transaction.pos.kill_house: + transaction.kill_house = transaction.pos.kill_house + + elif transaction.pos.guild: + transaction.guild = transaction.pos.guild + transaction.save() + + return Response("done!") diff --git a/authentication/sahandsms/__init__.py b/authentication/sahandsms/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/sahandsms/sms.py b/authentication/sahandsms/sms.py new file mode 100644 index 0000000..4e6d14e --- /dev/null +++ b/authentication/sahandsms/sms.py @@ -0,0 +1,590 @@ +# توابع مورد نیاز برای اتصال به ای پی آی سهند اس ام اس +from panel.helper import check_mobile_number +from ..models import SystemUserProfile +import requests +# USERNAME_SMS='user95' +# PASSWORD_SMS='Mm123456' +USERNAME_SMS='hamedan' +PASSWORD_SMS='hamedan12345' +USERNAME_SMS_FINANCIAL='hamedan' +PASSWORD_SMS_FINANCIAL='hamedan12345' +USERNAME_SMS_HAMEDAN='hamedan' +PASSWORD_SMS_HAMEDAN='hamedan12345' +OUT_SMS_USER='user95' +OUT_SMS_PASS='rasadyar123' +kill_house_price=21000 + +def test(): + user = SystemUserProfile.objects.all() + for i in user: + if i.id > 9: + if i.first_name != None: + first = i.first_name + else: + first = "" + + if i.last_name != None: + last = i.last_name + else: + last = "" + + i.fullname = first + " " + last + i.save() + print("Done") + + +# این تابع برای ارسال پیامک نام کاربری و پسوورد برای مرعدار استفاده میشود +def send_sms(receptor=None, rand=None): + url = 'https://km.ravandno.ir' + receptor = str(receptor) + user = SystemUserProfile.objects.get(id=1825) + mobile = receptor + password = rand + message = '\n' \ + 'اتحادیه مرغ گوشتی استان کرمانشاه' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه سبحان انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{0}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{1}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{2}' \ + '\n' \ + '\n' \ + 'هرگونه فروش مرغ بدون اطلاع اتحادیه و خارج از سامانه ذکر شده پیگرد قانونی دارد و مجوز جوجه ریزی صادر نخواهد شد.'.format( + url, + mobile, + password) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text, user.fullname, user.mobile, user.password) + + +def send_sms_2(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name='Poultry') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'مرغدار محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه فروش مرغ بدون اطلاع اتحادیه و خارج از سامانه ذکر شده پیگرد قانونی دارد و مجوز جوجه ریزی صادر نخواهد شد.' \ + '\n' \ + '\n' \ + 'اتحادیه مرغ گوشتی'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + + +# این تابع برای ارسال پیامک نام کاربری و پسوورد برای کشتارگاه استفاده میشود + +def send_sms_kill_house(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name='KillHouse') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + # time.sleep(2) + message = '\n' \ + 'کشتارگاه دار محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه خرید مرغ بدون اطلاع اتحادیه و خارج از سامانه ذکر شده پیگرد قانونی دارد.' \ + '\n' \ + '\n' \ + 'اتحادیه مرغ گوشتی'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + +# این تابع برای ارسال پیامک نام کاربری و پسوورد برای اپراتور استان استفاده میشود + +def send_sms_province(receptor=None, rand=None): + url = 'https://sha.ravandno.ir' + receptor = str(receptor) + message = '\n' \ + 'اتحادیه مرغ گوشتی استان لرستان' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{0}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{1}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{2}' \ + '\n' \ + '\n' \ + 'هرگونه خرید و فروش مرغ بدون اطلاع اتحادیه شهرستان و استان و خارج از سامانه ذکر شده پیگرد قانونی دارد.'.format( + url, + receptor, + rand) + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# این تابع برای ارسال پیامک نام کاربری و پسوورد برای اپراتور شهرستان استفاده میشود + +def send_sms_city(receptor, rand): + url = 'https://ravandno.ir' + receptor = str(receptor) + message = '\n' \ + 'اتحادیه مرغ گوشتی استان لرستان' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه سبحان انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{0}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{1}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{2}' \ + '\n' \ + '\n' \ + 'هرگونه خرید و فروش مرغ بدون اطلاع اتحادیه شهرستان و استان و خارج از سامانه ذکر شده پیگرد قانونی دارد.'.format( + url, + receptor, + rand) + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# این تابع برای ارسال کد پیامکی (ا تی پی ) به کاربر استفاده میشود + +def send_otp_code(receptor, rand): + receptor = str(receptor) + message = 'سلام همراه عزیز کد پیامکی ارسالی برای شما :{}'.format(rand) + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload, verify=False) + + print(response.text) + + +# این تابع برای ارسال پسورد به کاربر استفاده میشود +def send_password(receptor, rand): + receptor = str(receptor) + message = 'سلام همراه عزیز پسورد ارسالی برای شما :{}'.format(rand) + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from" \ + "=30002501&to={}&message={}".format(receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def sms_reminder(receptor, title, content, link_text, link, time): + receptor = str(receptor) + message = "\n{4}\n{3}\n{2}\n{1}\n{0}".format(title, content, link_text, link, time) + check_mobile = check_mobile_number(receptor) + if check_mobile: + url = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=" \ + "Aht00100&from=30002501&to={}&message={}".format(receptor, message) + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + return response + + +def price_reminder(receptor, fullname): + receptor = str(receptor) + message = 'کاربر گرامی {} 2 ساعت تا شزوع روز بعد باقی است لطفا قیمت های روز بعد را وارد نمایید'.format(fullname) + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# این تابع برای ارسال اطلاعات بار تخصیصی به کشتارگاه برای راننده استفاده میشود + +def driver_sms(driver_mobile, drive_rname, quantity, poultry, barcode, province, city, address, date, time, kill_house): + message = ' راننده گرامی {0}\nحواله بار {1} قطعه مرغ\n با بارکد: {2}\nاز مرغدار:{3}\nبه آدرس:{4}, {5},{6} در تاریخ {7} با بازه زمانی{8} جهت {9} به شما تخصیص داده شده است.\nنسبت به حمل آن اقدام نمایید.'.format( + drive_rname, quantity, barcode, poultry, province, city, address, date, time, kill_house) + check_mobile = check_mobile_number(driver_mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + driver_mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def send(receptor): + receptor = str(receptor) + message = 'کاربر گرامی آقای امیدی از درخواست کشتار 9000 قطعه شما \n 3000 قطعه به کشتارگاه پرطلایی \n 3000 قطعه به کشتارگاه افلاک \n 3000 قطعه به کشتارگاه پرند\n تخصیص داده شده است نسبت به تحویل بار به این واحد ها اقدام نمایید\n اطلاعات تکمیلی را در پنل سامانه سبحان مشاهده نمایید ' + + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def send_2(receptor): + receptor = str(receptor) + message = '' + check_mobile = check_mobile_number(receptor) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + receptor, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def sms_for_tabriz(receptor): + users = SystemUserProfile.objects.filter(role__name='KillHouse') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'کشتارگاه دار محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه خرید مرغ بدون اطلاع اتحادیه و خارج از سامانه ذکر شده پیگرد قانونی دارد.' \ + '\n' \ + '\n' \ + 'اتحادیه مرغ گوشتی استان آذربایجان شرقی'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + +def send_sms_for_jahad(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name='Jahad') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'ناظر محترم جهاد استان:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتار مرغ گوشتی از طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'جهت راه اندازی سامانه نیاز به همکاری شما دوستان در برطرف کردن مشکلات احتمالی می باشیم.' \ + '\n' \ + '\n' \ + 'باتشکر مدیریت سامانه رصدیار'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + + +def send_sms_for_province(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name='ProvinceOperator') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'اپراتور محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتار مرغ گوشتی از طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه خرید و فروش مرغ خارج از سامانه ذکر شده پیگرد قانونی دارد.'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + + +def send_sms_for_city(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name='CityOperator') + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'اپراتور محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتار مرغ گوشتی از طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه خرید و فروش مرغ خارج از سامانه ذکر شده پیگرد قانونی دارد.'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") + +def send_sms_for_vet(receptor=None, rand=None): + users = SystemUserProfile.objects.filter(role__name__in=('VetFarm','KillHouseVet')) + receptor = str(receptor) + for user in users: + url = 'https://sha.ravandno.ir' + message = '\n' \ + 'دامپزشک محترم:' \ + '\n' \ + '{0}' \ + '\n' \ + '\n' \ + 'از این پس کلیه امور کشتاراز طریق سامانه رصدیار انجام میگردد.' \ + '\n' \ + '\n' \ + 'لینک ورود به سامانه:' \ + '\n' \ + '\t\t\t{1}' \ + '\n' \ + '\n' \ + 'شماره همراه:\t{2}' \ + '\n' \ + '\n' \ + 'رمز عبور:\t{3}' \ + '\n' \ + '\n' \ + 'هرگونه خرید و فروش مرغ بدون اطلاع اتحادیه و خارج از سامانه ذکر شده پیگرد قانونی دارد.' \ + '\n' \ + '\n' \ + 'اتحادیه مرغ گوشتی'.format( + user.fullname, + url, + user.mobile, + user.password) + check_mobile = check_mobile_number(user.mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=pmstores&password=Aht00100&from=30002501&to={}&message={}".format( + user.mobile, message) + url = u.format() + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + response = requests.request("GET", url, headers=headers, data=payload) + print(user.mobile + " " + user.fullname + " " + "Done") diff --git a/authentication/serializer/__init__.py b/authentication/serializer/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/authentication/serializer/serializer.py b/authentication/serializer/serializer.py new file mode 100644 index 0000000..7bb7fd6 --- /dev/null +++ b/authentication/serializer/serializer.py @@ -0,0 +1,308 @@ +from django.contrib.auth.models import User, Group +from django.db.models import Q + +from authentication.models import ( + UserProfile, + Address, + BankCard, + SystemUserProfile, + PermissionLevel, ExternalTransaction +) +from rest_framework import serializers +from authentication.permission_views import GroupSerializer +from authentication.serializers import SystemAddressSerializer, UserSerializer, ProvinceSerializer, CitySerializer +from panel.models import KillHouse, WagePayment, ProvinceKillRequest + + +# سریالایزر مربوط به مدل آدرس +class AddressSerializer(serializers.ModelSerializer): + class Meta: + model = Address + fields = [ + 'key', + 'title', + 'country', + 'province', + 'city', + 'address', + 'postal_code', + 'breeding_unique_id', + 'phone', + 'phone_type', + 'no', + 'floor', + 'unit', + ] + + def create(self, validated_data): + return Address.objects.create(**validated_data) + + +# سریالایزر مربوط به مدل اطلاعات بانکی +class BankCardSerializer(serializers.ModelSerializer): + class Meta: + model = BankCard + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'created_by', + 'modified_by', + ) + extra_kwargs = { + 'name_of_bank_user': {'required': False, 'allow_null': True}, + 'bank_name': {'required': False, 'allow_null': True}, + 'card': {'required': False, 'allow_null': True}, + 'shaba': {'required': False, 'allow_null': True}, + 'account': {'required': False, 'allow_null': True}, + } + + +# سریالایزر مربوط به مدل کاربر +class UserProfileSerializer(serializers.ModelSerializer): + user_bank_info = BankCardSerializer(read_only=True) + address = AddressSerializer(read_only=True) + role = GroupSerializer(read_only=True) + job = serializers.SerializerMethodField('get_job') + + def get_job(self, instance): + # if instance.role.name == 'Poultry': + # pass + # if instance.role.name == 'CityOperator': + # pass + # if instance.role.name == 'ProvinceOperator': + # pass + if instance.role.name == 'KillHouse': + kill_house = KillHouse.objects.get(user=instance).name + return kill_house + else: + return None + + class Meta: + model = UserProfile + fields = [ + 'key', + 'create_date', + # 'token', + 'fullname', + 'first_name', + 'last_name', + 'natinal_id', + 'mobile', + 'birthday', + 'image', + 'state', + 'role', + 'address', + 'unit_name', + 'gis_code', + 'operating_licence_capacity', + 'number_of_halls', + 'tenant', + 'person_type', + 'economic_code', + 'system_code', + 'epidemiological_code', + 'breeding_unique_id', + 'total_capacity', + 'licence_number', + 'health_certificate_number', + 'number_of_requests', + 'hatching_date', + 'last_party_date', + 'number_of_incubators', + 'herd_age_by_day', + 'herd_age_by_week', + 'number_of_party', + 'communication_type', + 'cooperative', + 'date_of_register', + 'unit_status', + 'samasat_user_code', + 'user_bank_info', + 'job', + 'incubation_date', + ] + + +class SystemUserProfileForAutoAllocationSerializer(serializers.ModelSerializer): + class Meta: + model = SystemUserProfile + fields = ['fullname', 'first_name', 'last_name', 'base_order', 'mobile', 'national_id', 'national_code', 'key', + 'city', 'unit_name', 'unit_national_id', 'unit_registration_number', 'unit_economical_number', + 'unit_province', 'unit_city', 'unit_postal_code', 'unit_address'] + depth = 1 + + +class SystemUserProfileForGuildSerializer(serializers.ModelSerializer): + city = serializers.CharField(source='city.name', read_only=True) + + class Meta: + model = SystemUserProfile + fields = ['fullname', 'first_name', 'last_name', 'mobile', 'national_id', 'city','father_name','gender','is_alive','birthday','national_code'] + depth = 1 + + +class SystemUserProfileForInspectionSerializer(serializers.ModelSerializer): + province_name = serializers.CharField(source='province.name', read_only=True) + city_name = serializers.CharField(source='city.name', read_only=True) + + class Meta: + model = SystemUserProfile + fields = ['fullname', 'first_name', 'last_name', 'mobile', 'national_id', 'province_name', 'city_name','is_alive','national_code','gender','father_name','birthday', + 'password'] + + +class SystemUserProfileForAllUsersSerializer(serializers.ModelSerializer): + role = serializers.SerializerMethodField('get_role') + + class Meta: + model = SystemUserProfile + fields = ['fullname', 'national_id', 'mobile', 'birthday', 'password', 'role'] + + def get_role(self, instance): + role_list = [] + for item in instance.role.all(): + role_list.append(item.name) + return role_list + + +class SystemUserProfileSerializer(serializers.ModelSerializer): + # user=UserSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True, required=False) + role = serializers.SerializerMethodField('get_role') + city = serializers.SerializerMethodField('get_city') + province = serializers.SerializerMethodField('get_province') + + class Meta: + model = SystemUserProfile + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'token', + 'created_by', + 'modified_by', + 'user', + # 'password', + 'access_level', + ) + # extra_kwargs = {"access_level": {"required": False, "allow_null": True}} + + def get_city(self, instance): + if instance.city == None: + pass + else: + return instance.city.name + + def get_province(self, instance): + if instance.province == None: + pass + else: + return instance.province.name + + def get_role(self, instance): + role_list = [] + for item in instance.role.all(): + role_list.append(item.name) + return role_list + + +class SystemUserProfileForFactorSerializer(serializers.ModelSerializer): + class Meta: + model = SystemUserProfile + fields = ['key', 'fullname', 'first_name', 'last_name', 'mobile', 'unit_name', 'unit_national_id', + 'unit_registration_number', 'unit_economical_number', 'unit_province', 'unit_city', + 'unit_postal_code', 'unit_address'] + + +class SystemUserProfileBaseInfoSerializer(serializers.ModelSerializer): + role = GroupSerializer(many=True) + city = CitySerializer(read_only=True, required=False) + province = ProvinceSerializer(read_only=True, required=False) + + class Meta: + model = SystemUserProfile + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'token', + 'created_by', + 'modified_by', + 'user', + 'state', + # 'password', + 'access_level', + ) + + +class ExternalTransactionSerializer(serializers.ModelSerializer): + receiver = SystemUserProfileForAutoAllocationSerializer(read_only=True) + creator = SystemUserProfileForAutoAllocationSerializer(read_only=True) + information = serializers.SerializerMethodField('get_information') + + class Meta: + model = ExternalTransaction + fields = '__all__' + + def get_information(self, obj): + total_weight = 0 + total_quantity = 0 + total_request = 0 + wage_payment = WagePayment.objects.filter(Q(orderId=obj.orderId) | Q(tracking_code=obj.saleReferenceId), + trash=False).first() + if wage_payment.province_kill_request != None: + total_request = len(wage_payment.province_kill_request) + for province_kill_req in wage_payment.province_kill_request: + province_kill = ProvinceKillRequest.objects.get(key=province_kill_req, trash=False) + total_weight += province_kill.total_killed_weight + total_quantity += province_kill.total_killed_quantity + return { + "total_weight": total_weight, + "total_quantity": total_quantity, + "total_request_number": total_request, + } + + +class SystemUserProfileForPoultryLocSerializer(serializers.ModelSerializer): + class Meta: + model = SystemUserProfile + fields = ['fullname', 'mobile'] + + +class SystemUserProfileBaseInfoForTicketSerializer(serializers.ModelSerializer): + role = GroupSerializer(many=True) + city = CitySerializer(read_only=True, required=False) + province = ProvinceSerializer(read_only=True, required=False) + + class Meta: + model = SystemUserProfile + fields = ['birthday', 'first_name', 'fullname', 'key', 'last_name', 'mobile', 'national_code', 'role', 'city', + 'province'] + + +class SystemUserProfileForPoultryScienceSerializer(serializers.ModelSerializer): + role = serializers.SerializerMethodField('get_role') + + class Meta: + model = SystemUserProfile + fields = ['fullname', 'mobile','role'] + + def get_role(self, instance): + role_list = [] + for item in instance.role.all(): + role_list.append(item.name) + return role_list + + +class SystemUserProfileForPoultryScienceWithoutRoleSerializer(serializers.ModelSerializer): + city = CitySerializer(read_only=True, required=False) + + class Meta: + model = SystemUserProfile + fields = ['fullname', 'mobile','city'] + diff --git a/authentication/serializers.py b/authentication/serializers.py new file mode 100644 index 0000000..f5d6545 --- /dev/null +++ b/authentication/serializers.py @@ -0,0 +1,106 @@ +from django.contrib.auth.models import User, Group +from rest_framework import serializers + +from authentication.models import ( + UserProfile, + Address, + City, + Province, + SystemAddress, + CityUnit +) + + +# سریالایزر مربوط به مدل استان +from panel.models import ManagementSendSms + + +class ProvinceSerializer(serializers.ModelSerializer): + class Meta: + model = Province + fields = ['key', 'name'] + + +# سریالایزر مربوط به مدل شهرستان +class CitySerializer(serializers.ModelSerializer): + class Meta: + model = City + fields = ['key', 'name'] + + +class CityForProductPricingSerializer(serializers.ModelSerializer): + class Meta: + model = City + fields = ['key', 'name', 'product_price'] + + +# سریالایزر مربوط به مدل زیر بخش شهرستان +class CityUnitSerializer(serializers.ModelSerializer): + city = CitySerializer(read_only=True) + + class Meta: + model = CityUnit + fields = ['key', 'name'] + + +# سریالایزر مربوط به مدل آدرس +class SystemAddressSerializer(serializers.ModelSerializer): + province = ProvinceSerializer(required=False) + city = CitySerializer(required=False) + + class Meta: + model = SystemAddress + fields = ['province', 'city', 'address', 'postal_code'] + + +# سریالایزر مربوط به مدل آدرس +class AddressSerializer(serializers.ModelSerializer): + class Meta: + model = Address + fields = '__all__' + + +# سریالایزر مربوط به مدل کاربر +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = '__all__' + + +# سریالایزر مربوط به مدل نقش +class GroupSerializer(serializers.ModelSerializer): + class Meta: + model = Group + fields = ("name",) + + +# سریالایزر مربوط به مدل پروفایل کاربری +class UserProfileSerializer(serializers.ModelSerializer): + address = AddressSerializer(read_only=True) + + class Meta: + model = UserProfile + fields = '__all__' + + + + +# سریالایزر مربوط به مدل شهرستان +class CityForLocSerializer(serializers.ModelSerializer): + class Meta: + model = City + fields = ['name'] + + +class SystemAddressForLocSerializer(serializers.ModelSerializer): + city = CityForLocSerializer(required=False) + + class Meta: + model = SystemAddress + fields = ['city','address'] + + +class ManagementSendSmsSerializer(serializers.ModelSerializer): + class Meta: + model = ManagementSendSms + fields = '__all__' diff --git a/authentication/sms_management.py b/authentication/sms_management.py new file mode 100644 index 0000000..f2cf70d --- /dev/null +++ b/authentication/sms_management.py @@ -0,0 +1,3070 @@ +from datetime import datetime +import threading + +import jdatetime +from django.db.models import Q, Sum, F +from rest_framework import status, viewsets +from rest_framework.decorators import permission_classes, api_view +from rest_framework.permissions import AllowAny + +from authentication.models import SystemUserProfile, UserMessageSend +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from django.http import HttpResponse +import xml.etree.ElementTree as ET + +import requests + +from rest_framework.response import Response + +from deposit_percent import wage_percent +from general_urls import base_url_sms, base_url_for_sms_report, base_pos_id +from panel.KillHouse.helpers import get_finance_info +from panel.helper import UNION_NUMBER, COMPANY_NUMBER, GUILD_NUMBER, UNION_SECOND_NUMBER, SUPPORTER_NUMBER, \ + UNION_THIRD_NUMBER, UNION_FOURTH_NUMBER, UNION_NUMBER_2, COMPANY_NUMBER2, UNION_FIFTH_NUMBER, UNION_SIXTH_NUMBER +from panel.helper_excel import shamsi_date, to_locale_str +from panel.models import KillHouseRequest, VetCheckRequest, KillHouseVet, VetCheckAllocations, KillHouse, \ + KillHouseFreeBarInformation, InternalTransaction, ProvinceKillRequest, Poultry, VetFarm, KillHousePurchaseRequest, \ + OutProvincePoultryRequestBuyer, CityOperator, UserReports, ReportsUsers, LastUpdate, PoultryRequest, \ + CompanyBeneficiaryAccount, ManagementSendSms, StewardAllocation, SmsRecipient +from .sahandsms.sms import USERNAME_SMS, PASSWORD_SMS, USERNAME_SMS_FINANCIAL, PASSWORD_SMS_FINANCIAL, \ + USERNAME_SMS_HAMEDAN, PASSWORD_SMS_HAMEDAN, OUT_SMS_USER, OUT_SMS_PASS +from panel.helper import check_mobile_number +from .serializers import ManagementSendSmsSerializer + +management_sms = ManagementSendSms.objects.all() +gate_way = management_sms.filter(name='ارسال بدهی').first() +send_deactivate = management_sms.filter(name='ارسال مسدودی ها').first() +direct_buying = management_sms.filter(name='خرید مستقیم').first() +poultry_request = management_sms.filter(name='درخواست کشتار جدید').first() +poultry_link_out_sale = management_sms.filter(name='ارسال پیامک لینک فروش مرغ به خارج استان').first() +kill_req_market = management_sms.filter(name='پیامک پنل بورسی').first() +poultry_req_market = management_sms.filter(name='پیامک به مرغدار درخواست کشتار مرغدار برای پنل بورسی').first() +steward_allocation = management_sms.filter(name='پیامک کد احراز به مباشر').first() +guild_register = management_sms.filter(name='پیامک کد احراز برای ثبت صنف/مباشر').first() +sms_recipient = management_sms.filter(name='پیامک مرغ زنده و لاشه به شماره های خاص').first() +gate_way_username = gate_way.username +gate_way_password = gate_way.password +send_deactivate_username = send_deactivate.username +send_deactivate_password = send_deactivate.password +direct_buying_username = direct_buying.username +direct_buying_password = direct_buying.password +poultry_request_username = poultry_request.username +poultry_request_password = poultry_request.password +poultry_link_out_sale_username = poultry_link_out_sale.username +poultry_link_out_sale_password = poultry_link_out_sale.password +kill_req_market_username = kill_req_market.username +kill_req_market_password = kill_req_market.password +poultry_req_market_username = poultry_req_market.username +poultry_req_market_password = poultry_req_market.password +steward_allocation_username = steward_allocation.username +steward_allocation_password = steward_allocation.password +guild_register_username = guild_register.username +guild_register_password = guild_register.password +sms_recipient_username = sms_recipient.username +sms_recipient_password = sms_recipient.password + + +def sanitize_sms_message(message): + if not message: + return message + forbidden_words = {'شاه': 'ش..ه', 'SHAH': 'SH..AH', 'Shah': 'Sh..ah', 'shah': 'sh..ah'} + cleaned_message = message + for forbidden, replacement in forbidden_words.items(): + cleaned_message = cleaned_message.replace(forbidden, replacement) + return cleaned_message + + +def send_sms_request(url): + if 'message=' in url: + parts = url.split('message=') + if len(parts) == 2: + before_message = parts[0] + 'message=' + message_and_after = parts[1] + if '&' in message_and_after: + message = message_and_after.split('&')[0] + after_message = '&' + '&'.join(message_and_after.split('&')[1:]) + else: + message = message_and_after + after_message = '' + cleaned_message = sanitize_sms_message(message) + url = before_message + cleaned_message + after_message + return requests.get(url) + + +def transaction_sms_threading(*mobile): + percentage = CompanyBeneficiaryAccount.objects.filter(trash=False) + mother_percent = percentage.filter(unique_code=1).first().percent + for m in mobile: + for k, v in m.items(): + if k == 'payer': + payer = v + if k == 'date': + date = v + if k == 'share': + share = v + mother_share = ((int(v) * mother_percent) / 100) if mother_percent > 0 else 0 + + share = "{:,}".format(int(share)) + mother_share = "{:,}".format(int(mother_share)) + + if k == 'mobile': + phone = v + if k == 'province': + province = v + if k == 'killer': + killer = v + check_mobile = check_mobile_number(phone) + if check_mobile: + if phone == COMPANY_NUMBER: + # message = f'تراکنش موفق استان {province} (سهم شرکت)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if COMPANY_NUMBER2 is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER2}&message={message}") + message1 = f'تراکنش موفق استان {province} (سهم شرکت مادر)' \ + f'\n' \ + f'پرداخت کننده: {killer} {payer} ' \ + f'\n' \ + f'تاریخ : {date}' \ + f'\n' \ + f' مبلغ سهم شما : {mother_share} ریال ' + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_USER}&from=30002501&to=09121355674&message={message1}") + # message_kiani = f'تراکنش موفق استان {province} (سهم محمد کیانی)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {kiani_share} ریال ' + # req_kiani = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to=09364415690&message={message_kiani}") + # message_momeni = f'تراکنش موفق استان {province} (سهم مومنی)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {momeni_share} ریال ' + # req_momeni = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to=09201917727&message={message_momeni}") + + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message1}") + # elif phone == UNION_NUMBER: + # message = f'تراکنش موفق استان {province} (سهم اتحادیه)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if UNION_THIRD_NUMBER is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message}") + # elif phone == GUILD_NUMBER: + # message = f'تراکنش موفق {province} (سهم صنف)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if UNION_THIRD_NUMBER is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message}") + # else: + # message = f'تراکنش موفق' \ + # f'\n' \ + # f'پرداخت کننده: {payer}' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # req = send_sms_request( + # url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendFromUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&message={message}&fromNumber=30002501&toNumber={phone}") + + +def transaction_sms_threading_in_province(*mobile): + percentage = CompanyBeneficiaryAccount.objects.filter(trash=False) + kiani_percent = percentage.filter(unique_code=2).first().percent + momen_percent = percentage.filter(unique_code=3).first().percent + for m in mobile: + for k, v in m.items(): + if k == 'payer': + payer = v + if k == 'date': + date = v + if k == 'share': + share = v + # mother_share=int(v) * 0.06 + kiani_share = ((int(v) * kiani_percent) / 100) if kiani_percent > 0 else 0 + # momeni_share=((int(v) * momen_percent) / 100) if kiani_percent > 0 else 0 + share = "{:,}".format(int(share)) + # mother_share = "{:,}".format(int(mother_share)) + kiani_share = "{:,}".format(int(kiani_share)) + # momeni_share = "{:,}".format(int(momeni_share)) + if k == 'mobile': + phone = v + if k == 'province': + province = v + if k == 'killer': + killer = v + check_mobile = check_mobile_number(phone) + if check_mobile: + if phone == COMPANY_NUMBER: + # message = f'تراکنش موفق استان {province} (سهم شرکت)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if COMPANY_NUMBER2 is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER2}&message={message}") + # message1 = f'تراکنش موفق استان {province} (سهم شرکت مادر)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {mother_share} ریال ' + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to=09121355674&message={message1}") + message_kiani = f'تراکنش موفق استان {province} (سهم محمد کیانی)' \ + f'\n' \ + f'پرداخت کننده: {killer} {payer} ' \ + f'\n' \ + f'تاریخ : {date}' \ + f'\n' \ + f' مبلغ سهم شما : {kiani_share} ریال ' + req_kiani = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to=09364415690&message={message_kiani}") + # message_momeni = f'تراکنش موفق استان {province} (سهم مومنی)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {momeni_share} ریال ' + req_momeni = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={OUT_SMS_USER}&password={OUT_SMS_PASS}&from=30002501&to=09201917727&message={message_kiani}") + + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message1}") + # elif phone == UNION_NUMBER: + # message = f'تراکنش موفق استان {province} (سهم اتحادیه)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if UNION_THIRD_NUMBER is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message}") + # elif phone == GUILD_NUMBER: + # message = f'تراکنش موفق {province} (سهم صنف)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # if UNION_THIRD_NUMBER is not None: + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + # req = send_sms_request( + # f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message}") + # else: + # message = f'تراکنش موفق' \ + # f'\n' \ + # f'پرداخت کننده: {payer}' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ سهم شما : {share} ریال ' + # req = send_sms_request( + # url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendFromUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&message={message}&fromNumber=30002501&toNumber={phone}") + + +def transaction_sms_threading_for_company(*mobile): + pass + # for m in mobile: + # for k, v in m.items(): + # if k == 'payer': + # payer = v + # if k == 'date': + # date = v + # if k == 'share': + # share = v + # share = "{:,}".format(int(share)) + # if k == 'mobile': + # phone = v + # if k == 'province': + # province=v + # if k == 'killer': + # killer=v + # message = f'تراکنش موفق استان {province} (کل سهم)' \ + # f'\n' \ + # f'پرداخت کننده: {killer} {payer} ' \ + # f'\n' \ + # f'تاریخ : {date}' \ + # f'\n' \ + # f' مبلغ کل سهم : {share} ریال ' + # req = send_sms_request( + # url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendFromUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&message={message}&fromNumber=30002501&toNumber={phone}") + + +def transaction_sms_threading_appreciation(user, mobile): + message = f'کاربر گرامی {user}' \ + '\n' \ + 'از پرداخت شما سپاسگزاریم.' \ + '\n' \ + '(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendFromUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&message={message}&fromNumber=30002501&toNumber={mobile}") + + +def user_sms_threading(mobile, message): + for i in mobile: + check_mobile = check_mobile_number(i) + if check_mobile: + req = send_sms_request( + url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendFromUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&message={message}&fromNumber=30002501&toNumber={i}") + + msg = UserMessageSend( + + message=str(message), + ) + msg.save() + + +@api_view(["POST"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def user_sms(request): + operator = SystemUserProfile.objects.get(user=request.user) + roles = None + users = None + message = request.data['message'] + if 'role' in request.data.keys(): + roles = request.data['role'] + if 'user' in request.data.keys(): + users = request.data['user'] + + if roles != None and users != None: + users = SystemUserProfile.objects.filter(role__name__in=roles, key__in=users, + province=operator.province).only('mobile').order_by('id').values_list( + 'mobile', flat=True) + elif roles != None: + users = SystemUserProfile.objects.filter(role__name__in=roles, province=operator.province).only( + 'mobile').order_by('id').values_list('mobile', flat=True) + else: + users = SystemUserProfile.objects.filter(key__in=users, province=operator.province).only('mobile').order_by( + 'id').values_list('mobile', flat=True) + + send_sms = threading.Thread(target=user_sms_threading, args=(users, message)) + send_sms.start() + + return Response({'msg': 'send'}) + + +def hatching_sms(mobile, poultry_fullname, quantity, date, chicken_breed, province, city + ): + message = ' ثبت جوجه ریزی جدید:\n مرغدار:{0}\nتعداد:{1}\nتاریخ:{2}\nنژاد:{3}\nآدرس:استان {4},شهر {5}'.format( + poultry_fullname, quantity, date, chicken_breed, province, city) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def operator_hatching_sms(mobile, poultry_fullname, quantity, date, chicken_breed, province, city, + + ): + message = ' ثبت جوجه ریزی جدید:\n مرغدار:{0}\nتعداد:{1}\nتاریخ:{2}\nنژاد:{3}\nآدرس:استان {4},شهر {5}'.format( + poultry_fullname, quantity, date, chicken_breed, province, city) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# USERNAME_SMS +def operator_poultry_request_sms(mobile, poultry_fullname, quantity, chicken_breed, + order_code, send_date, sale_in_province, amount, request_kill_house, poultry_mobile + + ): + sale_type = 'آزاد' if sale_in_province == True else 'دولتی' + amount = "{:,}".format(int(amount)) + quantity = "{:,}".format(int(quantity)) + message = 'درخواست کشتار جدید' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'مرغدار:{poultry_fullname}' \ + f'\n' \ + f'کدسفارش:{order_code}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'(سامانه رصدیار)' \ + # message = 'درخواست کشتار\n مرغدار:{0}\nتعداد:{1}\nنژاد:{2}\n کدسفارش:{3}\nتاریخ کشتار:{4}'.format( + # poultry_fullname, quantity, chicken_breed, + # order_code, send_date) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + poultry_request_username, poultry_request_password, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + if UNION_NUMBER_2 is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_request_username}&password={poultry_request_password}&from=30002501&to={UNION_NUMBER_2}&message={message}") + + message2 = 'درخواست کشتار جدید' \ + f'\n' \ + f'مرغدار:{poultry_fullname}' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'کشتارگاه:{request_kill_house}' \ + f'\n' \ + f'کدسفارش:{order_code}' \ + f'\n' \ + f'قیمت :{amount} ریال' \ + f'\n' \ + f'(سامانه رصدیار)' + + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_request_username}&password={poultry_request_password}&from=30002501&to={poultry_mobile}&message={message2}") + + +# USERNAME_SMS +def operator_out_poultry_request_sms(mobile, poultry_fullname, quantity, chicken_breed, + order_code, send_date, sale_in_province, amount, vet_mobile=None + + ): + sale_type = 'آزاد' if sale_in_province == True else 'دولتی' + amount = "{:,}".format(int(amount)) + quantity = "{:,}".format(int(quantity)) + message = 'درخواست کشتار آزاد' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'مرغدار:{poultry_fullname}' \ + f'\n' \ + f'کدسفارش:{order_code}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'(سامانه رصدیار)' \ + # message = 'درخواست کشتار آزاد\n مرغدار:{0}\nتعداد:{1}\nنژاد:{2}\n کدسفارش:{3}\nتاریخ کشتار:{4}'.format( + # poultry_fullname, quantity, chicken_breed, + # order_code, send_date) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + if UNION_NUMBER_2 is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_NUMBER_2}&message={message}") + if vet_mobile is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={vet_mobile}&message={message}") + + +def poultry_request_receive_city_accept_sms(mobile, send_date, order_code, free_sale_in_province + + ): + sale_type = 'آزاد' if free_sale_in_province == True else 'دولتی' + message = ' مرغدار گرامی درخواست کشتار شما با نوع:{2} به تاریخ {0} با شماره سفارش:{1} توسط شهرستان تایید شد.'.format( + send_date, order_code, sale_type) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def poultry_request_receive_province_accept_sms(mobile, order_code + ): + message = 'درخواست کشتار با کد سفارش:{0} توسط استان تایید شد.'.format( + order_code) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# USERNAME_SMS +def confirm_price_poultry_request_sms(mobile, poultry_fullname, quantity, chicken_breed, order_code, send_date, + free_sale_in_province, amount, request_kill_house, confirm_code): + sale_type = 'آزاد' if free_sale_in_province == True else 'دولتی' + + message = 'درخواست کشتار جدید' \ + f'\n' \ + f'مرغدار:{poultry_fullname}' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'کشتارگاه:{request_kill_house}' \ + f'\n' \ + f'کدسفارش:{order_code}' \ + f'\n' \ + f'قیمت :{amount} ریال' \ + f'\n' \ + f'کداحراز :{confirm_code}' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + poultry_request_username, poultry_request_password, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# USERNAME_SMS +def confirm_price_poultry_request_direct_buying_sms(mobile, poultry_fullname, quantity, chicken_breed, send_date, + free_sale_in_province, amount, request_kill_house, confirm_code): + sale_type = 'آزاد' if free_sale_in_province == True else 'دولتی' + + message = 'درخواست خرید مستقیم:' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'خریدار:{request_kill_house}' \ + f'\n' \ + f'قیمت :{int(amount)} ریال' \ + f'\n' \ + f'کداحراز :{confirm_code}' \ + f'\n' \ + f'(سامانه رصدیار)' + # message = 'درخواست خرید مستقیم:' \ + # f'\n' \ + # f'مرغدار:{poultry_fullname}' \ + # f'\n' \ + # f'تعداد:{quantity}' \ + # f'\n' \ + # f'نژاد:{chicken_breed}' \ + # f'\n' \ + # f'تاریخ کشتار:{send_date}' \ + # f'\n' \ + # f'نوع فروش:{sale_type}' \ + # f'\n' \ + # f'خریدار:{request_kill_house}' \ + # f'\n' \ + # f'قیمت :{int(amount)} ریال' \ + # f'\n' \ + # f'کداحراز :{confirm_code}' \ + # f'\n' \ + # f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + direct_buying_username, direct_buying_password, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + +# USERNAME_SMS +def kill_request_province_sms(mobile, kill_house_name, quantity, chicken_breed, send_date, province, city, + + ): + message = ' اعلام نیاز جدید کشتارگاه:\n {0}\n تعداد درخواست:{1}\nنژاد:{2}\nتاریخ کشتار:{3}\nآدرس:استان {4}, شهر {5}\n'.format( + kill_house_name, quantity, chicken_breed, send_date, province, city) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + if UNION_NUMBER_2 is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_NUMBER_2}&message={message}") + + +def kill_request_delete_province_sms(mobile, kill_house_name, quantity, chicken_breed, send_date, province, city, + + ): + message = 'لغو درخواست کشتار:\n {0}\n تعداد درخواست:{1}\nنژاد:{2}\nتاریخ کشتار:{3}\nآدرس:استان {4}, شهر {5}'.format( + kill_house_name, quantity, chicken_breed, send_date, province, city) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def province_kill_request_to_kill_house_sms(mobile, quantity, chicken_breed, send_date, poultry_name, + poultry_mobile, province, city, sale_in_province, amount, kill_house_name + + ): + sale_type = 'آزاد' if sale_in_province == True else 'دولتی' + amount = "{:,}".format(int(amount)) + quantity = "{:,}".format(int(quantity)) + message = 'تخصیص کشتار جدید' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'خریدار:{kill_house_name}' \ + f'\n' \ + f'مرغدار:{poultry_name}' \ + f'\n' \ + f'تلفن مرغدار:{poultry_mobile}' \ + f'\n' \ + f'آدرس:{province} - {city}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'(سامانه رصدیار)' \ + # message = 'تخصیص کشتار جدید:\n تعداد:{0}\n نژاد: {1}\nتاریخ کشتار:{2}\nمرغدار:{3}\n تلفن مرغدار:{4}\nآدرس:استان {5}, شهر {6}\n '.format( + # quantity, chicken_breed, send_date, poultry_name, poultry_mobile, province, city, + # ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + if UNION_NUMBER_2 is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={UNION_NUMBER_2}&message={message}") + + +def kill_house_province_kill_request_accept_to_province_sms(mobile, provice_operator_name, quantity, + chicken_breed, send_date, poultry_name, + poultry_mobile, province, city, kill_house_name, + + ): + message = ' اپراتور گرامی: {0}\n تعداد {1} مرغ با نژاد: {2}\nدر تاریخ کشتار:{3}\n از مرغدار:{4} با شماره تماس:{5}\nبه آدرس:استان {6}, شهر {7}\n توسط:{8} تایید شد.'.format( + provice_operator_name, quantity, chicken_breed, send_date, poultry_name, poultry_mobile, province, city, + kill_house_name + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_request_to_poultry_sms(mobile, quantity, kill_house_name, send_date, driver_name, + driver_mobile, + type_car, pelak + + ): + message = 'اطلاعات تحویل بار:\n تعداد:{0}\nخریدار:{1}\nتاریخ تحویل:{2}\n راننده:{3}\n تلفن راننده:{4}\n ماشین:{5}\n با پلاک {6}'.format( + quantity, kill_house_name, send_date, driver_name, driver_mobile, type_car, pelak + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_request_to_vet_farm_clearnce_sms(mobile, quantity, index_weight, total_weight, poultry_name, + poultry_mobile, kill_house_user_name, kill_house_user_mobile, send_date, + driver_name, + driver_mobile, + type_car, pelak + + ): + message = 'اطلاعات بار(کد قرنطینه):\n تعداد:{0}\nمیانگین وزن:{1}\nوزن کل:{2}\nفروشنده:{3}-{4}\nخریدار:{5}-{6}\nتاریخ تحویل:{7}\nراننده:{8}-{9}\nماشین:{10}-{11}'.format( + quantity, index_weight, total_weight, poultry_name, poultry_mobile, kill_house_user_name, + kill_house_user_mobile, send_date, driver_name, + driver_mobile, + type_car, pelak + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_request_to_driver_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + poultry_mobile, + poultry_province, poultry_city, poultry_address, + kill_house_name, + kill_house_mobile, + kill_house_province, + kill_house_city, kill_house_address + + ): + message = 'اطلاعات تحویل بار:\nتاریخ:{0}\nازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\n مبدا:\nمرغدار:{4}\nشماره تماس:{5}\nآدرس:{6},{7},{8}\n مقصد:\nکشتارگاه:{9}\nشماره تماس:{10}\nآدرس:{11},{12},{13}\n'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, poultry_mobile, + poultry_province, poultry_city, poultry_address, + kill_house_name, + kill_house_mobile, + kill_house_province, + kill_house_city, kill_house_address + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_request_to_vet_farm_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + poultry_mobile, + poultry_province, poultry_city, poultry_address, + kill_house_name, + kill_house_mobile, + kill_house_province, + kill_house_city, kill_house_address, + driver_name, + driver_mobile, + driver_car, + pelak, + + ): + message = 'اعلام کد ترخیص:\nتاریخ:{0}\nبازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\n مبدا:\nمرغدار:{4}\nشماره تماس:{5}\nآدرس:{6},{7},{8}\n مقصد:\nکشتارگاه:{9}\nشماره تماس:{10}\nآدرس:{11},{12},{13}\راننده:{14}\n تلفن راننده:{15}\n ماشین:{16}\n با پلاک {17}'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, poultry_mobile, + poultry_province, poultry_city, poultry_address, + kill_house_name, + kill_house_mobile, + kill_house_province, + kill_house_city, kill_house_address, + driver_name, + driver_mobile, + driver_car, + pelak, + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_request_to_kill_house_vet_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + + ): + message = 'اعلام تحویل بار:\nتاریخ:{0}\nبازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\nاز مرغدار:{4}\nراننده:{5}\nماشین:{6}\nبا پلاک {7}\nتحویل شما داده میشود.'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_vet_to_poultry_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + + ): + message = 'اعلام تاییدتحویل بار:\nتاریخ:{0}\nبازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\nاز مرغدار:{4}\nراننده:{5}\nماشین:{6}\nبا پلاک {7}\nتحویل کشتارگاه شد.'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_vet_to_province_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + + ): + message = 'اعلام تاییدتحویل بار:\nتاریخ:{0}\nبازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\nاز مرغدار:{4}\nراننده:{5}\nماشین:{6}\nبا پلاک {7}\nتحویل کشتارگاه شد.'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_vet_to_kill_house_sms(mobile, send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + + ): + message = 'اعلام تاییدتحویل بار:\nتاریخ:{0}\nبازه زمانی:{1}\nتعداد:{2}\nنژاد:{3}\nاز مرغدار:{4}\nراننده:{5}\nماشین:{6}\nبا پلاک {7}\nتحویل کشتارگاه شد.'.format( + send_date, receive_time, quantity, chicken_breed, poultry_name, + driver_name, + driver_car, + pelak, + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def province_kill_request_reject_sms(mobile, kill_house_name + ): + message = ' کاربر گرامی: {0}\n درخواست اولیه کشتار شما توسط استان رد شد.'.format( + kill_house_name + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def allow_poultry_city_province_sms(mobile, Poultry_name + ): + message = ' کاربر گرامی:\nوکالت ثبت درخواست کشتار توسط مرغدار:{} برای شما صادر شد.'.format( + Poultry_name + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def allow_poultry_city_for_poultry_sms(mobile, Poultry_name + ): + message = ' مرغدار گرامی:{0}\n وکالت ثبت درخواست کشتار توسط شما برای شهرستان ثیت شد.'.format( + Poultry_name + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def allow_poultry_province_for_poultry_sms(mobile, Poultry_name + ): + message = ' مرغدار گرامی:{0}\n وکالت ثبت درخواست کشتار توسط شما برای استان ثیت شد.'.format( + Poultry_name + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def kill_house_vet_check_receive_sms(request): + url = 'http://webservice.sahandsms.com/NewSMSWebService.asmx/RecieveSMS' + params = {'Username': USERNAME_SMS, 'password': PASSWORD_SMS, 'phNo': '30002501', 'startdate': '5/1/2023', + 'enddate': '6/2/2023'} + response = send_sms_request(url, params=params) + if response.status_code != 200: + pass + else: + + xml_str = response.content + root = ET.fromstring(xml_str) + mobile = root.iter('RcvSmsfrom') + text = root.iter('RcvSmsText') + + for m, t in zip(mobile, text): + kill_house_request = KillHouseRequest.objects.filter(trash=False, bar_code=t.text).first() + if kill_house_request: + vet = KillHouseVet.objects.filter(vet__user__mobile=m.text + , trash=False, + kill_house=kill_house_request.killhouse_user).first() + if vet: + kill_house_request.vet_state = "accepted" + kill_house_request.save() + vet_check_request = VetCheckRequest( + kill_house_vet=vet, + kill_house_request=kill_house_request, + state='accepted' + + ) + vet_check_request.save() + + +def steward_allocation_sms(mobile, date, weight, seller, number, + buyer, amount): + message = 'اطلاعات خرید گوشت مرغ\n' \ + 'فروشنده: {0} \n' \ + 'تاریخ فروش: {1}\n' \ + 'وزن سفارش: {2} (کیلوگرم)\n' \ + 'مبلغ هر کیلو: {3} (ریال)\n' \ + 'کد احراز: {4}\n' \ + 'سامانه رصدیار'.format(seller, date, to_locale_str(weight), to_locale_str(amount), number) + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={steward_allocation_username}" + f"&password={steward_allocation_password}&from=30002501&to={mobile}&message={message}") + + +def direct_buying_code_sms(mobile, buyer, buyer_mobile, quantity, kill_place, date, code + ): + message = 'درخواست خرید مستقیم:\nخریدار:{0}-{1}\nتعداد:{2}\nمحل کشتار:{3}\nتاریخ:{4}\nکد احراز:{5}'.format( + buyer, buyer_mobile, quantity, kill_place, date, code + ) + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +# USERNAME_SMS +def export_code_sms(mobile, buyer, buyer_mobile, quantity, kill_place, date, export_country, code + , poultry_name, province_mobile): + message = f'درخواست خرید برای صادرات:' \ + f'\n' \ + f'مرغدار:{poultry_name}' \ + f'\n' \ + f'تلفن مرغدار:{mobile}' \ + f'\n' \ + f'خریدار:{buyer}' \ + f'\n' \ + f'تلفن خریدار:{buyer_mobile}' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'محل کشتار:{kill_place}' \ + f'\n' \ + f'تاریخ:{date}' \ + f'\n' \ + f'کشور مقصد:{export_country}' \ + f'\n' \ + f'کد احراز:{code}' \ + f'\n' \ + f'(سامانه رصدیار)' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password=" + f"{PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password=" + f"{PASSWORD_SMS}&from=30002501&to={province_mobile}&message={message}") + + +def steward2_allocation_sms(mobile=None): + message = 'مورخ تعداد با وزن کیلوگرم از طرف کشتارگاه به شما تخصیص داده شد \n کد احراز:' + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + + print(response.text) + + +def send_discharge_bar(text, mobile): + user_name = USERNAME_SMS + password = PASSWORD_SMS + message = f' بار با شماره {text} با موفقیت تایید تخلیه شد.' + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = (f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username=" + f"{user_name}&password={password}&from=30002501&to={mobile}&message={message}") + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + requests.request("GET", url, headers=headers, data=payload) + + +def receive_sms_panel(): + now = datetime.now().date() + user_name = USERNAME_SMS + password = PASSWORD_SMS + + url = 'http://webservice.sahandsms.com/NewSMSWebService.asmx/RecieveSMS' + params = {f'Username': {user_name}, 'password': {password}, 'phNo': '30002501', 'startdate': {now}, + 'enddate': {now}} + + response = send_sms_request(url, params=params) + + xml_str = response.content + root = ET.fromstring(xml_str) + mobile = root.iter('RcvSmsfrom') + text = root.iter('RcvSmsText') + + for m, t in zip(mobile, text): + try: + kill_house_request = KillHouseRequest.objects.filter(trash=False, bar_code=t.text, + vet_state='pending').first() + except: + continue + if kill_house_request: + kill_house_vet = KillHouseVet.objects.filter(vet__user__mobile=m.text, + kill_house=kill_house_request.killhouse_user).first() + if kill_house_vet: + kill_house_request.vet_state = 'complate' + VetCheckRequest.objects.create( + kill_house_vet=kill_house_vet, + kill_house_request=kill_house_request, + state='complete' + ) + VetCheckAllocations.objects.create( + vet=kill_house_vet.vet, + kill_house_request=kill_house_request + ) + kill_house_request.save() + send_sms = threading.Thread(target=send_discharge_bar, args=(t.text, m.text)) + send_sms.start() + + +def condition_of_sms(request): + query = UserMessageSend.objects.filter(trash=False).select_related('user') + list1 = [] + for q in query: + if len(q.receive_code) > 3: + req = send_sms_request( + url=f"http://webservice.sahandsms.com/newsmswebservice.asmx/GetQueueMessageStatus?username={USERNAME_SMS}&password={PASSWORD_SMS}&MessageIds={q.receive_code}" + ) + root = ET.fromstring(req.content) + int_value = int(root.find('.//{http://tempuri.org/}int').text) + else: + int_value = None + dict1 = { + "role": q.user.role.name, + "user": q.user.fullname, + "mobile": q.user.mobile, + "message": q.message, + "create_date": q.create_date, + 'receive_code': int_value, + } + list1.append(dict1) + return HttpResponse(list1) + + +def send_gate_way_sms(): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).select_related('kill_house_operator__user') \ + .only('name', 'killer', 'kill_house_operator__user__user_gate_way_id', 'kill_house_operator__user__mobile') + for kill_house in kill_houses: + total_paid_wage = 0 + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # trash=False, + # return_to_province=False, + # first_car_allocated_quantity=0, + # archive_wage=False, + # ).exclude(union_share=0, company_share=0, + # guilds_share=0).only( + # 'total_killed_weight', 'union_share', 'company_share', + # 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + # freezing_province_kill_requests = province_kill_requests.filter( + # province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + # 'company_share', + # 'guilds_share', 'total_wage_amount', + # 'total_killed_quantity') + # + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) | Q(killer=kill_house)), + # archive_wage=False, + # trash=False + # ).select_related('province_kill_request').only('accepted_real_weight', + # 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', + # 'accepted_real_quantity', 'accepted_real_quantity') + # kill_house_requests = kill_house_requests.filter( + # Q(killer=kill_house) | Q(killhouse_user=kill_house)).select_related( + # 'province_kill_request').only( + # 'accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # freezing_kill_house_requests = kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=True).select_related( + # 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + # trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount' + # ) + # + # + # province_kill_requests_total_wage = \ + # province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + # total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # if wage_percent > 0: + # province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + # freezing_province_kill_request_total_wage = \ + # freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + # + # kill_house_reqest_total_wage = \ + # kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=False).aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # if wage_percent > 0: + # kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + # freezing_kill_house_reqest_total_wage = \ + # freezing_kill_house_requests.aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # + # free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # + # free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage = free_bars_carcases_total_wage + kill_house_reqest_total_wage + \ + # freezing_kill_house_reqest_total_wage + province_kill_requests_total_wage + \ + # freezing_province_kill_request_total_wage + free_bars_live_total_wage + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + if kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتارکن' + kill_house_purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + + total_wage = total_unpaid_wage - (total_paid_wage + kill_house.off) + unpaid = "{:,}".format(int(total_wage)) + user_token = 'k' + kill_house.kill_house_operator.user.user_gate_way_id + message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + '\n' \ + 'باسلام' \ + '\n' \ + f'مبلغ بدهی تعرفه شما {unpaid} ریال می باشدبا توجه به سقف مجاز بدهی تعیین شده، در اسرع وقت اقدام به پرداخت تعرفه خود کنید.' \ + '\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{user_token}' \ + f'\n' \ + f'(سامانه رصدیار)' + + if kill_house_purchase and kill_house_purchase.limitation_number <= total_wage and \ + kill_house_purchase.limitation == True: + continue + else: + if int(total_wage) > 0: + # if kill_house_purchase.limitation_number > total_wage: + # debt=int(kill_house_purchase.limitation_number*0.5) + # if int(total_wage >= debt): + check_mobile = check_mobile_number(kill_house.kill_house_operator.user.mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={kill_house.kill_house_operator.user.mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={COMPANY_NUMBER}&message={message}") + if UNION_THIRD_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + + if UNION_FOURTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={UNION_FOURTH_NUMBER}&message={message}") + + +# OUT_SMS_PASS +def send_gate_way_sms_manual(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).select_related('kill_house_operator__user') \ + .only('name', 'killer', 'kill_house_operator__user__user_gate_way_id', 'kill_house_operator__user__mobile') + for kill_house in kill_houses: + total_paid_wage = 0 + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # trash=False, + # return_to_province=False, + # first_car_allocated_quantity=0, + # archive_wage=False, + # ).exclude(union_share=0, company_share=0, + # guilds_share=0).only( + # 'total_killed_weight', 'union_share', 'company_share', + # 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + # freezing_province_kill_requests = province_kill_requests.filter( + # province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + # 'company_share', + # 'guilds_share', 'total_wage_amount', + # 'total_killed_quantity') + # + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) | Q(killer=kill_house)), + # archive_wage=False, + # trash=False + # ).select_related('province_kill_request').only('accepted_real_weight', + # 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', + # 'accepted_real_quantity', 'accepted_real_quantity') + # kill_house_requests = kill_house_requests.filter( + # Q(killer=kill_house) | Q(killhouse_user=kill_house)).select_related( + # 'province_kill_request').only( + # 'accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # freezing_kill_house_requests = kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=True).select_related( + # 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + # trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount' + # ) + # + # + # province_kill_requests_total_wage = \ + # province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + # total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # if wage_percent > 0: + # province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + # freezing_province_kill_request_total_wage = \ + # freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + # + # kill_house_reqest_total_wage = \ + # kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=False).aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # if wage_percent > 0: + # kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + # freezing_kill_house_reqest_total_wage = \ + # freezing_kill_house_requests.aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # + # free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # + # free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage = free_bars_carcases_total_wage + kill_house_reqest_total_wage + \ + # freezing_kill_house_reqest_total_wage + province_kill_requests_total_wage + \ + # freezing_province_kill_request_total_wage + free_bars_live_total_wage + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + if kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتارکن' + kill_house_purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + + total_wage = total_unpaid_wage - (total_paid_wage + kill_house.off) + unpaid = "{:,}".format(int(total_wage)) + user_token = 'k' + kill_house.kill_house_operator.user.user_gate_way_id + message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + '\n' \ + 'باسلام' \ + '\n' \ + f'مبلغ بدهی تعرفه شما {unpaid} ریال می باشدبا توجه به سقف مجاز بدهی تعیین شده، در اسرع وقت اقدام به پرداخت تعرفه خود کنید.' \ + '\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{user_token}' \ + f'\n' \ + f'(سامانه رصدیار)' + + if kill_house_purchase and kill_house_purchase.limitation_number <= total_wage and \ + kill_house_purchase.limitation == True: + continue + else: + if int(total_wage) > 0: + # if kill_house_purchase.limitation_number > total_wage: + # debt=int(kill_house_purchase.limitation_number*0.5) + # if int(total_wage >= debt): + check_mobile = check_mobile_number(kill_house.kill_house_operator.user.mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={kill_house.kill_house_operator.user.mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={COMPANY_NUMBER}&message={message}") + if UNION_THIRD_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + + if UNION_FOURTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={gate_way_username}&password={gate_way_password}&from=30002501&to={UNION_FOURTH_NUMBER}&message={message}") + return HttpResponse('ok') + + +def send_province_request_pdf_sms(): + mobile = [UNION_NUMBER] + date = datetime.now().date() + province_kill_requests = ProvinceKillRequest.objects.filter(kill_request__recive_date__date=date, trash=False, + state__in=('pending', 'accepted'), + return_to_province=False) + poultry = Poultry.objects.filter( + key__in=province_kill_requests.values_list('province_request__poultry_request__poultry__key', flat=True)) + vat_farm = VetFarm.objects.filter(trash=False, poultry__in=poultry).values_list('vet__user__mobile', + flat=True).distinct() + mobile.extend(vat_farm) + message = 'کاربرگرامی' \ + '\n' \ + 'جهت دریافت گزارش روزانه تخصیص مرغ استان بر روی لینک کلیک کنید:' \ + '\n' \ + f'https://{base_url_sms}.rasadyaar.ir/reports/ds' + for m in mobile: + check_mobile = check_mobile_number(m) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={m}&message={message}") + + +def send_deactivate_panel_debt_sms(): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + kill_house_purchase = KillHousePurchaseRequest.objects.filter(limitation=True, kill_house=kill_house).first() + if kill_house_purchase: + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + total_paid_wage = 0 + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # trash=False, + # return_to_province=False, + # first_car_allocated_quantity=0, + # archive_wage=False, + # ).exclude(union_share=0, company_share=0, + # guilds_share=0).only( + # 'total_killed_weight', 'union_share', 'company_share', + # 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + # freezing_province_kill_requests = province_kill_requests.filter( + # province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + # 'company_share', + # 'guilds_share', 'total_wage_amount', + # 'total_killed_quantity') + # + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) | Q(killer=kill_house)), + # archive_wage=False, + # trash=False + # ).select_related('province_kill_request').only('accepted_real_weight', + # 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', + # 'accepted_real_quantity', 'accepted_real_quantity') + # kill_house_requests = kill_house_requests.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)).select_related( + # 'province_kill_request').only( + # 'accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # freezing_kill_house_requests = kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=True).select_related( + # 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + # trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount' + # ) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + + # province_kill_requests_total_wage = \ + # province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + # total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # if wage_percent > 0: + # province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + # freezing_province_kill_request_total_wage = \ + # freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + # + # kill_house_reqest_total_wage = \ + # kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=False).aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # if wage_percent > 0: + # kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + # freezing_kill_house_reqest_total_wage = \ + # freezing_kill_house_requests.aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # + # free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # + # free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage = free_bars_carcases_total_wage + kill_house_reqest_total_wage + \ + # freezing_kill_house_reqest_total_wage + province_kill_requests_total_wage + \ + # freezing_province_kill_request_total_wage + free_bars_live_total_wage + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_wage = total_unpaid_wage - (total_paid_wage + kill_house.off) + if kill_house_purchase.limitation_number <= total_wage: + unpaid = "{:,}".format(int(total_wage)) + if kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتارکن' + amount = "{:,}".format(int(kill_house_purchase.limitation_number)) + user_token = 'k' + kill_house.kill_house_operator.user.user_gate_way_id + message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + f'\n' \ + f'باسلام واحترام ' \ + f'\n' \ + f'باتوجه به عدم پرداخت بدهی تعرفه سامانه به مبلغ{unpaid} امکان ثبت کشتار برای شما وجود ندارد.جهت فعال سازی پنل، بدهی شما باید کمتر از {amount} ریال باشد.' \ + f'\n' \ + f'لازم به توضیح است که کشتار خارج از سامانه به عنوان کشتار و عرضه خارج از شبکه محسوب میگردد.' \ + f'\n' \ + f'لینک مشاهده و پرداخت بدهی:' \ + f'\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{user_token} \n' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(kill_house.kill_house_operator.user.mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={kill_house.kill_house_operator.user.mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={COMPANY_NUMBER}&message={message}") + if UNION_SECOND_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_SECOND_NUMBER}&message={message}") + if UNION_THIRD_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + if UNION_FIFTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_FIFTH_NUMBER}&message={message}") + if UNION_SIXTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_SIXTH_NUMBER}&message={message}") + + +# OUT_SMS_PASS +def send_deactivate_panel_debt_sms_manual(request): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + kill_house_purchase = KillHousePurchaseRequest.objects.filter(limitation=True, kill_house=kill_house).first() + if kill_house_purchase: + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + total_paid_wage = 0 + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # trash=False, + # return_to_province=False, + # first_car_allocated_quantity=0, + # archive_wage=False, + # ).exclude(union_share=0, company_share=0, + # guilds_share=0).only( + # 'total_killed_weight', 'union_share', 'company_share', + # 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + # freezing_province_kill_requests = province_kill_requests.filter( + # province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + # 'company_share', + # 'guilds_share', 'total_wage_amount', + # 'total_killed_quantity') + # + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) | Q(killer=kill_house)), + # archive_wage=False, + # trash=False + # ).select_related('province_kill_request').only('accepted_real_weight', + # 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', + # 'accepted_real_quantity', 'accepted_real_quantity') + # kill_house_requests = kill_house_requests.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)).select_related( + # 'province_kill_request').only( + # 'accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # freezing_kill_house_requests = kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=True).select_related( + # 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + # 'province_kill_request__wage', 'accepted_real_weight', + # 'province_kill_request__guilds_share_percent', + # 'province_kill_request__company_share_percent', 'accepted_real_quantity') + # + # free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + # trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount') + # free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + # 'weight_of_carcasses', + # 'company_share', + # 'guilds_share', + # 'total_wage_amount' + # ) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + + # province_kill_requests_total_wage = \ + # province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + # total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # if wage_percent > 0: + # province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + # freezing_province_kill_request_total_wage = \ + # freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + # + # kill_house_reqest_total_wage = \ + # kill_house_requests.filter( + # province_kill_request__province_request__poultry_request__freezing=False).aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # if wage_percent > 0: + # kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + # freezing_kill_house_reqest_total_wage = \ + # freezing_kill_house_requests.aggregate( + # total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # + # free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # + # free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage = free_bars_carcases_total_wage + kill_house_reqest_total_wage + \ + # freezing_kill_house_reqest_total_wage + province_kill_requests_total_wage + \ + # freezing_province_kill_request_total_wage + free_bars_live_total_wage + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_wage = total_unpaid_wage - (total_paid_wage + kill_house.off) + if kill_house_purchase.limitation_number <= total_wage: + unpaid = "{:,}".format(int(total_wage)) + if kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتارکن' + amount = "{:,}".format(int(kill_house_purchase.limitation_number)) + user_token = 'k' + kill_house.kill_house_operator.user.user_gate_way_id + message = f'کاربر گرامی {killer + "(" + kill_house.name + ")"}' \ + f'\n' \ + f'باسلام واحترام ' \ + f'\n' \ + f'باتوجه به عدم پرداخت بدهی تعرفه سامانه به مبلغ{unpaid} امکان ثبت کشتار برای شما وجود ندارد.جهت فعال سازی پنل، بدهی شما باید کمتر از {amount} ریال باشد.' \ + f'\n' \ + f'لازم به توضیح است که کشتار خارج از سامانه به عنوان کشتار و عرضه خارج از شبکه محسوب میگردد.' \ + f'\n' \ + f'لینک مشاهده و پرداخت بدهی:' \ + f'\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{user_token} \n' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(kill_house.kill_house_operator.user.mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={kill_house.kill_house_operator.user.mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={COMPANY_NUMBER}&message={message}") + if UNION_SECOND_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_SECOND_NUMBER}&message={message}") + if UNION_THIRD_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_THIRD_NUMBER}&message={message}") + if UNION_FIFTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_FIFTH_NUMBER}&message={message}") + if UNION_SIXTH_NUMBER is not None: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={send_deactivate_username}&password={send_deactivate_password}&from=30002501&to={UNION_SIXTH_NUMBER}&message={message}") + return HttpResponse('ok') + + +# USERNAME_SMS_FINANCIAL +def province_out_request_transaction_sms(province, buyer, poultry_name, quantity, index_weight, wage, mobile, + order_code, date, amount, sale_type): + date1 = datetime.strptime(str(date), + '%Y-%m-%d').date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + all_wage = "{:,}".format(int(wage)) + amount = "{:,}".format(int(amount)) + sale_type_free = 'آزاد' if sale_type == False else 'دولتی' + message = f'سفارش فروش مرغ زنده استان {province}' \ + '\n' \ + f'تاریخ: {date}' \ + f'\n' \ + f'خریدار: {buyer}' \ + '\n' \ + f'مرغدار: {poultry_name}' \ + '\n' \ + f'نوع فروش:{sale_type_free}' \ + '\n' \ + f'تعداد: {quantity}' \ + '\n' \ + f'وزن تقریبی سفارش: {index_weight}' \ + f'\n' \ + f'وزن تقریبی کل سفارش: {int(index_weight * quantity)}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'مبلغ کل تعرفه:{all_wage} ریال ' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه:' \ + f'\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{order_code}' \ + f'\n' \ + f'سامانه رصدیار' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={COMPANY_NUMBER}&message={message}") + + +# def daily_report_excel_and_pdf_send_from_sms(): +# message = f'سفارش فروش مرغ زنده استان {province}' \ +# '\n' \ +# f'تاریخ: {date}' \ +# f'\n' \ +# f'خریدار: {buyer}' \ +# '\n' \ +# f'مرغدار: {poultry_name}' \ +# '\n' \ +# f'تعداد: {quantity}' \ +# '\n' \ +# f'وزن تقریبی سفارش: {index_weight}' \ +# f'\n' \ +# f'مبلغ کل تعرفه:{all_wage} ریال ' \ +# f'\n' \ +# f'لینک مشاهده و پرداخت تعرفه:' \ +# f'\n' \ +# f'https://{base_url_sms}.rasadyar.net/pay/{order_code}' \ +# f'\n' \ +# f'سامانه رصدیار' +# check_mobile = check_mobile_number(mobile) +# if check_mobile: +# req = send_sms_request( +# f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + +# USERNAME_SMS_FINANCIAL + +def send_sms_for_final_approval_out_province_threading(buyer_list, poultry_request_list): + # users = SystemUserProfile.objects.filter(id__in=poultry_list).select_related('province').only('mobile', 'user_gate_way_id','province__name','fullname') + if base_url_sms == 'ha': + province_name = 'همدان' + elif base_url_sms == 'ku': + province_name = 'کردستان' + elif base_url_sms == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + base_url = f'rasadyar.net/pay/{base_pos_id}' + if poultry_request_list is not None: + poultry_requests = PoultryRequest.objects.filter(trash=False, id__in=poultry_request_list) + for poultry_request in poultry_requests: + if poultry_request.interface_number is not None: + mobile = poultry_request.interface_number + else: + mobile = poultry_request.poultry.user.mobile + token_user = 'p' + poultry_request.poultry.user.user_gate_way_id + + message = f' مرغدار محترم {poultry_request.poultry.user.fullname} ' \ + f'\n' \ + f'سفارش خرید مرغ زنده(فروش خارج از استان) با کد سفارش {poultry_request.order_code} برای شما در سامانه رصدیار استان {province_name} ثبت گردید جهت پرداخت تعرفه از طریق لینک زیر اقدام نمایید.' \ + f'\n' \ + f'**لازم به ذکر است: در صورت عدم پرداخت تعرفه تا پایان وقت امروز(16 بعد از ظهر) سفارشات شما لغو میگردد!' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه :' \ + f'\n' \ + f'https://{base_url}/{token_user}{poultry_request.order_code}' \ + f'\n' \ + f'سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_link_out_sale_username}&password={poultry_link_out_sale_password}&from=30002501&to={mobile}&message={message}") + + users = SystemUserProfile.objects.filter(id__in=buyer_list).select_related('province').only('mobile', + 'user_gate_way_id', + 'province__name', + 'fullname') + for user in users: + mobile = user.mobile + token_user = 'b' + user.user_gate_way_id + + message = f' خریدار محترم {user.fullname} ' \ + f'\n' \ + f'سفارش خرید مرغ زنده(فروش خارج از استان) برای شما در سامانه رصدیار استان {province_name} ثبت گردید جهت پرداخت تعرفه از طریق لینک زیر اقدام نمایید.' \ + f'\n' \ + f'**لازم به ذکر است: در صورت عدم پرداخت تعرفه تا پایان وقت امروز(16 بعد از ظهر) سفارشات شما لغو میگردد!' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه :' \ + f'\n' \ + f'https://{base_url}/{token_user}' \ + f'\n' \ + f'سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_link_out_sale_username}&password={poultry_link_out_sale_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_final_approval_out_province_buyer_threading(buyer_list): + users = SystemUserProfile.objects.filter(id__in=buyer_list).select_related('province').only('mobile', + 'user_gate_way_id', + 'province__name', + 'fullname') + for user in users: + mobile = user.mobile + token_user = 'b' + user.user_gate_way_id + message = f' خریدار محترم {user.fullname} ' \ + f'\n' \ + f'سفارش خرید مرغ زنده برای شما در سامانه رصدیار استان {user.province.name} ثبت گردید جهت پرداخت تعرفه از طریق لینک زیر اقدام نمایید.' \ + f'\n' \ + f'لازم به ذکر است در صورت عدم پرداخت تعرفه تا پایان وقت امروز(۱۲ شب) سفارشات شما لغو میگردد!' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه :' \ + f'\n' \ + f'https://rasadyar.net/pay/{base_pos_id}/{token_user}' \ + f'\n' \ + f'سامانه رصدیار' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + print({"status": req.status_code, "mobile": user.mobile}) + + +def sms_allocation_for_vet_farm(poultry_name, poultry_mobile, quantity, Index_weight, kill_house_name, kill_house_mobile + , city, send_date, mobile): + quantity_1 = "{:,}".format(int(quantity)) + message = f'تخصیص مرغ زنده (کشتار داخل استان)' \ + f'\n' \ + f'مرغدار:{poultry_name}' \ + f'\n' \ + f'تلفن:{poultry_mobile}' \ + f'\n' \ + f'تعداد:{quantity_1}' \ + f'\n' \ + f'میانگین وزن: {Index_weight}' \ + f'\n' \ + f'خریدار:{kill_house_name}' \ + f'\n' \ + f'تلفن:{kill_house_mobile}' \ + f'\n' \ + f'ادرس:{city}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'توضیحات: قبل از صدور مجوز حمل با مرغدار هماهنگی های لازم انجام دهید و کد قرنطینه در سامانه رصدیار ثبت گردد.(اتحادیه مرغداران گوشتی استان همدان)' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + + +def sms_chain_company_for_ver_farm(poultry_name, poultry_mobile, quantity, Index_weight, kill_house_name, + kill_house_mobile + , city, send_date, mobile, province): + quantity_1 = "{:,}".format(int(quantity)) + message = f'تخصیص مرغ زنده (کشتار زنجیره ها)' \ + f'\n' \ + f'مرغدار:{poultry_name}' \ + f'\n' \ + f'تلفن:{poultry_mobile}' \ + f'\n' \ + f'تعداد:{quantity_1}' \ + f'\n' \ + f'میانگین وزن: {Index_weight}' \ + f'\n' \ + f'خریدار:{kill_house_name}' \ + f'\n' \ + f'تلفن:{kill_house_mobile}' \ + f'\n' \ + f'ادرس:{city}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'اتحادیه مرغداران گوشتی استان {province}' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + + +def sms_ticket(province, fullname): + message = f'یک تیکت جدید از استان {province} دارید .' \ + '\n' \ + f'کاربر: {fullname}' + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={SUPPORTER_NUMBER}&message={message}") + + +def document_discrepancy_sms(killer, name, bar_code, doc, mobile, date): + killer_user = 'کشتارکن' if killer == True else 'کشتارگاه' + date1 = datetime.strptime(str(date), + '%Y-%m-%d').date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + message = f' کاربر گرامی {killer_user} {name}' \ + '\n' \ + f'بار به شماره {bar_code} در تاریخ({date}) به علت وضعیت ({doc}) نیازمند ویرایش میباشد.' \ + f'\n' \ + f'جهت ویرایش اطلاعات به پنل کاربری خود مراجعه فرمایید.' \ + f'\n' \ + f'(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={COMPANY_NUMBER}&message={message}") + + +def confirmation_of_the_need_for_slaughterhouse_sms_threading(name): + city_operator = CityOperator.objects.filter(trash=False).select_related('user').only('user__mobile') + mobiles = city_operator.values_list('user__mobile', flat=True).distinct() + message = f' کاربر گرامی {name}' \ + '\n' \ + 'باسلام' \ + '\n' \ + 'صرفا جهت اطلاع' \ + '\n' \ + f'درخواست نیاز شما مورد تایید قرار گرفت و امکان ثبت درخواست کشتار را دارید.' \ + f'\n' \ + f'(سامانه رصدیار)' + for mobile in mobiles: + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + + +# USERNAME_SMS +def province_kill_request_accept_sms(kill_house_name + ): + city_operator = CityOperator.objects.filter(trash=False).select_related('user').only('user__mobile') + mobiles = city_operator.values_list('user__mobile', flat=True).distinct() + message = f' کاربر گرامی {kill_house_name}' \ + '\n' \ + 'باسلام' \ + '\n' \ + 'صرفا جهت اطلاع' \ + '\n' \ + f'درخواست نیاز شما مورد تایید قرار گرفت و امکان ثبت درخواست کشتار را دارید.' \ + f'\n' \ + f'(سامانه رصدیار)' + for mobile in mobiles: + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + + +def reporting_sms(): + now = datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + reporst = ReportsUsers.objects.filter(active=True) + for r in reporst: + user_reporst = UserReports.objects.filter(active=True, user=r).order_by('id') + + message = f'کاربرگرامی {r.fullname}' \ + '\n' \ + 'با سلام' \ + '\n' \ + f'احتراماً لیست گزارشات کشتار و توزیع مرغ گوشتی استان مورخ {date} جهت اطلاع بحضورتان ارسال میگردد.' \ + '\n' + l = 1 + if user_reporst: + for user in user_reporst: + message = message + '\n' \ + f'{l}_{user.report.title}' \ + '\n' \ + f'https://{base_url_for_sms_report}backend.rasadyaar.ir/{user.report.end_point}/?key={r.user_token}' \ + '\n' + l += 1 + else: + message = message + '\n' \ + '(سامانه رصدیار)' + check_mobile = check_mobile_number(r.mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={r.mobile}&message={message}") + + +def car_allocation_vet_farm_sms(date, poultry, age, quantity, car, code, pelak, kill_house, mobile, amount, + free_sale_in_province): + date1 = datetime.strptime(str(date), + '%Y-%m-%d').date() + date = shamsi_date(date1) + quantity = "{:,}".format(int(quantity)) + amount = "{:,}".format(int(amount)) + sale_type = 'آزاد' if free_sale_in_province == False else 'دولتی' + message = f'اطلاعات بار' \ + f'\n' \ + f'تاریخ کشتار: {date}' \ + f'\n' \ + f'نوع کشتار:{sale_type}' \ + f'\n' \ + f'مرغدار: {poultry}' \ + f'\n' \ + f'سن: {age}' \ + f'\n' \ + f'قطعه: {quantity}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'ماشین: {car}' \ + f'\n' \ + f'کد حمل: {code}' \ + f'\n' \ + f'پلاک: {pelak}' \ + f'\n' \ + f'کشتارگاه: {kill_house}' \ + '\n' \ + '(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + + +def delete_car_allocation_vet_farm_sms(date, poultry, age, quantity, car, code, pelak, kill_house, mobile, amount, + free_sale_in_province): + date1 = datetime.strptime(str(date), + '%Y-%m-%d').date() + date = shamsi_date(date1) + quantity = "{:,}".format(int(quantity)) + amount = "{:,}".format(int(amount)) + sale_type = 'آزاد' if free_sale_in_province == False else 'دولتی' + message = f'اطلاعات بار حذف شده' \ + f'\n' \ + f'تاریخ کشتار: {date}' \ + f'\n' \ + f'نوع کشتار:{sale_type}' \ + f'\n' \ + f'مرغدار: {poultry}' \ + f'\n' \ + f'سن: {age}' \ + f'\n' \ + f'قطعه: {quantity}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'ماشین: {car}' \ + f'\n' \ + f'کد حمل: {code}' \ + f'\n' \ + f'پلاک: {pelak}' \ + f'\n' \ + f'کشتارگاه: {kill_house}' \ + '\n' \ + '(سامانه رصدیار)' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + + +def cron_for_update_sms(): + update_date = LastUpdate.objects.first().update_date.date() + num_list = [SUPPORTER_NUMBER, COMPANY_NUMBER, '09201917727'] + if base_url_for_sms_report == 'ha': + base = 'همدان' + elif base_url_for_sms_report == 'ma': + base = 'مرکزی' + else: + base = 'بوشهر' + if not update_date == datetime.now().date(): + message = f'جوجه ریزی آپدیت نشده است. استان {base}' + for num in num_list: + send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}" + f"&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={num}&message={message}") + + +def ticket_answered(mobile): + message = f'تیکت شما پاسخ داده شد.' \ + '\n' \ + f'(سامانه رصدیار)' + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_again_sms_for_final_approval_out_province(request): + key = request.GET['key'] + poultry_request = PoultryRequest.objects.get(trash=False, key=key) + if base_url_sms == 'ha': + province_name = 'همدان' + elif base_url_sms == 'ku': + province_name = 'کردستان' + elif base_url_sms == 'ma': + province_name = 'مرکزی' + else: + + province_name = 'تست' + base_url = f'rasadyar.net/pay/{base_pos_id}' + if poultry_request.payer_type == 'poultry': + if poultry_request.interface_number is not None: + mobile = poultry_request.interface_number + else: + mobile = poultry_request.poultry.user.mobile + token_user = 'p' + poultry_request.poultry.user.user_gate_way_id + + message = f' مرغدار محترم {poultry_request.poultry.user.fullname} ' \ + f'\n' \ + f'سفارش خرید مرغ زنده(فروش خارج از استان) با کد سفارش {poultry_request.order_code} برای شما در سامانه رصدیار استان {province_name} ثبت گردید جهت پرداخت تعرفه از طریق لینک زیر اقدام نمایید.' \ + f'\n' \ + f'**لازم به ذکر است: در صورت عدم پرداخت تعرفه تا پایان وقت امروز(16 بعد از ظهر) سفارشات شما لغو میگردد!' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه :' \ + f'\n' \ + f'https://{base_url}/{token_user}{poultry_request.order_code}' \ + f'\n' \ + f'سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_link_out_sale_username}&password={poultry_link_out_sale_password}&from=30002501&to={mobile}&message={message}") + else: + mobile = poultry_request.buyer_mobile + user = SystemUserProfile.objects.filter(mobile=mobile).first() + token_user = 'b' + user.user_gate_way_id + + message = f' خریدار محترم {user.fullname} ' \ + f'\n' \ + f'سفارش خرید مرغ زنده(فروش خارج از استان) برای شما در سامانه رصدیار استان {province_name} ثبت گردید جهت پرداخت تعرفه از طریق لینک زیر اقدام نمایید.' \ + f'\n' \ + f'**لازم به ذکر است: در صورت عدم پرداخت تعرفه تا پایان وقت امروز(16 بعد از ظهر) سفارشات شما لغو میگردد!' \ + f'\n' \ + f'لینک مشاهده و پرداخت تعرفه :' \ + f'\n' \ + f'https://{base_url}/{token_user}' \ + f'\n' \ + f'سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_link_out_sale_username}&password={poultry_link_out_sale_password}&from=30002501&to={mobile}&message={message}") + return HttpResponse('ok', status=status.HTTP_200_OK) + + +def vet_farm_out_poultry_request_sms(mobile, poultry_fullname, quantity, chicken_breed, + order_code, send_date, sale_in_province, amount): + sale_type = 'آزاد' if sale_in_province == True else 'دولتی' + amount = "{:,}".format(int(amount)) + quantity = "{:,}".format(int(quantity)) + message = 'درخواست فروش به خارج از استان' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'نژاد:{chicken_breed}' \ + f'\n' \ + f'تاریخ کشتار:{send_date}' \ + f'\n' \ + f'نوع فروش:{sale_type}' \ + f'\n' \ + f'مرغدار:{poultry_fullname}' \ + f'\n' \ + f'کدسفارش:{order_code}' \ + f'\n' \ + f'قیمت مرغدار:{amount}' \ + f'\n' \ + f'(سامانه رصدیار)' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + +def send_sms_for_kill_house_not_add_to_inventory(mobile, quantity): + quantity = "{:,}".format(int(quantity)) + message = 'درخواست فروش به خارج از استان' \ + f'\n' \ + f'تعداد:{quantity}' \ + f'\n' \ + f'\n' \ + f'(سامانه رصدیار)' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = "http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={}&password={}&from=30002501&to={}&message={}".format( + USERNAME_SMS, PASSWORD_SMS, + mobile, message) + + +def send_sms_for_bar_difference_request(mobile, quantity, poultry): + message = 'با سلام و احترام' \ + '\n' \ + f'کاربر گرامی برای شما حجم {quantity} قطعه اختلاف کشتار از مرغدار {poultry} ثبت گردیده لطفا جهت تعیین تکلیف به بخش مدیریت بار قسمت اختلاف کشتار مراجعه نمایید.باتشکر سامانه رصدیار ' + check_mobile = check_mobile_number(mobile) + if check_mobile: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile}&message={message}") + + +class ManagementSendSmsViewSet(viewsets.ModelViewSet): + queryset = ManagementSendSms.objects.all().order_by('id') + serializer_class = ManagementSendSmsSerializer + permission_classes = [TokenHasReadWriteScope] + + +def send_sms_fro_kill_request_market(kill_req): + poultry_name = kill_req.poultry.unit_name + mobile = kill_req.poultry.user.mobile + kill_house_name = kill_req.kill_house.name + kill_house_mobile = kill_req.kill_house.kill_house_operator.user.mobile + message = f' مرغدار محترم {poultry_name} ' \ + f'\n' \ + f'سفارش مرغ زنده در پنل بورسی برای شما ثبت شد:' \ + f'\n' \ + f'خریدار:{kill_house_name}({kill_house_mobile})' \ + f'\n' \ + f'حجم:{to_locale_str(kill_req.kill_capacity)}(قطعه)' \ + f'\n' \ + f'وزن:{to_locale_str(int(kill_req.kill_capacity * kill_req.Index_weight))}(کیلوگرم)' \ + f'\n' \ + f'مبلغ هر کیلو:{to_locale_str(kill_req.amount)}(ریال)' \ + f'\n' \ + f'حداکثر مهلت تسویه:{shamsi_date(kill_req.payment_deadline_date)}' \ + f'\n' \ + f'کد احراز:{kill_req.market_code}' \ + f'\n' \ + f'مهلت وارد کردن کد احراز 30 دقیقه میباشد و پس از آن درخواست لغو خواهد شد و گزارش برای دستگاه نظارتی ارسال میگردد.' \ + f'\n' \ + 'سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={kill_req_market_username}" + f"&password={kill_req_market_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_poultry_market(poultry_req): + poultry_name = poultry_req.poultry.unit_name + mobile = poultry_req.poultry.user.mobile + quantity = to_locale_str(poultry_req.quantity) + amount = to_locale_str(poultry_req.amount) + send_date = shamsi_date(poultry_req.send_date) + message = 'مرغدار محترم {0}' \ + '\n' \ + 'تعداد {1} قطعه مرغ گوشتی سهمیه کشتار در تاریخ {3} با قیمت مصوب {2} (ریال) برای شما در پنل بورسی سامانه رصدیار ثبت شده است.' \ + '\n' \ + 'درصورت عدم موجوی و یا عدم امکان تحویل تعداد مذکور با تعاونی شهرستان خود یا کاربر سامانه در اتحادیه استان تماس حاصل فرمایید.' \ + '\n' \ + 'سامانه رصدیار'.format(poultry_name, quantity, amount, send_date) + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={poultry_req_market_username}" + f"&password={poultry_req_market_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_guild(guilds): + mobile = guilds.user.mobile + type_role = 'مباشر' if guilds.steward == True else 'صنف' + message = 'کاربر گرامی\n' \ + 'برای شما کاربری {5} توسط {6}({7}) در سامانه رصدیار ثبت شده است.\n' \ + 'نام و نام خانوادگی: {0}\n' \ + 'نام واحد صنفی: {1}\n' \ + 'شهر: {2}\n' \ + 'آدرس: {3}\n' \ + 'درصورتی که اطلاعات مورد تایید شما میباشد کد احراز را به ثبت کننده تحویل دهید.\n' \ + 'کد احراز: {4}\n' \ + 'سامانه رصدیار'.format(guilds.user.fullname, guilds.guilds_name, guilds.address.city.name, + guilds.address.address, guilds.register_code, type_role, + guilds.registerar_fullname, + guilds.registerar_mobile) + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={guild_register_username}" + f"&password={guild_register_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_guild_for_register(guilds): + mobile = guilds.user.mobile + type_role = 'مباشر' if guilds.steward == True else 'صنف' + message = 'کاربر گرامی\n' \ + 'برای شما کاربری {5} در سامانه رصدیار ثبت شده است.\n' \ + 'نام و نام خانوادگی: {0}\n' \ + 'نام واحد صنفی: {1}\n' \ + 'شهر: {2}\n' \ + 'آدرس: {3}\n' \ + 'درصورتی که اطلاعات مورد تایید شما میباشد برای احراز شما در سامانه لطفا کد رو تحویل ثبت کننده دهید.\n' \ + 'کد احراز: {4}\n' \ + 'سامانه رصدیار'.format(guilds.user.fullname, guilds.guilds_name, guilds.address.city.name, + guilds.address.address, guilds.register_code, type_role, + guilds.registerar_fullname if guilds.registerar_fullname else '-', + guilds.registerar_mobile if guilds.registerar_mobile else '-') + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={guild_register_username}" + f"&password={guild_register_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_sale_bar(bar): + mobile = bar.buyer_mobile + date = shamsi_date(bar.date) + seller = bar.kill_house.name + weight = bar.weight_of_carcasses + number = bar.registration_code + buyer = bar.buyer_name + quanarntine_code = bar.clearance_code + provicne = bar.province + city = bar.city + + message = 'اطلاعات توزیع لاشه به خارج استان\n' \ + 'فروشنده: {0} \n' \ + 'تاریخ فروش: {1}\n' \ + 'خریدار: {2}\n' \ + 'استان: {6}\n' \ + 'شهر: {7}\n' \ + 'وزن لاشه: {3} (کیلوگرم)\n' \ + 'کد قرنطینه: {4} \n' \ + 'کد احراز: {5}\n' \ + 'سامانه رصدیار'.format(seller, date, buyer, to_locale_str(weight), quanarntine_code, number, provicne, + city) + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={steward_allocation_username}" + f"&password={steward_allocation_password}&from=30002501&to={mobile}&message={message}") + + +def send_sms_for_sale_bar_for_steward(bar): + mobile = bar.buyer_mobile + date = shamsi_date(bar.date) + seller = bar.steward.guilds_name + weight = bar.weight_of_carcasses + number = bar.registration_code + buyer = bar.buyer_name + quanarntine_code = bar.clearance_code + provicne = bar.province + city = bar.city + + message = 'اطلاعات توزیع لاشه به خارج استان\n' \ + 'فروشنده: {0} \n' \ + 'تاریخ فروش: {1}\n' \ + 'خریدار: {2}\n' \ + 'استان: {6}\n' \ + 'شهر: {7}\n' \ + 'وزن لاشه: {3} (کیلوگرم)\n' \ + 'کد قرنطینه: {4} \n' \ + 'کد احراز: {5}\n' \ + 'سامانه رصدیار'.format(seller, date, buyer, to_locale_str(weight), quanarntine_code, number, provicne, + city) + + check_mobile = check_mobile_number(mobile) + if check_mobile: + u = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={steward_allocation_username}" + f"&password={steward_allocation_password}&from=30002501&to={mobile}&message={message}") + + +def send_daily_slaughter_statistics_sms(): + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ku': + province_name = 'کردستان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).aggregate( + total_orders=Sum('id'), + total_quantity=Sum('total_killed_quantity'), + total_live_weight=Sum('total_killed_weight'), + ) + + orders_count = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).count() + + total_quantity = province_kill_requests['total_quantity'] or 0 + total_live_weight = province_kill_requests['total_live_weight'] or 0 + total_carcass_weight = int(total_live_weight * 0.75) + average_weight = round(total_live_weight / total_quantity, 1) if total_quantity > 0 else 0 + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).aggregate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight') + ) + + loads_count = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).count() + + loads_quantity = kill_house_requests['total_quantity'] or 0 + loads_weight = kill_house_requests['total_weight'] or 0 + + formatted_quantity = to_locale_str(int(total_quantity)) + formatted_live_weight = to_locale_str(int(total_live_weight)) + formatted_carcass_weight = to_locale_str(int(total_carcass_weight)) + formatted_loads_quantity = to_locale_str(int(loads_quantity)) + formatted_loads_weight = to_locale_str(int(loads_weight)) + + message = f'اطلاعات کشتار مرغ گوشتی مورخ {date_shamsi} استان {province_name}\n' \ + f'تعداد سفارشات: {orders_count}\n' \ + f'حجم سفارش کشتار: {formatted_quantity} قطعه\n' \ + f'وزن تقریبی زنده: {formatted_live_weight} کیلوگرم\n' \ + f'وزن تقریبی لاشه: {formatted_carcass_weight} کیلوگرم\n' \ + f'میانگین وزن زنده: {average_weight} کیلوگرم\n' \ + f'اطلاعات بارایجاد شده:\n' \ + f'تعداد بار: {loads_count}\n' \ + f'حجم بارها: {formatted_loads_quantity} قطعه\n' \ + f'وزن بارها(زنده): {formatted_loads_weight} کیلوگرم\n' \ + f'سامانه رصدیار' + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={sms_recipient_username}" + f"&password={sms_recipient_password}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +def send_daily_distribution_report_sms(): + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ku': + province_name = 'کردستان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).order_by('name') + + distribution_data = [] + total_distribution_weight = 0 + + for kill_house in kill_houses: + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + trash=False, + receiver_state__in=('pending', 'accepted'), + to_cold_house__isnull=True, + date__date=target_date, + warehouse=True + ).aggregate( + total_weight=Sum('real_weight_of_carcasses') + ) + + allocation_weight = kill_house_allocations['total_weight'] + + if allocation_weight and allocation_weight > 0: + distribution_data.append({ + 'name': kill_house.name, + 'weight': allocation_weight + }) + total_distribution_weight += allocation_weight + + if not distribution_data: + return HttpResponse('هیچ توزیعی برای امروز ثبت نشده است', status=status.HTTP_200_OK) + + message_lines = [f'گزارش توزیع گوشت مرغ داخل استان'] + message_lines.append(f'مورخ {date_shamsi} استان {province_name}') + + for item in distribution_data: + formatted_weight = to_locale_str(int(item['weight'])) + message_lines.append("kg {1}: {0}".format(item['name'], formatted_weight)) + + message_lines.append('-------------------------') + formatted_total = to_locale_str(int(total_distribution_weight)) + message_lines.append(' مجموع کل توزیع: {} kg'.format(formatted_total)) + message_lines.append('سامانه رصدیار') + + message = '\n'.join(message_lines) + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={sms_recipient_username}" + f"&password={sms_recipient_password}&from=30002501&to={mobile}&message={message}") + except Exception as e: + print(f"Error sending SMS to {mobile}: {str(e)}") + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_daily_distribution_report_sms_manual(request): + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ku': + province_name = 'کردستان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).order_by('name') + + distribution_data = [] + total_distribution_weight = 0 + + for kill_house in kill_houses: + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + trash=False, + receiver_state__in=('pending', 'accepted'), + to_cold_house__isnull=True, + date__date=target_date, + warehouse=True + ).aggregate( + total_weight=Sum('real_weight_of_carcasses') + ) + + allocation_weight = kill_house_allocations['total_weight'] + + if allocation_weight and allocation_weight > 0: + distribution_data.append({ + 'name': kill_house.name, + 'weight': allocation_weight + }) + total_distribution_weight += allocation_weight + + if not distribution_data: + return HttpResponse('هیچ توزیعی برای امروز ثبت نشده است', status=status.HTTP_200_OK) + + message_lines = [f'گزارش توزیع گوشت مرغ داخل استان'] + message_lines.append(f'مورخ {date_shamsi} استان {province_name}') + + for item in distribution_data: + formatted_weight = to_locale_str(int(item['weight'])) + message_lines.append("kg {1}: {0}".format(item['name'], formatted_weight)) + + message_lines.append('-------------------------') + formatted_total = to_locale_str(int(total_distribution_weight)) + message_lines.append(' مجموع کل توزیع: {} kg'.format(formatted_total)) + message_lines.append('سامانه رصدیار') + + message = '\n'.join(message_lines) + + success_count = 0 + failed_numbers = [] + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={sms_recipient_username}" + f"&password={sms_recipient_password}&from=30002501&to={mobile}&message={message}") + success_count += 1 + except Exception as e: + failed_numbers.append(mobile) + print(f"Error sending SMS to {mobile}: {str(e)}") + else: + failed_numbers.append(mobile) + + return HttpResponse( + f'گزارش توزیع با موفقیت برای {success_count} شماره ارسال شد. تعداد کشتارگاه: {len(distribution_data)}. شماره های ناموفق: {failed_numbers if failed_numbers else "ندارد"}', + status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def send_daily_slaughter_statistics_sms_manual(request): + mobile_objects = SmsRecipient.objects.filter(is_active=True) + mobile_numbers = [obj.phone_number for obj in mobile_objects] + # mobile_numbers = [ + # '09188176737', + # '09011110919', + # '09181112717', + # '09185914818', + # '09187040838', + # '09393946626', + # '09127687317', + # '09033073493', + # ] + + target_date = datetime.now().date() + date_shamsi = shamsi_date(target_date) + + if base_url_for_sms_report == 'ha': + province_name = 'همدان' + elif base_url_for_sms_report == 'ku': + province_name = 'کردستان' + elif base_url_for_sms_report == 'ma': + province_name = 'مرکزی' + else: + province_name = 'تست' + + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).aggregate( + total_orders=Sum('id'), + total_quantity=Sum('total_killed_quantity'), + total_live_weight=Sum('total_killed_weight'), + ) + + orders_count = ProvinceKillRequest.objects.filter( + trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=target_date + ).count() + + total_quantity = province_kill_requests['total_quantity'] or 0 + total_live_weight = province_kill_requests['total_live_weight'] or 0 + total_carcass_weight = int(total_live_weight * 0.75) + average_weight = round(total_live_weight / total_quantity, 1) if total_quantity > 0 else 0 + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).aggregate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight') + ) + + loads_count = KillHouseRequest.objects.filter( + kill_request__recive_date__date=target_date, + trash=False + ).count() + + loads_quantity = kill_house_requests['total_quantity'] or 0 + loads_weight = kill_house_requests['total_weight'] or 0 + + formatted_quantity = to_locale_str(int(total_quantity)) + formatted_live_weight = to_locale_str(int(total_live_weight)) + formatted_carcass_weight = to_locale_str(int(total_carcass_weight)) + formatted_loads_quantity = to_locale_str(int(loads_quantity)) + formatted_loads_weight = to_locale_str(int(loads_weight)) + + message = f'اطلاعات کشتار مرغ گوشتی مورخ {date_shamsi} استان {province_name}\n' \ + f'تعداد سفارشات: {orders_count}\n' \ + f'حجم سفارش کشتار: {formatted_quantity} قطعه\n' \ + f'وزن تقریبی زنده: {formatted_live_weight} کیلوگرم\n' \ + f'وزن تقریبی لاشه: {formatted_carcass_weight} کیلوگرم\n' \ + f'میانگین وزن زنده: {average_weight} کیلوگرم\n' \ + f'اطلاعات بارایجاد شده:\n' \ + f'تعداد بار: {loads_count}\n' \ + f'حجم بارها: {formatted_loads_quantity} قطعه\n' \ + f'وزن بارها(زنده): {formatted_loads_weight} کیلوگرم\n' \ + f'سامانه رصدیار' + + success_count = 0 + failed_numbers = [] + + for mobile in mobile_numbers: + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={sms_recipient_username}" + f"&password={sms_recipient_password}&from=30002501&to={mobile}&message={message}") + success_count += 1 + except Exception as e: + failed_numbers.append(mobile) + print(f"Error sending SMS to {mobile}: {str(e)}") + else: + failed_numbers.append(mobile) + + return HttpResponse( + f'پیامک با موفقیت برای {success_count} شماره ارسال شد. شماره های ناموفق: {failed_numbers if failed_numbers else "ندارد"}', + status=status.HTTP_200_OK) + + +def test_sms_simple(): + """ + تابع ساده برای تست ارسال پیامک + """ + mobile = '09165597588' + message = 'تست ارسال پیامک از سامانه رصدیار' + + check_mobile = check_mobile_number(mobile) + if check_mobile: + try: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS}&password={PASSWORD_SMS}&from=30002501&to={mobile}&message={message}") + print(f"SMS sent successfully. Status: {req.status_code}") + return f"پیامک با موفقیت ارسال شد. Status: {req.status_code}" + except Exception as e: + print(f"Error sending SMS: {str(e)}") + return f"خطا در ارسال پیامک: {str(e)}" + else: + return "شماره موبایل معتبر نیست" + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def test_sms_endpoint(request): + print('so') + """ + Endpoint برای تست ارسال پیامک + """ + result = test_sms_simple() + return HttpResponse(result, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/authentication/tests.py b/authentication/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/authentication/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/authentication/urls.py b/authentication/urls.py new file mode 100644 index 0000000..252a155 --- /dev/null +++ b/authentication/urls.py @@ -0,0 +1,235 @@ +from django.urls import path, include +import oauth2_provider.views as oauth2_views +from rest_framework import routers +from django.conf import settings + +from authentication.healthcheck import health_check +from authentication.message.views import ( + UserMessageViewSet, + SendingMessageMethodViewSet, + SendSMSViewSet +) +from authentication.register import get_driver_excel, create_driver_excel_template, upload_driver_excel, get_poultry_hatching_excel, check_poultry_hatching_excel, \ + reset_hatching_excel, enter_driver_hamedan, integration_of_hatching, check_poultry_in_db, \ + update_chicken_age_from_login, violation_archive_true, update_chicken_breed_from_excel, ye_chee_bani, \ + get_server_time, transaction_fix, internal_transaction_fix, convert_utm_to_location, change_last_digit_to_six, \ + fix_guild_steward, check_product, kill_house_requests_product_warehousing, \ + kill_house_free_buying_product_warehousing, kill_house_allocations_product_warehousing, \ + kill_house_free_sale_product_warehousing, kill_house_cold_house_allocations_product_warehousing, \ + check_kill_house_request_calculate, check_kill_house_free_bar_information_calculate, \ + check_kill_house_free_sale_bar_information_calculate, check_steward_allocations_calculate, temporary_trash_true, \ + archive_hatching_temporary_true, PoultryRequest_temporary_trash_true, CityOperatorCheckRequest_temporary_trash_true, \ + KillRequest_temporary_trash_true, ProvinceKillRequest_temporary_trash_true, KillHouseRequest_temporary_trash_true, \ + KillHouseAssignmentInformation_temporary_trash_true, KillHouseFreeBarInformation_temporary_trash_true, \ + StewardAllocation_temporary_trash_true, ColdHouseAllocations_temporary_trash_true, \ + StewardFreeBarInformation_temporary_trash_true, StewardFreeSaleBarInformation_temporary_trash_true, \ + InternalTransaction_temporary_trash_true, ExternalTransaction_temporary_trash_true, \ + ChainAllocation_temporary_trash_true, duplicate_order_code, fix_duplicate_order_code, fix_duplicate_order_code_new, \ + add_vet_farm_to_poultry_request, create_city_guild, add_killing_age_to_poultry_request, add_poultry_prediction, \ + fix_out_quantity_hatching, live_chicken_transportation, heards_meat_flow, chat_bot_info, detail_heards_meat_flow, \ + breed, fix_kill_req_njsndb, add_to_warehouse_manual, add_free_bar_to_warehouse_manual, \ + warning_free_bar_to_warehouse_manual, warning_to_warehouse_manual, warning_province_kill_request_without_bar_manual, \ + update_chicken_age_from_login_manual, add_free_bar_to_warehouse_automatic_type_manual, KillHouseStressTestView, \ + fix_warehouse_input_province_bars_for_limitation, fix_warehouse_out_buying_bars_for_limitation, \ + fix_warehouse_in_province_allocations_for_limitation, fix_warehouse_free_sale_for_limitation, \ + fix_warehouse_cold_house_for_limitation, fix_warehouse_segmentation_for_limitation, fix_warehouse_for_limitation, \ + fix_time_error, fix_steward_free_buying_product_warehousing_for_limitation, \ + fix_guild_steward_product_segmentation_warehousing_for_limitation, \ + fix_guild_steward_free_sale_warehousing_for_limitation, \ + fix_steward_guild_steward_allocations_warehousing_for_limitation, \ + fix_steward_guild_pos_allocations_warehousing_for_limitation, fix_steward_warehouse_for_limitation, fix_pos_owner, \ + fix_guild_steward_archive_warehousing, fix_guild_steward_pos_allocation_weight_for_product, \ + fix_kill_house_archive_warehousing +from authentication.sms_management import user_sms, kill_house_vet_check_receive_sms, \ + send_again_sms_for_final_approval_out_province, send_gate_way_sms_manual, send_deactivate_panel_debt_sms_manual, \ + ManagementSendSmsViewSet, test_sms_endpoint +from authentication.views import ( + login, + register, + new_login, + new_register, + new_send_otp, + forget_password, + UserProfileViewSet, + check_otp, + change_password, + AddressViewSet, + BankCardViewSet, + UserProfileSearchViewSet, + CheckChickenQuntityViewSet, + ProvinceViewSet, + CityViewSet, + CityUnitViewSet, + SystemAddressViewSet, + SystemUserProfileViewSet, ShowSystemUserProfileViewSet, ForceDiagramViewSet, CityWithOutProvinceKeyViewSet, + ProvinceChangeBankCardViewSet, TotalSystemUserProfileStatisticsDashboardViewSet, + TotalPricingStatisticsDashboardViewSet, ExternalTransactionViewSet, pos_login, show_transaction_info, + TokenVerification, new_pos_login, CityForProducctPricingViewSet, register_tenant, + SystemUserProfileّForFactorProfileViewSet, CitysViewSet +) + +router = routers.DefaultRouter() +router.register(r'user-profile', UserProfileViewSet, basename='user-profile') +router.register(r'transactions', ExternalTransactionViewSet, basename='transactions') +router.register(r'system_user_profile', SystemUserProfileViewSet, basename='system-user-profile') +router.register(r'system_user_profile-for-factor', SystemUserProfileّForFactorProfileViewSet, basename='system_user_profile-for-factor') +router.register(r'user-profile_search', UserProfileSearchViewSet, basename='user-profile_search') +router.register(r'user-bank_card', BankCardViewSet, basename='user-bank_card') +router.register(r'province_change_bank_card', ProvinceChangeBankCardViewSet, basename='province_change_bank_card') +router.register(r'address', AddressViewSet, basename='address') +router.register(r'province', ProvinceViewSet, basename='province') +router.register(r'city', CityViewSet, basename='city') +router.register(r'city-product-pricing', CityForProducctPricingViewSet, basename='city-product-pricing') +router.register(r'province_cities', CityWithOutProvinceKeyViewSet, basename='province_cities') +router.register(r'cities', CitysViewSet, basename='cities') +router.register(r'city-unit', CityUnitViewSet, basename='city-unit') +router.register(r'system_address', SystemAddressViewSet, basename='system_address') +router.register(r'user_message', UserMessageViewSet, basename="user_message") +router.register(r'show_users', ShowSystemUserProfileViewSet, basename='show_users') +router.register(r'diageram', ForceDiagramViewSet, basename='diageram') +router.register(r'total_system_user_profile_dashboard', TotalSystemUserProfileStatisticsDashboardViewSet, + basename='total_system_user_profile_dashboard') +router.register(r'total_pricing_dashboard', TotalPricingStatisticsDashboardViewSet, + basename='total_pricing_dashboard') +router.register(r'sending_message_method', SendingMessageMethodViewSet, basename="sending_message_method") +router.register(r'send_sms', SendSMSViewSet, basename="send_sms") +router.register(r'quantity', CheckChickenQuntityViewSet, basename="quantity") +router.register(r'management-send-sms', ManagementSendSmsViewSet, basename="management-send-sms") + +oauth2_endpoint_views = [ + path('login/', new_login, name="login"), + path('pos-login/', pos_login, name="pos-login"), + path('new-pos-login/', new_pos_login, name="new-pos-login"), + path('newregister/', new_register, name="new_register"), + path('new_send/', new_send_otp, name='new_send'), + path('send/', new_send_otp, name="send_otp"), + path('check/', check_otp, name="check_otp"), + # path('login/', login, name="login"), + path('register/', register, name="register"), + path('forget/', forget_password, name="forget_password"), + path('change_password/', change_password, name="change_password"), + path('token/', oauth2_views.TokenView.as_view(), name="token"), + +] + +if settings.DEBUG: + # OAuth2 Application Management endpoints + oauth2_endpoint_views += [ + path('applications/', oauth2_views.ApplicationList.as_view(), name="list"), + path('applications/register/', oauth2_views.ApplicationRegistration.as_view(), name="register"), + path('applications//', oauth2_views.ApplicationDetail.as_view(), name="detail"), + path('applications//delete/', oauth2_views.ApplicationDelete.as_view(), name="delete"), + path('applications//update/', oauth2_views.ApplicationUpdate.as_view(), name="update"), + ] + + # OAuth2 Token Management endpoints + oauth2_endpoint_views += [ + path('authorized-tokens/', oauth2_views.AuthorizedTokensListView.as_view(), name="authorized-token-list"), + path('authorized-tokens//delete/', oauth2_views.AuthorizedTokenDeleteView.as_view(), + name="authorized-token-delete"), + ] + +urlpatterns = [ + path('', include(router.urls)), + path('api/', include((oauth2_endpoint_views, 'oauth2_provider.urls'), namespace="oauth2_provider")), + # path('sms/', user_sms_wrapper), + path('sms/', user_sms), + path("health/", health_check), + path('driver_excel/', get_driver_excel), + path('driver_excel_template/', create_driver_excel_template), + path('upload_driver_excel/', upload_driver_excel), + path('hatching_excel/', get_poultry_hatching_excel), + path('check_hatching_excel/', check_poultry_hatching_excel), + path('vet_check_sms/', kill_house_vet_check_receive_sms), + path('reset_hatching_excel/', reset_hatching_excel), + path('enter_driver_hamedan/', enter_driver_hamedan), + path('integration_of_hatching/', integration_of_hatching), + path('check_poultry_in_db/', check_poultry_in_db), + path('show_transaction_info/', show_transaction_info), + path('update_chicken_age_from_login/', update_chicken_age_from_login), + path('violation_archive_true/', violation_archive_true), + path('update_chicken_breed_from_excel/', update_chicken_breed_from_excel), + path('token-verification/', TokenVerification), + path('ye_chee_bani/', ye_chee_bani), + path('get_server_time/', get_server_time), + path('transaction_fix/', transaction_fix), + path('internal_transaction_fix/', internal_transaction_fix), + path('convert_utm_to_location/', convert_utm_to_location), + path('change_last_digit_to_six/', change_last_digit_to_six), + path('send_again_sms_for_final_approval_out_province/', send_again_sms_for_final_approval_out_province), + path('fix_guild_steward/', fix_guild_steward), + path('check_product/', check_product), + path('register_tenant/', register_tenant), + path('kill_house_requests_product_warehousing/', kill_house_requests_product_warehousing), + path('kill_house_free_buying_product_warehousing/', kill_house_free_buying_product_warehousing), + path('kill_house_allocations_product_warehousing/', kill_house_allocations_product_warehousing), + path('kill_house_free_sale_product_warehousing/', kill_house_free_sale_product_warehousing), + path('kill_house_cold_house_allocations_product_warehousing/', + kill_house_cold_house_allocations_product_warehousing), + path('check_kill_house_request_calculate/', check_kill_house_request_calculate), + path('check_kill_house_free_bar_information_calculate/', check_kill_house_free_bar_information_calculate), + path('check_kill_house_free_sale_bar_information_calculate/', check_kill_house_free_sale_bar_information_calculate), + path('check_steward_allocations_calculate/', check_steward_allocations_calculate), + path('temporary_trash_true/', temporary_trash_true), + path('archive_hatching_temporary_true/', archive_hatching_temporary_true), + path('PoultryRequest_temporary_trash_true/', PoultryRequest_temporary_trash_true), + path('CityOperatorCheckRequest_temporary_trash_true/', CityOperatorCheckRequest_temporary_trash_true), + path('KillRequest_temporary_trash_true/', KillRequest_temporary_trash_true), + path('ProvinceKillRequest_temporary_trash_true/', ProvinceKillRequest_temporary_trash_true), + path('KillHouseRequest_temporary_trash_true/', KillHouseRequest_temporary_trash_true), + path('KillHouseAssignmentInformation_temporary_trash_true/', KillHouseAssignmentInformation_temporary_trash_true), + path('KillHouseFreeBarInformation_temporary_trash_true/', KillHouseFreeBarInformation_temporary_trash_true), + path('StewardAllocation_temporary_trash_true/', StewardAllocation_temporary_trash_true), + path('ColdHouseAllocations_temporary_trash_true/', ColdHouseAllocations_temporary_trash_true), + path('StewardFreeBarInformation_temporary_trash_true/', StewardFreeBarInformation_temporary_trash_true), + path('StewardFreeSaleBarInformation_temporary_trash_true/', StewardFreeSaleBarInformation_temporary_trash_true), + path('InternalTransaction_temporary_trash_true/', InternalTransaction_temporary_trash_true), + path('ExternalTransaction_temporary_trash_true/', ExternalTransaction_temporary_trash_true), + path('ChainAllocation_temporary_trash_true/', ChainAllocation_temporary_trash_true), + path('duplicate_order_code/', duplicate_order_code), + path('fix_duplicate_order_code/', fix_duplicate_order_code), + path('fix_duplicate_order_code_new/', fix_duplicate_order_code_new), + path('add_vet_farm_to_poultry_request/', add_vet_farm_to_poultry_request), + path('create_city_guild/', create_city_guild), + path('add_killing_age_to_poultry_request/', add_killing_age_to_poultry_request), + path('add_poultry_prediction/', add_poultry_prediction), + path('fix_out_quantity_hatching/', fix_out_quantity_hatching), + path('live_chicken_transportation/', live_chicken_transportation), + path('heards_meat_flow/', heards_meat_flow), + path('detail_heards_meat_flow/', detail_heards_meat_flow), + path('breed/', breed), + path('chat_bot_info/', chat_bot_info), + path('fix_kill_req_njsndb/', fix_kill_req_njsndb), + path('add_to_warehouse_manual/', add_to_warehouse_manual), + path('add_free_bar_to_warehouse_manual/', add_free_bar_to_warehouse_manual), + path('send_gate_way_sms_manual/', send_gate_way_sms_manual), + path('fix_warehouse_for_limitation/', fix_warehouse_for_limitation), + path('fix_warehouse_input_province_bars_for_limitation/', fix_warehouse_input_province_bars_for_limitation), + path('fix_warehouse_out_buying_bars_for_limitation/', fix_warehouse_out_buying_bars_for_limitation), + path('fix_warehouse_in_province_allocations_for_limitation/', fix_warehouse_in_province_allocations_for_limitation), + path('fix_warehouse_free_sale_for_limitation/', fix_warehouse_free_sale_for_limitation), + path('fix_warehouse_cold_house_for_limitation/', fix_warehouse_cold_house_for_limitation), + path('fix_warehouse_segmentation_for_limitation/', fix_warehouse_segmentation_for_limitation), + path('fix_kill_house_archive_warehousing/', fix_kill_house_archive_warehousing), + path('fix_time_error/', fix_time_error), + path('fix_pos_owner/', fix_pos_owner), + path('send_deactivate_panel_debt_sms_manual/', send_deactivate_panel_debt_sms_manual), + path('test_sms/', test_sms_endpoint), + path('warning_free_bar_to_warehouse_manual/', warning_free_bar_to_warehouse_manual), + path('warning_to_warehouse_manual/', warning_to_warehouse_manual), + path('warning_province_kill_request_without_bar_manual/', warning_province_kill_request_without_bar_manual), + path('update_chicken_age_from_login_manual/', update_chicken_age_from_login_manual), + path('add_free_bar_to_warehouse_automatic_type_manual/', add_free_bar_to_warehouse_automatic_type_manual), + + path('fix_steward_free_buying_product_warehousing_for_limitation/', fix_steward_free_buying_product_warehousing_for_limitation), + path('fix_steward_guild_steward_allocations_warehousing_for_limitation/', fix_steward_guild_steward_allocations_warehousing_for_limitation), + path('fix_guild_steward_free_sale_warehousing_for_limitation/', fix_guild_steward_free_sale_warehousing_for_limitation), + path('fix_guild_steward_product_segmentation_warehousing_for_limitation/', fix_guild_steward_product_segmentation_warehousing_for_limitation), + path('fix_steward_guild_pos_allocations_warehousing_for_limitation/', fix_steward_guild_pos_allocations_warehousing_for_limitation), + path('fix_steward_warehouse_for_limitation/', fix_steward_warehouse_for_limitation), + path('fix_guild_steward_archive_warehousing/', fix_guild_steward_archive_warehousing), + path('fix_guild_steward_pos_allocation_weight_for_product/', fix_guild_steward_pos_allocation_weight_for_product), + + path("killhouse-stress/", KillHouseStressTestView.as_view(), name="killhouse-stress"), + +] diff --git a/authentication/views.py b/authentication/views.py new file mode 100644 index 0000000..dd91517 --- /dev/null +++ b/authentication/views.py @@ -0,0 +1,3163 @@ +import datetime +import threading +from datetime import timedelta +from django.shortcuts import get_object_or_404, redirect + +import jdatetime +from django.http import HttpResponse +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, + OAuth2Authentication, +) +from oauth2_provider.models import AccessToken +from rest_framework.pagination import PageNumberPagination + +from general_urls import CLIENT_ID, CLIENT_SECRET, BASE_URL +from panel.ReportingPanel.filterset import ProfileFilterSet +from panel.admin import PROJECT_API_KEY +from panel.filterset import WagePaymentFilterSet +from panel.models import WareHouseFactor, InspectorOperator, KillHouseVet, Itransaction, Wallet, KillHousePercentage, \ + Jahad, Admin, VetSupervisor, ProvincialGovernment, CityJahad, ProvinceAllowKillHouseChooseStewardGuilds, \ + ProvinceAllowPoultryChooseKillHouse, Pricing, Guilds, POSMachine, PosVersion, PosItem, POSId, UserLoginLog, \ + ProvinceAllowKillHouseDirectBuying +from ticket.helper import send_image_to_server +from .filterset import UserProfileFilterSet, SystemUserProfileFilteSet, ExternalTransactionFilterSet +from .helper.refresh import refresh +from .sahandsms.sms import ( + send_sms, + send_otp_code, + send_password +) +from .serializer.serializer import ( + AddressSerializer, + UserProfileSerializer, + BankCardSerializer, + SystemUserProfileSerializer, SystemUserProfileForAllUsersSerializer, SystemUserProfileBaseInfoSerializer, + ExternalTransactionSerializer, + # SystemUserProfileInfoSerializer +) +from .serializers import SystemAddressSerializer, CityForProductPricingSerializer +from panel.CityOperator.serializers import CityOperatorSerializer, CityOperatorForAllUserSerializer +from panel.ProvinceOperator.serializers import ProvinceOperatorSerializer, InspectorOperatorSerializer, JahadSerializer, \ + AdminSerializer, VetSupervisorSerializer, ProvincialGovernmentSerializer, ProvinceOperatorForAllUserSerializer, \ + InspectorOperatorForAllUserSerializer, JahadForAllUserSerializer, AdminForAllUserSerializer, \ + VetSupervisorForAllUserSerializer, ProvincialGovernmentForAllUserSerializer, CityJahadForAllUserSerializer, \ + PricingSerializer, GeneralGuildsSerializer +from panel.poultry.serializers import ( + PoultrySerializer, + PoultryTenantSerializer, PoultryForAllUserSerializer +) +from panel.KillHouse.serializers import ( + KillHouseOperatorSerializer, + VetSerializer, KillHouseSerializer, KillHouseVetSerializer, KillHouseDriverSerializer, + KillHouseOperatorForAllUserSerializer, VetForAllUserSerializer, KillHouseDriverForAllUserSerializer, + KillHouseVetForAllUserSerializer, KillHouseForAllUserSerializer +) +from rest_framework.permissions import ( + AllowAny, + IsAuthenticated, + DjangoModelPermissions +) +from rest_framework.authentication import TokenAuthentication +from rest_framework.decorators import permission_classes, api_view +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework.decorators import authentication_classes +from rest_framework.authentication import get_authorization_header +from django.core.cache.backends.base import DEFAULT_TIMEOUT +from authentication.models import CityUnit, ExternalTransaction +from django.contrib.auth.hashers import make_password +from django.contrib.auth.views import LoginView +from panel.helper import ( + create_except_profile, + update_except_profile, + remove_null_fields, operator_update_except_profile +) +from authentication.models import ( + UserProfile, + Address, + BankCard, + SystemUserProfile, + SystemAddress, + City, + Province +) +from panel.models import ( + Poultry, + ProvinceOperator, + CityOperator, + KillHouseOperator, + Vet, + KillHouseDriver, + KillHouseADDCAR, + PoultryTenant, + KillHouse, + +) +from rest_framework.response import Response +from django.contrib.auth.models import User, Group +from django.core.cache import cache +from django.conf import settings +from rest_framework import status +from oauth2_provider.models import AccessToken +from .helper.image_services import ( + upload_image, + upload_listed_image +) +from django.http.response import JsonResponse, HttpResponseRedirect +import requests +import json +import random +import uuid +from django.contrib.auth.views import LoginView +from django.contrib.auth.hashers import make_password +import cryptocode +import string +import random +import os +from django_filters.rest_framework import DjangoFilterBackend +from django.http import QueryDict +import xlsxwriter +from io import StringIO, BytesIO + +# آدرس پایه برای ارسال در خواست ثبت نام به سیستم پایه شرکت آرتا +from .serializers import SystemAddressSerializer, CityUnitSerializer, CitySerializer, ProvinceSerializer + +ARTA_URL_REGISTER = "https://userbackend.rasadyar.com/api/register/" +# آدرس پایه برای ارسال در خواست ورود به سیستم پایه شرکت آرتا +ARTA_URL_LOGIN = "https://userbackend.rasadyar.com/api/login/" +# آدرس پایه برای سیستم ورود و ثبت نام بر اساس توکن +ARTA_URL_CHANGE_MOBILE_NUMBER = "https://userbackend.rasadyar.com/change_mobile_number/" +CACHE_TTL = getattr(settings, "CACHE_TTL", DEFAULT_TIMEOUT) +# آدرس پایه برای ذخیره تصویر کاربر در استوریج آروان +ARVAN_User_Image_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +# ARVAN_User_Image_URL = 'http://user-image-gallery.s3.ir-thr-at1.arvanstorage.ir/' + +ARTA_URL_SEND_OTP = "https://userbackend.rasadyar.com/api/send_otp/" +ARTA_URL_CHECK_OTP = "https://userbackend.rasadyar.com/api/check_otp/" +ARTA_URL_CHANGE_PASSWORD = "https://userbackend.rasadyar.com/api/change_password/" + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +class ExternalTransactionViewSet(viewsets.ModelViewSet): + queryset = ExternalTransaction.objects.all() + serializer_class = ExternalTransactionSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = ExternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions_list = [] + if request.GET['role'] == 'KillHouse': + + if request.GET['state'] == 'failed': + if 'type' in request.GET: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='failed', + transaction_type='wallet', + + trash=False).order_by('id') + else: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='failed', + transaction_type='wage-gateway', + + trash=False).order_by('id') + else: + if 'type' in request.GET: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='completed', + transaction_type='wallet', + trash=False).order_by('id') + else: + + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='completed', + transaction_type='wage-gateway', + trash=False).order_by('id') + else: + + if request.GET['state'] == 'failed': + if 'type' in request.GET: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='failed', + transaction_type='wallet', + trash=False).order_by('id') + else: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='failed', + transaction_type='wage-gateway', + trash=False).order_by('id') + else: + if 'type' in request.GET: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + transaction_type='wallet', + trash=False).order_by('id') + else: + + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + transaction_type='wage-gateway', + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = ExternalTransactionSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = ExternalTransactionSerializer(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به استان +class ProvinceViewSet(viewsets.ModelViewSet): + queryset = Province.objects.all() + serializer_class = ProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + province = Province.objects.filter(key=user.province.key) + serializer = CitySerializer(province, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به شهرستان +class CityViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + refresh(request.user.id) + city = City.objects.filter( + province=Province.objects.get(key=request.GET['province_key']) + # province=Province.objects.get(key='1e364f53-f873-4af9-9e93-7e4816e889ae') + ) + serializer = CitySerializer(city, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityForProducctPricingViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CityForProductPricingSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + city = City.objects.filter(trash=False, province=user.province).order_by('id') + serializer = self.serializer_class(city, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + city = City.objects.get(trash=False, key=request.data['city_key']) + request.data.pop('city_key') + serializer = self.serializer_class(city) + serializer.update(instance=city, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityWithOutProvinceKeyViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + city = City.objects.filter( + province=Province.objects.get(key=user.province.key) + ) + serializer = CitySerializer(city, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CitysViewSet(viewsets.ModelViewSet): + queryset = City.objects.all() + serializer_class = CitySerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + city = City.objects.filter( + province=Province.objects.get(key=user.province.key) + ).exclude(name='فاقد شهرستان') + serializer = CitySerializer(city, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به زیربخش شهرستان +class CityUnitViewSet(viewsets.ModelViewSet): + queryset = CityUnit.objects.all() + serializer_class = CityUnitSerializer + permission_classes = [TokenHasReadWriteScope] + + +# ویوست مربوط به آدرس +class SystemAddressViewSet(viewsets.ModelViewSet): + queryset = SystemAddress.objects.all() + serializer_class = SystemAddressSerializer + permission_classes = [TokenHasReadWriteScope] + + +# ویوست مربوط به جستجو اطلاعات کاربر یا کاربران +class UserProfileSearchViewSet(viewsets.ModelViewSet): + queryset = UserProfile.objects.all() + serializer_class = UserProfileSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = UserProfileFilterSet + filterset_fields = [ + 'fullname', + 'mobile', + 'first_name', + 'last_name', + 'breeding_unique_id', + 'address__city', + 'address__province', + 'role__name', + ] + + def list(self, request, *args, **kwargs): + if 'type' in request.GET: + if request.GET['type'] == 'filter': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=self.queryset + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=self.queryset) + filtered_user = ps.filter() + serializer = self.serializer_class(filtered_user, many=True) + return Response(serializer.data) + return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN) + else: + queryset = self.queryset.all() + serializer = UserProfileSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به پروفایل کاربری که شامل ساخت و ویرایش و حذف +class UserProfileViewSet(viewsets.ModelViewSet): + queryset = UserProfile.objects.all() + serializer_class = UserProfileSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ثبت پروفایل کاربر + def create(self, request, *args, **kwargs): + role = Group.objects.get(name__exact=request.data['role']) + request.data.pop('role') + city = request.data['city'] + province = request.data['province'] + address = request.data['address'] + try: + image = request.data['image'] + request.data.pop('image') + except: + image = "" + + request.data.pop('city') + request.data.pop('province') + request.data.pop('address') + mobile = request.data['mobile'] + if UserProfile.objects.filter(mobile=mobile): + return Response('user already exist') + index = UserProfile.objects.all().last().base_order + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + user_profile = serializer.create(validated_data=request.data) + user_profile.image = send_image_to_server(image) + password = str(random.randint(10000, 99000)) + + user = User( + first_name=user_profile.fullname, + username=user_profile.mobile, + password=cryptocode.encrypt(password, password) + ) + user.save() + user_address = Address( + city=city, + province=province, + address=address, + ) + user_address.save() + user_profile.user = user + user_profile.role = role + user_profile.address = user_address + user_profile.base_order = index + 1 + user_profile.fullname = user_profile.first_name + " " + user_profile.last_name + user_profile.save() + send_password(user_profile.mobile, password) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش اطلاعات پروفایل کاربر + def list(self, request, *args, **kwargs): + if 'type' in request.GET: + if request.GET['type'] == 'operator': + queryset = self.queryset.filter(role__name__exact="Poultry") + serializer = UserProfileSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if request.GET['type'] == 'user': + queryset = UserProfile.objects.all().filter(user__exact=request.user) + serializer = UserProfileSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response({'Msg': 'Enter type parameter in url'}) + + # تابع مربوط به ویرایش اطلاعات پروفایل کاربر + def update(self, request, pk=None, *args, **kwargs): + try: + if request.data['image'] == "": + user_image = None + + else: + user_image = request.data['image'] + request.data.pop('image') + + except: + user_image = None + + try: + role = request.data['role'] + request.data.pop('role') + + except: + role = None + + try: + city = request.data['city'] + request.data.pop('city') + + except: + city = None + + try: + province = request.data['province'] + request.data.pop('province') + + except: + province = None + + try: + address = request.data['address'] + request.data.pop('address') + + except: + address = None + + queryset = UserProfile.objects.get(key=request.data["key"]) + user_address = Address.objects.get(id=queryset.address.id) + request.data.pop('key') + if user_image: + queryset.image = send_image_to_server(user_image) + if role: + queryset.role = Group.objects.get(name__exact=role) + if city: + user_address.city = city + if province: + user_address.province = province + if address: + user_address.address = address + user_address.save() + queryset.save() + serializer = self.serializer_class(queryset) + serializer.update(instance=queryset, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به حذف اطلاعات پروفایل کاربر + def destroy(self, request, pk=None, *args, **kwargs): + user_profile = UserProfile.objects.get(key__exact=request.GET["key"]) + user = User.objects.get(id=user_profile.user.id) + address = Address.objects.get(id=user_profile.address.id) + user_profile.delete() + user.delete() + address.delete() + return Response('user deleted', status=status.HTTP_200_OK) + + +class ForceDiagramViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + + if 'role' in request.GET: + role = request.GET['role'].split(',') + new_persons = [] + + persons = SystemUserProfile.objects.filter(role__name__in=role, province=user.province).order_by('id') + if persons.count() > 0: + for person in persons: + if person in new_persons: + pass + else: + new_persons.append(person) + serializer = SystemUserProfileSerializer(new_persons, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + if 'all' in request.GET: + poultry = Poultry.objects.filter(user__province=user.province) + city_operator = CityOperator.objects.filter(user__province=user.province) + province_operator = ProvinceOperator.objects.filter(user__province=user.province, + user__role__name='ProvinceOperator') + financial_operator = Poultry.objects.filter(user__province=user.province, + user__role__name='ProvinceFinancial') + inspector_operator = InspectorOperator.objects.filter(user__province=user.province) + killhouse_operator = KillHouseOperator.objects.filter(user__province=user.province) + driver = KillHouseDriver.objects.filter(user__province=user.province) + vet = Vet.objects.filter(user__province=user.province) + killhouse_vet = KillHouseVet.objects.filter(vet__user__province=user.province) + diageram_dict = { + "poultry": poultry.count(), + "city_operator": city_operator.count(), + "province_operator": province_operator.count(), + "financial_operator": financial_operator.count(), + "inspector_operator": inspector_operator.count(), + "killhouse_operator": killhouse_operator.count(), + "driver": driver.count(), + "vet": vet.count(), + "killhouse_vet": killhouse_vet.count(), + } + + return Response(diageram_dict, status=status.HTTP_200_OK) + elif 'Poultry' in request.GET: + poultry = Poultry.objects.filter(address__province=user.province) + serializer = PoultrySerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif 'CityOperator' in request.GET: + cityoperator = CityOperator.objects.filter(address__province=user.province) + serializer = CityOperatorSerializer(cityoperator, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif 'ProvinceOperator' in request.GET: + operator = SystemUserProfile.objects.filter(role__name='ProvinceOperator', + province=user.province) + provinceoperator = ProvinceOperator.objects.filter(user=operator.last()) + serializer = ProvinceOperatorSerializer(provinceoperator, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'ProvinceFinancial' in request.GET: + operator = SystemUserProfile.objects.filter(role__name='ProvinceFinancial', + province=user.province) + provincefinancial = ProvinceOperator.objects.filter(user=operator.last()) + + serializer = ProvinceOperatorSerializer(provincefinancial, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif 'ProvinceInspector' in request.GET: + provinceinspector = InspectorOperator.objects.filter(address__province=user.province) + serializer = InspectorOperatorSerializer(provinceinspector, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif 'KillHouse' in request.GET: + killhouse = KillHouse.objects.filter(system_address__province=user.province) + serializer = KillHouseSerializer(killhouse, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif 'KillHouseVet' in request.GET: + killhousevet = KillHouseVet.objects.filter(kill_house__system_address__province=user.province) + serializer = KillHouseVetSerializer(killhousevet, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # elif 'VetFarm' in request.GET: + # + # vetfarm = SystemUserProfile.objects.filter(role__name='VetFarm', + # province=user.province) + # serializer = self.serializer_class(vetfarm, many=True) + # return Response(serializer.data, status=status.HTTP_200_OK) + elif 'Driver' in request.GET: + + driver = KillHouseDriver.objects.filter(address_province=user.province) + serializer = KillHouseDriverSerializer(driver, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalSystemUserProfileStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + users = SystemUserProfile.objects.filter().only('user_id') + guilds = Guilds.objects.filter(trash=False) + poultrys = Poultry.objects.filter(trash=False).only('user_id') + price = Pricing.objects.filter(trash=False).last() + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + poultries = poultrys.filter(city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + poultries = poultrys.filter(address__city=user.city) + else: + poultries = poultrys + else: + poultries = poultrys + return Response({ + "users": users.count(), + "poultries": poultries.count(), + "guilds": guilds.count(), + }) + + +class TotalPricingStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = Pricing.objects.all() + serializer_class = PricingSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + price = Pricing.objects.filter(trash=False).last() + + return Response( + {"last_price": price.live_chicken_price, "last_change": str(price.modify_date.date())} + ) + + +class ShowSystemUserProfileViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به نمایش اطلاعات پروفایل کاربر + def list(self, request, *args, **kwargs): + refresh(request.user.id) + if 'role' in request.GET: + queryset = self.queryset.filter(role__name__exact=request.GET['role']) + if queryset.count() > 0: + serializer = UserProfileSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + return Response([], status=status.HTTP_200_OK) + else: + users_info = [] + for user in SystemUserProfile.objects.all().exclude(role__isnull=True): + city = user.city.name if user.city != None else None + province = user.province.name if user.province != None else None + for role in user.role.all(): + if role.name == 'KillHouse': + oprator = KillHouseOperator.objects.get(user=user) + kill_house_wallet = oprator.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=kill_house_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "national_id": user.national_id, + "wallet_key": oprator.wallet.key, + "inventory": oprator.wallet.inventory, + "city": city, + "province": province, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + + elif role.name == 'Poultry': + poultry_wallet = Poultry.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=poultry_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": poultry_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + elif role.name == 'CityOperator': + + city_wallet = CityOperator.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=city_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": city_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "depositable": (creditor + deposit) - (debtor + penalty) + } + users_info.append(internal_dict) + elif role.name == 'ProvinceOperator': + province_wallet = ProvinceOperator.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=province_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": province_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + elif role.name == 'ProvinceInspector': + inspector_wallet = InspectorOperator.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=inspector_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": inspector_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + elif role.name == 'ProvinceFinancial': + financial_wallet = ProvinceOperator.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=financial_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": financial_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + elif role.name == 'Driver': + + driver_wallet = KillHouseDriver.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=driver_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": driver_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + elif role.name == 'KillHouseVet': + kill_house_vet_wallet = Vet.objects.get(user=user).wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=kill_house_vet_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": user.base_order, + "fullname": user.fullname, + "id": user.id, + "role": role.name, + "mobile": user.mobile, + "wallet_key": kill_house_vet_wallet.key, + "national_id": user.national_id, + "province": province, + "city": city, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + users_info.append(internal_dict) + return Response(users_info, status=status.HTTP_200_OK) + + +# class StandardResultsSetPagination(PageNumberPagination): +# page_size = 2 +# page_size_query_param = 'page_size' +# max_page_size = 1000 + + +object_classes_total = { + 'Poultry': Poultry, + 'CityOperator': CityOperator, + 'ProvinceOperator': ProvinceOperator, + 'KillHouse': KillHouse, + 'ProvinceInspector': InspectorOperator, + 'ProvinceFinancial': ProvinceOperator, + 'Vet': Vet, + 'Jahad': Jahad, + 'CityJahad': CityJahad, + 'Driver': KillHouseDriver, + 'Admin': Admin, + 'VetFarm': Vet, + 'KillHouseVet': KillHouseVet, + 'VetSupervisor': VetSupervisor, + 'ProvincialGovernment': ProvincialGovernment, +} +serializer_object_classes_total = { + + 'Poultry': PoultryForAllUserSerializer, + 'CityOperator': CityOperatorForAllUserSerializer, + 'ProvinceOperator': ProvinceOperatorForAllUserSerializer, + 'KillHouse': KillHouseForAllUserSerializer, + # 'KillHouse': KillHouseOperatorForAllUserSerializer, + 'ProvinceInspector': InspectorOperatorForAllUserSerializer, + 'ProvinceFinancial': ProvinceOperatorForAllUserSerializer, + 'Vet': VetForAllUserSerializer, + 'Jahad': JahadForAllUserSerializer, + 'CityJahad': CityJahadForAllUserSerializer, + 'Driver': KillHouseDriverForAllUserSerializer, + 'Admin': AdminForAllUserSerializer, + 'VetFarm': VetForAllUserSerializer, + 'KillHouseVet': KillHouseVetForAllUserSerializer, + 'VetSupervisor': VetSupervisorForAllUserSerializer, + 'ProvincialGovernment': ProvincialGovernmentForAllUserSerializer, +} + + +def get_data_list(user): + data_list = [] + for item in user.role.all(): + object_class = object_classes_total.get(item.name) + serializer = serializer_object_classes_total.get(item.name) + if object_class and serializer: + if item.name == 'KillHouseVet': + query = object_class.objects.filter(vet__user=user) + elif item.name == 'KillHouse': + query = object_class.objects.filter(kill_house_operator__user=user) + else: + query = object_class.objects.filter(user=user) + if query.exists(): + for queries in query: + data_list.append({ + "role_name": item.name, + "details": serializer(queries).data + }) + return data_list + + +class SystemUserProfileViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ProfileFilterSet + filterset_fields = [ + 'base_order', + 'mobile', + 'fullname', + 'first_name', + 'last_name', + 'city__name', + + ] + + object_classes = { + 'Poultry': Poultry, + 'CityOperator': CityOperator, + 'ProvinceOperator': ProvinceOperator, + 'KillHouse': KillHouseOperator, + 'ProvinceInspector': InspectorOperator, + 'ProvinceFinancial': ProvinceOperator, + 'Vet': Vet, + 'Jahad': ProvinceOperator, + 'Driver': KillHouseDriver, + 'PoultryTenant': PoultryTenant, + 'VetFarm': Vet, + 'Guilds': Guilds, + 'Steward': Guilds, + 'KillHouseVet': KillHouseVet + } + serializer_object_classes = { + 'Poultry': PoultrySerializer, + 'CityOperator': CityOperatorSerializer, + 'ProvinceOperator': ProvinceOperatorSerializer, + 'Guilds': GeneralGuildsSerializer, + 'Steward': GeneralGuildsSerializer, + 'KillHouse': KillHouseOperatorSerializer, + 'ProvinceInspector': InspectorOperatorSerializer, + 'ProvinceFinancial': ProvinceOperatorSerializer, + 'Vet': VetSerializer, + 'Jahad': ProvinceOperatorSerializer, + 'Driver': KillHouseDriverSerializer, + # 'PoultryTenant': PoultryTenant, + 'VetFarm': VetSerializer, + 'KillHouseVet': KillHouseVetSerializer + } + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + if 'self-profile' in request.GET: + userprofile = SystemUserProfile.objects.get(user=request.user) + serializer = self.serializer_class(userprofile) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'city_users' in request.GET: + out_list = [] # contains out put list + users = [] + + city_operator = CityOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user)) + city = city_operator.address.city + city_unit_list = [] + city_units = CityUnit.objects.filter(city=city) + for city in city_units: + city_unit_list.append(city.name) + + for u in SystemUserProfile.objects.filter(role__name='Poultry', city__name__in=city_unit_list): + users.append(u) + for user_without_role in SystemUserProfile.objects.filter(city__name__in=city_unit_list): + if len(user_without_role.role.all()) == 0: + users.append(user_without_role) + for user in users: + out_list.append({'profile': self.serializer_class(user).data}) + return Response(out_list, status=status.HTTP_200_OK) + elif 'users_info' in request.GET: + # inspector = InspectorOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user)) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + userprofile_list = [] + province = user.province + out_put = [] # contains out put list + role = request.GET['roles'].split(',') if request.GET['roles'] != "" else None + if role != None: + userprofile = SystemUserProfile.objects.filter(role__name__in=role, province=province, trash=False) + else: + userprofile = SystemUserProfile.objects.filter(province=province, trash=False).exclude( + role__name='SuperAdmin') # contains userprofile object + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=userprofile + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=userprofile) + userprofile_list = ps.filter() + userprofile = [] if len(userprofile_list) == 0 else userprofile_list + # if request.GET['search'] == 'filter': + # if request.GET['value'] != "": + # for item in self.filterset_fields: + # query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + # if (self.filterset_class( + # data=query, + # queryset=userprofile + # ) + # ).filter(): + # ps = self.filterset_class(data=query, queryset=userprofile) + # userprofile_list = ps.filter() + # userprofile = [] if len(userprofile_list) == 0 else userprofile_list + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(userprofile) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(userprofile, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + # for user in userprofile: + # out_put.append({'profile': self.serializer_class(user).data}) + # return Response(out_put, status=status.HTTP_200_OK) + + elif 'users_base_info' in request.GET: + users = SystemUserProfile.objects.filter(province=user.province, trash=False) + serializer_base_info = SystemUserProfileBaseInfoSerializer(users, many=True) + return Response(serializer_base_info.data, status=status.HTTP_200_OK) + + elif 'all_users' in request.GET: + user = self.queryset.get(key=request.GET['userprofile_key']) + data_list = get_data_list(user) + return Response(data_list, status=status.HTTP_200_OK) + # return super().list(request, *args, **kwargs) + + # if 'page' in request.GET: + # end = int(request.GET['page']) * 3 + # start = end - 3 + + def retrieve(self, request, *args, **kwargs): + refresh(request.user.id) + user = self.queryset.get(key=request.GET['userprofile_key']) # contains user profile object + + data_list = [] # contains list of roles data + role_list = [] # contains list of roles names + + # iterate in user roles + if user.role is not None: + for item in user.role.all(): + if item.name == 'Admin': + continue + object_class = self.object_classes[item.name] # contains related class object to role + if item.name == 'KillHouseVet': + if object_class.objects.filter(vet__user=user).exists(): + query = object_class.objects.filter(vet__user=user) # contains query objects + for queries in query: + serializer = self.serializer_object_classes[ + item.name] # contains related serializer to role + data_list.append({item.name: serializer(queries).data}) + role_list.append(item.name) + + else: + if object_class.objects.filter(user=user).exists(): + query = object_class.objects.filter(user=user) # contains query objects + for queries in query: + serializer = self.serializer_object_classes[ + item.name] # contains related serializer to role + data_list.append({item.name: serializer(queries).data}) + role_list.append(item.name) + + serializer = self.serializer_class(user) + + return Response({ + 'profile': serializer.data, + 'roles_data': data_list, + 'roles_list': role_list + }, + status=status.HTTP_200_OK + ) + + # if user does not exists + else: + return Response(status=status.HTTP_409_CONFLICT) + + def create(self, request, *args, **kwargs): + refresh(request.user.id) + if 'userprofile_key' in request.data.keys(): + person = SystemUserProfile.objects.get(key=request.data['userprofile_key']) + else: + person = None + + edit_type = request.data['type'] + request.data.pop('type') + + if edit_type == 'check_user': + # if user exists in system + if self.queryset.filter( + mobile=request.data['value'] + ).exists() or self.queryset.filter( + national_id=request.data['value'] + ).exists() or self.queryset.filter( + base_order=request.data['value'] + ).exists(): + + if self.queryset.filter( + mobile=request.data['value'] + ).exists(): + # contains user object + user = self.queryset.get( + mobile=request.data['value'], + ) + + if self.queryset.filter( + national_id=request.data['value'] + ).exists(): + # contains user object + user = self.queryset.get( + national_id=request.data['value'], + ) + if self.queryset.filter( + base_order=request.data['value'] + ).exists(): + # contains user object + user = self.queryset.get( + base_order=request.data['value'], + ) + + data_list = [] # contains list of roles data + role_list = [] # contains list of roles names + + # iterate in user roles + if user.role is not None: + for item in user.role.all(): + if item.name == 'Admin': + continue + object_class = self.object_classes[item.name] # contains related class object to role + if item.name == 'KillHouseVet': + if object_class.objects.filter(vet__user=user).exists(): + query = object_class.objects.filter(vet__user=user) # contains query objects + for queries in query: + serializer = self.serializer_object_classes[ + item.name] # contains related serializer to role + data_list.append({item.name: serializer(queries).data}) + role_list.append(item.name) + else: + if object_class.objects.filter(user=user).exists(): + query = object_class.objects.filter(user=user) # contains query objects + for queries in query: + serializer = self.serializer_object_classes[ + item.name] # contains related serializer to role + data_list.append({item.name: serializer(queries).data}) + role_list.append(item.name) + + serializer = self.serializer_class(user) + + return Response({ + 'profile': serializer.data, + 'roles_data': data_list, + 'roles_list': role_list + }, + status=status.HTTP_200_OK + ) + + # if user does not exists + else: + url = 'https://userbackend.rasadyar.com/user_identity/' + # url = 'https://artasystemback.sstit.ir/user_identity/' + headers = { + "Authorization": str(request.headers['Authorization']), + "Content-Type": "application/json" + } + request.data['type'] = edit_type + + req = requests.post( + url=url, + data=json.dumps(request.data), + headers=headers, + verify=False + ) + if req.status_code == 200: + return Response(req.json(), status=status.HTTP_200_OK) + else: + return Response(status=status.HTTP_409_CONFLICT) + if edit_type == 'profile': + + # create user object + if not User.objects.filter(username=request.data['mobile']).exists(): + user = User(username=request.data['mobile']) + else: + return Response({"result": "کاربر قبلا ثیت شده است !"}, status=status.HTTP_403_FORBIDDEN) + + # register user to base system + data = { + "username": request.data['mobile'], + "password": request.data['password'], + "first_name": request.data['first_name'], + "last_name": request.data['last_name'], + "national_code": request.data['national_code'], + "api_key": PROJECT_API_KEY, + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + if req.status_code == 200: + # set password for user by admin + if request.data['password'] != "": + password = request.data['password'] + user.password = cryptocode.encrypt(password, password) + user.save() + + # get city object + city = City.objects.get( + key=request.data['city'] + ) + request.data.pop('city') + + # get province object + province = Province.objects.get( + key=request.data['province'] + ) + request.data.pop('province') + + # upload user image + req = upload_image(req=request, field='image') + + # send request data to serializer + serializer = self.serializer_class(data=req.data) + base_order = SystemUserProfile.objects.all() + if base_order.count(): + base_order = base_order.last().base_order + 1 + else: + base_order = 1000 + if serializer.is_valid(): + userprofile_object = serializer.create(validated_data=req.data) + userprofile_object.city = city + userprofile_object.province = province + userprofile_object.user = user + userprofile_object.password = password + userprofile_object.base_order = base_order + userprofile_object.save() + serializer = self.serializer_class(userprofile_object) + return Response(serializer.data, status=status.HTTP_201_CREATED) + else: + return Response({"result": "کاربر قبلا ثیت شده است !"}, status=status.HTTP_400_BAD_REQUEST) + if edit_type == "Poultry": + # poultry owner object + user = self.queryset.get(key=request.data['owner_key']) + + for poultry_items in request.data['poultry_list']: + # if poultry exists show response + if Poultry.objects.filter(breeding_unique_id=poultry_items['breeding_unique_id']).exists(): + return Response({"result": "مرغداری قبلا ثبت شده است !"}, status=status.HTTP_403_FORBIDDEN) + + if poultry_items['address'] != "" or poultry_items['address'] is not None: + # Create Address Object + city = City.objects.get(key=poultry_items['address']['city_key']) # contain city object + poultry_items['address'].pop('city_key') + + # contains province object + province = Province.objects.get(key=poultry_items['address']['province_key']) + poultry_items['address'].pop('province_key') + + # object created + address = SystemAddress.objects.create(**poultry_items['address']) + address.city = city + address.province = province + address.save() + poultry_items.pop('address') # remove address key from data + else: + address = None + + if poultry_items['user_bank_info'] != "" or poultry_items['user_bank_info'] is not None: + # Create Bank Card Object + bank_info = BankCard.objects.create(**poultry_items['user_bank_info']) + poultry_items.pop('user_bank_info') + else: + bank_info = None + + wallet = Wallet() + wallet.save() + + # tenant user key + if 'tenant_key' in poultry_items.keys(): + tenant_key = poultry_items['tenant_key'] + poultry_items.pop('tenant_key') + else: + tenant_key = "" + + # send data to serializer to create poultry + serializer = PoultrySerializer(data=poultry_items) + if serializer.is_valid(): + poultry_object = serializer.create(validated_data=poultry_items) + poultry_object.user = user + poultry_object.incubation_date = datetime.datetime.now() + poultry_object.address = address + poultry_object.user_bank_info = bank_info + poultry_object.wallet = wallet + poultry_object.save() + create_province_allow_poultry_choose_kill_house = ProvinceAllowPoultryChooseKillHouse( + poultry=poultry_object) + create_province_allow_poultry_choose_kill_house.save() + owner_poultry = Poultry.objects.get(key=poultry_object.key) # contains poultry owner object + else: + return Response({"result": "وارد کردن تمامی مقادیر الزامیست! "}, status=status.HTTP_403_FORBIDDEN) + + if tenant_key != "": + # get tenant user object + tenant_user = self.queryset.get(key=tenant_key) + + owner_poultry.has_tenant = True + owner_poultry.save() + + # Copy Poultry Object and Create New One + poultry_object.pk = None + poultry_object.key = uuid.uuid4() + poultry_object.user = tenant_user + poultry_object.save() # save copied object + poultry_object.owner = owner_poultry + poultry_object.wallet = wallet + poultry_object.save() + + user.role.add(Group.objects.get(name='Poultry')) + return Response(status=status.HTTP_201_CREATED) + if edit_type == "CityOperator": + # if person != None: + # city_unit = CityUnit.objects.get(name=person.city.name) + # if CityOperator.objects.filter(address__city__name=city_unit.city.name).exists(): + # return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE) + + serializer = create_except_profile( + request=request, + queryset=CityOperator, + serializer=CityOperatorSerializer, + role=edit_type + ) + return Response(serializer[0], status=serializer[1]) + if edit_type == "ProvinceOperator": + if person != None: + province_operator = SystemUserProfile.objects.filter(role__name='ProvinceOperator', + province=person.province) + if province_operator.count() > 0: + if ProvinceOperator.objects.filter(user=province_operator.last()).exists(): + return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE) + if SystemUserProfile.objects.filter(role__name='ProvinceFinancial', province=person.province, + key=person.key).exists(): + group = Group.objects.get(name=edit_type) + person.role.add(group) + return Response(status=status.HTTP_201_CREATED) + else: + + serializer = create_except_profile( + request=request, + queryset=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + role=edit_type + ) + return Response(serializer[0], status=serializer[1]) + if edit_type == "ProvinceFinancial": + if person != None: + province_operator = SystemUserProfile.objects.filter(role__name='ProvinceFinancial', + province=person.province) + if province_operator.count() > 0: + if ProvinceOperator.objects.filter(user=province_operator.last()).exists(): + return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE) + if SystemUserProfile.objects.filter(role__name='ProvinceOperator', province=person.province, + key=person.key).exists(): + group = Group.objects.get(name=edit_type) + person.role.add(group) + return Response(status=status.HTTP_201_CREATED) + + else: + serializer = create_except_profile( + request=request, + queryset=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + role=edit_type + ) + return Response(serializer[0], status=serializer[1]) + if edit_type == "KillHouse": + + # contains kill house data + kill_house_data = request.data['killhouse_data'] + request.data.pop('killhouse_data') + if 'address' in request.data.keys(): + if request.data['address'] == "": + request.data.pop('address') + if 'postal_code' in request.data.keys(): + if request.data['postal_code'] == "": + request.data.pop('postal_code') + + serializer = create_except_profile( + request=request, + queryset=KillHouseOperator, + serializer=KillHouseOperatorSerializer, + role=edit_type + ) + + for items in kill_house_data: + if items['address'] != "" or items['address'] is not None: + # Create Address Object + city = City.objects.get(key=items['address']['city_key']) # contain city object + items['address'].pop('city_key') + + # contains province object + province = Province.objects.get(key=items['address']['province_key']) + items['address'].pop('province_key') + if items['address']['postal_code'] == "": + items['address'].pop('postal_code') + + # object created + address = SystemAddress.objects.create(**items['address']) + address.city = city + address.province = province + address.save() + items.pop('address') # remove address key from data + else: + address = None + if 'user_bank_info' in items.keys(): + items.pop('user_bank_info') + + # send data to serializer to create poultry + if 'capacity' in items.keys(): + if items['capacity'] == "": + items.pop('capacity') + if 'name' in items.keys(): + if items['name'] == "": + items.pop('name') + if 'phone' in items.keys(): + if items['phone'] == "": + items.pop('phone') + + kill_house_serializer = KillHouseSerializer(data=items) + if kill_house_serializer.is_valid(): + kill_house_object = kill_house_serializer.create(validated_data=items) + kill_house_object.system_address = address + kill_house_object.kill_house_operator = serializer[2] + kill_house_object.save() + create_choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds( + kill_house=kill_house_object) + create_choose_steward_guilds.save() + percentage = KillHousePercentage(kill_house=kill_house_object) + percentage.save() + province_allow_kill_house_choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds( + kill_house=kill_house_object) + province_allow_kill_house_choose_steward_guilds.save() + province_allow_direct_buying = ProvinceAllowKillHouseDirectBuying(kill_house=kill_house_object) + province_allow_direct_buying.save() + + return Response(status=status.HTTP_201_CREATED) + if edit_type == "KillHouseVet": + # get kill house object + kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key']) + request.data.pop('kill_house_key') + if 'address' in request.data.keys(): + if request.data['address'] == "": + request.data.pop('address') + if 'postal_code' in request.data.keys(): + if request.data['postal_code'] == "": + request.data.pop('postal_code') + # Create Kill House Vet Object + + kill_house_vet = KillHouseVet() + vet = Vet.objects.filter(user=person) + if vet.count() > 0: + vet = vet.last() + kill_house_vet.vet = vet + + + else: + serializer = create_except_profile( + request=request, + queryset=Vet, + serializer=VetSerializer, + role=edit_type + ) + kill_house_vet.vet = serializer[2] + + kill_house_vet.kill_house = kill_house_object + kill_house_vet.save() + + # send object to serializer + serializer = KillHouseVetSerializer(kill_house_vet) + return Response(serializer.data, status=status.HTTP_201_CREATED) + if edit_type == "Driver": + # get user profile object + userprofile = self.queryset.get(key=request.data['userprofile_key']) + request.data.pop('userprofile_key') + + # Create driver Bank Account Information + bank_info_object = BankCard.objects.create(**request.data['user_bank_info']) + request.data.pop('user_bank_info') + + # send data to serializer for create object + serializer = KillHouseDriverSerializer(data=request.data) + if serializer.is_valid(): + driver_object = serializer.create(validated_data=request.data) + driver_wallet = Wallet() + driver_wallet.save() + driver_object.user = userprofile + driver_object.user_bank_info = bank_info_object + driver_object.wallet = driver_wallet + driver_object.save() + userprofile.role.add( + Group.objects.get(name='Driver') + ) + serializer = KillHouseDriverSerializer(driver_object) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + if edit_type == "VetFarm": + if Vet.objects.filter(user=person).exists(): + group = Group.objects.get(name=edit_type) + person.role.add(group) + return Response(status=status.HTTP_201_CREATED) + else: + serializer = create_except_profile( + request=request, + queryset=Vet, + serializer=VetSerializer, + role=edit_type + ) + return Response(serializer[0], status=serializer[1]) + if edit_type == "ProvinceInspector": + if person != None: + province_operator = SystemUserProfile.objects.filter(role__name='ProvinceInspector', + province=person.province) + if province_operator.count() > 0: + if InspectorOperator.objects.filter(user=province_operator.last()).exists(): + return Response({"msg": "exist"}, status=status.HTTP_406_NOT_ACCEPTABLE) + serializer = create_except_profile( + request=request, + queryset=InspectorOperator, + serializer=InspectorOperatorSerializer, + role=edit_type + ) + return Response(serializer[0], status=serializer[1]) + + return Response({"msg": "error"}, status=status.HTTP_403_FORBIDDEN) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'second_mobile_number' in request.data.keys(): + user_profile = SystemUserProfile.objects.get(key=request.data['userprofile_key']) + first_mobile_number = user_profile.mobile + second_mobile_number = request.data['second_mobile_number'] + request.data.pop('second_mobile_number') + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + # return Response(req.status_code) + if req.status_code == 200: + second_mobile_number = second_mobile_number + # request.data.pop('userprofile_key') + user = User.objects.get(id=user_profile.user.id) + user.username = second_mobile_number + user.save() + user_profile.mobile = second_mobile_number + user_profile.save() + # return Response({"result": "شماره تماس با موفقیت ویرایش شد."}, status=status.HTTP_200_OK) + # else: + # return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_200_OK) + if 'last_name' in request.data: + if request.data['last_name'] == "": + request.data.pop('last_name') + if 'national_code' in request.data: + if request.data['national_code'] == "": + request.data.pop('national_code') + if 'national_id' in request.data: + if request.data['national_id'] == "": + request.data.pop('national_id') + edit_type = request.data['type'] + request.data.pop('type') + + person_type = request.data['person_type'] + request.data.pop('person_type') + + # edit profile & roles by user + if person_type == 'self': + if edit_type == 'self_profile': + + url = 'https://userbackend.rasadyar.com/user_identity/0/' + headers = { + "Authorization": str(request.headers['Authorization']), + "Content-Type": "application/json" + } + + # remove null fields from request + request = remove_null_fields(type='req', request=request) + # get profile object + queryset = self.queryset.get(user=request.user) + + payload = { + 'userprofile_key': str(queryset.key), + 'mobile': queryset.mobile, + 'first_name': queryset.first_name, + 'last_name': queryset.last_name, + 'national_id': queryset.national_id, + 'national_code': queryset.national_code + } + req = requests.put( + url=url, + data=json.dumps(payload), + headers=headers, + verify=False + ) + + if req.status_code == 200: + # upload image + req = upload_image(req=request, field='image') + + # send data to serializer + serializer = self.serializer_class(data=req.data) + if serializer.is_valid(): + obj = serializer.update(validated_data=req.data, instance=queryset) + serializer = self.serializer_class(obj) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors) + else: + return Response({'msg': 'Bad Request'}, status=status.HTTP_400_BAD_REQUEST) + if edit_type == 'Poultry': + pass + if edit_type == "CityOperator": + serializer = update_except_profile( + model=CityOperator, + serializer=CityOperatorSerializer, + request=request + ) + return Response(serializer, status=status.HTTP_200_OK) + if edit_type == "ProvinceOperator": + serializer = update_except_profile( + model=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "ProvinceFinancial": + serializer = update_except_profile( + model=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "ProvinceInspector": + serializer = update_except_profile( + model=InspectorOperator, + serializer=InspectorOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "KillHouse": + serializer = update_except_profile( + model=KillHouseOperator, + serializer=KillHouseOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "KillHouseVet": + # get kill house object + kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key']) + + # get kill house vet object + kill_house_vet_object = KillHouseVet.objects.get(key=request.data['vet_key']) + + kill_house_vet_object.kill_house = kill_house_object + kill_house_vet_object.save() + + # send object to serializer + serializer = KillHouseVetSerializer(kill_house_vet_object) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "VetFarm": + serializer = update_except_profile( + model=Vet, + serializer=VetSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "Driver": + # get driver object + driver = KillHouseDriver.objects.get(key=request.data['driver_key']) + request.data.pop('driver_key') + + # send data to serializer for update + serializer = KillHouseDriverSerializer(data=request.data) + if serializer.is_valid(): + driver_update = serializer.update(instance=driver, validated_data=request.data) + serializer = KillHouseDriverSerializer(driver_update) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + # edit profile & roles by operator + if person_type == 'operator': + if edit_type == 'self_profile': + # remove null fields from request + request = remove_null_fields(type='req', request=request) + + # get profile object + queryset = self.queryset.get(key=request.data['userprofile_key']) + request.data.pop('userprofile_key') + + # upload image + req = upload_image(req=request, field='image') + + # Change Password By Operator + if req.data['password'] != "": + data = { + 'username': queryset.mobile, + 'password': req.data['password'] + } + req_change_pass = requests.post( + url=ARTA_URL_CHANGE_PASSWORD, + data=data, + verify=False + ) + if req_change_pass.status_code == 200: + queryset.password = req.data['password'] + queryset.save() + req.data.pop('password') + else: + return Response({"Msg": "Password Not Change"}, status=status.HTTP_400_BAD_REQUEST) + else: + req.data.pop('password') + + # send data to serializer + serializer = self.serializer_class(data=req.data) + + if serializer.is_valid(): + # if 'city' in request.data.keys(): + # city = City.objects.get(key=request.data['city']) + # request.data.pop('city') + # queryset.city = city + # queryset.save() + obj = serializer.update(validated_data=req.data, instance=queryset) + serializer = self.serializer_class(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors) + if edit_type == "CityOperator": + serializer = operator_update_except_profile( + model=CityOperator, + serializer=CityOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "ProvinceOperator": + serializer = operator_update_except_profile( + model=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "ProvinceFinancial": + serializer = operator_update_except_profile( + model=ProvinceOperator, + serializer=ProvinceOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "ProvinceInspector": + serializer = operator_update_except_profile( + model=InspectorOperator, + serializer=InspectorOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "Poultry": + serializer = operator_update_except_profile( + model=Poultry, + serializer=PoultrySerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "KillHouse": + serializer = operator_update_except_profile( + model=KillHouseOperator, + serializer=KillHouseOperatorSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "KillHouseVet": + # get kill house object + kill_house_object = KillHouse.objects.get(key=request.data['kill_house_key']) + + # get kill house vet object + kill_house_vet_object = KillHouseVet.objects.get(key=request.data['vet_key']) + + kill_house_vet_object.kill_house = kill_house_object + kill_house_vet_object.save() + + # send object to serializer + serializer = KillHouseVetSerializer(kill_house_vet_object) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "VetFarm": + serializer = operator_update_except_profile( + model=Vet, + serializer=VetSerializer, + request=request + ) + return Response(serializer.data, status=status.HTTP_200_OK) + if edit_type == "Driver": + # get driver object + driver = KillHouseDriver.objects.get(key=request.data['driver_key']) + request.data.pop('driver_key') + + # send data to serializer for update + serializer = KillHouseDriverSerializer(data=request.data) + if serializer.is_valid(): + if driver.user_bank_info is not None: + bank_serializer = BankCardSerializer(data=request.data['user_bank_info']) + if bank_serializer.is_valid(): + bank_object = bank_serializer.update( + instance=driver.user_bank_info, + validated_data=request.data['user_bank_info'] + ) + driver.user_bank_info = bank_object + else: + bank_serializer = BankCardSerializer(data=request.data['user_bank_info']) + if bank_serializer.is_valid(): + bank_object = bank_serializer.create( + validated_data=request.data['user_bank_info'] + ) + driver.user_bank_info = bank_object + driver.save() + request.data.pop('user_bank_info') + driver_update = serializer.update(instance=driver, validated_data=request.data) + serializer = KillHouseDriverSerializer(driver_update) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def destroy(self, request, *args, **kwargs): + refresh(request.user.id) + + # contains role class model + role_class = self.object_classes[request.GET['role']] + + # get role class object + role_object = role_class.objects.get(key=request.GET['role_data_key']) + + # deactivate role class models + if request.GET['type'] == 'Deactivate': + if request.GET['role'] == 'KillHouseVet': + role_object.vet.trash = True # set trash field to False + role_object.vet.save() + if request.GET['role'] == 'VetFarm': + role_object.vet.trash = True # set trash field to False + role_object.vet.save() + role_object.trash = True # set trash field to False + role_object.save() + return Response({'Msg': 'Deactivated'}, status=status.HTTP_200_OK) + + # activate role class models + elif request.GET['type'] == 'Activate': + if request.GET['role'] == 'KillHouseVet': + role_object.vet.trash = False # set trash field to False + role_object.vet.save() + if request.GET['role'] == 'VetFarm': + role_object.vet.trash = False # set trash field to False + role_object.vet.save() + role_object.trash = False # set trash field to False + role_object.save() + return Response({'Msg': 'Activated'}, status=status.HTTP_200_OK) + + +class SystemUserProfileّForFactorProfileViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [AllowAny] + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(key=request.data['userprofile_key'], trash=False) + request.data.pop('userprofile_key') + serializer = self.serializer_class(user) + serializer.update(instance=user, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class AdminSystemUserProfileViewSet(viewsets.ModelViewSet): + queryset = SystemUserProfile.objects.all() + serializer_class = SystemUserProfileSerializer + permission_classes = [AllowAny] + + def create(self, request, *args, **kwargs): + refresh(request.user.id) + city = City.objects.get(key=request.data['city']) + province = Province.objects.get(key=request.data['province']) + address = request.data['address'] + password = request.data['password'] + role = Group.objects.get(name=request.data['role']).name + main_address = SystemAddress(city=city, province=province, address=address) + main_address.save() + data = { + "username": request.data['mobile'], + "password": password, + "role": role, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + if req.status_code == 200: + user = User( + username=request.data['mobile'], + first_name=request.data['firstname'], + last_name=request.data['lastname'] + ) + user.save() + base_id = SystemUserProfile.objects.all().last() + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + fullname=request.data['firstname'] + " " + request.data['lastname'], + user=user, + birthday=request.data['birthday'], + national_id=request.data['national_id'], + city=city, + province=province, + base_order=int(base_id.base_order) + 1, + password=password + ) + system_profile.save() + system_profile.role.add(role) + system_profile.save() + if role == 'CityOperator': + city_operator = CityOperator(user=system_profile, address=main_address) + city_operator.save() + elif role == 'ProvinceOperator' or role == 'ProvinceFinancial': + province_operator = ProvinceOperator(user=system_profile, address=main_address) + province_operator.save() + elif role == 'ProvinceInspector': + province_inspector = InspectorOperator(user=system_profile, address=main_address) + province_inspector.save() + elif role == 'KillHouse': + kill_house_operator = KillHouseOperator(user=system_profile, address=main_address) + kill_house_operator.save() + kill_house = KillHouse( + kill_house_operator=kill_house_operator, + system_address=main_address, + name=request.data['name'], + capacity=request.data['capacity'], + phone=request.data['phone'], + ) + kill_house.save() + elif role == 'KillHouseVet': + vet = Vet(user=system_profile, address=main_address) + vet.save() + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + kill_house_vet = KillHouseVet(vet=vet, kill_house=kill_house) + kill_house_vet.save() + # elif role == 'KillHouseVet': + + +class CheckChickenQuntityViewSet(viewsets.ModelViewSet): + queryset = UserProfile.objects.all() + serializer_class = UserProfileSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + refresh(request.user.id) + info_list = [] + users = UserProfile.objects.all() + now = datetime.datetime.now() + timedelta(days=6) + for i in range(10, 13): + count = 0 + poultry = [] + for user in users: + age = (now - user.hatching_date).days + if i == age: + poultry.append({ + 'full_name': user.fullname, + 'quantity': user.number_of_incubators + }) + count += user.number_of_incubators + + internal_dict_info = {'age': i, + 'count': count, + 'weight': count * 3} + internal_dict_info.update({'users': poultry}) + info_list.append(internal_dict_info) + + return Response(info_list) + + +# ویوست مربوط اطلاعات حساب بانکی کاربر +class BankCardViewSet(viewsets.ModelViewSet): + queryset = BankCard.objects.all() + serializer_class = BankCardSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ثبت اطلاعات حساب بانکی کاربر + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + bank_card = serializer.create(validated_data=request.data) + if 'role' in request.GET: + if request.GET['role'] == 'Poultry': + poultry = Poultry.objects.get(key=request.data['key']) + poultry.user_bank_info = bank_card + poultry.save() + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + city_operator.user_bank_info = bank_card + city_operator.save() + elif request.GET['role'] == 'ProvinceFinancial': + province_operator = ProvinceOperator.objects.get(user=user) + province_operator.user_bank_info = bank_card + province_operator.save() + elif request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user) + kill_house_operator.user_bank_info = bank_card + kill_house_operator.save() + elif request.GET['role'] == 'Vet': + vet = Vet.objects.get(user=user) + vet.user_bank_info = bank_card + vet.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به ویرایش اطلاعات حساب بانکی کاربر + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + bank_card = BankCard.objects.get(key__exact=request.data["key"]) + request.data.pop('key') + bank_card.save() + serializer = self.serializer_class(bank_card) + serializer.update(instance=bank_card, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceChangeBankCardViewSet(viewsets.ModelViewSet): + queryset = BankCard.objects.all() + serializer_class = BankCardSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ثبت اطلاعات حساب بانکی کاربر + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + role = request.data['role'] + if role == 'Poultry': + poultry = Poultry.objects.get(key=request.data['poultry_key'], trash=False) + if poultry.user_bank_info != None: + request.data.pop('role') + request.data.pop('poultry_key') + bank_card = BankCard.objects.get(key=poultry.user_bank_info.key) + serializer = self.serializer_class(bank_card) + serializer.update(instance=bank_card, validated_data=request.data) + else: + request.data.pop('role') + request.data.pop('poultry_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + bank_card = serializer.create(validated_data=request.data) + poultry.user_bank_info = bank_card + poultry.save() + else: + operator = ProvinceOperator.objects.filter(key=request.data['operator_key'], trash=False) + if operator.user_bank_info != None: + request.data.pop('role') + request.data.pop('operator_key') + bank_card = BankCard.objects.get(key=operator.user_bank_info.key) + serializer = self.serializer_class(bank_card) + serializer.update(instance=bank_card, validated_data=request.data) + else: + request.data.pop('role') + request.data.pop('poultry_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + bank_card = serializer.create(validated_data=request.data) + operator.user_bank_info = bank_card + operator.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +# ویوست مربوط آدرس کاربر +class AddressViewSet(viewsets.ModelViewSet): + queryset = Address.objects.all() + serializer_class = AddressSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + if "key" in request.GET: + add_obj = Address.objects.get(key__exact=request.GET["key"]) + serializer = self.serializer_class(add_obj) + return Response(serializer.data, status=status.HTTP_200_OK) + if "title" in request.GET: + add_obj = Address.objects.filter(user_id=request.user.id) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + queryset = Address.objects.all() + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + address = serializer.create(validated_data=request.data) + address.user = UserProfile.objects.get(user=request.user) + address.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def retrieve(self, request, pk=None, *args, **kwargs): + queryset = Address.objects.get(key__exact=request.GET["key"]) + serializer = self.serializer_class(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + queryset = Address.objects.get(key__exact=request.GET["key"]) + queryset.save() + serializer = self.serializer_class(queryset) + serializer.update(instance=queryset, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def partial_update(self, request, pk=None, *args, **kwargs): + pass + + def destroy(self, request, pk=None, *args, **kwargs): + queryset = Address.objects.get(key__exact=request.GET["wallet_id"]) + queryset.trash = True + queryset.save() + return Response(status=status.HTTP_200_OK) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def new_send_otp(request): + # if request.headers['Origin'] == 'test.sstit.ir': + # return redirect('test.ravandno.ir') + # else: + req = requests.post( + url=ARTA_URL_SEND_OTP, + data=request.data, + verify=False + ) + + return Response(req.json()) + + +# تابع برای برای بررسی یکسان بودن کد پیامکی استفاده میشود +@api_view(["POST"]) +@permission_classes([AllowAny]) +def check_otp(request): + req = requests.post( + url=ARTA_URL_CHECK_OTP, + data=request.data, + verify=False + ) + return Response(req.json(), status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@authentication_classes([OAuth2Authentication]) +def change_password(request): + user = SystemUserProfile.objects.get(user=request.user) + req = requests.post( + url=ARTA_URL_CHANGE_PASSWORD, + data=request.data, + verify=False + ) + if req.status_code == 200: + user.password = request.data['password'] + user.save() + + return Response(req.json(), status=status.HTTP_200_OK) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def new_register(request): + req = requests.post( + url=ARTA_URL_REGISTER, + data=request.data, + verify=False + ) + if req.status_code == 500: + error_message = req.content.decode('utf-8') # Decode response content + return Response(error_message) + if req.status_code == 200: + role = Group.objects.get(name=request.data['role']) + password = request.data['password'] + user = User( + username=request.data['username'], + password=cryptocode.encrypt(password, password) + ) + user.save() + userprofile = SystemUserProfile( + user=user, + mobile=request.data['username'], + password=password + ) + + userprofile.base_order = \ + 1000 if len(SystemUserProfile.objects.all()) == 0 \ + else SystemUserProfile.objects.all().order_by('create_date').last().base_order + 1 + userprofile.save() + userprofile.role.add(role) + + # add tenant for a Poultry + if 'tenant' in request.data.keys(): + + # Check if has access + if get_authorization_header(request) != "": + # complete UserProfile information + province = Province.objects.get(key=request.data['tenant']['province']) + city = City.objects.get(key=request.data['tenant']['city']) + userprofile.province = province + userprofile.city = city + userprofile.national_code = request.data['tenant']['national_code'] + userprofile.first_name = request.data['tenant']['first_name'] + userprofile.last_name = request.data['tenant']['last_name'] + userprofile.save() + + # set the tenant poultry owner + owner_poultry = Poultry.objects.get(key=request.data['tenant']['poultry_key']) + owner_poultry.has_tenant = True + owner_poultry.save() + + # create tenant + address = SystemAddress( + city=city, + province=province, + address=request.data['tenant']['address'], + postal_code=request.data['tenant']['postal_code'] + ) + address.save() + tenant_poultry = Poultry( + user=userprofile, + owner=owner_poultry, + unit_name=owner_poultry.unit_name, + breeding_unique_id=request.data['tenant']['unique_id'], + address=address + ) + tenant_poultry.tenant = True + tenant_poultry.save() + serializer = PoultrySerializer(tenant_poultry) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + access_token = AccessToken( + token=req.json()['access_token'], + user=user, + expires=req.json()['expire_time'], + scope="read write" + ) + access_token.save() + return Response(req.json(), status.HTTP_201_CREATED) + if req.status_code == 400: + return Response({"result": 'کاربر قبلا ثبت شده است !'}, status.HTTP_403_FORBIDDEN) + + +# @api_view(['POST']) +# @permission_classes([AllowAny]) +# def new_login(request): +# if User.objects.filter(username__exact=request.data['username']).exists(): +# user = User.objects.get(username__exact=request.data['username']) +# userprofile = SystemUserProfile.objects.get( +# user=user +# ) +# +# # for recognize if user role are deactivated can not login +# role_classes = SystemUserProfileViewSet.object_classes +# role_object = role_classes[request.data['role']].objects.filter(user=userprofile) +# for item in role_object: +# if item.trash == False: +# return Response(status=status.HTTP_203_NON_AUTHORITATIVE_INFORMATION) +# # ########################################################################## +# +# roles = [] +# for item in userprofile.role.all(): +# roles.append(item.name) +# request.data['role'] = roles +# request.data['user_key'] = str(userprofile.key) +# req = requests.post( +# url=ARTA_URL_LOGIN, +# json=request.data, +# verify=False +# ) +# if req.status_code == 200: +# access_token = AccessToken( +# user=user, +# token=req.json()['access_token'], +# expires=req.json()['expire_time'], +# scope="read write" +# ) +# access_token.save() +# userprofile.token = access_token.token +# userprofile.save() +# for item in req.json()['role']: +# group = Group.objects.get(name=item) +# if not SystemUserProfile.objects.filter(user=user, role=group): +# userprofile.role.add(group) +# internal_login_dict = { +# "access_token": req.json()['access_token'], +# "expires_in": req.json()['token_type'], +# "scope": req.json()['scope'], +# "expire_time": req.json()['expire_time'], +# "mobile": userprofile.mobile, +# "fullname": userprofile.fullname, +# "firstname": userprofile.first_name, +# "lastname": userprofile.last_name, +# "city": userprofile.city.name, +# "province": userprofile.province.name, +# "national_code": userprofile.national_code, +# "national_id": userprofile.national_id, +# "birthday": userprofile.birthday, +# "image": userprofile.image, +# "base_order": userprofile.base_order, +# "role": req.json()['role'], +# } +# +# return Response(internal_login_dict, status.HTTP_200_OK) +# if req.status_code == 401: +# return Response({'msg': 'unauthorized'}, status.HTTP_401_UNAUTHORIZED) +# else: +# return Response({'msg': 'unauthorized'}, status.HTTP_401_UNAUTHORIZED) + + +def expire_user_access_tokens(token,user): + now = datetime.datetime.now().date() + accesses = AccessToken.objects.filter(user=user,created__date=now).exclude(token=token).order_by('-created') + accesses_to_expire = accesses[1:] + for access in accesses_to_expire: + access.expires = now - timedelta(days=2) + access.save() + + +def create_login_log(request, user_profile): + headers = dict(request.headers) + + UserLoginLog.objects.create( + user_profile=user_profile, + headers=headers, + ip_address=request.META.get('REMOTE_ADDR'), + user_agent=request.META.get('HTTP_USER_AGENT') + ) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def new_login(request): + username = request.data['username'] + if User.objects.filter(username__exact=username).exists(): + user = User.objects.get(username__exact=username) + userprofile = SystemUserProfile.objects.get(user=user) + roles = list(userprofile.role.all().values_list('name', flat=True)) + request.data['role'] = roles + request.data['user_key'] = str(userprofile.key) + req_data = { + "api_key": PROJECT_API_KEY, + "password": request.data['password'], + "username": request.data['username'], + "user_key": str(userprofile.key), + "role": roles, + } + req = requests.post( + url=ARTA_URL_LOGIN, + json=req_data, + verify=False + ) + if req.status_code == 200: + expires_datetime = datetime.datetime.strptime(req.json()['expire_time'], + "%Y-%m-%dT%H:%M:%S.%f") + datetime.timedelta(days=1) + access_token = AccessToken( + user=user, + token=req.json()['access_token'], + expires=expires_datetime, + scope="read write" + ) + access_token.save() + userprofile.token = access_token.token + userprofile.save() + for item in req.json()['role']: + group = Group.objects.get(name=item) + if not SystemUserProfile.objects.filter(user=user, role=group): + userprofile.role.add(group) + internal_login_dict = { + "access_token": req.json()['access_token'], + "expires_in": req.json()['token_type'], + "scope": req.json()['scope'], + "expire_time": req.json()['expire_time'], + "mobile": userprofile.mobile, + "fullname": userprofile.fullname, + "firstname": userprofile.first_name, + "lastname": userprofile.last_name, + "city": userprofile.city.name, + "province": userprofile.province.name, + "national_code": userprofile.national_code, + "national_id": userprofile.national_id, + "birthday": userprofile.birthday, + "image": userprofile.image, + "base_order": userprofile.base_order, + "role": req.json()['role'], + } + # expire_user_access_tokens_tread = threading.Thread(target=expire_user_access_tokens, args=(req.json()['access_token'],user)) + # expire_user_access_tokens_tread.start() + try: + create_login_log(request, userprofile) + except: + pass + return Response(internal_login_dict, status.HTTP_200_OK) + if req.status_code == 401: + return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE) + else: + return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE) +# def new_login(request): +# username = request.data['username'] +# password = (request.data['password'],) +# +# if User.objects.filter(username__exact=username).exists(): +# user = User.objects.get(username__exact=username) +# userprofile = SystemUserProfile.objects.get(user=user) +# decrypted_password = cryptocode.decrypt(user.password, password[0]) +# if decrypted_password != password[0]: +# return Response({'result': 'رمز ورود اشتباه است!'}, status=status.HTTP_401_UNAUTHORIZED) +# roles = list(userprofile.role.all().values_list('name', flat=True)) +# data = { +# "username": user.username, +# "password": userprofile.password, +# "client_id": CLIENT_ID, +# "client_secret": CLIENT_SECRET, +# "grant_type": "client_credentials", +# "scope": "read write", +# } +# +# r = requests.post(url=BASE_URL + "token/", data=json.dumps(data), verify=False) +# access_token = AccessToken.objects.get(token=r.json()["access_token"]) +# access_token.user = user +# access_token.expires += timedelta(days=3) +# access_token.save() +# userprofile.token = access_token.token +# userprofile.save() +# internal_login_dict = { +# "access_token": access_token.token, +# "expires_in": access_token.expires, +# "scope": "read write", +# "expire_time": access_token.expires, +# "mobile": userprofile.mobile, +# "fullname": userprofile.fullname, +# "firstname": userprofile.first_name, +# "lastname": userprofile.last_name, +# "city": userprofile.city.name, +# "province": userprofile.province.name, +# "national_code": userprofile.national_code, +# "national_id": userprofile.national_id, +# "birthday": userprofile.birthday, +# "image": userprofile.image, +# "base_order": userprofile.base_order, +# "role": roles, +# } +# +# return Response(internal_login_dict, status.HTTP_200_OK) +# +# else: +# return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE) + + +# تابع مربوط به ازسال کد پیامکی برای چند حالت استفاده می شود +# یرای فراموشی رمز عبور و برای تغییر رمز عبور و تغییر موبایل و ... +# @api_view(["POST"]) +# @permission_classes([AllowAny]) +# def send_otp(request): +# mobile = request.data["mobile"] +# state = request.data["state"] +# if len(mobile) < 11 or len(mobile) > 11: +# return Response({"pattern": "wrong", }, status=status.HTTP_403_FORBIDDEN, ) +# key = str(uuid.uuid4()) +# rand = random.randint(10000, 99000) +# cache.set(key, str(rand), timeout=CACHE_TTL) +# userprofile = SystemUserProfile.objects.filter(mobile=mobile) +# +# if userprofile.count() == 0: +# return Response({"is_user": False}, status=status.HTTP_404_NOT_FOUND) +# +# elif state == "forget_password": +# receptor = mobile +# send_otp_code(receptor, rand) +# return Response({"is_user": True, "key": key}, status=status.HTTP_200_OK) +# +# elif state == "change_password": +# receptor = mobile +# send_otp_code(receptor, rand) +# return Response({"is_user": True, "key": key}, status=status.HTTP_200_OK, ) +# +# elif state == "change_mobile": +# receptor = mobile +# send_otp_code(receptor, rand) +# return Response({"state": "change_mobile", "key": key}, status=status.HTTP_200_OK) +# +# elif state == "": +# list1 = [] +# if userprofile.count() > 1: +# +# for user in userprofile: +# user_dict = { +# "userprofile_id": user.id, +# "fullname": user.fullname, +# "first_name": user.first_name, +# "last_name": user.last_name, +# "mobile": user.mobile, +# "role": user.role.name, +# "province": user.address.province, +# "city": user.address.city, +# "address": user.address.address +# } +# list1.append(user_dict) +# return Response( +# { +# "result": list1, +# }, +# status=status.HTTP_200_OK, +# ) +# +# else: +# +# return Response( +# { +# "is_user": True, +# }, +# status=status.HTTP_200_OK, +# ) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +def login(request): + username = request.data["mobile"] + password = request.data["password"] + api_key = request.data["api_key"] + data = { + "username": username, + "password": password, + "api_key": api_key, + } + r = requests.post(url=ARTA_URL_LOGIN, data=data) + if "is_user" in r.json().keys(): + return Response({'is_user': False}, status=status.HTTP_401_UNAUTHORIZED) + elif "password" in r.json().keys(): + return Response({'password': 'wrong'}, status=status.HTTP_401_UNAUTHORIZED) + user_profile = UserProfile.objects.get(mobile=username) + user = User.objects.get(id=user_profile.user.id) + user_profile.token = r.json()["access_token"] + user_profile.save() + access = AccessToken(token=r.json()['access_token'], user=user, scope=r.json()['scope'], + expires=r.json()['expire_time']) + access.save() + role = Group.objects.get(id=user_profile.role.id) + response = { + "access_token": r.json()['access_token'], + "expires_in": r.json()['expires_in'], + "token_type": r.json()['token_type'], + "scope": r.json()['scope'], + "role": role.name + } + return Response(response, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +def register(request): + username = request.data["username"] + password = request.data["password"] + api_key = request.data["api_key"] + province = request.data['province'] + city = request.data['city'] + role = request.data['role'] + role = Group.objects.get(name=role) + data = { + "username": username, + "password": password, + "api_key": api_key, + } + r = requests.post(url=ARTA_URL_REGISTER, data=data) + if 'result' in r.json().keys(): + return Response({"result": "user already exist"}) + + user = User( + username=username, password=cryptocode.encrypt(password, password) + ) + user.save() + access = AccessToken(token=r.json()['access_token'], user=user, scope=r.json()['scope'], + expires=r.json()['expire_time']) + access.save() + + address = Address(province=province, city=city) + address.save() + userprofile = UserProfile(user=user, mobile=username, address=address, role=role) + userprofile.base_order = 1000 if len(UserProfile.objects.all()) == 0 else UserProfile.objects.all().order_by( + 'create_date').last().base_order + 1 + userprofile.user = user + userprofile.token = r.json()['access_token'] + userprofile.save() + return Response(r.json(), status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +# @authentication_classes([OAuth2Authentication]) +def forget_password(request): + # user = SystemUserProfile.objects.get(user=request.user) + # user.password = request.data['password'] + # user.save() + req = requests.post( + url=ARTA_URL_CHANGE_PASSWORD, + data=request.data, + verify=False + ) + if req.status_code == 200: + user = SystemUserProfile.objects.get(mobile=request.data['username']) + + user.password = request.data['password'] + user.save() + + return Response(req.json(), status=status.HTTP_200_OK) + + # mobile = request.data["mobile"] + # password = request.data["password"] + # try: + # userprofile = UserProfile.objects.get(mobile__exact=mobile) + # except UserProfile.DoesNotExist: + # return Response(status=status.HTTP_401_UNAUTHORIZED) + # user = User.objects.get(id=userprofile.user.id) + # user.password = cryptocode.encrypt(password, password) + # user.save() + # data = { + # "username": str(user.username), + # "password": user.password, + # "client_id": CLIENT_ID, + # "client_secret": CLIENT_SECRET, + # "grant_type": "client_credentials", + # "scope": "read write", + # } + # r = requests.post(url=BASE_URL + "token/", data=json.dumps(data)) + # userprofile.token = r.json()["access_token"] + # userprofile.save() + # access = AccessToken.objects.get(token=userprofile.token) + # access.user = userprofile.user + # access.save() + # role = Group.objects.get(id=userprofile.role.id) + # response = { + # "access_token": r.json()['access_token'], + # "expires_in": r.json()['expires_in'], + # "token_type": r.json()['token_type'], + # "scope": r.json()['scope'], + # "role": role.name + # } + # return Response(response, status=status.HTTP_200_OK) + + +# @api_view(["GET"]) +# @permission_classes([AllowAny]) +# تابع برای گرفتن گزارش تعداد جوجه و سن جوجه مرغداران استفاده میشود که بصورت فایل اکسل است +def resulting(request): + list2 = [] + today = datetime.datetime.now() + if 'age' in request.GET: + users = UserProfile.objects.filter(role_id=1).exclude(incubation_date=None) + for user in users: + age = (today - user.incubation_date).days + if int(age) == int(request.GET['age']): + list2.append(user) + elif 'state' in request.GET: + users = UserProfile.objects.filter(role_id=1).exclude(incubation_date=None) + for user in users: + age = (today - user.incubation_date).days + if int(age) >= int(request.GET['age1']) and int(age) <= int(request.GET['age2']): + list2.append(user) + excel_options = [ + 'نام و نام خانوادگی' + , 'تاریخ جوجه ریزی' + , 'سن مرغ' + , 'تعداد جوجه ریزی', + 'شماره همراه', 'استان', + 'شهرستان', + 'آدرس' + ] + output = BytesIO() + workbook = xlsxwriter.Workbook(output) + worksheet = workbook.add_worksheet() + for count in range(len(excel_options)): + worksheet.write(0, count, excel_options[count]) + l = 0 + for user in list2: + l += 1 + today = datetime.datetime.now() + if user.incubation_date != None: + age = (today - user.incubation_date).days + gregorian_date = jdatetime.date.fromgregorian( + day=user.incubation_date.day, + month=user.incubation_date.month, + year=user.incubation_date.year + ) + incubation_date = gregorian_date + else: + age = 'ندارد' + incubation_date = 'ندارد' + list1 = [ + user.fullname, + str(incubation_date), + str(age), + user.number_of_incubators, + user.mobile, + user.address.province, + user.address.city, + user.address.address, + ] + for item in range(len(list1)): + worksheet.write(l, item, list1[item]) + list1 = [] + workbook.close() + output.seek(0) + + response = HttpResponse(content_type='application/vnd.ms-excel') + + response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"' + response.write(output.getvalue()) + + return response + + +# تابع برای دریافت گزارش اطلاعات مربوط به فاکتور های مرغ منجمد به صورت فایل اکسل استفاده میشود +def ware_house_factor(request): + list2 = [] + factors = WareHouseFactor.objects.filter(trash=False).order_by('create_date') + for factor in factors: + list2.append(factor) + + excel_options = [ + 'تاریخ', + 'نام و نام خانوادگی', + 'کدملی' + , 'شماره همراه' + , 'نوع کالا' + , + 'شماره نامه جهاد', + 'شماره نامه استان', + 'قیمت', + 'وزن' + ] + output = BytesIO() + workbook = xlsxwriter.Workbook(output) + worksheet = workbook.add_worksheet() + for count in range(len(excel_options)): + worksheet.write(0, count, excel_options[count]) + l = 0 + for factor in factors: + l += 1 + gregorian_date = jdatetime.date.fromgregorian( + day=factor.date.day, + month=factor.date.month, + year=factor.date.year + ) + list1 = [ + str(gregorian_date), + factor.customer, + str(factor.national_code), + factor.mobile, + factor.product_type, + str(factor.letter_number_jahad), + factor.letter_number, + factor.fee, + factor.weight + ] + for item in range(len(list1)): + worksheet.write(l, item, list1[item]) + + list1 = [] + + workbook.close() + output.seek(0) + + response = HttpResponse(content_type='application/vnd.ms-excel') + + response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"' + response.write(output.getvalue()) + + return response + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def pos_login(request): + build_id = None + link = None + pos_version = PosVersion.objects.filter(trash=False).first() + if pos_version: + build_id = pos_version.build_id + link = pos_version.latest_downloadlink + try: + pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False) + if pos.active == False: + return Response({"result": "این کلید غیر فعال میباشد! "}, status=status.HTTP_401_UNAUTHORIZED) + + + except: + return Response({"result": "دستگاه پوزی با این شناسه وجود ندارد! "}, status=status.HTTP_401_UNAUTHORIZED) + + if User.objects.filter(username__exact=pos.user.mobile).exists(): + user = User.objects.get(username__exact=pos.user.mobile) + userprofile = SystemUserProfile.objects.get( + user=user + ) + data = { + "username": user.username, + "password": userprofile.password, + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "grant_type": "client_credentials", + "scope": "read write", + } + + r = requests.post(url=BASE_URL + "token/", data=json.dumps(data), verify=False) + access_token = AccessToken.objects.get(token=r.json()["access_token"]) + access_token.user = user + access_token.expires += timedelta(days=3) + access_token.save() + userprofile.token = access_token.token + userprofile.save() + pos.token = access_token.token + pos.save() + if pos.guild: + store_name = pos.guild.guilds_name + phone = pos.guild.phone + else: + store_name = pos.kill_house.name + phone = pos.kill_house.phone + internal_login_dict = { + "access_token": userprofile.token, + "build_id": build_id, + "latest_downloadlink": link, + "profile": { + "pos_id": pos.pos_id, + "store_name": store_name, + "phone": phone, + "mobile": userprofile.mobile, + "fullname": userprofile.fullname, + "firstname": userprofile.first_name, + "lastname": userprofile.last_name, + "city": userprofile.city.name, + "province": userprofile.province.name, + "national_code": userprofile.national_code, + "national_id": userprofile.national_id, + "birthday": userprofile.birthday, + } + + } + for pos_item in PosItem.objects.all(): + internal_login_dict[pos_item.name] = pos_item.value + + return Response(internal_login_dict, status.HTTP_200_OK) + + else: + return Response({'msg': 'unauthorized'}, status.HTTP_410_GONE) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def new_pos_login(request): + pos_id = request.data.get('pos-id') + pos = get_object_or_404(POSMachine, pos_id=pos_id, trash=False) + + if not pos.active: + return Response({"result": "این کلید غیر فعال میباشد! "}, status=status.HTTP_401_UNAUTHORIZED) + + user = get_object_or_404(User, username=pos.user.mobile) + user_profile = get_object_or_404(SystemUserProfile, user=user) + + pos_info = get_pos_info(pos) + + data = { + "username": user.username, + "password": user_profile.password, + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "grant_type": "client_credentials", + "scope": "read write", + } + + response = requests.post(url=f"{BASE_URL}token/", data=json.dumps(data), verify=False) + access_token = update_access_token(response.json()["access_token"], user) + + user_profile.token = access_token.token + user_profile.save() + + pos.token = access_token.token + pos.save() + + internal_login_dict = build_internal_login_response(user_profile, pos_info, pos.pos_id) + + return Response(internal_login_dict, status.HTTP_200_OK) + + +def get_pos_info(pos): + if pos.kill_house: + return { + "type": "KillHouse", + "name": pos.kill_house.name, + "phone": pos.kill_house.phone + } + elif pos.guild: + return { + "type": "Guild", + "name": pos.guild.guilds_name, + "phone": pos.guild.phone + } + else: + return { + "type": "Dispenser", + "name": pos.dispenser.user.fullname, + "phone": pos.dispenser.user.mobile + } + + +def update_access_token(token_str, user): + access_token = AccessToken.objects.get(token=token_str) + access_token.user = user + access_token.expires += timedelta(days=3) + access_token.save() + return access_token + + +def build_internal_login_response(user_profile, pos_info, pos_id): + return { + "access_token": user_profile.token, + "type": pos_info["type"], + "profile": { + "pos_id": pos_id, + "name": pos_info["name"], + "phone": pos_info["phone"], + "mobile": user_profile.mobile, + "fullname": user_profile.fullname, + "firstname": user_profile.first_name, + "lastname": user_profile.last_name, + "city": user_profile.city.name, + "province": user_profile.province.name, + "national_code": user_profile.national_code, + "national_id": user_profile.national_id, + "birthday": user_profile.birthday, + } + } + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def show_transaction_info(request): + request.data['registered'] = True + return Response(request.data) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def TokenVerification(request): + token = AccessToken.objects.get(token=request.data['token']) + user = SystemUserProfile.objects.filter(user=token.user, trash=False).select_related('province', 'city').first() + + return Response({ + "username": user.mobile, + "password": user.password, + "province": user.province.name, + "city": user.city.name, + }) + + # def create(self, request, *args, **kwargs): + # group = Group.objects.filter(name__in=request.data['roles']) + # users = SystemUserProfile.objects.filter(trash=False,role__in=group).order_by('id') + # notis_user = users.values_list('id',flat=True) + # return Response(notis_user) + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # notice = serializer.create(validated_data=request.data) + # notice.users = notis_user + # notice.save() + # for user in notis_user: + # user_notice = UserNoticeInfo( + # notice=notice, + # user = user, + # + # ) + # user_notice.save() + # serializer = self.serializer_class(notice) + # return Response(serializer.data) + # return Response(serializer.errors) + + +@api_view(['POST']) +@permission_classes([AllowAny]) +def register_tenant(request): + province = Province.objects.get(key=request.data['province']) + city = City.objects.get(key=request.data['city']) + breeding_uniq_id = request.data['unique_id'] + if Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).exists(): + return Response({'result': 'شناسه یکتا برای شخص دیگری است!'}, status=status.HTTP_403_FORBIDDEN) + owner_poultry = Poultry.objects.get(key=request.data['poultry_key']) + owner_poultry.has_tenant = True + + address = SystemAddress( + city=city, + province=province, + address=request.data['address'], + postal_code=request.data['postal_code'] + ) + address.save() + tenant_poultry = Poultry( + user=owner_poultry.user, + owner=owner_poultry, + unit_name=request.data['unit_name'], + breeding_unique_id=breeding_uniq_id, + address=address, + city_number=city.id, + province_number=province.id, + city_name=city.name, + province_name=province.name + ) + tenant_poultry.tenant = True + owner_poultry.save() + tenant_poultry.save() + serializer = PoultrySerializer(tenant_poultry) + return Response(serializer.data, status=status.HTTP_201_CREATED) diff --git a/bot_eata.py b/bot_eata.py new file mode 100644 index 0000000..d105194 --- /dev/null +++ b/bot_eata.py @@ -0,0 +1,1855 @@ +from datetime import datetime, timedelta + +import jdatetime +import requests +from django.db.models import Sum, Q, F +from django.http import HttpResponse + +from general_urls import base_url_for_sms_report +from helper_eata import token, chat_id, chat_id_mali +from panel.ProvinceOperator.serializers import TotalWageInformationSerializer +from panel.helper_excel import shamsi_date, to_locale_str +from panel.models import PoultryHatching, ProvinceKillRequest, KillHousePercentage, TotalWageInformation, \ + InternalTransaction, TokenEitaaForEachVet, VetFarm, KillHouseRequest, PoultryRequest, Poultry + + +def format_datetime_to_shamsi(input_date): + if isinstance(input_date, datetime): + input_date = input_date.date() + + shamsi_date = jdatetime.date.fromgregorian(date=input_date) + shamsi_date_str = shamsi_date.strftime('%Y/%m/%d') + + weekday_str = input_date.strftime('%A') + weekdays = { + 'Saturday': 'شنبه', + 'Sunday': 'یکشنبه', + 'Monday': 'دوشنبه', + 'Tuesday': 'سه‌شنبه', + 'Wednesday': 'چهارشنبه', + 'Thursday': 'پنج‌شنبه', + 'Friday': 'جمعه' + } + weekday_str_fa = weekdays.get(weekday_str, '') + + formatted_date = f"گزارش {weekday_str_fa} به تاریخ {shamsi_date_str}" + + return formatted_date + + +def bot_eitaa_for_bar(request): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + response = requests.get( + f'https://{base_url_for_sms_report}backend.rasadyaar.ir/province_request_letter/?date={date}') + date_time_jalali = format_datetime_to_shamsi(date) + + if response.status_code == 200: + data = response.json() + + allocation = data.get('allocation', []) + kill_house_num = 1 + messages_sent = 0 + + for entry in allocation: + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_بار_داخل_استان #{date_shamsi}\n\n' + total_quantity = entry.get('total_quantity') + if total_quantity and int(total_quantity) > 0: + len_bar = entry.get('province_kill_request') + killer = 'کشتارگاه' if entry.get('killer') == False else 'کشتارکن' + name = entry.get("name").replace(' ', '_') + mobile = entry.get("kill_house_operator").get("user").get("mobile") + total_quantity = "{:,}".format(int(total_quantity)) + + current_message = base_message + current_message += f'🟢 {killer} #{name} ({mobile})\n' + current_message += f'تعداد کل بار: {len(len_bar)}\n' + current_message += f'حجم کل بار: {total_quantity}\n' + current_message += f'--------------------------------\n' + + m = 1 + for request1 in entry.get('province_kill_request', []): + poultry = request1.get('poultry', 'نامشخص') + poultry_mobile = request1.get('poultry_mobile', 'نامشخص') + quantity = request1.get('quantity', 0) + average_weight = request1.get('Index_weight', 'نامشخص') + weight = request1.get('weight', 'نامشخص') + car_type = request1.get('car_type', 'نامشخص') + driver_name = request1.get('driver_name', 'نامشخص') + traffic_code = request1.get('traffic_code', 'نامشخص') + pelak = request1.get('pelak', 'نامشخص') + quantity = "{:,}".format(int(quantity)) + weight = "{:,}".format(int(weight)) + + current_message += f'\n🔸{m}-مرغدار: {poultry} ({poultry_mobile})\n' + current_message += f'میانگین وزن بار: {average_weight}\n' + current_message += f'حجم بار: {quantity}\n' + current_message += f'وزن بار: {weight}\n' + current_message += f'نوع ماشین: {car_type}\n' + current_message += f'نام راننده: {driver_name}\n' + current_message += f'کد حمل و نقل: {traffic_code}\n' + current_message += f'پلاک: {pelak}\n' + current_message += '-' * 30 + '\n' + m += 1 + + data = { + 'chat_id': chat_id, + 'text': current_message, + } + response = requests.post(url, data=data, verify=False) + if response.status_code == 200: + messages_sent += 1 + kill_house_num += 1 + + return HttpResponse(f'{messages_sent} پیام با موفقیت ارسال شد.') + + return HttpResponse('Error fetching data', status=500) + + +def bot_eitaa_free_bar(request): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + response = requests.get( + f'https://{base_url_for_sms_report}backend.rasadyaar.ir/province_request_letter/?date={date}') + date_time_jalali = format_datetime_to_shamsi(date) + if response.status_code == 200: + data = response.json() + date_shamsi = shamsi_date(date).replace('-', '_') + out_province = data.get('out_province', []) + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_خارج_استان #{date_shamsi}\n\n' + base_message += f'تعداد کل سفارشات: {len(out_province)}\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + for entry in out_province: + quantity = entry['quantity'] + poultry_name = entry['poultry']['user']['fullname'] + poultry_mobile = entry['poultry']['user']['mobile'] + buyer_fullname = entry['out_province_poultry_request_buyer']['fullname'] + buyer_mobile = entry['out_province_poultry_request_buyer']['mobile'] + buyer_city = entry['out_province_poultry_request_buyer']['city'] + city = entry['poultry']['user']['city']['name'] + weight = entry.get('Index_weight', 'نامشخص') + weight_all = quantity * weight + quantity = "{:,}".format(entry['quantity']) + weight_all = "{:,}".format(int(weight_all)) + + new_message_part = f'{m}:\n' + new_message_part += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + new_message_part += f"شهر: {city}\n" + new_message_part += f"🔸 خریدار : {buyer_fullname} ({buyer_mobile})\n" + new_message_part += f"شهر: {buyer_city}\n" + new_message_part += f"میانگین وزن : {weight}\n" + new_message_part += f" تعداد : {quantity}\n" + new_message_part += f" وزن تقریبی : {weight_all}\n" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + m += 1 + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse(f'{len(messages)} پیام ارسال شد.') + + +def bot_eitaa_for_hatching_gt_50(request): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + date_time_jalali = format_datetime_to_shamsi(date) + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_فارم_بالای_50_روز #{date_shamsi}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + poultry_hatching = PoultryHatching.objects.filter(trash=False, chicken_age__gte=50) + m = 1 + for hatching in poultry_hatching: + message = f'{m}-مرغدار {hatching.poultry.unit_name}\n' \ + f'' + m += 1 + base_message += message + data = { + 'chat_id': chat_id, + 'text': base_message, + } + response = requests.post(url, data=data, verify=False) + return HttpResponse(f'{len(base_message)} پیام ارسال شد.') + + +def bot_eitaa_for_province_kill_request(request): + if base_url_for_sms_report in ('ma', 'test'): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('accepted', 'pending'), + return_to_province=False, + kill_request__recive_date__date=date) \ + .order_by('-kill_request__recive_date').only('main_quantity', 'quantity', + 'province_request__poultry_request__Index_weight', + 'main_quantity', 'province_request__poultry_request__export', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__city_request_Poultry__poultry_request__poultry__user__mobile', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city__name', + 'kill_request__kill_house__name', + 'kill_request__kill_house__kill_house_operator__user__mobile', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__order_code', + 'kill_request__kill_house__system_address__city__name') + date_time_jalali = format_datetime_to_shamsi(date) + + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_تخصیصات #{date_shamsi}\n\n' + base_message += f'تعداد کل تخصیصات: {len(province_kill_requests)}\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + for entry in province_kill_requests: + main_quantity = entry.main_quantity + remain_quantity = entry.quantity if entry.return_to_province == False else 0 + poultry_name = entry.province_request.poultry_request.poultry.unit_name + poultry_mobile = entry.province_request.poultry_request.poultry.user.mobile + + city = entry.province_request.poultry_request.poultry.user.city.name + buyer = entry.kill_request.kill_house.name + buyer_city = entry.kill_request.kill_house.system_address.city.name + buyer_mobile = entry.kill_request.kill_house.kill_house_operator.user.mobile + weight = entry.province_request.poultry_request.Index_weight + order_code = entry.province_request.poultry_request.order_code + weight_all = remain_quantity * weight + main_quantity = "{:,}".format(main_quantity) + remain_quantity = "{:,}".format(remain_quantity) + weight_all = "{:,}".format(int(weight_all)) + + if entry.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif entry.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + else: + province_type = 'اتحادیه' + new_message_part = f'{m}:\n' + new_message_part += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + new_message_part += f"شهر: {city}\n" + new_message_part += f"کد سفارش: {order_code}\n" + new_message_part += f"نوع فروش: {province_type}\n" + new_message_part += f" تعداد تخصیصی :{main_quantity}\n" + new_message_part += f"مانده قابل تخصیص :{remain_quantity}\n" + new_message_part += f"میانگین وزن : {weight}\n" + new_message_part += f"وزن تقریبی :{weight_all}\n" + new_message_part += f"\n" + new_message_part += f"🔴🔴خریدار : {buyer} ({buyer_mobile})\n" + new_message_part += f"شهر خریدار: {buyer_city}\n" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + m += 1 + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse(f'{len(messages)} پیام ارسال شد.') + + +def bot_eitaa_for_each_province_kill_request(entry, vet): + if base_url_for_sms_report in ('ma', 'test'): + messages = [] + chat_id_eitaa = None + if vet: + chat_id_eitaa = TokenEitaaForEachVet.objects.filter(vet_mobile=vet.vet.user.mobile).first() + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + + date_time_jalali = format_datetime_to_shamsi(date) + + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_تخصیصات #{date_shamsi}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + current_message = base_message + m = 1 + + main_quantity = entry.main_quantity + remain_quantity = (entry.main_quantity - entry.total_killed_quantity) if ( + entry.main_quantity - entry.total_killed_quantity) > 0 else 0 + poultry_name = entry.province_request.poultry_request.poultry.unit_name + poultry_mobile = entry.province_request.poultry_request.poultry.user.mobile + + city = entry.province_request.poultry_request.poultry.user.city.name + buyer = entry.kill_request.kill_house.name + buyer_city = entry.kill_request.kill_house.system_address.city.name + buyer_mobile = entry.kill_request.kill_house.kill_house_operator.user.mobile + weight = entry.province_request.poultry_request.Index_weight + order_code = entry.province_request.poultry_request.order_code + weight_all = entry.total_killed_quantity * weight + main_quantity = "{:,}".format(main_quantity) + remain_quantity = "{:,}".format(remain_quantity) + weight_all = "{:,}".format(int(weight_all)) + + if entry.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif entry.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + elif entry.market == True: + province_type = 'پنل معاملاتی' + else: + province_type = 'اتحادیه' + new_message_part = f'{m}:\n' + new_message_part += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + new_message_part += f"شهر: {city}\n" + new_message_part += f"کد سفارش: {order_code}\n" + new_message_part += f"نوع فروش: {province_type}\n" + new_message_part += f" تعداد تخصیصی :{main_quantity}\n" + new_message_part += f"مانده قابل تخصیص :{remain_quantity}\n" + new_message_part += f"میانگین وزن : {weight}\n" + new_message_part += f"وزن تقریبی :{weight_all}\n" + new_message_part += f"\n" + new_message_part += f"🔴🔴خریدار : {buyer} ({buyer_mobile})\n" + new_message_part += f"شهر خریدار: {buyer_city}\n" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + m += 1 + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + if chat_id_eitaa: + chat_id_eitaa = chat_id_eitaa.token + for message in messages: + data = { + 'chat_id': chat_id_eitaa, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + +def bot_eitaa_for_each_delete_province_kill_request(entry): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + order_code = entry.province_request.poultry_request.order_code + date_time_jalali = format_datetime_to_shamsi(date) + + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_تخصیصات_حذف_شده #{date_shamsi}\n\n' + base_message += f'❗❗❗❗اصلاحیه تخصیص حذف شده با کد سفارش {order_code}❗❗❗❗\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + + main_quantity = entry.main_quantity + remain_quantity = (entry.main_quantity - entry.total_killed_quantity) if ( + entry.main_quantity - entry.total_killed_quantity) > 0 else 0 + poultry_name = entry.province_request.poultry_request.poultry.unit_name + poultry_mobile = entry.province_request.poultry_request.poultry.user.mobile + + city = entry.province_request.poultry_request.poultry.user.city.name + buyer = entry.kill_request.kill_house.name + buyer_city = entry.kill_request.kill_house.system_address.city.name + buyer_mobile = entry.kill_request.kill_house.kill_house_operator.user.mobile + weight = entry.province_request.poultry_request.Index_weight + + weight_all = entry.total_killed_quantity * weight + main_quantity = "{:,}".format(main_quantity) + remain_quantity = "{:,}".format(remain_quantity) + weight_all = "{:,}".format(int(weight_all)) + + if entry.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif entry.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + elif entry.market == True: + province_type = 'پنل معاملاتی' + else: + province_type = 'اتحادیه' + new_message_part = f'{m}:\n' + new_message_part += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + new_message_part += f"شهر: {city}\n" + new_message_part += f"کد سفارش: {order_code}\n" + new_message_part += f"نوع فروش: {province_type}\n" + new_message_part += f" تعداد تخصیصی :{main_quantity}\n" + new_message_part += f"مانده قابل تخصیص :{remain_quantity}\n" + new_message_part += f"میانگین وزن : {weight}\n" + new_message_part += f"وزن تقریبی :{weight_all}\n" + new_message_part += f"\n" + new_message_part += f"🔴🔴خریدار : {buyer} ({buyer_mobile})\n" + new_message_part += f"شهر خریدار: {buyer_city}\n" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + new_message_part += f'❗❗❗تخصیص با کد سفارش {order_code} حذف شده است❗❗❗' + m += 1 + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + +def bot_eitaa_out_province_live_bar(request, poultry_requests, vet): + chat_id_eitaa = None + if vet: + chat_id_eitaa = TokenEitaaForEachVet.objects.filter(vet_mobile=vet.vet.user.mobile).first() + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + response = poultry_requests + date_time_jalali = format_datetime_to_shamsi(date) + + date_shamsi = shamsi_date(date).replace('-', '_') + out_province = len(poultry_requests) + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_فروش_مرغ_زنده_خارج_استان #{date_shamsi}\n\n' + base_message += f'تعداد کل سفارشات: {out_province}\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + + quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_name = poultry_requests.last().poultry.user.fullname + poultry_mobile = poultry_requests.last().poultry.user.mobile + buyer_fullname = poultry_requests.last().out_province_poultry_request_buyer.fullname + buyer_mobile = poultry_requests.last().out_province_poultry_request_buyer.mobile + buyer_city = poultry_requests.last().out_province_poultry_request_buyer.city + city = poultry_requests.last().poultry.user.city.name + weight = poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + weight = weight / out_province if out_province > 0 else 0 + weight_all = quantity * weight + quantity = "{:,}".format(quantity) + weight_all = "{:,}".format(int(weight_all)) + + new_message_part = f'{m}:\n' + new_message_part += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + new_message_part += f"شهر: {city}\n" + new_message_part += f"🔸 خریدار : {buyer_fullname} ({buyer_mobile})\n" + new_message_part += f"شهر: {buyer_city}\n" + new_message_part += f"میانگین وزن : {weight}\n" + new_message_part += f" تعداد : {quantity}\n" + new_message_part += f" وزن تقریبی : {weight_all}\n" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + m += 1 + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + if chat_id_eitaa: + chat_id_eitaa = chat_id_eitaa.token + for message in messages: + data = { + 'chat_id': chat_id_eitaa, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse(f'{len(messages)} پیام ارسال شد.') + + +def transaction_for_eata(request, transaction): + if transaction.payer_type == 'poultry': + pass + else: + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + if base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f' #گزارش_تراکنش_پرداختی #{date_shamsi}\n' + base_message += f' #استان_{province}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + + from_date = jdatetime.date.fromgregorian( + year=transaction.date.year, + month=transaction.date.month, + day=transaction.date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + union_share = "{:,}".format(transaction.union_share) + company_share = "{:,}".format(transaction.company_share) + guilds_share = "{:,}".format(transaction.guilds_share) + others_share = "{:,}".format(transaction.other_share) + amount = "{:,}".format(transaction.amount) + + if transaction.payer_type == 'kill_house': + if transaction.kill_house.killer == True and transaction.kill_house.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=transaction.kill_house, trash=False) + payer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif transaction.kill_house.killer == True and transaction.kill_house.type == 'public': + payer_type = 'کشتارکن عمومی' + else: + payer_type = 'کشتارگاه' + payer_unit_name = transaction.kill_house.name + else: + payer_type = 'مرغدار' + payer_unit_name = transaction.poultry.unit_name + + new_message_part = f"🟢 پرداخت کننده : {transaction.payer_fullname}\n" + new_message_part += f"🟢 تلفن : {transaction.payer_mobile}\n" + new_message_part += f"🟢 ماهیت پرداخت کننده : {payer_type}\n" + new_message_part += f"🟢 نام واحد : {payer_unit_name}\n" + new_message_part += f"تاریخ پرداخت: {date}\n" + new_message_part += f"مبلغ کل تراکنش: {amount} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔸 سهم اتحادیه مرغدارن : {union_share} ریال \n" + new_message_part += f"🔸 سهم شرکت : {company_share} ریال \n" + new_message_part += f"🔸 سهم صنف پروتئین : {guilds_share} ریال \n" + new_message_part += f"🔸 سهم دامپزشک : {others_share} ریال \n" + new_message_part += f"\n" + if base_url_for_sms_report == 'ma': + new_message_part += f"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + else: + new_message_part += f"‼توجه: سهم صنف پروتئین و مسئول فنی فارم به حساب اتحادیه مرغدارن واریز شد.‼" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id_mali, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse('ok') + + +def daily_cron_job_transaction_for_eata(): + total_wage_info = TotalWageInformation.objects.get(trash=False) + serializer = TotalWageInformationSerializer(total_wage_info).data + total_wage = "{:,}".format(int(serializer['wage_info']['total_wage'])) + total_unpaid_wage = "{:,}".format(int(serializer['wage_info']['total_unpaid_wage'])) + total_paid_wage = "{:,}".format(int(serializer['wage_info']['total_paid_wage'])) + + company_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), None) + company_total_unpaid_wage = "{:,}".format(int(company_unpaid_wage)) if company_unpaid_wage is not None else "0" + company_total_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), None) + company_total_wage = "{:,}".format(int(company_total_wage)) if company_total_wage is not None else "0" + company_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), + None) + company_total_paid_wage = "{:,}".format(int(company_paid_wage)) if company_paid_wage is not None else "0" + + guilds_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), + None) + guilds_total_unpaid_wage = "{:,}".format(int(guilds_unpaid_wage)) if guilds_unpaid_wage is not None else "0" + guilds_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), None) + guilds_total_wage = "{:,}".format(int(guilds_wage)) if guilds_wage is not None else "0" + + guilds_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), + None) + guilds_total_paid_wage = "{:,}".format(int(guilds_paid_wage)) if guilds_paid_wage is not None else "0" + + union_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), None) + union_total_unpaid_wage = "{:,}".format(int(union_unpaid_wage)) if union_unpaid_wage is not None else "0" + union_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), None) + union_total_wage = "{:,}".format(int(union_wage)) if union_wage is not None else "0" + union_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), + None) + union_total_paid_wage = "{:,}".format(int(union_paid_wage)) if union_paid_wage is not None else "0" + + other_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_unpaid_wage = "{:,}".format(int(other_unpaid_wage)) if other_unpaid_wage is not None else "0" + other_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_wage = "{:,}".format(int(other_wage)) if other_wage is not None else "0" + other_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_paid_wage = "{:,}".format(int(other_paid_wage)) if other_paid_wage is not None else "0" + + date = datetime.now().date() + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + + if base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f' #اطلاعات_جامع_تعرفه #{date_shamsi}\n' + base_message += f' #استان_{province}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + + union_share = union_total_paid_wage + company_share = company_total_paid_wage + guilds_share = guilds_total_paid_wage + other_share = other_total_paid_wage + + amount = total_paid_wage + + new_message_part = f"مجموع تعرفه: {total_wage} ریال \n" + new_message_part += f"مجموع پرداختی: {amount} ریال \n" + new_message_part += f"مجموع باقیمانده: {total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔸 کل سهم اتحادیه مرغدارن : {union_total_wage} ریال \n" + new_message_part += f"🔸واریزی سهم اتحادیه مرغدارن : {union_share} ریال \n" + new_message_part += f"🔸مانده سهم اتحادیه مرغدارن : {union_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔹کل سهم شرکت : {company_total_wage} ریال \n" + new_message_part += f"🔹واریزی سهم شرکت : {company_share} ریال \n" + new_message_part += f"🔹مانده سهم شرکت : {company_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔻 کل سهم صنف پروتئین : {guilds_total_wage} ریال \n" + new_message_part += f"🔻 واریزی سهم صنف پروتئین : {guilds_share} ریال \n" + new_message_part += f"🔻 مانده سهم صنف پروتئین : {guilds_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + if base_url_for_sms_report == 'ma': + new_message_part += f"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + else: + new_message_part += f"\n" + new_message_part += f"🔻 کل سهم دامپزشک : {other_total_wage} ریال \n" + new_message_part += f"🔻 واریزی سهم دامپزشک : {other_share} ریال \n" + new_message_part += f"🔻 مانده سهم دامپزشک : {other_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"‼توجه: سهم صنف پروتئین و مسئول فنی فارم به حساب اتحادیه مرغدارن واریز شد.‼" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id_mali, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + +def bot_eitaa_for_bug_reporter(text): + token = "bot363954:e3d4dca2-f1b3-4f44-b5a9-d48aa11c79b8" + chat_id = 10473672 + url = f'https://eitaayar.ir/api/{token}/sendMessage' + t = f"\n" + t += f" {text['result']} \n" + t += f"\n" + t += f"\n" + t += f"عنوان خطا:" + t += f"\n" + t += f"\n" + t += f"{text['error_title']} \n" + t += f"\n" + t += f"\n" + t += f"پیغام خطا:" + t += f"\n" + t += f"\n" + t += f"{text['error_message']} \n" + t += f"\n" + t += f"\n" + t += f"توضیحات بیشتر:" + t += f"\n" + t += f"\n" + t += f"{text['error_traceback']} \n" + + data = { + 'chat_id': chat_id, + 'text': t, + } + response = requests.post(url, data=data, verify=False) + + +def daily_manual_transaction_for_eata(request): + total_wage_info = TotalWageInformation.objects.get(trash=False) + serializer = TotalWageInformationSerializer(total_wage_info).data + total_wage = "{:,}".format(int(serializer['wage_info']['total_wage'])) + total_unpaid_wage = "{:,}".format(int(serializer['wage_info']['total_unpaid_wage'])) + total_paid_wage = "{:,}".format(int(serializer['wage_info']['total_paid_wage'])) + + company_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), None) + company_total_unpaid_wage = "{:,}".format(int(company_unpaid_wage)) if company_unpaid_wage is not None else "0" + company_total_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), None) + company_total_wage = "{:,}".format(int(company_total_wage)) if company_total_wage is not None else "0" + company_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "شرکت"), + None) + company_total_paid_wage = "{:,}".format(int(company_paid_wage)) if company_paid_wage is not None else "0" + + guilds_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), + None) + guilds_total_unpaid_wage = "{:,}".format(int(guilds_unpaid_wage)) if guilds_unpaid_wage is not None else "0" + guilds_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), None) + guilds_total_wage = "{:,}".format(int(guilds_wage)) if guilds_wage is not None else "0" + + guilds_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "صنف پروتئین"), + None) + guilds_total_paid_wage = "{:,}".format(int(guilds_paid_wage)) if guilds_paid_wage is not None else "0" + + union_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), None) + union_total_unpaid_wage = "{:,}".format(int(union_unpaid_wage)) if union_unpaid_wage is not None else "0" + union_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), None) + union_total_wage = "{:,}".format(int(union_wage)) if union_wage is not None else "0" + union_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "اتحادیه"), + None) + union_total_paid_wage = "{:,}".format(int(union_paid_wage)) if union_paid_wage is not None else "0" + + other_unpaid_wage = next( + (share["total_unpaid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_unpaid_wage = "{:,}".format(int(other_unpaid_wage)) if other_unpaid_wage is not None else "0" + other_wage = next( + (share["total_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_wage = "{:,}".format(int(other_wage)) if other_wage is not None else "0" + other_paid_wage = next( + (share["total_paid_wage"] for share in serializer['wage_info']['shares'] if share["name"] == "دامپزشک"), None) + other_total_paid_wage = "{:,}".format(int(other_paid_wage)) if other_paid_wage is not None else "0" + + date = datetime.now().date() + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + + if base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f' #اطلاعات_جامع_تعرفه #{date_shamsi}\n' + base_message += f' #استان_{province}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + + union_share = union_total_paid_wage + company_share = company_total_paid_wage + guilds_share = guilds_total_paid_wage + other_share = other_total_paid_wage + + amount = total_paid_wage + + new_message_part = f"مجموع تعرفه: {total_wage} ریال \n" + new_message_part += f"مجموع پرداختی: {amount} ریال \n" + new_message_part += f"مجموع باقیمانده: {total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔸 کل سهم اتحادیه مرغدارن : {union_total_wage} ریال \n" + new_message_part += f"🔸واریزی سهم اتحادیه مرغدارن : {union_share} ریال \n" + new_message_part += f"🔸مانده سهم اتحادیه مرغدارن : {union_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔹کل سهم شرکت : {company_total_wage} ریال \n" + new_message_part += f"🔹واریزی سهم شرکت : {company_share} ریال \n" + new_message_part += f"🔹مانده سهم شرکت : {company_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔻 کل سهم صنف پروتئین : {guilds_total_wage} ریال \n" + new_message_part += f"🔻 واریزی سهم صنف پروتئین : {guilds_share} ریال \n" + new_message_part += f"🔻 مانده سهم صنف پروتئین : {guilds_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + if base_url_for_sms_report == 'ma': + new_message_part += f"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + else: + new_message_part += f"\n" + new_message_part += f"🔻 کل سهم دامپزشک : {other_total_wage} ریال \n" + new_message_part += f"🔻 واریزی سهم دامپزشک : {other_share} ریال \n" + new_message_part += f"🔻 مانده سهم دامپزشک : {other_total_unpaid_wage} ریال \n" + new_message_part += f"\n" + new_message_part += f"‼توجه: سهم صنف پروتئین و مسئول فنی فارم به حساب اتحادیه مرغدارن واریز شد.‼" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id_mali, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse('ok') + + +def transaction_for_eata_new(request): + transactions = InternalTransaction.objects.filter(trash=False, status='completed', date__date=datetime.now().date()) + for transaction in transactions: + if transaction.payer_type == 'poultry': + pass + else: + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + if base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f' #گزارش_تراکنش_پرداختی #{date_shamsi}\n' + base_message += f' #استان_{province}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + + from_date = jdatetime.date.fromgregorian( + year=transaction.date.year, + month=transaction.date.month, + day=transaction.date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + union_share = "{:,}".format(transaction.union_share) + company_share = "{:,}".format(transaction.company_share) + guilds_share = "{:,}".format(transaction.guilds_share) + others_share = "{:,}".format(transaction.other_share) + amount = "{:,}".format(transaction.amount) + + if transaction.payer_type == 'kill_house': + if transaction.kill_house.killer == True and transaction.kill_house.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=transaction.kill_house, trash=False) + payer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif transaction.kill_house.killer == True and transaction.kill_house.type == 'public': + payer_type = 'کشتارکن عمومی' + else: + payer_type = 'کشتارگاه' + payer_unit_name = transaction.kill_house.name + else: + payer_type = 'مرغدار' + payer_unit_name = transaction.poultry.unit_name + + new_message_part = f"🟢 پرداخت کننده : {transaction.payer_fullname}\n" + new_message_part += f"🟢 تلفن : {transaction.payer_mobile}\n" + new_message_part += f"🟢 ماهیت پرداخت کننده : {payer_type}\n" + new_message_part += f"🟢 نام واحد : {payer_unit_name}\n" + new_message_part += f"تاریخ پرداخت: {date}\n" + new_message_part += f"مبلغ کل تراکنش: {amount} ریال \n" + new_message_part += f"\n" + new_message_part += f"🔸 سهم اتحادیه مرغدارن : {union_share} ریال \n" + new_message_part += f"🔸 سهم شرکت : {company_share} ریال \n" + new_message_part += f"🔸 سهم صنف پروتئین : {guilds_share} ریال \n" + new_message_part += f"🔸 سهم دامپزشک : {others_share} ریال \n" + new_message_part += f"\n" + if base_url_for_sms_report == 'ma': + new_message_part += f"‼توجه: سهم صنف پروتئین به حساب اتحادیه مرغدارن واریز شد.‼" + else: + new_message_part += f"‼توجه: سهم صنف پروتئین و مسئول فنی فارم به حساب اتحادیه مرغدارن واریز شد.‼" + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id_mali, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + return HttpResponse('ok') + + +def daily_report_for_each_vet_farm_manual(request): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + today = datetime.now().date() + date_time_jalali = format_datetime_to_shamsi(today) + date_shamsi = shamsi_date(date1).replace('-', '_') + date_shamsi2 = shamsi_date(date2).replace('-', '_') + + vet_tokens = list( + TokenEitaaForEachVet.objects + .all() + .only("vet_mobile", "token") + .values_list('vet_mobile', flat=True) + .distinct() + ) + if not vet_tokens: + return HttpResponse('no vets') + + vet_farms_qs = VetFarm.objects.filter(trash=False, vet__user__mobile__in=vet_tokens) \ + .only("id", "vet__user__mobile", "poultry__id") + + poultry_qs = Poultry.objects.filter(trash=False, id__in=vet_farms_qs.values_list('poultry__id', flat=True)) \ + .only("id", "unit_name", "breeding_unique_id") + + poultry_map = {p.id: p.breeding_unique_id for p in poultry_qs} + poultry_breeding_ids = set(poultry_map.values()) + + vet_farm_pairs = list(vet_farms_qs.values_list('vet__user__mobile', 'poultry__id')) + breeding_to_vets = {} + for vet_mobile, poultry_id in vet_farm_pairs: + breeding = poultry_map.get(poultry_id) + if breeding: + breeding_to_vets.setdefault(breeding, set()).add(vet_mobile) + + kill_request_qs = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultry_qs + ).only( + "bar_code", "accepted_real_quantity", "clearance_code", "quarantine_quantity", + "quarantine_code_state", + "kill_request__recive_date", + "killhouse_user__name", + "province_request__poultry_request__poultry__unit_name", + ) + + poultry_request_out_qs = PoultryRequest.objects.filter( + trash=False, + out=True, + send_date__date__gte=date1, + send_date__date__lte=date2, + poultry__in=poultry_qs + ).only( + "order_code", "quantity", "send_date", "quarantine_code", + "buyer_fullname", "buyer_province", "buyer_city", + "poultry__unit_name" + ) + + kill_house_request_code_quarantine = list(kill_request_qs.values_list('clearance_code', flat=True).distinct()) + kill_house_free_sale = list(poultry_request_out_qs.filter(quarantine_code__isnull=False) + .values_list('quarantine_code', flat=True).distinct()) + result = list(filter(None, kill_house_request_code_quarantine)) + list(filter(None, kill_house_free_sale)) + + rsi_url = ( + f'https://rsibackend.rasadyar.com/app/send_different_bar/?province={base_url_for_sms_report}' + f'&date1={date1}&date2={date2}' + ) + try: + rsi_resp = requests.post(rsi_url, json=result, headers={'Content-Type': 'application/json'}) + rsi_data = rsi_resp.json() if rsi_resp.status_code == 200 else [] + except Exception: + rsi_data = [] + + diffrent_rsi_by_vet = {vet: {'in': [], 'out': []} for vet in vet_tokens} + + for data in rsi_data: + try: + part_code = data['hatching']['poultry']['PartIdCode'] + except Exception: + continue + if part_code not in breeding_to_vets: + continue + date_str = str(data.get('Date', '')).split('T')[0] + try: + date_n = datetime.strptime(date_str, '%Y-%m-%d').date() + except Exception: + continue + + info = 'کد قرنطینه: {0} - حجم: {1} قطعه-مرغدار:{2} - مقصد بار: {3} - تاریخ بار: ({4})'.format( + data.get('TrackingCode', ''), + to_locale_str(int(data.get('GoodAmount', 0))), + data.get('hatching', {}).get('poultry', {}).get('UnitName', ''), + data.get('DesUnitName', ''), + shamsi_date(date_n), + ) + vets_for_part = breeding_to_vets.get(part_code, set()) + for v in vets_for_part: + if data.get('Out') is False: + diffrent_rsi_by_vet[v]['in'].append(info) + else: + diffrent_rsi_by_vet[v]['out'].append(info) + + for vet_mobile in vet_tokens: + vet_specific_farms_qs = vet_farms_qs.filter(vet__user__mobile=vet_mobile) + if not vet_specific_farms_qs.exists(): + continue + + vet_poultry_ids = list(vet_specific_farms_qs.values_list('poultry__id', flat=True).distinct()) + + vet_kill_request = kill_request_qs.filter( + province_request__poultry_request__poultry__in=vet_poultry_ids + ) + vet_poultry_request_out = poultry_request_out_qs.filter(poultry__in=vet_poultry_ids) + + base_message = ( + '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + f'❗{date_time_jalali}❗\n' + f' #گزارش_بارهای_فاقد_مجوز_از_تاریخ_{date_shamsi}_تا_تاریخ_{date_shamsi2} #\n\n' + f'➖➖➖➖➖➖➖➖➖➖\n' + ) + current_message = base_message + messages = [] + + def _add_text(txt): + nonlocal current_message, messages, base_message + if not txt: + return + if len(current_message) + len(txt) > 4000: + messages.append(current_message) + current_message = base_message + current_message += txt + + in_has_code_qs = vet_kill_request.filter(clearance_code__isnull=False) + in_no_code_qs = vet_kill_request.filter(clearance_code__isnull=True) + in_has_code_count = in_has_code_qs.count() + in_no_code_count = in_no_code_qs.count() + + base_vet_message = 'دامپزشک محترم فارم({0}) گزارش عملکرد بارها به شرح زیر میباشد:\n'.format( + vet_specific_farms_qs.first() + .vet.user.fullname if vet_specific_farms_qs.first() else '-') + _add_text(base_vet_message) + bars_info = [] + for kill_req in in_no_code_qs: + try: + unit_name = kill_req.province_request.poultry_request.poultry.unit_name + except Exception: + unit_name = '' + bars_info.append( + 'کد بار: {0} - حجم: {1} قطعه-مرغدار:{4} - مقصد بار: {2} - تاریخ بار: ({3})'.format( + kill_req.bar_code, + to_locale_str(int(kill_req.accepted_real_quantity or 0)), + getattr(kill_req.killhouse_user, 'name', ''), + shamsi_date(kill_req.kill_request.recive_date) if getattr(kill_req.kill_request, 'recive_date', + None) else '', + unit_name + ) + ) + bars_details = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + diffrent_bars_info = [] + diffrent_qs = in_has_code_qs.filter(~Q(quarantine_quantity=F('quantity'))) + for kill_req in diffrent_qs: + if kill_req.quarantine_quantity: + quarantine_quantity = to_locale_str(int(kill_req.quarantine_quantity)) + diffrent_quantity = to_locale_str( + int(kill_req.quarantine_quantity) - int(kill_req.accepted_real_quantity)) + else: + state = getattr(kill_req, 'quarantine_code_state', None) + if state == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif state == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif state == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + else: + quarantine_quantity = 'ادغام' + diffrent_quantity = 0 + diffrent_bars_info.append( + 'کد بار: {0} - حجم: {1} قطعه-مرغدار:{4} - کد قرنطینه: {2} - استعلام از قرنطینه: ({3})-اختلاف:{6}- تاریخ بار: ({5})'.format( + kill_req.bar_code, + to_locale_str(int(kill_req.accepted_real_quantity or 0)), + kill_req.clearance_code or '', + quarantine_quantity, + getattr(kill_req.province_request.poultry_request.poultry, 'unit_name', ''), + shamsi_date(kill_req.kill_request.recive_date) if getattr(kill_req.kill_request, 'recive_date', + None) else '', + diffrent_quantity + ) + ) + diffrent_bars_details = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(diffrent_bars_info)]) + + new_message_part_in = '❗❗ - تعداد بارهای داخل استان دارای مجوز قرنطینه {0} عدد و تعداد بار های فاقد مجوز {1} عدد میباشد.\n\n'.format( + in_has_code_count, in_no_code_count + ) + if bars_info: + new_message_part_in += "بارهای داخل استان فاقد قرنطینه به شرح زیر میباشد:\n" + new_message_part_in += f"{bars_details}\n" + new_message_part_in += "--------------------------------\n" + if diffrent_bars_info: + new_message_part_in += "از بارهای داخل استان دارای مجوز تعداد {} بار دارای مغایرت در داده هستند:\n".format( + diffrent_qs.count()) + new_message_part_in += f"{diffrent_bars_details}\n" + new_message_part_in += "--------------------------------\n" + + rsi_in_list = diffrent_rsi_by_vet.get(vet_mobile, {}).get('in', []) + if rsi_in_list: + new_message_part_in += "با توجه به رصد هوش مصنوعی سامانه تعداد {} بار داخل استان در سامانه رصدیار ثبت نشده است:\n".format( + len(rsi_in_list)) + new_message_part_in += "\n".join([f"{i + 1}. {it}" for i, it in enumerate(rsi_in_list)]) + new_message_part_in += "\n--------------------------------\n" + + new_message_part_in += "\n➖➖➖➖➖➖➖➖➖➖\n" + + _add_text(new_message_part_in) + + out_has_code_count = vet_poultry_request_out.filter(quarantine_code__isnull=False).count() + out_no_code_qs = vet_poultry_request_out.filter(quarantine_code__isnull=True) + out_no_code_count = out_no_code_qs.count() + + bars_info_out = [] + for poultry_req in out_no_code_qs: + bars_info_out.append( + 'کد سفارش: {0} - حجم: {1} قطعه-مرغدار:{4} - خریدار: {2} - استان خریدار:{5} - شهر خریدار:{6} - تاریخ بار: ({3})'.format( + poultry_req.order_code, + to_locale_str(int(poultry_req.quantity or 0)), + poultry_req.buyer_fullname or '', + shamsi_date(poultry_req.send_date) if getattr(poultry_req, 'send_date', None) else '', + getattr(poultry_req.poultry, 'unit_name', ''), + poultry_req.buyer_province or '', + poultry_req.buyer_city or '', + ) + ) + bars_details_out = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info_out)]) + + new_message_part_out = '❗❗ - تعداد بارهای خارج استان دارای مجوز قرنطینه {0} عدد و تعداد بار های فاقد مجوز {1} عدد میباشد.\n\n'.format( + out_has_code_count, out_no_code_count + ) + if bars_info_out: + new_message_part_out += "بارهای خارج استان فاقد قرنطینه به شرح زیر میباشد:\n" + new_message_part_out += f"{bars_details_out}\n" + new_message_part_out += "--------------------------------\n" + + rsi_out_list = diffrent_rsi_by_vet.get(vet_mobile, {}).get('out', []) + if rsi_out_list: + new_message_part_out += "با توجه به رصد هوش مصنوعی سامانه تعداد {} بار خارج استان در سامانه رصدیار ثبت نشده است:\n".format( + len(rsi_out_list)) + new_message_part_out += "\n".join([f"{i + 1}. {it}" for i, it in enumerate(rsi_out_list)]) + new_message_part_out += "\n--------------------------------\n" + + new_message_part_out += "\n➖➖➖➖➖➖➖➖➖➖\n" + + _add_text(new_message_part_out) + + if current_message and current_message != base_message: + messages.append(current_message) + + chat_token = TokenEitaaForEachVet.objects.filter(vet_mobile=vet_mobile).values_list('token', flat=True).first() + if chat_token and messages: + for message in messages: + try: + requests.post(url, data={'chat_id': chat_token, 'text': message}, verify=False) + except Exception: + pass + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + return HttpResponse('ok') + + +def daily_report_for_each_vet_farm_cron(): + today = datetime.now().date() - timedelta(days=1) + + date1 = today + date2 = today + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date_time_jalali = format_datetime_to_shamsi(today) + date_shamsi = shamsi_date(date1).replace('-', '_') + date_shamsi2 = shamsi_date(date2).replace('-', '_') + + vet_tokens = list( + TokenEitaaForEachVet.objects + .all() + .only("vet_mobile", "token") + .values_list('vet_mobile', flat=True) + .distinct() + ) + if not vet_tokens: + return HttpResponse('no vets') + + vet_farms_qs = VetFarm.objects.filter(trash=False, vet__user__mobile__in=vet_tokens) \ + .only("id", "vet__user__mobile", "poultry__id") + + poultry_qs = Poultry.objects.filter(trash=False, id__in=vet_farms_qs.values_list('poultry__id', flat=True)) \ + .only("id", "unit_name", "breeding_unique_id") + + poultry_map = {p.id: p.breeding_unique_id for p in poultry_qs} + poultry_breeding_ids = set(poultry_map.values()) + + vet_farm_pairs = list(vet_farms_qs.values_list('vet__user__mobile', 'poultry__id')) + breeding_to_vets = {} + for vet_mobile, poultry_id in vet_farm_pairs: + breeding = poultry_map.get(poultry_id) + if breeding: + breeding_to_vets.setdefault(breeding, set()).add(vet_mobile) + + kill_request_qs = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultry_qs + ).only( + "bar_code", "accepted_real_quantity", "clearance_code", "quarantine_quantity", + "quarantine_code_state", + "kill_request__recive_date", + "killhouse_user__name", + "province_request__poultry_request__poultry__unit_name", + ) + + poultry_request_out_qs = PoultryRequest.objects.filter( + trash=False, + out=True, + send_date__date__gte=date1, + send_date__date__lte=date2, + poultry__in=poultry_qs + ).only( + "order_code", "quantity", "send_date", "quarantine_code", + "buyer_fullname", "buyer_province", "buyer_city", + "poultry__unit_name" + ) + + kill_house_request_code_quarantine = list(kill_request_qs.values_list('clearance_code', flat=True).distinct()) + kill_house_free_sale = list(poultry_request_out_qs.filter(quarantine_code__isnull=False) + .values_list('quarantine_code', flat=True).distinct()) + result = list(filter(None, kill_house_request_code_quarantine)) + list(filter(None, kill_house_free_sale)) + + rsi_url = ( + f'https://rsibackend.rasadyar.com/app/send_different_bar/?province={base_url_for_sms_report}' + f'&date1={date1}&date2={date2}' + ) + try: + rsi_resp = requests.post(rsi_url, json=result, headers={'Content-Type': 'application/json'}) + rsi_data = rsi_resp.json() if rsi_resp.status_code == 200 else [] + except Exception: + rsi_data = [] + + diffrent_rsi_by_vet = {vet: {'in': [], 'out': []} for vet in vet_tokens} + + for data in rsi_data: + try: + part_code = data['hatching']['poultry']['PartIdCode'] + except Exception: + continue + if part_code not in breeding_to_vets: + continue + date_str = str(data.get('Date', '')).split('T')[0] + try: + date_n = datetime.strptime(date_str, '%Y-%m-%d').date() + except Exception: + continue + + info = 'کد قرنطینه: {0} - حجم: {1} قطعه-مرغدار:{2} - مقصد بار: {3} - تاریخ بار: ({4})'.format( + data.get('TrackingCode', ''), + to_locale_str(int(data.get('GoodAmount', 0))), + data.get('hatching', {}).get('poultry', {}).get('UnitName', ''), + data.get('DesUnitName', ''), + shamsi_date(date_n), + ) + vets_for_part = breeding_to_vets.get(part_code, set()) + for v in vets_for_part: + if data.get('Out') is False: + diffrent_rsi_by_vet[v]['in'].append(info) + else: + diffrent_rsi_by_vet[v]['out'].append(info) + + for vet_mobile in vet_tokens: + vet_specific_farms_qs = vet_farms_qs.filter(vet__user__mobile=vet_mobile) + if not vet_specific_farms_qs.exists(): + continue + + vet_poultry_ids = list(vet_specific_farms_qs.values_list('poultry__id', flat=True).distinct()) + + vet_kill_request = kill_request_qs.filter( + province_request__poultry_request__poultry__in=vet_poultry_ids + ) + vet_poultry_request_out = poultry_request_out_qs.filter(poultry__in=vet_poultry_ids) + + base_message = ( + '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + f'❗{date_time_jalali}❗\n' + f' #گزارش_بارهای_فاقد_مجوز_از_تاریخ_{date_shamsi}_تا_تاریخ_{date_shamsi2} #\n\n' + f'➖➖➖➖➖➖➖➖➖➖\n' + ) + current_message = base_message + messages = [] + + def _add_text(txt): + nonlocal current_message, messages, base_message + if not txt: + return + if len(current_message) + len(txt) > 4000: + messages.append(current_message) + current_message = base_message + current_message += txt + + in_has_code_qs = vet_kill_request.filter(clearance_code__isnull=False) + in_no_code_qs = vet_kill_request.filter(clearance_code__isnull=True) + in_has_code_count = in_has_code_qs.count() + in_no_code_count = in_no_code_qs.count() + + base_vet_message = 'دامپزشک محترم فارم({0}) گزارش عملکرد بارها به شرح زیر میباشد:\n'.format( + vet_specific_farms_qs.first() + .vet.user.fullname if vet_specific_farms_qs.first() else '-') + _add_text(base_vet_message) + bars_info = [] + for kill_req in in_no_code_qs: + try: + unit_name = kill_req.province_request.poultry_request.poultry.unit_name + except Exception: + unit_name = '' + bars_info.append( + 'کد بار: {0} - حجم: {1} قطعه-مرغدار:{4} - مقصد بار: {2} - تاریخ بار: ({3})'.format( + kill_req.bar_code, + to_locale_str(int(kill_req.accepted_real_quantity or 0)), + getattr(kill_req.killhouse_user, 'name', ''), + shamsi_date(kill_req.kill_request.recive_date) if getattr(kill_req.kill_request, 'recive_date', + None) else '', + unit_name + ) + ) + bars_details = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + + diffrent_bars_info = [] + diffrent_qs = in_has_code_qs.filter(~Q(quarantine_quantity=F('quantity'))) + for kill_req in diffrent_qs: + if kill_req.quarantine_quantity: + quarantine_quantity = to_locale_str(int(kill_req.quarantine_quantity)) + diffrent_quantity = to_locale_str( + int(kill_req.quarantine_quantity) - int(kill_req.accepted_real_quantity)) + else: + state = getattr(kill_req, 'quarantine_code_state', None) + if state == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif state == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif state == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + else: + quarantine_quantity = 'ادغام' + diffrent_quantity = 0 + diffrent_bars_info.append( + 'کد بار: {0} - حجم: {1} قطعه-مرغدار:{4} - کد قرنطینه: {2} - استعلام از قرنطینه: ({3})-اختلاف:{6}- تاریخ بار: ({5})'.format( + kill_req.bar_code, + to_locale_str(int(kill_req.accepted_real_quantity or 0)), + kill_req.clearance_code or '', + quarantine_quantity, + getattr(kill_req.province_request.poultry_request.poultry, 'unit_name', ''), + shamsi_date(kill_req.kill_request.recive_date) if getattr(kill_req.kill_request, 'recive_date', + None) else '', + diffrent_quantity + ) + ) + diffrent_bars_details = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(diffrent_bars_info)]) + + new_message_part_in = '❗❗ - تعداد بارهای داخل استان دارای مجوز قرنطینه {0} عدد و تعداد بار های فاقد مجوز {1} عدد میباشد.\n\n'.format( + in_has_code_count, in_no_code_count + ) + if bars_info: + new_message_part_in += "بارهای داخل استان فاقد قرنطینه به شرح زیر میباشد:\n" + new_message_part_in += f"{bars_details}\n" + new_message_part_in += "--------------------------------\n" + if diffrent_bars_info: + new_message_part_in += "از بارهای داخل استان دارای مجوز تعداد {} بار دارای مغایرت در داده هستند:\n".format( + diffrent_qs.count()) + new_message_part_in += f"{diffrent_bars_details}\n" + new_message_part_in += "--------------------------------\n" + + rsi_in_list = diffrent_rsi_by_vet.get(vet_mobile, {}).get('in', []) + if rsi_in_list: + new_message_part_in += "با توجه به رصد هوش مصنوعی سامانه تعداد {} بار داخل استان در سامانه رصدیار ثبت نشده است:\n".format( + len(rsi_in_list)) + new_message_part_in += "\n".join([f"{i + 1}. {it}" for i, it in enumerate(rsi_in_list)]) + new_message_part_in += "\n--------------------------------\n" + + new_message_part_in += "\n➖➖➖➖➖➖➖➖➖➖\n" + + _add_text(new_message_part_in) + + out_has_code_count = vet_poultry_request_out.filter(quarantine_code__isnull=False).count() + out_no_code_qs = vet_poultry_request_out.filter(quarantine_code__isnull=True) + out_no_code_count = out_no_code_qs.count() + + bars_info_out = [] + for poultry_req in out_no_code_qs: + bars_info_out.append( + 'کد سفارش: {0} - حجم: {1} قطعه-مرغدار:{4} - خریدار: {2} - استان خریدار:{5} - شهر خریدار:{6} - تاریخ بار: ({3})'.format( + poultry_req.order_code, + to_locale_str(int(poultry_req.quantity or 0)), + poultry_req.buyer_fullname or '', + shamsi_date(poultry_req.send_date) if getattr(poultry_req, 'send_date', None) else '', + getattr(poultry_req.poultry, 'unit_name', ''), + poultry_req.buyer_province or '', + poultry_req.buyer_city or '', + ) + ) + bars_details_out = "\n".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info_out)]) + + new_message_part_out = '❗❗ - تعداد بارهای خارج استان دارای مجوز قرنطینه {0} عدد و تعداد بار های فاقد مجوز {1} عدد میباشد.\n\n'.format( + out_has_code_count, out_no_code_count + ) + if bars_info_out: + new_message_part_out += "بارهای خارج استان فاقد قرنطینه به شرح زیر میباشد:\n" + new_message_part_out += f"{bars_details_out}\n" + new_message_part_out += "--------------------------------\n" + + rsi_out_list = diffrent_rsi_by_vet.get(vet_mobile, {}).get('out', []) + if rsi_out_list: + new_message_part_out += "با توجه به رصد هوش مصنوعی سامانه تعداد {} بار خارج استان در سامانه رصدیار ثبت نشده است:\n".format( + len(rsi_out_list)) + new_message_part_out += "\n".join([f"{i + 1}. {it}" for i, it in enumerate(rsi_out_list)]) + new_message_part_out += "\n--------------------------------\n" + + new_message_part_out += "\n➖➖➖➖➖➖➖➖➖➖\n" + + _add_text(new_message_part_out) + + if current_message and current_message != base_message: + messages.append(current_message) + + chat_token = TokenEitaaForEachVet.objects.filter(vet_mobile=vet_mobile).values_list('token', flat=True).first() + if chat_token and messages: + for message in messages: + try: + requests.post(url, data={'chat_id': chat_token, 'text': message}, verify=False) + except Exception: + pass + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + +def send_all_bar_to_eitaa(request): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + + all_kill_house_requests = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date=date + ).select_related( + 'province_request__poultry_request__poultry__user__city', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city', + 'add_car__driver' + ) + + poultry_ids = all_kill_house_requests.values_list( + 'province_request__poultry_request__poultry__id', + flat=True + ).distinct() + + vet_farms = VetFarm.objects.filter( + trash=False, + poultry__id__in=poultry_ids + ).select_related('vet__user', 'poultry') + + vet_to_poultries = {} + for vet_farm in vet_farms: + vet_mobile = vet_farm.vet.user.mobile + if vet_mobile not in vet_to_poultries: + vet_to_poultries[vet_mobile] = [] + vet_to_poultries[vet_mobile].append(vet_farm.poultry.id) + + if not vet_to_poultries: + return HttpResponse('هیچ دامپزشکی یافت نشد.') + + for vet_mobile, poultry_list in vet_to_poultries.items(): + chat_id_eitaa = TokenEitaaForEachVet.objects.filter(vet_mobile=vet_mobile).first() + + if not chat_id_eitaa: + continue + + vet_kill_requests = all_kill_house_requests.filter( + province_request__poultry_request__poultry__id__in=poultry_list + ) + + if not vet_kill_requests.exists(): + continue + + date_time_jalali = format_datetime_to_shamsi(date) + date_shamsi = shamsi_date(date).replace('-', '_') + + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_بارها #{date_shamsi}\n\n' + base_message += f'تعداد کل بارها: {vet_kill_requests.count()}\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + + for entry in vet_kill_requests: + try: + main_quantity = entry.accepted_real_quantity + real_weight = entry.accepted_real_weight + poultry_name = entry.province_request.poultry_request.poultry.unit_name + poultry_mobile = entry.province_request.poultry_request.poultry.user.mobile + + city = entry.province_request.poultry_request.poultry.user.city.name + buyer = entry.kill_request.kill_house.name + buyer_city = entry.kill_request.kill_house.system_address.city.name + buyer_mobile = entry.kill_request.kill_house.kill_house_operator.user.mobile + weight = entry.province_request.poultry_request.Index_weight + order_code = entry.bar_code + recive_date = entry.kill_request.recive_date + recive_date_shamsi = shamsi_date(recive_date) if recive_date else '' + main_quantity = "{:,}".format(int(main_quantity)) + real_weight = "{:,}".format(int(real_weight)) + + driver_name = '-' + driver_mobile = '-' + driver_pelak = '-' + driver_health_code = '-' + if entry.add_car and entry.add_car.driver: + driver_name = entry.add_car.driver.driver_name or '-' + driver_mobile = entry.add_car.driver.driver_mobile or '-' + driver_pelak = entry.add_car.driver.pelak or '-' + driver_health_code = entry.add_car.driver.health_code or '-' + + if entry.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif entry.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + else: + province_type = 'اتحادیه' + + driver_info = f' - راننده: {driver_name} ({driver_mobile}) پلاک: {driver_pelak} کد حمل: {driver_health_code}' + + new_message_part = f'{m}. کد بار: {order_code} - حجم بار: {main_quantity} قطعه - وزن بار: {real_weight} - میانگین وزن: {weight} - مرغدار: {poultry_name} ({poultry_mobile}) - شهر: {city} - نوع فروش: {province_type} - خریدار: {buyer} ({buyer_mobile}) - شهر خریدار: {buyer_city}{driver_info} - تاریخ بار: ({recive_date_shamsi})\n\n' + m += 1 + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + except Exception as e: + continue + + if current_message and current_message != base_message: + messages.append(current_message) + + chat_id_eitaa_token = chat_id_eitaa.token + for message in messages: + try: + data = { + 'chat_id': chat_id_eitaa_token, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + except Exception: + pass + + return HttpResponse('پیام‌ها ارسال شد.') + + +def send_all_bar_to_eitaa_cron(): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + + all_kill_house_requests = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date=date + ).select_related( + 'province_request__poultry_request__poultry__user__city', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city', + 'add_car__driver' + ) + + poultry_ids = all_kill_house_requests.values_list( + 'province_request__poultry_request__poultry__id', + flat=True + ).distinct() + + vet_farms = VetFarm.objects.filter( + trash=False, + poultry__id__in=poultry_ids + ).select_related('vet__user', 'poultry') + + vet_to_poultries = {} + for vet_farm in vet_farms: + vet_mobile = vet_farm.vet.user.mobile + if vet_mobile not in vet_to_poultries: + vet_to_poultries[vet_mobile] = [] + vet_to_poultries[vet_mobile].append(vet_farm.poultry.id) + + if not vet_to_poultries: + return + + for vet_mobile, poultry_list in vet_to_poultries.items(): + chat_id_eitaa = TokenEitaaForEachVet.objects.filter(vet_mobile=vet_mobile).first() + + if not chat_id_eitaa: + continue + + vet_kill_requests = all_kill_house_requests.filter( + province_request__poultry_request__poultry__id__in=poultry_list + ) + + if not vet_kill_requests.exists(): + continue + + date_time_jalali = format_datetime_to_shamsi(date) + date_shamsi = shamsi_date(date).replace('-', '_') + + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_بارها #{date_shamsi}\n\n' + base_message += f'تعداد کل بارها: {vet_kill_requests.count()}\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + m = 1 + + for entry in vet_kill_requests: + try: + main_quantity = entry.accepted_real_quantity + real_weight = entry.accepted_real_weight + poultry_name = entry.province_request.poultry_request.poultry.unit_name + poultry_mobile = entry.province_request.poultry_request.poultry.user.mobile + + city = entry.province_request.poultry_request.poultry.user.city.name + buyer = entry.kill_request.kill_house.name + buyer_city = entry.kill_request.kill_house.system_address.city.name + buyer_mobile = entry.kill_request.kill_house.kill_house_operator.user.mobile + weight = entry.province_request.poultry_request.Index_weight + order_code = entry.bar_code + recive_date = entry.kill_request.recive_date + recive_date_shamsi = shamsi_date(recive_date) if recive_date else '' + main_quantity = "{:,}".format(int(main_quantity)) + real_weight = "{:,}".format(int(real_weight)) + + driver_name = '-' + driver_mobile = '-' + driver_pelak = '-' + driver_health_code = '-' + if entry.add_car and entry.add_car.driver: + driver_name = entry.add_car.driver.driver_name or '-' + driver_mobile = entry.add_car.driver.driver_mobile or '-' + driver_pelak = entry.add_car.driver.pelak or '-' + driver_health_code = entry.add_car.driver.health_code or '-' + + if entry.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif entry.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + else: + province_type = 'اتحادیه' + + driver_info = f' - راننده: {driver_name} ({driver_mobile}) پلاک: {driver_pelak} کد حمل: {driver_health_code}' + + new_message_part = f'{m}. کد بار: {order_code} - حجم بار: {main_quantity} قطعه - وزن بار: {real_weight} - میانگین وزن: {weight} - مرغدار: {poultry_name} ({poultry_mobile}) - شهر: {city} - نوع فروش: {province_type} - خریدار: {buyer} ({buyer_mobile}) - شهر خریدار: {buyer_city}{driver_info} - تاریخ بار: ({recive_date_shamsi})\n\n' + m += 1 + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + except Exception as e: + continue + + if current_message and current_message != base_message: + messages.append(current_message) + + chat_id_eitaa_token = chat_id_eitaa.token + for message in messages: + try: + data = { + 'chat_id': chat_id_eitaa_token, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + except Exception: + pass + + return HttpResponse('پیام‌ها ارسال شد.') + + +def send_single_bar_to_eitaa(kill_house_request): + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.now().date() + + if not kill_house_request: + return + + poultry = kill_house_request.province_request.poultry_request.poultry + + vet_farm = VetFarm.objects.filter( + trash=False, + poultry=poultry + ).select_related('vet__user').first() + + if not vet_farm: + return + + vet_mobile = vet_farm.vet.user.mobile + + chat_id_eitaa = TokenEitaaForEachVet.objects.filter(vet_mobile=vet_mobile).first() + + if not chat_id_eitaa: + return + + date_time_jalali = format_datetime_to_shamsi(date) + date_shamsi = shamsi_date(date).replace('-', '_') + + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f'❗{date_time_jalali}❗\n' + base_message += f' #گزارش_بار_جدید #{date_shamsi}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + try: + main_quantity = kill_house_request.accepted_real_quantity + real_weight = kill_house_request.accepted_real_weight + poultry_name = kill_house_request.province_request.poultry_request.poultry.unit_name + poultry_mobile = kill_house_request.province_request.poultry_request.poultry.user.mobile + + city = kill_house_request.province_request.poultry_request.poultry.user.city.name + buyer = kill_house_request.kill_request.kill_house.name + buyer_city = kill_house_request.kill_request.kill_house.system_address.city.name + buyer_mobile = kill_house_request.kill_request.kill_house.kill_house_operator.user.mobile + weight = kill_house_request.province_request.poultry_request.Index_weight + order_code = kill_house_request.bar_code + main_quantity = "{:,}".format(int(main_quantity)) + real_weight = "{:,}".format(int(real_weight)) + + if kill_house_request.province_request.poultry_request.direct_buying == True: + province_type = 'خرید مستقیم' + elif kill_house_request.province_request.poultry_request.export == True: + province_type = 'فروش به خارج استان' + else: + province_type = 'اتحادیه' + + message = base_message + message += f"🟢 مرغدار : {poultry_name} ({poultry_mobile})\n" + message += f"شهر: {city}\n" + message += f"کد بار: {order_code}\n" + message += f"نوع فروش: {province_type}\n" + message += f" حجم بار :{main_quantity}\n" + message += f" وزن بار :{real_weight}\n" + message += f"میانگین وزن : {weight}\n" + message += f"\n" + message += f"🔴🔴خریدار : {buyer} ({buyer_mobile})\n" + message += f"شهر خریدار: {buyer_city}\n" + message += '\n➖➖➖➖➖➖➖➖➖➖\n' + + chat_id_eitaa_token = chat_id_eitaa.token + data = { + 'chat_id': chat_id_eitaa_token, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + except Exception as e: + pass \ No newline at end of file diff --git a/cancel_bar_and_provice_request.py b/cancel_bar_and_provice_request.py new file mode 100644 index 0000000..23f196f --- /dev/null +++ b/cancel_bar_and_provice_request.py @@ -0,0 +1,12 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from panel.ReportingPanel.views import archive_kill_house_remain_limitation_weight_cron + + +archive_kill_house_remain_limitation_weight_cron() diff --git a/cron_gid.py b/cron_gid.py new file mode 100644 index 0000000..c459c8f --- /dev/null +++ b/cron_gid.py @@ -0,0 +1,14 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") +django.setup() +from panel.ReportingPanel.views import cron_find_gid_code +from authentication.register import fix_duplicate_order_code_cron +from panel.excel_processing import test_all_excel_functions_cron + + +cron_find_gid_code() +test_all_excel_functions_cron() +# fix_duplicate_order_code_cron() \ No newline at end of file diff --git a/cron_out_province_request.py b/cron_out_province_request.py new file mode 100644 index 0000000..a871429 --- /dev/null +++ b/cron_out_province_request.py @@ -0,0 +1,15 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from authentication.register import canceled_out_province_request +from bot_eata import send_all_bar_to_eitaa_cron +from authentication.sms_management import send_daily_slaughter_statistics_sms + +canceled_out_province_request() +# send_all_bar_to_eitaa_cron() +# send_daily_slaughter_statistics_sms() \ No newline at end of file diff --git a/cron_report.py b/cron_report.py new file mode 100644 index 0000000..64a01f2 --- /dev/null +++ b/cron_report.py @@ -0,0 +1,15 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() +from authentication.sms_management import reporting_sms +from authentication.register import add_to_warehouse, add_free_bar_to_warehouse, \ + add_free_bar_to_warehouse_automatic_type_cron + +reporting_sms() +# add_to_warehouse() +# add_free_bar_to_warehouse() +#add_free_bar_to_warehouse_automatic_type_cron() \ No newline at end of file diff --git a/cron_return_archive.py b/cron_return_archive.py new file mode 100644 index 0000000..51fab6d --- /dev/null +++ b/cron_return_archive.py @@ -0,0 +1,11 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from authentication.register import return_from_archive_poultry_hatching_with_cron_job + +return_from_archive_poultry_hatching_with_cron_job() \ No newline at end of file diff --git a/cron_send_sms_from_notif.py b/cron_send_sms_from_notif.py new file mode 100644 index 0000000..209ba55 --- /dev/null +++ b/cron_send_sms_from_notif.py @@ -0,0 +1,11 @@ + +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() +from panel.ReportingPanel.views import send_sms_for_poultry_from_age_notification + +send_sms_for_poultry_from_age_notification() \ No newline at end of file diff --git a/cron_seven_am.py b/cron_seven_am.py new file mode 100644 index 0000000..bdf705c --- /dev/null +++ b/cron_seven_am.py @@ -0,0 +1,19 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from authentication.register import update_chicken_age_from_login, \ + fix_duplicate_order_code_new_cron +from panel.ReportingPanel.views import remove_access_token +from ticket.views import closed_unread_ticket_cron + + +update_chicken_age_from_login() +remove_access_token() +# fix_duplicate_order_code_new_cron() + +# closed_unread_ticket_cron() diff --git a/cron_sms.py b/cron_sms.py new file mode 100644 index 0000000..3d3e8bf --- /dev/null +++ b/cron_sms.py @@ -0,0 +1,16 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from authentication.sms_management import send_gate_way_sms, send_deactivate_panel_debt_sms,cron_for_update_sms +from authentication.register import accept_bar_difference_request_pending_cron_job + +send_gate_way_sms() +send_deactivate_panel_debt_sms() +cron_for_update_sms() +accept_bar_difference_request_pending_cron_job() + diff --git a/delete_kill_request_cron.py b/delete_kill_request_cron.py new file mode 100644 index 0000000..94ef314 --- /dev/null +++ b/delete_kill_request_cron.py @@ -0,0 +1,12 @@ +import os + +import django + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from panel.ReportingPanel.views import delete_kill_req_cron, delete_steward_allocation_cron + +delete_kill_req_cron() +# delete_steward_allocation_cron() diff --git a/deposit_id.py b/deposit_id.py new file mode 100644 index 0000000..a837214 --- /dev/null +++ b/deposit_id.py @@ -0,0 +1,25 @@ +arta_deposit_id = 1945299661 +company_shaba_id = 'IR200120020000009055694184' +# arta_deposit_id=9700383709 +sha_deposit_id = 1031990414 +ha_deposit_id = 318967648 +ha_shaba_id = 'IR540160000000000318967648' +ar_deposit_id = 101866861 +ma_deposit_id = 656171877 +ma_shaba_id = 'IR580160000000000656171877' +guilds_deposit_id = 1945299661 +test_guild_shaba_id = 'IR200120020000009055694184' +ma_guild_shaba_id = 'IR200120020000009055694184' +ha_guild_shaba_id = 'IR540160000000000318967648' +ha_other_shaba_id = 'IR310700010001106549058001' +ma_other_shaba_id = 'IR740660000000203705208007' +test_other_shaba_id = 'IR740660000000203705208007' +# test_other_shaba_id='IR200120020000009055694184' +wage_counting_type = 'carcass' +out_selling_ignore = True +new_out_selling_count_wage = True +new_out_selling_count_wage_date = '2025-08-07' +before_out_buying_count_wage_amount = 1000 +extra_company_amount = 200 +province_id = '50' +market_code_state = True diff --git a/deposit_percent.py b/deposit_percent.py new file mode 100644 index 0000000..e92d396 --- /dev/null +++ b/deposit_percent.py @@ -0,0 +1,13 @@ +arta_sha_deposit_percent = 25 / 100 +guilds_sha_deposit_percent = 25 / 100 +arta_ha_deposit_percent = 25 / 100 +guilds_ha_deposit_percent = 15 / 100 +arta_ar_deposit_percent = 15 / 100 +arta_ma_deposit_percent = 25 / 100 +guilds_ma_deposit_percent = 25 / 100 +sha_deposit_percent = 50 / 100 +ha_deposit_percent = 60 / 100 +ar_deposit_percent = 85 / 100 +ma_deposit_percent = 50 / 100 +wage_percent=25/100 +carcases_sell=True \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..57fabf6 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,7 @@ +services: + web: + build: ./ + volumes: + - .:/app + ports: + - "8000:8000" \ No newline at end of file diff --git a/every_12_hours.py b/every_12_hours.py new file mode 100644 index 0000000..77c9bfb --- /dev/null +++ b/every_12_hours.py @@ -0,0 +1,16 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() + +from authentication.register import warning_province_kill_request_without_bar_cron, \ + warning_to_warehouse_cron, warning_free_bar_to_warehouse_cron +from panel.ReportingPanel.views import create_update_chicken_commission_prices_cron + +# warning_province_kill_request_without_bar_cron() +# warning_to_warehouse_cron() +# warning_free_bar_to_warehouse_cron() +# create_update_chicken_commission_prices_cron \ No newline at end of file diff --git a/general_urls.py b/general_urls.py new file mode 100644 index 0000000..b3f2455 --- /dev/null +++ b/general_urls.py @@ -0,0 +1,11 @@ +# کلاینت سیکرت برای سیستم ورود و ثبت نام بر اساس توکن +CLIENT_SECRET = "M3pBv8nUjHTH9UlWsHy8gW0fPKqiJhhV1aMqMFjzIgAjphBRApj7yBUB1HWQ6ZPafO6seTzafGU7Z8JPFglaSRwRCxV2GTvVYyWVahXdEu4e0hZxc0gUgLf2DA7e2zmr" +# کلاینت ای دی برای سیستم ورود و ثبت نام بر اساس توکن +CLIENT_ID = "nNgiZ19e9tiH0o6jjPfcTyhVGnPaLa9De4Tztiex" + +BASE_URL = "https://kubackend.rasadyar.com/api/" +base_pos_id = 'ku' +base_user_gate_way_id = 'k' + +base_url_sms = 'ku' +base_url_for_sms_report = 'ku' diff --git a/helper_eata.py b/helper_eata.py new file mode 100644 index 0000000..5f41e17 --- /dev/null +++ b/helper_eata.py @@ -0,0 +1,3 @@ +token = 'bot291669:9298e675-8b3c-4b8f-a69d-5c89a3f0bdde' +chat_id = '10046800' +chat_id_mali = '10046800' \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..5596b44 --- /dev/null +++ b/main.py @@ -0,0 +1,16 @@ +# This is a sample Python script. + +# Press Shift+F10 to execute it or replace it with your code. +# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings. + + +def print_hi(name): + # Use a breakpoint in the code line below to debug your script. + print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint. + + +# Press the green button in the gutter to run the script. +if __name__ == '__main__': + print_hi('PyCharm') + +# See PyCharm help at https://www.jetbrains.com/help/pycharm/ diff --git a/manage.py b/manage.py new file mode 100644 index 0000000..580656c --- /dev/null +++ b/manage.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'KuChicken.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/notification/__init__.py b/notification/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notification/admin.py b/notification/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/notification/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/notification/apps.py b/notification/apps.py new file mode 100644 index 0000000..8757bbe --- /dev/null +++ b/notification/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class NotificationConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'notification' diff --git a/notification/consumers.py b/notification/consumers.py new file mode 100644 index 0000000..5ce2237 --- /dev/null +++ b/notification/consumers.py @@ -0,0 +1,48 @@ +# chat/consumers.py + +from channels.generic.websocket import AsyncWebsocketConsumer +import json + +from core.tools import translate_text + + +class ChatConsumer(AsyncWebsocketConsumer): + async def connect(self): + # print(self.scope["session"]["_auth_user_id"]) + print("here connect method started!") + # user_id = self.scope["session"]["_auth_user_id"] + user_id = self.scope['user'] + if user_id.is_anonymous: + await self.disconnect(0) + else: + print("user_id first is ::::::, ", user_id) + user_id = user_id.id + print("user_id is::::::", user_id) + self.group_name = "{}".format(user_id) + # Join room group + await self.channel_layer.group_add(self.group_name, self.channel_name) + await self.accept() + + async def disconnect(self, close_code): + # Leave room group + await self.channel_layer.group_discard(self.group_name, self.channel_name) + + # Receive message from WebSocket + async def receive(self, text_data=None, bytes_data=None): + + text_data_json = json.loads(text_data) + message = text_data_json["message"] + # print("msg is: ", message) + # message = translate_text(message) + # Send message to room group + await self.channel_layer.group_send( + self.chat_group_name, {"type": "recieve_group_message", "message": message} + ) + + async def recieve_group_message(self, event): + message = event["message"] + # print("msg is: ", message) + + # message = translate_text(message) + # Send message to WebSocket + await self.send(text_data=json.dumps({"message": message})) diff --git a/notification/middleware.py b/notification/middleware.py new file mode 100644 index 0000000..f5ed30a --- /dev/null +++ b/notification/middleware.py @@ -0,0 +1,56 @@ +from urllib.parse import parse_qs + +from django.contrib.auth import get_user_model +from django.contrib.auth.models import AnonymousUser +from django.db import close_old_connections +from channels.auth import AuthMiddleware, AuthMiddlewareStack, UserLazyObject +from channels.db import database_sync_to_async +from channels.sessions import CookieMiddleware, SessionMiddleware +# from rest_framework_simplejwt.tokens import AccessToken +from rest_framework.authtoken.models import Token + + +User = get_user_model() + +"""[summary] +plucks the JWT access token from the query string and retrieves the associated user. + Once the WebSocket connection is opened, all messages can be sent and received without + verifying the user again. Closing the connection and opening it again + requires re-authorization. +for example: +ws://localhost:8000//?token= + +""" + + +@database_sync_to_async +def get_user(scope): + close_old_connections() + query_string = parse_qs(scope['query_string'].decode()) + token = query_string.get('token') + # print("token query is::::", token) + if not token: + return AnonymousUser() + try: + t = Token.objects.get(key=token[0]) + access_token = Token(key=token[0]) + + #access_token = AccessToken(token[0]) + + user = t.user + + # user = User.objects.get(id=access_token['id']) + except Exception as exception: + return AnonymousUser() + if not user.is_active: + return AnonymousUser() + return user + + +class TokenAuthMiddleware(AuthMiddleware): + async def resolve_scope(self, scope): + scope['user']._wrapped = await get_user(scope) + + +def TokenAuthMiddlewareStack(inner): + return CookieMiddleware(SessionMiddleware(TokenAuthMiddleware(inner))) diff --git a/notification/migrations/0001_initial.py b/notification/migrations/0001_initial.py new file mode 100644 index 0000000..2693e25 --- /dev/null +++ b/notification/migrations/0001_initial.py @@ -0,0 +1,115 @@ +# Generated by Django 3.2.13 on 2023-09-18 19:32 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('authentication', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='NotificationActions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(default='', max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationactions_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='NotificationType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(choices=[('user', 'USER'), ('alluser', 'AllUSER'), ('group', 'GROUP'), ('allgroup', 'AllGROUP'), ('usergroup', 'UserGroup'), ('poultry', 'Poultry'), ('province_accept', 'ProvinceAccept'), ('province_rejected', 'ProvinceRejected'), ('city_operator_accept', 'CityOperatorAccept'), ('city_operator_rejected', 'CityOperatorRejected'), ('assignment_accepted', 'AssignmentAccepted'), ('assignment_rejected', 'AssignmentRejected')], default='', max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationtype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationtype_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='NotificationToken', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('token', models.CharField(max_length=100)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationtoken_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationtoken_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_user', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='NotificationButton', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('content', models.CharField(default='', max_length=20, null=True)), + ('order', models.IntegerField(default=0, null=True)), + ('action', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='btn_actions', to='notification.notificationactions')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationbutton_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notificationbutton_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Notification', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(default='', max_length=200, null=True)), + ('content', models.CharField(default='', max_length=500, null=True)), + ('image', models.CharField(max_length=100, null=True)), + ('icon', models.CharField(max_length=100, null=True)), + ('app_ids', models.CharField(default='', max_length=200, null=True)), + ('device_ids', models.CharField(default='', max_length=200, null=True)), + ('hash_id', models.CharField(default='', max_length=20, null=True)), + ('status', models.CharField(choices=[('read', 'Read'), ('pending', 'Pending'), ('sent', 'Sent'), ('unread', 'Unread'), ('silent', 'Silent')], default='', max_length=10, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notification_modifiedby', to=settings.AUTH_USER_MODEL)), + ('notif_action', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='actions', to='notification.notificationactions')), + ('notif_button', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='buttons', to='notification.notificationbutton')), + ('notif_type', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='types', to='notification.notificationtype')), + ('notification_group', models.ManyToManyField(null=True, related_name='group', to='auth.Group')), + ('notification_user', models.ManyToManyField(null=True, related_name='notification_token', to='notification.NotificationToken')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/notification/migrations/0002_auto_20250121_0857.py b/notification/migrations/0002_auto_20250121_0857.py new file mode 100644 index 0000000..4bc41b2 --- /dev/null +++ b/notification/migrations/0002_auto_20250121_0857.py @@ -0,0 +1,39 @@ +# Generated by Django 3.2.13 on 2025-01-21 08:57 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('notification', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='notification', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='notificationactions', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='notificationbutton', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='notificationtoken', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='notificationtype', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + ] diff --git a/notification/migrations/0003_dashboardnotification.py b/notification/migrations/0003_dashboardnotification.py new file mode 100644 index 0000000..2a4fc7a --- /dev/null +++ b/notification/migrations/0003_dashboardnotification.py @@ -0,0 +1,38 @@ +# Generated by Django 3.2.13 on 2025-06-15 12:44 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('notification', '0002_auto_20250121_0857'), + ] + + operations = [ + migrations.CreateModel( + name='DashboardNotification', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=250, null=True)), + ('text', models.TextField(null=True)), + ('date', models.DateTimeField(null=True)), + ('status', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dashboardnotification_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dashboardnotification_modifiedby', to=settings.AUTH_USER_MODEL)), + ('role', models.ManyToManyField(null=True, related_name='notification_token', to='auth.Group')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/notification/migrations/0004_alter_dashboardnotification_role.py b/notification/migrations/0004_alter_dashboardnotification_role.py new file mode 100644 index 0000000..1f80b94 --- /dev/null +++ b/notification/migrations/0004_alter_dashboardnotification_role.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.13 on 2025-06-15 12:45 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ('notification', '0003_dashboardnotification'), + ] + + operations = [ + migrations.AlterField( + model_name='dashboardnotification', + name='role', + field=models.ManyToManyField(null=True, related_name='dashboard_notification', to='auth.Group'), + ), + ] diff --git a/notification/migrations/__init__.py b/notification/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notification/models.py b/notification/models.py new file mode 100644 index 0000000..90807af --- /dev/null +++ b/notification/models.py @@ -0,0 +1,151 @@ +from django.db import models + +from authentication.models import BaseModel +from authentication.models import UserProfile, Group + + +# from numpy import char + + +# Create your models here. + + +class NotificationActions(BaseModel): + name = models.CharField(max_length=100, default="", null=True) + + def __str__(self) -> str: + return self.name + + def save(self, *args, **kwargs): + super(NotificationActions, self).save(*args, **kwargs) + + pass + + +class NotificationButton(BaseModel): + content = models.CharField(max_length=20, default="", null=True) + order = models.IntegerField(default=0, null=True) + action = models.ForeignKey( + NotificationActions, + on_delete=models.CASCADE, + default=None, + null=True, + related_name="btn_actions", + ) + + def __str__(self) -> str: + return self.content + + def save(self, *args, **kwargs): + super(NotificationButton, self).save(*args, **kwargs) + + pass + + +class NotificationType(BaseModel): + notif_types = ( + ("user", "USER"), + ("alluser", "AllUSER"), + ("group", "GROUP"), + ("allgroup", "AllGROUP"), + ("usergroup", "UserGroup"), + ("poultry", "Poultry"), + ("province_accept", "ProvinceAccept"), + ("province_rejected", "ProvinceRejected"), + ("city_operator_accept", "CityOperatorAccept"), + ("city_operator_rejected", "CityOperatorRejected"), + ("assignment_accepted", "AssignmentAccepted"), + ("assignment_rejected", "AssignmentRejected"), + ) + name = models.CharField(choices=notif_types, max_length=50, default="", null=True) + + def __str__(self) -> str: + return self.name + + def save(self, *args, **kwargs): + super(NotificationType, self).save(*args, **kwargs) + + pass + + +class NotificationToken(BaseModel): + token = models.CharField(max_length=100) + user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name="notification_user", null=True) + + def __str__(self) -> str: + return self.token + + def save(self, *args, **kwargs): + super(NotificationToken, self).save(*args, **kwargs) + + pass + + +class Notification(BaseModel): + s = ( + ("read", "Read"), + ("pending", "Pending"), + ("sent", "Sent"), + ("unread", "Unread"), + ("silent", "Silent"), + ) + notif_type = models.ForeignKey( + NotificationType, + on_delete=models.CASCADE, + null=True, + default=None, + related_name="types", + ) + notif_action = models.ForeignKey( + NotificationActions, + on_delete=models.CASCADE, + null=True, + default=None, + related_name="actions", + ) + notif_button = models.ForeignKey( + NotificationButton, + on_delete=models.CASCADE, + null=True, + default=None, + related_name="buttons", + ) + notification_user = models.ManyToManyField( + NotificationToken, + null=True, + related_name="notification_token" + ) + notification_group = models.ManyToManyField( + Group, + null=True, + related_name="group" + ) + title = models.CharField(max_length=200, default="", null=True) + content = models.CharField(max_length=500, default="", null=True) + image = models.CharField(max_length=100, null=True) + icon = models.CharField(max_length=100, null=True) + app_ids = models.CharField(max_length=200, default="", null=True) + device_ids = models.CharField(max_length=200, default="", null=True) + hash_id = models.CharField(max_length=20, default="", null=True) + status = models.CharField(choices=s, max_length=10, default="", null=True) + + def __str__(self) -> str: + return self.title + + def save(self, *args, **kwargs): + super(Notification, self).save(*args, **kwargs) + + pass + + +class DashboardNotification(BaseModel): + role = models.ManyToManyField(Group, + null=True, + related_name="dashboard_notification") + title = models.CharField(max_length=250, null=True) + text = models.TextField(null=True) + date = models.DateTimeField(null=True) + status = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(DashboardNotification, self).save(*args, **kwargs) \ No newline at end of file diff --git a/notification/najva/__init__.py b/notification/najva/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notification/najva/get_segments_detail.py b/notification/najva/get_segments_detail.py new file mode 100644 index 0000000..56bcf9f --- /dev/null +++ b/notification/najva/get_segments_detail.py @@ -0,0 +1,17 @@ +from django.http.response import JsonResponse +import requests +import json + + +def get_segments(request): + url = "https://app.najva.com/api/v1/websites/65b3a75a-d634-48c5-824f-c80c703534af/segments/" + + headers = { + 'content-type': "application/json", + 'authorization': "Token 982c17c1d460fec1eef6270c7d6550e3b9b33d2d", + 'cache-control': "no-cache", + } + + response = requests.request('GET', url=url, headers=headers) + resp = json.loads(response.text.encode('utf8')) + return JsonResponse(resp, safe=False) diff --git a/notification/najva/send_notif_to_segments.py b/notification/najva/send_notif_to_segments.py new file mode 100644 index 0000000..671b742 --- /dev/null +++ b/notification/najva/send_notif_to_segments.py @@ -0,0 +1,75 @@ +from django.http.response import JsonResponse +from datetime import datetime, timezone, timedelta +import requests +import json + + +def send_notification_to_all_segments( + title=None, + body=None, + content=None, + icon=None, + image=None, + segments_include=None, + segments_exclude=None, +): + url = "https://app.najva.com/api/v1/notifications/" + + payload = { + "api_key": "65b3a75a-d634-48c5-824f-c80c703534af", + "title": "title", + "body": "body", + "priority": "high", + "onclick_action": "open-link", + "url": "https://imedstores.ir/", + "content": "content", + "icon": "", + "image": "", + # "json": "{"key":"value"}", + "sent_time": datetime.now() + timedelta(minutes=1), + "segments_include": [], + "segments_exclude": [], + "one_signal_enabled": False, + "one_signal_accounts": [] + } + headers = { + 'authorization': "Token 982c17c1d460fec1eef6270c7d6550e3b9b33d2d", + 'content-type': "application/json", + 'cache-control': "no-cache", + } + + response = requests.request("POST", url, data=json.dumps(payload, default=str), headers=headers) + resp = json.loads(response.text.encode('utf-8')) + return resp + + +def send_notification_to_specific_segment( + title="سامانه سبحان طیور", + body="خوش آمدید", + content="سامانه مدیریت درخواست های مرغداران", + icon="https://user-image-gallery.s3.ir-thr-at1.arvanstorage.com/1WGPTMFND3TREWD.jpg", + image="https://user-image-gallery.s3.ir-thr-at1.arvanstorage.com/1WGPTMFND3TREWD.jpg", + subscriber_tokens=None, +): + url = "https://app.najva.com/notification/api/v1/notifications/" + payload = { + "api_key": "65b3a75a-d634-48c5-824f-c80c703534af", + "subscriber_tokens": subscriber_tokens, + "title": title, + "body": body, + "onclick_action": "open-link", + "url": "https://imedstores.ir/", + "content": content, + "icon": icon, + "image": image, + "sent_time": datetime.now() + timedelta(minutes=3), + } + headers = { + 'authorization': "Token 982c17c1d460fec1eef6270c7d6550e3b9b33d2d", + 'content-type': "application/json", + 'cache-control': "no-cache", + } + + response = requests.request("POST", url, data=json.dumps(payload, default=str), headers=headers) + resp = json.loads(response.text.encode('utf-8')) + return resp diff --git a/notification/najva_views.py b/notification/najva_views.py new file mode 100644 index 0000000..bdf2f57 --- /dev/null +++ b/notification/najva_views.py @@ -0,0 +1,159 @@ +import datetime + +from django.http import QueryDict +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from rest_framework.permissions import AllowAny +from ticket.helper import send_image_to_server +from notification.models import ( + Notification, + NotificationToken, + NotificationType, + Group +) +from panel.models import ( + PoultryRequest, + CityOperatorCheckRequest, + ProvinceCheckOperatorRequest, + KillHouseRequest, + FunctionExecutor +) +from notification.serializers import NotificationSerializer +from authentication.filterset import UserProfileFilterSet +from django_filters.rest_framework import DjangoFilterBackend +from authentication.models import UserProfile +from rest_framework.response import Response +from rest_framework import viewsets, status +from django.shortcuts import render +from .najva.send_notif_to_segments import ( + send_notification_to_all_segments, + send_notification_to_specific_segment +) +from .najva.get_segments_detail import ( + get_segments +) +from authentication.views import ( + CLIENT_ID, + CLIENT_SECRET, + CACHE_TTL, + ARVAN_User_Image_URL +) +import random +import string +import os + +ARVAN_NOTIFICATION_GALLERY_URL = "https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/" + + +class NajvaNotificationViewSet(viewsets.ModelViewSet): + queryset = NotificationToken.objects.all() + serializer_class = NotificationSerializer + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + filterset_class = UserProfileFilterSet + filterset_fields = [ + 'fullname', + 'mobile', + 'breeding_unique_id', + 'address__city', + 'address__province', + 'role__name', + ] + + def list(self, request, *args, **kwargs): + if "key" in request.GET: + add_obj = Notification.objects.get(key__exact=request.GET["key"]) + serializer = self.serializer_class(add_obj) + return Response(serializer.data, status=status.HTTP_200_OK) + if "read_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="read" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if "unread_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="unread" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if "pending_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="pending" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + queryset = Notification.objects.all() + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + segments = [] + userprofile = UserProfile.objects.get(user=request.user) + ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + notification = Notification() + if 'image' in request.data.keys(): + image = request.data['image'] + notification_image = send_image_to_server(image) + if 'icon' in request.data.keys(): + icon = request.data['icon'] + notification_icon = send_image_to_server(icon) + if 'request_type' in request.data.keys(): + if request.data['request_type'] == "token": + if not NotificationToken.objects.filter(user=userprofile): + notification = NotificationToken() + notification.token = request.data['token'] + notification.user = userprofile + notification.save() + return Response(status=status.HTTP_200_OK) + else: + return Response({"msg": "user already has token"}, status=status.HTTP_403_FORBIDDEN) + if 'value' in request.data.keys(): + if not request.data['value']: + send_notification = send_notification_to_specific_segment( + # title=request.data['title'], + # body=request.data['body'], + # content=request.data['content'], + # icon=notification_icon, + # image=notification_image, + # segments_include=request.data['segments_include'], + # segments_exclude=request.data['segments_exclude'], + subscriber_tokens=['c22206d3-248a-4c81-b7c2-de2cfe5e5766'] + # subscriber_tokens=['2cc244fc-1340-4942-bf19-2ba9f66f44e6'] + ) + return Response(send_notification) + notification.notif_type = NotificationType.objects.get(name="alluser") + else: + for key in request.data['value']: + if UserProfile.objects.filter(key__exact=key): + notif_user = NotificationToken.objects.get(user__key__exact=key) + segments.append(notif_user.token) + if Group.objects.filter(name__exact=key): + for item in NotificationToken.objects.filter(user__role__name=key): + segments.append(item.token) + send_notification = send_notification_to_specific_segment( + title=request.data['title'], + body=request.data['body'], + content=request.data['content'], + icon=notification_icon, + image=notification_image, + subscriber_tokens=segments + ) + notification.notif_type = NotificationType.objects.get(name=request.data['request_type']) + notification.title = request.data['title'] + notification.content = request.data['content'] + notification.icon = notification_icon + notification.image = notification_image + notification.save() + if 'value' in request.data.keys(): + for key in request.data['value']: + if UserProfile.objects.filter(key__exact=key): + notification.notif_user.add(UserProfile.objects.get(key__exact=key)) + elif Group.objects.filter(name__exact=key): + notification.notif_group.add(Group.objects.get(name__exact=key)) + for item in UserProfile.objects.filter(role=Group.objects.get(name__exact=key)): + notification.notif_user.add(item) + return Response(send_notification) diff --git a/notification/notify.py b/notification/notify.py new file mode 100644 index 0000000..5f5ed10 --- /dev/null +++ b/notification/notify.py @@ -0,0 +1,25 @@ + +from asgiref.sync import async_to_sync +from channels.layers import get_channel_layer + + +@classmethod +def notify_ws_clients(self, message): + """ + Inform client there is a new message. + """ + + notification = { + "type": "recieve_group_message", + "message": "{}".format(message), + } + + channel_layer = get_channel_layer() + print("user.id {}".format(self.user.id)) + print("user.id {}".format(self.recipient.id)) + + async_to_sync(channel_layer.group_send)("{}".format(self.user.id), notification) + async_to_sync(channel_layer.group_send)( + "{}".format(self.recipient.id), notification + ) + diff --git a/notification/pushe/__init__.py b/notification/pushe/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notification/pushe/constants.py b/notification/pushe/constants.py new file mode 100644 index 0000000..955c863 --- /dev/null +++ b/notification/pushe/constants.py @@ -0,0 +1,3 @@ +# Obtain token -> https://docs.pushe.co/docs/web-api/authentication + +TOKEN = "YOUR_TOKEN" diff --git a/notification/pushe/send_custom_content_notification.py b/notification/pushe/send_custom_content_notification.py new file mode 100644 index 0000000..3ff54de --- /dev/null +++ b/notification/pushe/send_custom_content_notification.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# vim: ts=4 sw=4 et + +import requests +from notification.pushe.constants import TOKEN + + +def send_custom_content_notification(data): + # set header + headers = {"Authorization": "Token " + TOKEN, "Content-Type": "application/json"} + + # Webpush doc -> http://docs.pushe.co/docs/web-api/custom-content-notification/ + + data = { + "app_ids": [ + "YOUR_APP_ID", + ], + "data": { + "title": "Title", + "content": "Content", + }, + "custom_content": {"key1": "value1", "key2": "value2"}, + } + + # send request + response = requests.post( + "https://api.pushe.co/v2/messaging/notifications/web/", + json=data, + headers=headers, + ) + + # get status_code and response + print("status code => ", response.status_code) + print("response => ", response.json()) + print("==========") + + if response.status_code == 201: + print("Success!") + + data = response.json() + + # hashed_id just generated for Non-Free plan + if data["hashed_id"]: + report_url = "https://pushe.co/report?id=%s" % data["hashed_id"] + else: + report_url = "no report url for your plan" + + notif_id = data["wrapper_id"] + print("report_url: %s" % report_url) + print("notification id: %s" % notif_id) + else: + print("failed") + pass diff --git a/notification/pushe/send_filtered_notification.py b/notification/pushe/send_filtered_notification.py new file mode 100644 index 0000000..21a57d9 --- /dev/null +++ b/notification/pushe/send_filtered_notification.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +# vim: ts=4 sw=4 et + + +import requests +from notification.pushe.constants import TOKEN + + +def send_filtered_notification(data): + # set header + headers = {"Authorization": "Token " + TOKEN, "Content-Type": "application/json"} + + # Webpush doc -> https://docs.pushe.co/docs/web-api/filtered-notification + + data = { + "app_ids": [ + "YOUR_APP_ID", + ], + "data": { + "title": "This is a filtered push", + "content": "Only users with specified device_id(s) will see this notification.", + }, + "filters": {"device_id": ["DEIVCE_ID_1", "DEVICE_ID_2"]} + # additional keywords -> https://docs.pushe.co/docs/web-api/notification-keys + } + + response = requests.post( + "https://api.pushe.co/v2/messaging/notifications/web/", + json=data, + headers=headers, + ) + + print("status code => ", response.status_code) + print("response => ", response.json()) + print("==========") + + if response.status_code == 201: + print("Success!") + + data = response.json() + + # hashed_id only generated for Non-Free plan + if data["hashed_id"]: + report_url = "https://pushe.co/report?id=%s" % data["hashed_id"] + else: + report_url = "no report url for your plan" + + notif_id = data["wrapper_id"] + print("report_url: %s" % report_url) + print("notification id: %s" % notif_id) + else: + print("failed") + + pass diff --git a/notification/pushe/send_notification_with_action.py b/notification/pushe/send_notification_with_action.py new file mode 100644 index 0000000..d49fbc1 --- /dev/null +++ b/notification/pushe/send_notification_with_action.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 +# vim: ts=4 sw=4 et + +import requests +from notification.pushe.constants import TOKEN + + +def send_notification_with_action(data): + # set header + headers = {"Authorization": "Token " + TOKEN, "Content-Type": "application/json"} + + data = { + "app_ids": [ + "YOUR_APP_ID", + ], + "data": { + "title": "Title", + "content": "Content", + # Actions -> https://docs.pushe.co/docs/web-api/notification-actions + "action": { + "action_type": "U", + "url": "https://pushe.co", + }, + "buttons": [ + { + "btn_content": "YOUR_CONTENT", + "btn_action": {"action_type": "U", "url": "https://pushe.co"}, + "btn_order": 0, + }, + { + "btn_content": "YOUR_CONTENT", + "btn_action": {"action_type": "U", "url": "https://pushe.co"}, + "btn_order": 1, + }, + ], + }, + } + + # send request + response = requests.post( + "https://api.pushe.co/v2/messaging/notifications/web/", + json=data, + headers=headers, + ) + + # get status_code and response + print("status code => ", response.status_code) + print("response => ", response.json()) + print("==========") + + if response.status_code == 201: + print("Success!") + + data = response.json() + + # hashed_id only generated for Non-Free plan + if data["hashed_id"]: + report_url = "https://pushe.co/report?id=%s" % data["hashed_id"] + else: + report_url = "no report url for your plan" + + notif_id = data["wrapper_id"] + print("report_url: %s" % report_url) + print("notification id: %s" % notif_id) + else: + print("failed") + pass diff --git a/notification/pushe/send_simple_notification.py b/notification/pushe/send_simple_notification.py new file mode 100644 index 0000000..ee55a86 --- /dev/null +++ b/notification/pushe/send_simple_notification.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +# vim: ts=4 sw=4 et + +import requests +from notification.pushe.constants import TOKEN + +# Webpush doc -> https://docs.pushe.co/docs/web-api/filtered-notification + + +def send_simple_notification(data): + headers = {"Authorization": "Token " + TOKEN, "Content-Type": "application/json"} + + data = { + "app_ids": [ + "YOUR_APP_ID", + ], + "data": { + "title": "This is a filtered push", + "content": "Only users with specified device_id(s) will see this notification.", + }, + "filters": {"device_id": ["DEIVCE_ID_1", "DEVICE_ID_2"]} + # additional keywords -> https://docs.pushe.co/docs/web-api/notification-keys + } + + response = requests.post( + "https://api.pushe.co/v2/messaging/notifications/web/", + json=data, + headers=headers, + ) + + print("status code => ", response.status_code) + print("response => ", response.json()) + print("==========") + + if response.status_code == 201: + print("Success!") + + data = response.json() + + # hashed_id only generated for Non-Free plan + if data["hashed_id"]: + report_url = "https://pushe.co/report?id=%s" % data["hashed_id"] + else: + report_url = "no report url for your plan" + + notif_id = data["wrapper_id"] + print("report_url: %s" % report_url) + print("notification id: %s" % notif_id) + else: + print("failed") + + pass diff --git a/notification/pushe/send_transactional_notification.py b/notification/pushe/send_transactional_notification.py new file mode 100644 index 0000000..f37f509 --- /dev/null +++ b/notification/pushe/send_transactional_notification.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +# vim: ts=4 sw=4 et + +import requests +from notification.pushe.constants import TOKEN + + +def send_transactional_notification(data): + # set header + headers = {"Authorization": "Token " + TOKEN, "Content-Type": "application/json"} + + # Webpush doc -> http://docs.pushe.co/docs/web-api/transactional-notification/ + + data = { + "app_ids": [ + "YOUR_APP_ID", + ], + "data": { + "title": "Title", + "content": "Content", + }, + "custom_content": {"key1": "value1", "key2": "value2"}, + "device_id": [ + "device_id_1", + "device_id_2", + ], + } + + # send request + response = requests.post( + "https://api.pushe.co/v2/messaging/web-rapid/", + json=data, + headers=headers, + ) + + # get status_code and response + print("status code => ", response.status_code) + print("response => ", response.json()) + print("==========") + + if response.status_code == 201: + print("Success!") + + data = response.json() + + # hashed_id just generated for Non-Free plan + if data["hashed_id"]: + report_url = "https://pushe.co/report?id=%s" % data["hashed_id"] + else: + report_url = "no report url for your plan" + + notif_id = data["wrapper_id"] + print("report_url: %s" % report_url) + print("notification id: %s" % notif_id) + else: + print("failed") + pass diff --git a/notification/routing.py b/notification/routing.py new file mode 100644 index 0000000..0583aa3 --- /dev/null +++ b/notification/routing.py @@ -0,0 +1,7 @@ +from core import consumers + +from django.conf.urls import url + +websocket_urlpatterns = [ + url(r'^ws$', consumers.ChatConsumer.as_asgi()), +] diff --git a/notification/serializers.py b/notification/serializers.py new file mode 100644 index 0000000..750c8d1 --- /dev/null +++ b/notification/serializers.py @@ -0,0 +1,27 @@ +from rest_framework import serializers + +from notification.models import Notification, NotificationToken, DashboardNotification +from authentication.serializers import GroupSerializer + + +class NotificationTokenSerializer(serializers.ModelSerializer): + class Meta: + Model = NotificationToken + fields = "__all__" + + +class NotificationSerializer(serializers.ModelSerializer): + notif_user = NotificationTokenSerializer() + notif_group = GroupSerializer() + + class Meta: + Model = Notification + fields = "__all__" + + +class DashboardNotificationSerializer(serializers.ModelSerializer): + role = GroupSerializer(read_only=True,many=True) + + class Meta: + model = DashboardNotification + fields = "__all__" diff --git a/notification/signals.py b/notification/signals.py new file mode 100644 index 0000000..f10cc35 --- /dev/null +++ b/notification/signals.py @@ -0,0 +1,16 @@ +from django.db import models +from django.contrib.auth.models import User +from django.db.models.signals import post_save +from django.dispatch import receiver +from core.models import Profile + + +@receiver(post_save, sender=User) +def create_user_profile(sender, instance, created, **kwargs): + if created: + Profile.objects.create(user=instance) + + +@receiver(post_save, sender=User) +def save_user_profile(sender, instance, **kwargs): + instance.profile.save() diff --git a/notification/tests.py b/notification/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/notification/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/notification/urls.py b/notification/urls.py new file mode 100644 index 0000000..e3fc157 --- /dev/null +++ b/notification/urls.py @@ -0,0 +1,16 @@ +from notification.najva.get_segments_detail import get_segments +from notification.najva.send_notif_to_segments import send_notification_to_all_segments +from rest_framework.routers import DefaultRouter +from django.urls import include, path +from . import najva_views,views + +router = DefaultRouter() +router.register(r'notification-user', najva_views.NajvaNotificationViewSet, basename="notification-user") +router.register(r'dashboard_notification', views.DashboardNotificationViewSet, basename="dashboard-notification") +# router.register(r'get-segments', get_segments(), basename="get-segments") + +urlpatterns = [ + path('', include(router.urls)), + path('get-segments', get_segments), + path('all-segments', send_notification_to_all_segments), +] diff --git a/notification/views.py b/notification/views.py new file mode 100644 index 0000000..16e5025 --- /dev/null +++ b/notification/views.py @@ -0,0 +1,103 @@ +import datetime + +from django.contrib.auth.models import Group +from django.shortcuts import render +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from notification.serializers import NotificationSerializer, DashboardNotificationSerializer +from rest_framework import viewsets, status +from rest_framework.response import Response +from notification.models import Notification, DashboardNotification + + +# Create your views here. +class NotificationViewSet(viewsets.ModelViewSet): + queryset = Notification.objects.all() + serializer_class = NotificationSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + if "key" in request.GET: + add_obj = Notification.objects.get(key__exact=request.GET["key"]) + serializer = self.serializer_class(add_obj) + return Response(serializer.data, status=status.HTTP_200_OK) + if "read_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="read" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if "unread_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="unread" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if "pending_notif" in request.GET: + add_obj = Notification.objects.filter( + user_id=request.user.id, status="pending" + ) + query = [x for x in add_obj] + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + queryset = Notification.objects.all() + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + obj = serializer.create(validated_data=request.data) + obj.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def retrieve(self, request, pk=None, *args, **kwargs): + queryset = Notification.objects.get(key__exact=request.GET["key"]) + serializer = self.serializer_class(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + queryset = Notification.objects.get(key__exact=request.GET["key"]) + + queryset.save() + serializer = self.serializer_class(queryset) + serializer.update(instance=queryset, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def partial_update(self, request, pk=None, *args, **kwargs): + pass + + def destroy(self, request, pk=None, *args, **kwargs): + queryset = Notification.objects.get(key__exact=request.GET["key"]) + queryset.trash = True + queryset.save() + return Response(status=status.HTTP_200_OK) + + +class DashboardNotificationViewSet(viewsets.ModelViewSet): + queryset = DashboardNotification.objects.all() + serializer_class = DashboardNotificationSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + role=request.GET.get('role') + query=self.queryset.filter(role__name=role,trash=False).order_by('-date') + ser_data=self.serializer_class(query,many=True).data + return Response(ser_data,status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + grop=Group.objects.filter(name__in=request.data['role']) + request.data.pop('role') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + obj = serializer.create(validated_data=request.data) + obj.date=datetime.datetime.now() + obj.save() + obj.role.set(grop) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) \ No newline at end of file diff --git a/panel/CityOperator/__init__.py b/panel/CityOperator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/CityOperator/helpers.py b/panel/CityOperator/helpers.py new file mode 100644 index 0000000..9b9ffef --- /dev/null +++ b/panel/CityOperator/helpers.py @@ -0,0 +1,456 @@ +from itertools import chain + +from django.db.models import Sum, Q, F + +from deposit_id import wage_counting_type +from panel.KillHouse.helpers import get_difference_carcasses_weight +from panel.models import KillHouse, ProvinceKillRequest, KillHouseRequest, PoultryHatching, PoultryRequest, WageType, \ + PercentageOfWageType, SubSectorTransactions, SubSectorPercentageOfWageType, Poultry, KillHouseFreeBarInformation, \ + KillHouseFreeSaleBarInformation, BarDifferenceRequest + + +def get_percent_for_city_sub_sector_finance_info(): + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + temporary_trash=False, temporary_deleted=False, + province_request__poultry_request__hatching__in=hatchings) + kill_houses = KillHouse.objects.filter(pk__in=province_kill_requests.values_list('killhouse_user', flat=True)) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - out_selling_out_carcasses_buying_difference + + internal_percent = ( + total_pure_province_carcasses_weight / total_province_carcasses_weight) * 100 if total_province_carcasses_weight > 0 else 0 + external_percent = 100 - internal_percent + + return {"internal_percent": internal_percent, "external_percent": external_percent} + + +# def get_city_sub_sector_finance_info(poultries,operator): +# total_wage_type = WageType.objects.filter(trash=False) +# province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount +# free_sell_carcesses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount +# out_poultry_request_amount = total_wage_type.filter(en_name='poultry-sell-out-province', trash=False).first().amount +# +# percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) +# union_province_kill_request_percent = percentages_wage_type.filter( +# wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 +# union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', +# share_type__en_name='union').first().percent / 100 +# +# union_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', +# share_type__en_name='union').first().percent / 100 +# city_percent_province_kill_request= SubSectorPercentageOfWageType.objects.filter(percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 +# city_percent_carcasse_sell= SubSectorPercentageOfWageType.objects.filter(percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 +# city_percent_out_poultry_request= SubSectorPercentageOfWageType.objects.filter(percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 +# union_province_kill_request_final_amount = union_province_kill_request_percent * province_live_wage_amount +# union_carcasse_sell_final_amount = union_free_sell_carcasses_percent * free_sell_carcesses_wage_amount +# union_out_poultry_request_amount = union_out_poultry_request_percent * out_poultry_request_amount +# city_province_kill_request_final_amount = union_province_kill_request_final_amount * city_percent_province_kill_request +# city_carcasse_sell_final_amount = union_carcasse_sell_final_amount * city_percent_carcasse_sell +# city_out_poultry_request_final_amount = union_out_poultry_request_amount * city_percent_out_poultry_request +# +# +# +# hatchings = PoultryHatching.objects.filter(poultry__in=poultries,killed_quantity__gt=0, trash=False).order_by('poultry') +# +# hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ +# 'total'] or 0 +# poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), +# province_state__in=('pending', 'accepted'), out=True, +# out_province_request_cancel=False, temporary_trash=False, +# temporary_deleted=False, hatching__in=hatchings) +# out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ +# 'total'] or 0 +# out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# +# +# +# province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, +# archive_wage=False, +# state__in=('pending', 'accepted'), +# temporary_trash=False, temporary_deleted=False, +# # first_car_allocated_quantity=0, +# province_request__poultry_request__hatching__in=hatchings) +# +# total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ +# 'total'] or 0 +# total_province_carcasses_weight = total_province_live_weight * 0.75 +# weight_percent = get_percent_for_city_sub_sector_finance_info() +# total_pure_internal_province_carcasses_weight = (weight_percent['internal_percent']/100) * total_province_carcasses_weight +# total_pure_external_province_carcasses_weight = (weight_percent['external_percent']/100) * total_province_carcasses_weight +# total_pure_internal_province_carcasses_amount = total_pure_internal_province_carcasses_weight * city_province_kill_request_final_amount +# total_pure_external_province_carcasses_amount = total_pure_external_province_carcasses_weight * city_carcasse_sell_final_amount +# out_province_poultry_request_amount = out_province_poultry_request_weight * city_out_poultry_request_final_amount +# total_wage_amount = total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount +# total_killed_quantity = total_province_live_quantity + out_province_poultry_request_quantity +# hatching_killing_percent = ((total_killed_quantity / hatching_quantity) if hatching_quantity > 0 else 0) * 100 +# city_operator_deposit = SubSectorTransactions.objects.filter(trash=False,city_operator=operator) +# city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 +# total_remain_wage_amount = total_wage_amount - city_deposit +# +# result = { +# "poultries": len(poultries), +# "hatchings": len(hatchings), +# "hatchings_quantity": hatching_quantity, +# "total_province_kill_requests_quantity": total_province_live_quantity, +# "total_province_kill_requests_weight": total_province_live_weight, +# "total_province_carcasses_weight": total_province_carcasses_weight, +# "total_pure_internal_province_carcasses_weight": total_pure_internal_province_carcasses_weight, +# "total_pure_external_province_carcasses_weight": total_pure_external_province_carcasses_weight, +# "out_province_poultry_request_quantity": out_province_poultry_request_quantity, +# "out_province_poultry_request_weight": out_province_poultry_request_weight, +# "total_killed_quantity": total_killed_quantity, +# "hatching_killing_percent": hatching_killing_percent, +# "out_province_poultry_request_amount": out_province_poultry_request_amount, +# "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, +# "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, +# "total_wage_amount": total_wage_amount, +# "number_of_city_deposit": len(city_operator_deposit), +# "city_deposit": city_deposit, +# "total_remain_wage_amount": total_remain_wage_amount, +# } +# return result + + +def get_city_sub_sector_finance_info(poultries, operator,date1,date2): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + if date1 is not None: + total_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + 'id') + total_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings, + send_date__date__gte=date1, + send_date__date__lte=date2) + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False, city_operator=operator, + date__date__gte=date1, date__date__lte=date2) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted', acceptor_date__date__gte=date1, + acceptor_date__date__lte=date2) + + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, poultry__in=poultries, + temporary_deleted=False) + total_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + total_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False, city_operator=operator) + + total_province_live_weight = total_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += total_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += total_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses,date1,date2) + + different_percent = (total_pure_province_carcasses_weight / total_province_carcasses_weight) if total_province_carcasses_weight > 0 else 0 + + province_kill_requests = total_province_kill_requests.filter( + province_request__poultry_request__hatching__in=hatchings).order_by('id') + kill_house_requests = total_kill_house_requests.filter( + province_request__poultry_request__hatching__in=hatchings).order_by('id') + + + province_kill_requests_kill_houses = KillHouse.objects.filter(pk__in=province_kill_requests.values_list('killhouse_user',flat=True)).order_by('id') + + + hatching_list1 = hatchings.filter( + pk__in=province_kill_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list2 = hatchings.filter( + pk__in=kill_house_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list3 = hatchings.filter(pk__in=poultry_requests.values_list('hatching', flat=True), poultry__in=poultries, + killed_quantity__gt=0, trash=False).values_list('id', flat=True) + total_hatching_list = chain(hatching_list1, hatching_list2, hatching_list3) + hatchings = hatchings.filter(pk__in=total_hatching_list) + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = poultry_requests.filter(hatching__id__in=hatching_list3) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + province_live_weight += \ + difference_requests.filter(kill_house__in=province_kill_requests_kill_houses).aggregate(total=Sum('weight'))['total'] or 0 + + province_carcasses_weight = province_live_weight * 0.75 + + internal_total_pure_province_carcasses_weight = province_carcasses_weight * different_percent + external_total_pure_province_carcasses_weight = province_carcasses_weight - internal_total_pure_province_carcasses_weight + + # total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + # total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + + union_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='union').first().percent / 100 + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_carcasse_sell = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + union_province_kill_request_final_amount = union_province_kill_request_percent * province_live_wage_amount + union_carcasse_sell_final_amount = union_free_sell_carcasses_percent * free_sell_carcasses_wage_amount + union_out_poultry_request_amount = union_out_poultry_request_percent * out_poultry_request_wage_amount + city_province_kill_request_final_amount = union_province_kill_request_final_amount * city_percent_province_kill_request + city_carcasse_sell_final_amount = union_carcasse_sell_final_amount * city_percent_carcasse_sell + city_out_poultry_request_final_amount = union_out_poultry_request_amount * city_percent_out_poultry_request + + total_pure_internal_province_carcasses_amount = internal_total_pure_province_carcasses_weight * city_province_kill_request_final_amount + total_pure_external_province_carcasses_amount = external_total_pure_province_carcasses_weight * city_carcasse_sell_final_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * city_out_poultry_request_final_amount + total_wage_amount = total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_killed_quantity = province_live_quantity + out_province_poultry_request_quantity + hatching_killing_percent = ((total_killed_quantity / hatching_quantity) if hatching_quantity > 0 else 0) * 100 + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_remain_wage_amount = total_wage_amount - city_deposit + + result = { + "poultries": len(poultries), + "hatchings": len(hatchings), + "hatchings_quantity": hatching_quantity, + "total_province_kill_requests_quantity": province_live_quantity, + "total_province_kill_requests_weight": province_live_weight, + "total_province_carcasses_weight": province_carcasses_weight, + "total_pure_internal_province_carcasses_weight": internal_total_pure_province_carcasses_weight, + "total_pure_external_province_carcasses_weight": external_total_pure_province_carcasses_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "total_killed_quantity": total_killed_quantity, + "hatching_killing_percent": hatching_killing_percent, + "out_province_poultry_request_amount": out_province_poultry_request_amount, + "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, + "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, + "total_wage_amount": total_wage_amount, + "number_of_city_deposit": len(city_operator_deposit), + "city_deposit": city_deposit, + "total_remain_wage_amount": total_remain_wage_amount, + } + return result + + +def get_city_sub_sector_finance_info_with_date(poultries, operator,date1,date2): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + total_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0,kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by('id') + total_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True,kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + + total_province_live_weight = total_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += total_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += total_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, state='accepted',acceptor_date__date__gte=date1,acceptor_date__date__lte=date2) + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + + different_percent = total_pure_province_carcasses_weight / total_province_carcasses_weight + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + province_kill_requests = total_province_kill_requests.filter( + province_request__poultry_request__hatching__in=hatchings).order_by('id') + kill_house_requests = total_kill_house_requests.filter( + province_request__poultry_request__hatching__in=hatchings).order_by('id') + + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings,send_date__date__gte=date1, + send_date__date__lte=date2) + province_kill_requests_kill_houses = KillHouse.objects.filter(pk__in=province_kill_requests.values_list('killhouse_user',flat=True)).order_by('id') + + + hatching_list1 = hatchings.filter( + pk__in=province_kill_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list2 = hatchings.filter( + pk__in=kill_house_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list3 = hatchings.filter(pk__in=poultry_requests.values_list('hatching', flat=True), poultry__in=poultries, + killed_quantity__gt=0, trash=False).values_list('id', flat=True) + total_hatching_list = chain(hatching_list1, hatching_list2, hatching_list3) + hatchings = hatchings.filter(pk__in=total_hatching_list) + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = poultry_requests.filter(hatching__id__in=hatching_list3) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + province_live_weight += \ + difference_requests.filter(kill_house__in=province_kill_requests_kill_houses).aggregate(total=Sum('weight'))['total'] or 0 + + province_carcasses_weight = province_live_weight * 0.75 + + internal_total_pure_province_carcasses_weight = province_carcasses_weight * different_percent + external_total_pure_province_carcasses_weight = province_carcasses_weight - internal_total_pure_province_carcasses_weight + + # total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + # total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + + union_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='union').first().percent / 100 + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_carcasse_sell = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + union_province_kill_request_final_amount = union_province_kill_request_percent * province_live_wage_amount + union_carcasse_sell_final_amount = union_free_sell_carcasses_percent * free_sell_carcasses_wage_amount + union_out_poultry_request_amount = union_out_poultry_request_percent * out_poultry_request_wage_amount + city_province_kill_request_final_amount = union_province_kill_request_final_amount * city_percent_province_kill_request + city_carcasse_sell_final_amount = union_carcasse_sell_final_amount * city_percent_carcasse_sell + city_out_poultry_request_final_amount = union_out_poultry_request_amount * city_percent_out_poultry_request + + total_pure_internal_province_carcasses_amount = internal_total_pure_province_carcasses_weight * city_province_kill_request_final_amount + total_pure_external_province_carcasses_amount = external_total_pure_province_carcasses_weight * city_carcasse_sell_final_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * city_out_poultry_request_final_amount + total_wage_amount = total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_killed_quantity = province_live_quantity + out_province_poultry_request_quantity + hatching_killing_percent = ((total_killed_quantity / hatching_quantity) if hatching_quantity > 0 else 0) * 100 + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False, city_operator=operator,date__date__gte=date1,date__date__lte=date2) + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_remain_wage_amount = total_wage_amount - city_deposit + + result = { + "poultries": len(poultries), + "hatchings": len(hatchings), + "hatchings_quantity": hatching_quantity, + "total_province_kill_requests_quantity": province_live_quantity, + "total_province_kill_requests_weight": province_live_weight, + "total_province_carcasses_weight": province_carcasses_weight, + "total_pure_internal_province_carcasses_weight": internal_total_pure_province_carcasses_weight, + "total_pure_external_province_carcasses_weight": external_total_pure_province_carcasses_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "total_killed_quantity": total_killed_quantity, + "hatching_killing_percent": hatching_killing_percent, + "out_province_poultry_request_amount": out_province_poultry_request_amount, + "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, + "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, + "total_wage_amount": total_wage_amount, + "number_of_city_deposit": len(city_operator_deposit), + "city_deposit": city_deposit, + "total_remain_wage_amount": total_remain_wage_amount, + } + return result diff --git a/panel/CityOperator/serializers.py b/panel/CityOperator/serializers.py new file mode 100644 index 0000000..243e09d --- /dev/null +++ b/panel/CityOperator/serializers.py @@ -0,0 +1,138 @@ +import datetime + +from django.db.models import Sum, F +from rest_framework import serializers + +from authentication.serializer.serializer import SystemUserProfileSerializer, BankCardSerializer, \ + SystemUserProfileForGuildSerializer +from authentication.serializers import SystemAddressSerializer +from panel.CityOperator.helpers import get_city_sub_sector_finance_info, get_city_sub_sector_finance_info_with_date +from panel.models import CityOperatorCheckRequest, CityOperator, ProvinceKillRequest, ProvinceCheckOperatorRequest, \ + WageType, PercentageOfWageType, PoultryHatching, Poultry, PoultryRequest, KillHouseFreeBarInformation, \ + KillHouseFreeSaleBarInformation, KillHouse +from panel.poultry.serializers import PoultryRequestSerializer + + +# سریالایزر مربوط به اپراتور شهرستان +class CityOperatorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True, required=False) + + class Meta: + model = CityOperator + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + ) + + +class CityOperatorForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True, required=False) + + class Meta: + model = CityOperator + fields = ['address', 'user_bank_info', 'identity_documents', 'phone', 'unit_name'] + + +class CityOperatorForPoultrySerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = CityOperator + fields = ['key', 'address', 'unit_name'] + + +class CityOperatorForSubSectorTransactionsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = CityOperator + fields = ['key', 'user', 'unit_name'] + + +class CityOperatorForSubSectorSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = CityOperator + fields = ['key', 'user', 'unit_name','wage_info'] + + + def get_wage_info(self, obj): + date1=None + date2=None + if self.context.get('request').GET.get('date1'): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + poultries = Poultry.objects.filter(city_operator=obj.unit_name,trash=False).order_by('id') + info=get_city_sub_sector_finance_info(poultries,obj,date1,date2) + return info + + + +# سریالایزر مربوط به بررسی درخواست مرغدار توسط شهرستان (تایید یا رد) +class CityOperatorCheckRequestSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + quantity = serializers.SerializerMethodField('get_quantity') + + # city_operator = CityOperatorSerializer() + + class Meta: + model = CityOperatorCheckRequest + fields = '__all__' + + def get_quantity(self, instance): + allocated_number = 0 + returned_number = 0 + assignable_number = 0 + province_check_req = ProvinceCheckOperatorRequest.objects.filter(city_request_Poultry=instance) + if province_check_req.count() > 0: + province_check_req = province_check_req.last() + assignable_number = province_check_req.quantity + else: + assignable_number = instance.poultry_request.quantity + + province_kill_requests = ProvinceKillRequest.objects.filter(province_request__city_request_Poultry=instance, + trash=False, state__in=('pending', 'accepted')) + if province_kill_requests.count() > 0: + for province_kill_request in province_kill_requests: + if province_kill_request.return_to_province == False: + allocated_number += province_kill_request.main_quantity + else: + returned_number += province_kill_request.main_quantity + + quantity = { + "allocated_number": allocated_number, + "assignable_number": assignable_number, + "returned_number": returned_number, + } + return quantity + + +class CityOperatorForSubSectorSerializerForExcel(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = CityOperator + fields = ['key', 'user', 'unit_name','wage_info'] + + + def get_wage_info(self, obj): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + + poultries = Poultry.objects.filter(city_operator=obj.unit_name,trash=False).order_by('id') + info=get_city_sub_sector_finance_info_with_date(poultries,obj,date1,date2) + return info \ No newline at end of file diff --git a/panel/CityOperator/views.py b/panel/CityOperator/views.py new file mode 100644 index 0000000..2bbe9b1 --- /dev/null +++ b/panel/CityOperator/views.py @@ -0,0 +1,666 @@ +import threading + +import jdatetime +from rest_framework.pagination import PageNumberPagination + +# . + +from authentication.helper.refresh import refresh +from authentication.sms_management import poultry_request_receive_city_accept_sms, \ + poultry_request_receive_province_accept_sms + +from panel.CityOperator.serializers import ( + CityOperatorCheckRequestSerializer, + CityOperatorSerializer, CityOperatorForPoultrySerializer, CityOperatorForSubSectorSerializer, + CityOperatorForSubSectorTransactionsSerializer +) +from authentication.serializer.serializer import ( + SystemAddressSerializer, + BankCardSerializer +) +from authentication.models import SystemAddress, CityUnit +from panel.poultry.serializers import PoultrySerializer, PoultryRequestSerializer, \ + PoultryRequestForKillingInformationSerializer +from panel.convert_date import convert_to_miladi +from panel.models import ( + CityOperatorCheckRequest, + PoultryRequest, + CityOperator, + PoultryRequestAuction, + ProvinceOperator, + Poultry, PoultryHatching, VetFarm, VetFarmInspection, SmsLicense, ProvinceCheckOperatorRequest, ProvinceKillRequest, + KillHouseCheckRequest, KillRequest +) +from authentication.models import ( + City, + Province +) +from authentication.models import SystemUserProfile +from panel.filterset import UserProfileFilterSet, CityOperatorRequestFilterSet, PoultryRequestFilterSet +from django_filters.rest_framework import DjangoFilterBackend +from authentication.permissions import CityOperator as CityOperatorPermission +from authentication.permissions import ProvinceOperator as provinceOperatorPermission +from authentication.models import UserProfile, UserMessage +from rest_framework.response import Response +from django.contrib.auth.models import User +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, + OAuth2Authentication, +) +from rest_framework import status +from django.http import QueryDict +from datetime import datetime, timedelta +from django.db.models import Q +from panel.helper import remove_null_fields + +class CustomPagination(PageNumberPagination): + page_size = 10 + +class ShowCityOperatorViewSet(viewsets.ModelViewSet): + queryset = CityOperator.objects.all() + serializer_class = CityOperatorSerializer + permission_classes = [TokenHasReadWriteScope] + + # def list(self, request, *args, **kwargs): + # # refresh(request.user.id) + # if 'breeding_uniq_id' in request.GET: + # poultry = Poultry.objects.get(breeding_unique_id=request.GET['breeding_uniq_id']) + # else: + # + # user = SystemUserProfile.objects.get(user=request.user) + # poultry = Poultry.objects.get(user=user) + # # city = City.objects.get(key=poultry.address.city.key) + # + # city_unit = CityUnit.objects.get(name=poultry.address.city.name) + # # city_operator_system = CityOperator.objects.get(address__city=city_unit.city, trash=False) + # operator_list = [] + # opertors = CityOperator.objects.filter(address__city__name__in=(city_unit.city.name, 'فاقد شهرستان'), + # trash=False) + # # poultry_request = PoultryRequest.objects.filter(trash=False, poultry=poultry).select_related( + # # 'city_operator').last() + # + # for opertor in opertors: + # last = True if poultry.city_operator == opertor.unit_name else False + # operator_dict = { + # "key": opertor.key, + # "unit_name": opertor.unit_name, + # "last": last + # } + # operator_list.append(operator_dict) + # + # return Response(operator_list) + + def list(self, request, *args, **kwargs): + operator_list = [] + if 'breeding_uniq_id' in request.GET: + poultry = Poultry.objects.get(breeding_unique_id=request.GET['breeding_uniq_id']) + else: + + user = SystemUserProfile.objects.get(user=request.user) + poultry = Poultry.objects.get(user=user) + opertor = CityOperator.objects.filter(unit_name=poultry.city_operator, + + trash=False).last() + if not opertor: + opertor = CityOperator.objects.filter(unit_name='اتحادیه استان (فاقد تعاونی)', + + trash=False).last() + + operator_dict = { + "key": opertor.key, + "unit_name": opertor.unit_name, + } + operator_list.append(operator_dict) + + return Response(operator_list) + + +# ویوست مربوط به اپراتور شهرستان +class CityOperatorViewSet(viewsets.ModelViewSet): + queryset = CityOperator.objects.all() + serializer_class = CityOperatorSerializer + permission_classes = [TokenHasReadWriteScope] + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + # get city operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + operator = user.city_operator_user.all() + + # send to serializer + serializer = self.serializer_class(operator[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + city_operators = CityOperator.objects.filter(address__province=user.province, trash=False) + serializer = CityOperatorForPoultrySerializer(city_operators, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + +class CityOperatorForSubSectorViewSet(viewsets.ModelViewSet): + queryset = CityOperator.objects.all() + serializer_class = CityOperatorForSubSectorSerializer + permission_classes = [TokenHasReadWriteScope] + + + def list(self, request, pk=None, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + city_operators = CityOperator.objects.filter(address__province=user.province, trash=False) + if 'operators' in request.GET: + + serializer = CityOperatorForSubSectorTransactionsSerializer(city_operators, many=True) + else: + serializer = self.serializer_class(city_operators, many=True,context={'request':request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به بررسی درخواست مرغدار +class CityOperatorCheckRequestViewSet(viewsets.ModelViewSet): + queryset = CityOperatorCheckRequest.objects.all() + serializer_class = CityOperatorCheckRequestSerializer + # permission_classes = [TokenHasReadWriteScope, provinceOperatorPermission, CityOperatorPermission] + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = CityOperatorRequestFilterSet + filterset_fields = [ + 'poultry_request__user__mobile', + 'poultry_request__user__fullname', + 'poultry_request__user__first_name', + 'poultry_request__user__last_name', + 'poultry_request__user__address__breeding_unique_id', + 'poultry_request__order_code', + ] + + # تابع برای تایید یا رد درخواست مرغدار توسط شهرستان + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + # refresh(request.user.id) + role = request.data['role'] + request.data.pop('role') + key = request.data['key'] + state = request.data['state'] + poultry_request = PoultryRequest.objects.get(key=key, trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if role == 'ProvinceOperator': + province_operator = SystemUserProfile.objects.filter(user=request.user, trash=False) + if province_operator.count() > 0: + province_operator = province_operator.last() + # city_unit = CityUnit.objects.get(name=poultry_request.poultry.address.city.name) + # city_operator_system = CityOperator.objects.get(address__city=city_unit.city, trash=False) + city_operator_system = CityOperator.objects.get(key=poultry_request.city_operator.key, trash=False) + city_operator = SystemUserProfile.objects.get(key=city_operator_system.user.key, trash=False) + + else: + city_operator = SystemUserProfile.objects.get(user=request.user, trash=False) + city_operator_system = CityOperator.objects.get(key=poultry_request.city_operator.key, trash=False) + province = city_operator.province.name + province_operator = SystemUserProfile.objects.filter(role__name='ProvinceOperator', + province__name=province, trash=False).last() + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + city_operator_check_request = serializer.create(validated_data=request.data) + if state == 'accept': + poultry_request.state = { + "city_operator": city_operator.first_name + " " + city_operator.last_name, + "city_state": "accepted", + "city_operator_mobile": city_operator.mobile, + "city_operator_date_time_accepted": str(city_operator_check_request.create_date), + "province_operator": province_operator.first_name + " " + province_operator.last_name, + "provice_operator_mobile": province_operator.mobile, + "province_state": "pending" + } + poultry_request.state_process = 'accepted' + poultry_auctions = PoultryRequestAuction.objects.filter(poultry_request=poultry_request, + trash=False).order_by( + 'auction_date') + if poultry_auctions.count() > 0: + list2 = [] + i = 0 + for poultry_auction in poultry_auctions: + if i == 0: + poultry_auction.auction_date = datetime.now() + timedelta( + hours=int(poultry_auction.hour)) + poultry_auction.state = 'active' + poultry_auction.save() + list2.append(poultry_auction) + else: + poultry_auction.auction_date = list2[0].auction_date + timedelta( + hours=int(poultry_auction.hour)) + poultry_auction.save() + list2.clear() + list2.append(poultry_auction) + + i += 1 + + message = UserMessage( + message="درخواست شما با کد سفارش {0} از طرف کارشناس شهرستان {1} تایید شده است و در حال حاضر در انتظار تایید کارشناس استان {2} میباشد ".format( + poultry_request.order_code, city_operator.fullname, province_operator.fullname), + heading="پیام سیستم ثبت شده در تاریخ {0}".format(datetime.now()), + sender=city_operator + ) + message.save() + message.users.add(poultry_request.poultry.user) + + if state == 'reject': + if poultry_request.kill_house_list != None and len(poultry_request.kill_house_list) > 0: + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=poultry_request.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + kill_request.remain_quantity_for_poultry -= poultry_request.quantity + kill_request.save() + poultry_request.state = { + "city_operator": city_operator.first_name + " " + city_operator.last_name, + "city_state": " rejected", + "city_operator_date_time_rejected": str(city_operator_check_request.create_date), + "province_operator": "", + "province_state": "" + } + # hatching.left_over += (poultry_request.quantity + poultry_request.losses) + hatching.losses -= poultry_request.losses + hatching.state = 'pending' + hatching.allow_hatching = 'pending' + hatching.save() + poultry_request.message = city_operator_check_request.message + poultry_request.state_process = 'rejected' + message = UserMessage( + message="درخواست شما با کد سفارش {0} از طرف کارشناس شهرستان {1} رد شده است ".format( + poultry_request.order_code, city_operator.fullname), + heading="پیام سیستم ثبت شده در تاریخ {0}".format(datetime.now()), + sender=city_operator + ) + message.save() + message.users.add(poultry_request.poultry.user) + city_operator_check_request.city_operator_system = city_operator_system + city_operator_check_request.poultry_request = poultry_request + if poultry_request.auction == True: + city_operator_check_request.show_province = False + poultry_request.save() + if role == 'ProvinceOperator': + city_operator_check_request.province_accept = True + city_operator_check_request.save() + if state == 'accept': + if SmsLicense.objects.filter(city_approval=True).exists(): + poultry_mobile = city_operator_check_request.poultry_request.poultry.user.mobile + order_code = city_operator_check_request.poultry_request.order_code + date_str = str(city_operator_check_request.poultry_request.send_date) + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + sms_poultry_request_receive_city_accept_sms = threading.Thread( + target=poultry_request_receive_city_accept_sms, + args=( + poultry_mobile, + send_date,city_operator_check_request.poultry_request.order_code, + send_date,city_operator_check_request.poultry_request.free_sale_in_province, + + )) + sms_poultry_request_receive_city_accept_sms.start() + + if role == 'ProvinceOperator': + poultry_mobile = city_operator_check_request.poultry_request.poultry.user.mobile + order_code = city_operator_check_request.poultry_request.order_code + + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=city_operator_check_request.poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + city_operator_check_request.province_state = 'accept' + city_operator_check_request.save() + poultry_request.province_state = 'accepted' + poultry_request.save() + sms_poultry_request_receive_province_accept_sms_sms = threading.Thread( + target=poultry_request_receive_province_accept_sms, + args=( + poultry_mobile, order_code)) + sms_poultry_request_receive_province_accept_sms_sms.start() + + return Response({"result": "درخواست شما با موفقیت برای استان ارسال شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع برای نمایش درخواست های تایید شده مرغدار توسط شهرستان + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + queryset = [] + + if 'state' in request.GET: + user = SystemUserProfile.objects.get(user=request.user) + + if request.GET['state'] == 'waiting': + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now().date() + + queryset = [] + queryset = CityOperatorCheckRequest.objects.filter( + show_province=True, city_operator_system__address__province=user.province, + poultry_request__final_state='pending', trash=False, poultry_request__direct_buying=False, + poultry_request__send_date__year=date.year, poultry_request__send_date__month=date.month, + poultry_request__send_date__day=date.day + ).order_by( + '-poultry_request__send_date') + # item_list = CityOperatorCheckRequest.objects.filter( + # show_province=True, city_operator_system__address__province=user.province, + # poultry_request__final_state='pending', trash=False, + # poultry_request__send_date__year=date.year, poultry_request__send_date__month=date.month, + # poultry_request__send_date__day=date.day + # ).order_by( + # '-poultry_request__send_date') + # for req in item_list: + # province_check_req = ProvinceCheckOperatorRequest.objects.filter(city_request_Poultry=req) + # if province_check_req.count() > 0: + # province_check_req = province_check_req.last() + # if province_check_req.quantity > 0 and province_check_req.state == 'accept' or province_check_req.state == 'pending': + # if req in queryset: + # pass + # else: + # queryset.append(req) + # province_kill_reqs = ProvinceKillRequest.objects.filter(province_request=province_check_req) + # if province_kill_reqs.count() > 0: + # counter = 0 + # for province_kill_req in province_kill_reqs: + # if KillHouseCheckRequest.objects.filter( + # province_kill_request=province_kill_req, state='accepted').exists(): + # counter += 1 + # if province_kill_reqs.count() == counter and province_check_req.quantity == 0: + # pass + # else: + # + # if req in queryset: + # pass + # else: + # queryset.append(req) + + elif request.GET['state'] == 'all': + queryset = CityOperatorCheckRequest.objects.filter( + show_province=True, city_operator_system__address__province=user.province, + poultry_request__final_state='pending', trash=False).order_by( + '-poultry_request__send_date') + elif request.GET['state'] == 'new': + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + queryset_list = CityOperatorCheckRequest.objects.filter(state='accept', province_state='pending', + show_province=True, + city_operator_system__address__province=user.province, + trash=False).order_by( + 'poultry_request__send_date') + + queryset = [ + city_check for city_check in queryset_list + if date1 <= city_check.poultry_request.send_date.date() <= date2 + ] + else: + pass + # if 'state' in request.GET: + # if request.GET['state'] == 'CityOperator': + # user = SystemUserProfile.objects.get(user=request.user) + # city_operator = CityOperator.objects.get(user=user) + # queryset = CityOperatorCheckRequest.objects.filter( + # poultry_request__user__address__city=city_operator.address.city).order_by('-create_date') + + if 'type' in request.GET: + if request.GET['type'] == 'filter': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=self.queryset.filter(state__exact="accept", trash=False) + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=self.queryset) + filtered_city_operator = ps.filter() + serializer = self.serializer_class(filtered_city_operator, many=True) + return Response(serializer.data) + return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN) + + serializer = CityOperatorCheckRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + +class CityOperatorCheckRequestNewViewSet(viewsets.ModelViewSet): + queryset = CityOperatorCheckRequest.objects.all() + serializer_class = CityOperatorCheckRequestSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = CityOperatorRequestFilterSet + filterset_fields = [ + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__user__fullname', + 'poultry_request__poultry__user__first_name', + 'poultry_request__poultry__user__last_name', + 'poultry_request__poultry__user__city__name', + 'poultry_request__order_code', + ] + + # تابع برای نمایش درخواست های تایید شده مرغدار توسط شهرستان + def list(self, request, *args, **kwargs): + queryset = [] + + if 'state' in request.GET: + user = SystemUserProfile.objects.get(user=request.user) + + if request.GET['state'] == 'waiting': + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now().date() + + queryset = [] + queryset = CityOperatorCheckRequest.objects.filter( + show_province=True, city_operator_system__address__province=user.province, + poultry_request__final_state='pending', trash=False, poultry_request__direct_buying=False, + poultry_request__send_date__year=date.year, poultry_request__send_date__month=date.month, + poultry_request__send_date__day=date.day + ).order_by( + '-poultry_request__send_date') + + + elif request.GET['state'] == 'all': + queryset = CityOperatorCheckRequest.objects.filter( + show_province=True, city_operator_system__address__province=user.province, + poultry_request__final_state='pending', trash=False).order_by( + '-poultry_request__send_date') + elif request.GET['state'] == 'new': + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + queryset = CityOperatorCheckRequest.objects.filter(state='accept', province_state='pending', + show_province=True, + poultry_request__send_date__date__gte=date1, + poultry_request__send_date__date__lte=date2, + city_operator_system__address__province=user.province, + trash=False).order_by( + 'poultry_request__send_date') + + # queryset = [ + # city_check for city_check in queryset_list + # if date1 <= city_check.poultry_request.send_date.date() <= date2 + # ] + else: + pass + + if 'search' in request.GET: + city_check_requests = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=queryset + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=queryset) + city_check_requests = ps.filter() + queryset = [] if len(city_check_requests) == 0 else city_check_requests + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = CityOperatorCheckRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + +class PoultryEditByCityOperatorViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultrySerializer + + def update(self, request, *args, **kwargs): + # refresh(request.user.id) + # get poultry object + poultry_object = self.queryset.get(key=request.data['poultry_key'], trash=False) + request.data.pop('poultry_key') + + # Remove Null Fields From Address Body + request = remove_null_fields(type='item', request=request, item='address') + # Remove Null Fields From User Bank Info Body + request = remove_null_fields(type='item', request=request, item='user_bank_info') + # Remove Null Fields From request Body + request = remove_null_fields(type='req', request=request) + + # update address information + address_data = request.data['address'] + province = None + city = None + if 'province' and 'city' in address_data.keys(): + province = Province.objects.get(key=address_data['province'], trash=False) + address_data.pop('province') + city = City.objects.get(key=address_data['city'], trash=False) + address_data.pop('city') + address_serializer = SystemAddressSerializer(data=address_data) + if address_serializer.is_valid(): + addr_object = address_serializer.update( + instance=poultry_object.address, + validated_data=address_data + ) + if province != None and city != None: + addr_object.province = province + addr_object.city = city + addr_object.save() + request.data.pop('address') + + # update user bank information + if poultry_object.user_bank_info != None: + bank_data = request.data['user_bank_info'] + bank_serializer = BankCardSerializer(data=bank_data) + if bank_serializer.is_valid(): + bank_object = bank_serializer.update( + instance=poultry_object.user_bank_info, + validated_data=bank_data + ) + request.data.pop('user_bank_info') + else: + bank_data = request.data['user_bank_info'] + bank_serializer = BankCardSerializer(data=bank_data) + if bank_serializer.is_valid(): + bank_object = bank_serializer.create( + validated_data=bank_data + ) + request.data.pop('user_bank_info') + + # sending data to serializer & update poultry object + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + obj = serializer.update( + instance=poultry_object, + validated_data=request.data + ) + obj.user_bank_info = bank_object + obj.save() + serializer = self.serializer_class(obj) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class ManagementRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + # filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + def list(self, request, *args, **kwargs): + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + poultry_requests = [] + user = SystemUserProfile.objects.get(user=request.user) + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + trash=False, state_process__in=('pending', 'accepted'), + province_state='pending', + final_state='pending', out=False, + send_date__date__gte=date1, send_date__date__lte=date2 + ).order_by('-send_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (PoultryRequestFilterSet( + data=query, + queryset=queryset + ) + ).filter(): + ps = PoultryRequestFilterSet(data=query, queryset=queryset) + poultry_requests = ps.filter() + queryset = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = PoultryRequestForKillingInformationSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForKillingInformationSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/panel/KillHouse/__init__.py b/panel/KillHouse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/KillHouse/excel_processing.py b/panel/KillHouse/excel_processing.py new file mode 100644 index 0000000..e9fc577 --- /dev/null +++ b/panel/KillHouse/excel_processing.py @@ -0,0 +1,19548 @@ +import datetime +import string +from io import BytesIO +from datetime import timedelta +import jdatetime +import openpyxl +from django.contrib.auth.models import Group +from django.db.models import Sum, F, Q, Count +from django.http import QueryDict, HttpResponse +from django.views.decorators.csrf import csrf_exempt +from openpyxl import Workbook +from openpyxl.chart import Reference, BarChart, LineChart +from openpyxl.drawing.image import Image +from openpyxl.styles import PatternFill, Alignment, Font +from openpyxl.utils import get_column_letter +from django.db.models import Value +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny + +from authentication.models import SystemUserProfile, City, Province +from general_urls import base_url_sms +from panel.KillHouse.serializers import KillHouseForProvinceWareHouseDashboardSerializer, \ + KillHouseRequestForBarManagementSerializer, TotalKillHouseWarehouseArchiveDashboardSerializer +from panel.ProvinceOperator.serializers import WarehouseArchiveSerializer +from panel.convert_date import convert_to_shamsi +from panel.filterset import KillRequestFilterSet, KillHouseRequestFilterSet, KillHouseFreeBarInformationFilterSet, \ + OutProvinceCarcassesBuyerFilterSet, StewardAllocationFilterSet, DashboardEnterLoadInformationFilterSet, \ + WarehouseArchiveFilterSet, KillHouseFilterSet +from panel.helper import build_query +from panel.helper_excel import shamsi_date, create_header, create_header_freez, \ + excel_description, create_value, Alignment_CELL, blue_fill, cell_color_changer, add_chart, convert_str_to_date +from panel.models import KillRequest, KillHouse, KillHouseVet, KillHousePercentage, ProvinceKillRequest, \ + KillHouseRequest, CityOperator, VetFarm, PoultryRequest, VetCheckRequest, KillHouseAssignmentInformation, Vet, \ + KillHouseFreeBarInformation, KillHouseOperator, Poultry, ChainAllocation, KillHouseWareHouse, StewardAllocation, \ + OutProvinceCarcassesBuyer, KillHouseFreeSaleBarInformation, WageType, RolesProducts, ColdHouse, Guilds, \ + WarehouseArchive +from django.db.models import Sum, F, Case, When, BooleanField + + +def direct_purchase_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + ] + kill_requests = KillRequest.objects.filter( + trash=False, + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + direct_buying_state__in=( + 'accepted', 'rejected', 'deleted', 'pending'), + export_status=False + ).order_by( + Case( + When(direct_buying_state='pending', then=Value(0)), + default=Value(1) + ), + '-recive_date' # مرتب‌سازی بر اساس تاریخ بعد از مرتب‌سازی بر اساس حالت + ) + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_requests = kill_requests.filter(kill_house__kill_house_operator__user=user) + else: + kill_requests = kill_requests + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_requests) + kill_requests = ps.filter() + + excel_options = [ + 'ردیف', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'خریدار', + 'تلفن خریدار', + 'محل کشتار', + 'مرغدار', + 'تلفن مرغدار', + 'نژاد', + 'تعداد درخواستی', + 'تعداد تایید شده', + 'میانگین وزنی', + 'وزن کل(کیلوگرم)', + 'کد احراز', + 'حداکثر مهلت تسویه', + 'وضعیت', + ] + header_list = [ + 'تعداد کل خرید', + 'مجموع تعداد درخواستی', + 'مجموع وزن(کیلوگرم)', + 'تعداد درخواست دارای کد احراز', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header_freez(worksheet, excel_options, 1, 4, 5, height=18, width=20.1) + create_header(worksheet, header_list, 4, 2, height=24, width=20.01) + + row = 3 + m = 1 + all_direct_buying_code = 0 + for kill_request in kill_requests: + row += 1 + recive_date = jdatetime.date.fromgregorian( + day=kill_request.recive_date.day, + month=kill_request.recive_date.month, + year=kill_request.recive_date.year + ) if kill_request.recive_date else '-' + create_date = jdatetime.date.fromgregorian( + day=kill_request.create_date.day, + month=kill_request.create_date.month, + year=kill_request.create_date.year + ) if kill_request.create_date else '-' + if kill_request.slaughter_house is not None: + kill_place = kill_request.slaughter_house.name + else: + kill_place = kill_request.kill_house.name + if kill_request.direct_buying_state == 'pending': + state = 'درانتظار تایید' + elif kill_request.direct_buying_state == 'rejected': + state = 'رد شده' + elif kill_request.direct_buying_state == 'deleted': + state = 'حذف شده' + else: + state = 'تایید شده' + cepacity = kill_request.kill_capacity if kill_request.kill_capacity else '-' + if kill_request.input_direct_buying_code: + direct_buying_code = kill_request.input_direct_buying_code + all_direct_buying_code += 1 + else: + direct_buying_code = '-' + list1 = [ + m, + str(create_date), + str(recive_date), + kill_request.kill_house.name, + kill_request.kill_house.kill_house_operator.user.mobile, + kill_place, + kill_request.poultry.unit_name, + kill_request.poultry.user.mobile, + kill_request.chicken_breed, + kill_request.previous_kill_capacity, + cepacity, + kill_request.Index_weight, + kill_request.Index_weight * kill_request.previous_kill_capacity, + direct_buying_code, + str(shamsi_date(kill_request.payment_deadline_date, in_value=True)) if kill_request.payment_deadline_date else '-', + state, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + m += 1 + total_quantity = kill_requests.aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + total_wight = kill_requests.aggregate( + total_quantity=Sum(F('Index_weight') * F('previous_kill_capacity'))).get( + 'total_quantity') or 0 + value_list = [ + m - 1, + total_quantity, + total_wight, + all_direct_buying_code, + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_list[item]) + value = value_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="خرید مستقیم.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def direct_purchase_archive_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + ] + kill_requests = KillRequest.objects.filter( + trash=False, + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + direct_buying_state__in=( + 'accepted', 'rejected', 'deleted') + ).order_by( + 'recive_date') + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_requests = kill_requests.filter(kill_house__kill_house_operator__user=user) + else: + kill_requests = kill_requests + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_requests) + kill_requests = ps.filter() + + excel_options = [ + 'ردیف', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'خریدار', + 'تلفن خریدار', + 'محل کشتار', + 'مرغدار', + 'تلفن مرغدار', + 'نژاد', + 'تعداد درخواستی', + 'تعداد تایید شده', + 'میانگین وزنی', + 'وزن کل(کیلوگرم)', + 'کد احراز', + 'وضعیت', + ] + header_list = [ + 'تعداد کل خرید', + 'مجموع تعداد درخواستی', + 'مجموع وزن(کیلوگرم)', + 'تعداد درخواست دارای کد احراز', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header_freez(worksheet, excel_options, 1, 4, 5, height=18, width=20.1) + create_header(worksheet, header_list, 4, 2, height=24, width=20.01) + + row = 3 + m = 1 + all_direct_buying_code = 0 + for kill_request in kill_requests: + row += 1 + recive_date = jdatetime.date.fromgregorian( + day=kill_request.recive_date.day, + month=kill_request.recive_date.month, + year=kill_request.recive_date.year + ) if kill_request.recive_date else '-' + create_date = jdatetime.date.fromgregorian( + day=kill_request.create_date.day, + month=kill_request.create_date.month, + year=kill_request.create_date.year + ) if kill_request.create_date else '-' + if kill_request.slaughter_house is not None: + kill_place = kill_request.slaughter_house.name + else: + kill_place = kill_request.kill_house.name + if kill_request.direct_buying_state == 'pending': + state = 'درانتظار تایید' + elif kill_request.direct_buying_state == 'rejected': + state = 'رد شده' + else: + state = 'تایید شده' + cepacity = kill_request.kill_capacity if kill_request.kill_capacity else '-' + if kill_request.input_direct_buying_code: + direct_buying_code = kill_request.input_direct_buying_code + all_direct_buying_code += 1 + else: + direct_buying_code = '-' + list1 = [ + m, + str(create_date), + str(recive_date), + kill_request.kill_house.name, + kill_request.kill_house.kill_house_operator.user.mobile, + kill_place, + kill_request.poultry.unit_name, + kill_request.poultry.user.mobile, + kill_request.chicken_breed, + kill_request.previous_kill_capacity, + cepacity, + kill_request.Index_weight, + kill_request.Index_weight * kill_request.previous_kill_capacity, + direct_buying_code, + state, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + m += 1 + total_quantity = kill_requests.aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + total_wight = kill_requests.aggregate( + total_quantity=Sum(F('Index_weight') * F('previous_kill_capacity'))).get( + 'total_quantity') or 0 + value_list = [ + m - 1, + total_quantity, + total_wight, + all_direct_buying_code, + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_list[item]) + value = value_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="بایگانی خرید مستقیم.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_assignment_information_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('ware_house_accepted_real_quantity', 'ware_house_accepted_real_weight', + 'weight_loss', 'message', 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', 'killer').values('ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + ) + if 'key' in request.GET: + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + + else: + filtered_kill_reqs = filtered_kill_request + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های داری سند', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + if kill['assignment_state_archive'] == 'True': + all_assignment_state_archive_state += 1 + assignment_state_archive_state = 'وارد شده است' + else: + assignment_state_archive_state = 'وارد نشده است' + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + state_delete, + assignment_state_archive_state, + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + ware_house_accepted_real_weight, + weight_loss, + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(all_weight_loss / len_weight_loss, 2) + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + all_assignment_state_archive_state, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + all_weight_loss + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if request.GET['role'] == 'KillHouse': + name = filtered_kill_request.first()['killhouse_user__name'] + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_user_excel(request): + kill_houses = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user').order_by('id') + excel_options = [ + 'ردیف', + 'ماهیت', + 'نام واحد', + 'نام و نام خانوادگی', + 'تلفن', + 'دامپزشک کشتارگاه', + ' تلفن دامپزشک کشتارگاه', + 'آدرس', + 'محل کشتار', + 'تعداد سفارشات', + 'حجم سفارشات', + 'وزن سفارشات', + 'تعداد بارها', + 'حجم بارها', + 'وزن بارها', + 'میانگین وزنی', + 'تعداد بار ورودی به انبار', + 'حجم ورودی به انبار', + 'وزن ورودی به انبار', + 'درصد افت', + 'لینک پرداخت', + 'تعداد بارهای فاقد قرنطینه تخلیه شده', + 'درصد بارهای فاقد قرنطینه تخلیه شده', + 'تعداد بارهای دارای قرنطینه تخلیه نشده', + 'درصد بارهای دارای قرنطینه تخلیه نشده', + 'تعداد بارهای تخلیه شده', + 'درصد بارهای تخلیه شده', + 'تعداد بارهای ارزیابی شده', + 'درصد بارهای ارزیابی شده', + 'تعداد بارهای تایید شده در سند', + 'درصد بارهای تایید شده در سند', + 'تعداد بارهای مغایرت دارد در سند', + 'درصد بارهای مغایرت دارد در سند', + 'تعداد بارهای فاقد کیفیت در سند', + 'درصد بارهای فاقد کیفیت در سند', + 'تعداد بارهای تایید شده بدون کیفیت در سند', + 'درصد بارهای تایید شده بدون کیفیت در سند', + 'تعداد بارهای دست نویس در سند', + 'درصد بارهای دست نویس در سند', + 'تعداد بارهای باطل شده در سند', + 'درصد بارهای باطل شده در سند', + 'تعداد بارهای تخلیه نشده', + 'درصد بارهای تخلیه نشده', + 'میانگین وزن کشتار روزانه', + 'میانگین حجم کشتار روزانه', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[4].height = 25 + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد خریداران', + 'تعداد کشتارکن', + 'تعداد کشتارکن های عمومی', + 'تعداد کشتارکن های اختصاصی', + 'تعداد کل سفارشات', + 'حجم کل سفارشات', + 'وزن کل سفارشات', + 'تعداد بارها', + 'حجم بارها', + 'وزن بارها', + 'تعداد بار ورودی به انبار', + 'حجم ورودی به انبار', + 'وزن ورودی به انبار', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['B1'] = f'مدیریت خریداران از تاریخ {from_date_1} تا {to_date_1}' + else: + worksheet['B1'] = f'مدیریت خریداران' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 4 + m = 1 + killer_type_public = 0 + killer_type_exclusive = 0 + killer = 0 + len_province_kill_request = 0 + all_province_weight = 0 + all_province_quantity = 0 + len_kill_request = 0 + all_kill_request_quantity = 0 + all_kill_request_weight = 0 + all_len_kill_req1 = 0 + all_ware_house_accepted_real_weight = 0 + all_ware_house_accepted_real_quantity = 0 + all_weight_loss = 0 + for kill_house in kill_houses: + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + province_kill_request = ProvinceKillRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False, return_to_province=False, + state__in=('accepted', 'pending'), + killhouse_user=kill_house).select_related( + 'province_request__poultry_request') \ + .only('main_quantity', 'province_request__poultry_request__Index_weight') + + kill_request = KillHouseRequest.objects.filter(Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False + , kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).only( + 'accepted_assignment_real_quantity', + 'accepted_assignment_real_weight') + else: + province_kill_request = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('accepted', 'pending'), + killhouse_user=kill_house).select_related( + 'province_request__poultry_request') \ + .only('main_quantity', 'province_request__poultry_request__Index_weight') + + kill_request = KillHouseRequest.objects.filter(Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False + ).only('accepted_assignment_real_quantity', + 'accepted_assignment_real_weight') + + percentage = KillHousePercentage.objects.filter(kill_house=kill_house).select_related('kill_house_for_killer', + 'kill_house').first() + if percentage: + if percentage.kill_house_for_killer != None: + place = percentage.kill_house_for_killer.name + else: + place = percentage.kill_house.name + else: + place = kill_house.name + if kill_house.killer == True: + killer += 1 + type = 'کشتارکن' + if kill_house.type == 'public': + killer_type = f'{type} عمومی ' + killer_type_public += 1 + else: + killer_type = f' {type} اختصاصی ({place})' + killer_type_exclusive += 1 + + else: + type = 'کشتارگاه' + killer_type = f'{type} ' + + all_recive_date = set(kill_request.values_list('kill_request__recive_date__date', flat=True)) + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_house).first() + + if kill_house_vet: + vet_fullname = kill_house_vet.vet.user.fullname + vet_mobile = kill_house_vet.vet.user.mobile + else: + vet_fullname = '-' + vet_mobile = '-' + + len_province_kill_request += len(province_kill_request) + len_kill_request += len(kill_request) + province_quantity = province_kill_request.aggregate( + total=Sum('main_quantity'))[ + 'total'] or 0 + province_weight = province_kill_request.aggregate( + total=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight')))[ + 'total'] or 0 + all_province_weight += int(province_weight) + all_province_quantity += province_quantity + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight = kill_request.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + kill_req_ware_house_confirmation = kill_request.filter(ware_house_confirmation=True, killhouse_user=kill_house) + ware_house_accepted_real_quantity = kill_req_ware_house_confirmation.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + + ware_house_accepted_real_weight = kill_req_ware_house_confirmation.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity') or 0 + weight_loss1 = kill_req_ware_house_confirmation.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity') or 0 + weight_loss = weight_loss1 / len(kill_req_ware_house_confirmation) if len( + kill_req_ware_house_confirmation) > 0 else 0 + + all_len_kill_req1 += len(kill_req_ware_house_confirmation) + + all_ware_house_accepted_real_weight += ware_house_accepted_real_weight + all_ware_house_accepted_real_quantity += ware_house_accepted_real_quantity + all_weight_loss += int(weight_loss) + + all_kill_request_quantity += kill_request_quantity + all_kill_request_weight += int(kill_request_weight) + link = f'https://{base_url_sms}.rasadyaar.ir/pay/k{kill_house.kill_house_operator.user.user_gate_way_id}' + hasnt_code = len( + kill_request.filter(Q(assignment_state_archive='True') | Q(vet_state='accepted'), + clearance_code__isnull=True)) + percent_hasnt_code = round(hasnt_code * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + has_code = len( + kill_request.filter(vet_state='pending', assignment_state_archive='pending', clearance_code__isnull=False)) + percent_has_code = round(has_code * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + + has_assignment = len( + kill_request.filter(Q(vet_state='accepted') | Q(assignment_state_archive='True'))) + percent_has_assignment = round(has_assignment * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + hasnt_assignment = len( + kill_request.filter(assignment_state_archive='pending', vet_state='pending')) + percent_hasnt_assignment = round(hasnt_assignment * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + evaluated_bar = len( + kill_request.filter(bar_document_status__isnull=False)) + percent_evaluated_bar = round(evaluated_bar * 100 / has_assignment, 2) if has_assignment > 0 else 0 + + accepeted_bar = len( + kill_request.filter(bar_document_status__title='تایید شده')) + percent_accepeted_bar = round(accepeted_bar * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + diffrent_bar = len( + kill_request.filter(bar_document_status__title='مغایرت دارد')) + percent_diffrent_bar = round(diffrent_bar * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + no_quality = len( + kill_request.filter(bar_document_status__title='فاقد کیفیت')) + percent_no_quality = round(no_quality * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + accepted_low_quality = len( + kill_request.filter(bar_document_status__title='تایید شده بدون کیفیت')) + percent_low_quality = round(accepted_low_quality * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + hand_write = len( + kill_request.filter(bar_document_status__title='دست نویس')) + percent_hand_write = round(hand_write * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + cancled = len( + kill_request.filter(bar_document_status__title='باطل شده')) + percent_cancled = round(cancled * 100 / evaluated_bar, 2) if evaluated_bar > 0 else 0 + list1 = [ + m, + killer_type, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + vet_fullname, + vet_mobile, + kill_house.kill_house_operator.user.city.name, + place, + len(province_kill_request), + province_quantity, + int(province_weight), + len(kill_request), + kill_request_quantity, + int(kill_request_weight), + round(kill_request_weight / kill_request_quantity, 1) if kill_request_weight > 0 else 0, + len(kill_req_ware_house_confirmation), + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f"{int(weight_loss)}%", + link, + hasnt_code, + f'%{percent_hasnt_code}', + has_code, + f'%{percent_has_code}', + has_assignment, + f'%{percent_has_assignment}', + evaluated_bar, + f'%{percent_evaluated_bar}', + + accepeted_bar, + f'%{percent_accepeted_bar}', + diffrent_bar, + f'%{percent_diffrent_bar}', + no_quality, + f'%{percent_no_quality}', + accepted_low_quality, + f'%{percent_low_quality}', + hand_write, + f'%{percent_hand_write}', + cancled, + f'%{percent_cancled}', + hasnt_assignment, + f'%{percent_hasnt_assignment}', + (int(kill_request_weight / len(all_recive_date)) if len(all_recive_date) > 0 else 0), + (int(kill_request_quantity / len(all_recive_date)) if len(all_recive_date) > 0 else 0), + + ] + m += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + worksheet.column_dimensions[get_column_letter(item + 1)].width = 17.01 + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + l += 1 + + # last_age=sorted(reversed(all_age)) + + value_header_list2 = [ + len(kill_houses), + killer, + killer_type_public, + killer_type_exclusive, + len_province_kill_request, + all_province_quantity, + all_province_weight, + len_kill_request, + all_kill_request_quantity, + all_kill_request_weight, + all_len_kill_req1, + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت خریداران.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() if 'start' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() if 'end' in request.GET else now + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'province_kill_request__kill_house_price', + 'price', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'province_kill_request__kill_house_price', + 'price', + 'bar_document_status__title' + ) + + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(key=request.GET['key']) + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key']) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__address__city=user.city) + elif request.GET['role'] == 'VetFarm': + user = SystemUserProfile.objects.get(key=request.GET['key']) + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(out_province=False, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_reqs.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_reqs.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_reqs + else: + filtered_kill_reqs = filtered_kill_reqs + if 'search' in request.GET: + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + filtered_kill_reqs = filtered_kill_reqs.filter( + build_query(DashboardEnterLoadInformationFilterSet, value) + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + 'اختلاف مجوز', + + ] + + from_date_1 = shamsi_date(date1) + + to_date_1 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'حجم بارهای ایجاد شده', + 'وزن بارهای ایجاد شده', + 'میانگین وزن بارهای ایجاد شده', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'حجم بارها', + 'وزن بارها', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + header_list3 = [ + 'درصد بارهای دارای کد قرنطینه', + 'درصد تعداد بارهای احراز شده از قرنطینه', + 'درصد تعداد بارهای تکمیل شده کشتارگاه', + 'درصد وزن نهایی در کشتارگاه نسبت به وزن کل', + 'درصد بارهای فاقد کد قرنطینه', + 'درصد بارهای اختلاف دار در قرنطینه و رصدیار', + 'درصد تعداد بارهای ورودی به انبار', + 'درصد وزن لاشه ها در انبار نسبت به وزن کل', + 'درصد وزن لاشه در انبار نسبت به وزن نهایی در کشتارگاه', + + ] + create_header(worksheet, header_list, 9, 2, height=21.8) + + create_header(worksheet, header_list2, 6, 2, height=21.8, color='green') + + create_header(worksheet, header_list3, 6, 5, height=43, color='orange', text_color='0D0D0D') + create_header_freez(worksheet, excel_options, 1, 8, 9, height=21, len_with=True) + + excel_description(worksheet, 'B1', 'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی', color='red', row2='D1') + + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + excel_description(worksheet, 'B2', f'استان {name}', color='red', row2='D2') + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + + l = 8 + m = 1 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + if kill['assignment_state_archive'] == 'True' or kill['ware_house_confirmation'] == True: + net_weighte = kill['accepted_real_weight'] + real_quantity = kill['accepted_real_quantity'] + else: + net_weighte = 0 + real_quantity = 0 + net_weighte2, real_quantity2, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + round(kill['accepted_real_weight'], 1), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else quarantine_quantity + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + + province_kill_request = ProvinceKillRequest.objects.filter( + pk__in=filtered_kill_reqs.values( + 'province_kill_request')).aggregate( + total_quantity_melak=Sum('total_killed_quantity'), + total_weight_melak=Sum('total_killed_weight'), + ) + + # province_kill_request = filtered_kill_reqs.values_list( + # 'province_kill_request',flat=True).distinct().aggregate( + # total_quantity_melak=Sum('total_killed_quantity'), + # total_weight_melak=Sum('total_killed_weight'), + # ) + accepted_real_quantity_melak = province_kill_request['total_quantity_melak'] or 0 + + accepted_real_wight_melak = province_kill_request['total_weight_melak'] or 0 + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity_melak, + accepted_real_wight_melak, + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 3, 6) + value_header_list2 = [ + f'%{round((has_code * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((has_qarantine * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((len(bar_complete) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_net_weighte) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((len(hasnt_code1) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((difference_bar * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((all_state_ware_house_confirmation * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_net_weighte), 2) if int(all_net_weighte) > 0 else 0}' + ] + create_value(worksheet, value_header_list2, 6, 6) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if request.GET['role'] == 'KillHouse': + name = filtered_kill_reqs.first()['killhouse_user__name'] + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + elif 'state' in request.GET: + if request.GET['state'] == 'bar_pending': + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل نشده.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل شده.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_excel_trash_true(request): + filterset_class = KillHouseRequestFilterSet + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_request = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=True, temporary_trash=False, temporary_deleted=False).select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', 'traffic_code', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', 'message', + 'bar_remover', 'province_request__poultry_request__freezing', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', ).values('province_kill_request__kill_house_price', + 'killhouse_user', + 'province_request__poultry_request__freezing', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'message', + 'bar_remover', + 'traffic_code', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + + ) + if 'key' in request.GET: + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__address__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد وارد شده در قرنطینه', + 'تاریخ حذف', + 'حذف کننده', + 'دلیل حذف', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارحذف شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه حذف شده', + 'مجموع وزن بار حذف شده', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'مدیریت بارهای حذف شده' + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + + l = 3 + m = 1 + all_quantity = 0 + all_weighte = 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + + l += 1 + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = kill['quarantine_quantity'] if kill['quarantine_quantity'] != None else '-' + if kill['bar_remover'] is not None: + date_remover = kill['bar_remover']['date'].split('-') + bar_remover_date = jdatetime.date.fromgregorian( + day=int(date_remover[2]), + month=int(date_remover[1]), + year=int(date_remover[0]) + ) if date_remover else '-' + else: + bar_remover_date = '-' + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + str(bar_remover_date), + kill['bar_remover']['full_name'] if kill['bar_remover'] != None else '-', + kill['message'] if kill['message'] != None else '-', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + all_weighte, + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if request.GET['role'] == 'KillHouse': + name = filtered_kill_request.first()['killhouse_user__name'] + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای حذف شده کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="بارهای حذف شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_wage_excel(request): + kill_house = KillHouse.objects.filter(trash=False) + sheet_names2 = [ + 'اطلاعات کلی', + 'بارهای روزانه', + 'تخصیص روزانه', + 'مرغ زنده', + 'لاشه', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_house, + + archive_wage=False, + trash=False).order_by('id') + + filtered_kill_reqs = KillHouseRequest.objects.filter( + trash=False, + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('document_status', 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', 'killer').values('document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + ) + + province_kill_request = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + first_car_allocated_quantity=0, + trash=False).order_by( + 'kill_request__recive_date') + + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'بارهای روزانه': + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + filtered_kill_reqs = filtered_kill_reqs.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + else: + filtered_kill_reqs = filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + date_of_poultry_request = '-' + send_date = kill.get('province_request__poultry_request__send_date') + if send_date: + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + weight = 0 + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + if kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight'): + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = '-' + if kill.get('province_request__poultry_request__send_date') and kill.get( + 'province_request__poultry_request__hatching__date'): + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['document_status'] if kill['document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{weight_loss}', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity') or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity') or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + int(all_weighte), + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'تخصیص روزانه': + worksheet['H3'] = 'در این قسمت تخصیصات فاقد بار نمایش داده میشود' + merge_range1 = 'H3:K3' + worksheet.merge_cells(merge_range1) + worksheet['H3'].font = Font(color="C00000", bold=True) + worksheet['H3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + province_kill_request = province_kill_request.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).order_by( + 'kill_request__recive_date') + else: + province_kill_request = province_kill_request + + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'جمع کل سهم', + ] + for col_num, option in enumerate(header_list, 3): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'تعرفه اتحادیه(ریال)', + 'سهم شما(ریال)', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + for province_kill in province_kill_request: + + kill_date = jdatetime.date.fromgregorian( + year=province_kill.province_request.poultry_request.send_date.year, + month=province_kill.province_request.poultry_request.send_date.month, + day=province_kill.province_request.poultry_request.send_date.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(kill_date.split("-")) + separate = "-" + kill_date_1 = separate.join(reversed_date1) + + if province_kill.kill_request.slaughter_house is not None: + kill_place = province_kill.kill_request.slaughter_house.name + else: + kill_place = province_kill.kill_request.kill_house.name + + total_amount = province_kill.total_wage_amount + + list1 = [ + m, + province_kill.province_request.poultry_request.order_code, + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.wage, + total_amount, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_weight = \ + province_kill_request.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_killed_quantity = \ + province_kill_request.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_wage_amount = \ + province_kill_request.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 3, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + elif sheet_name == 'مرغ زنده': + # type = request.GET['type'] + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_free_bar_info = kill_house_free_bar_info.filter(date__date__gte=date1, + date__date__lte=date2, buy_type='live', ) + else: + kill_house_free_bar_info = kill_house_free_bar_info.filter(buy_type='live') + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + header_list = [ + 'تعداد خریداران', + 'تعداد کل', + 'وزن کل', + 'مبلغ کل', + ] + excel_options = [ + 'ردیف', + 'نام خریدار', + 'تلفن خریدار', + 'نام فروشنده', + 'تلفن فروشنده', + 'شهر', + 'تعداد', + 'وزن', + 'تعرفه', + 'مبلغ کل', + ] + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + + list1 = [ + m, + kill.kill_house.name, + kill.kill_house.kill_house_operator.user.mobile, + kill.poultry_name, + kill.poultry_mobile, + kill.city, + kill.quantity, + kill.live_weight, + kill.wage, + kill.total_wage_amount, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_quantity = \ + kill_house_free_bar_info.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_wage_amount = \ + kill_house_free_bar_info.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + value_list = [ + m - 1, + total_quantity, + total_weight, + total_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 4, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + elif sheet_name == 'لاشه': + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_free_bar_info2 = kill_house_free_bar_info.filter(date__date__gte=date1, + date__date__lte=date2, buy_type='carcass') + else: + kill_house_free_bar_info2 = kill_house_free_bar_info.filter(buy_type='carcass') + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + header_list = [ + 'تعداد خریداران', + 'تعداد کل', + 'وزن کل', + 'مبلغ کل', + ] + excel_options = [ + 'ردیف', + 'نام خریدار', + 'تلفن خریدار', + 'نام فروشنده', + 'تلفن فروشنده', + 'شهر', + 'تعداد', + 'وزن', + 'تعرفه', + 'مبلغ کل', + ] + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + if kill_house_free_bar_info2: + for kill in kill_house_free_bar_info2: + + list1 = [ + m, + kill.kill_house.name, + kill.kill_house.kill_house_operator.user.mobile, + kill.poultry_name, + kill.poultry_mobile, + kill.city, + kill.quantity, + kill.live_weight, + kill.wage, + kill.total_wage_amount, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_quantity = \ + kill_house_free_bar_info2.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = \ + kill_house_free_bar_info2.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_wage_amount = \ + kill_house_free_bar_info2.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + value_list = [ + m - 1, + total_quantity, + total_weight, + total_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 4, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="اطلاعات کلی تعرفه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def slaughterhouse_export_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if "date1" in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if "date2" in request.GET else now + if 'key' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + transactions = KillHouseRequest.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='failed', + transaction_type='wage-gateway', + trash=False).order_by('id') + else: + transactions = KillHouseRequest.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='failed', + transaction_type='wage-gateway', + trash=False).order_by('id') + + excel_options = [ + 'ردیف', + 'تاریخ و زمان', + 'پرداخت کننده', + 'تعداد سفارشات', + 'تعداد کل(قطعه)', + 'وزن کل(کیلوگرم)', + 'شماره درخواست', + 'شماره پیگیری', + 'کد سفارش', + 'شماره کارت', + 'قیمت(ریال)', + 'متن خطا', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + for transaction in transactions: + total_weight = 0 + total_quantity = 0 + total_request = 0 + wage_payment = KillRequest.objects.filter( + Q(orderId=transaction.orderId) | Q(tracking_code=transaction.saleReferenceId), + trash=False).first() + if wage_payment.province_kill_request != None: + total_request = len(wage_payment.province_kill_request) + for province_kill_req in wage_payment.province_kill_request: + province_kill = ProvinceKillRequest.objects.get(key=province_kill_req, trash=False) + total_weight += province_kill.total_killed_weight + total_quantity += province_kill.total_killed_quantity + date = transaction.date + date_create = convert_to_shamsi(datetime=date) + message = transaction.message + if message == 'ﻛﺎرﺑﺮ_از_اﻧﺠﺎم_ﺗﺮاﻛﻨﺶ_ﻣﻨﺼﺮف_ﺷﺪه_اﺳﺖ': + message = 'ﻛﺎرﺑﺮ از اﻧﺠﺎم ﺗﺮاﻛﻨﺶ ﻣﻨﺼﺮف ﺷﺪه اﺳﺖ' + + list1 = [ + m, + str(date_create), + transaction.payer, + total_request, + total_quantity, + total_weight, + str(transaction.refId) if transaction.refId != None else '-', + str(transaction.saleReferenceId) if transaction.saleReferenceId != None else '-', + str(transaction.orderId) if transaction.orderId != None else '-', + str(transaction.cardHolderPan) if transaction.cardHolderPan != None else '-', + transaction.amount, + message + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 29 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های ناموفق.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def export_kill_house_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + + querysets = KillRequest.objects.filter(kill_house__in=kill_house, recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, + ).order_by( + 'recive_date') + else: + querysets = KillRequest.objects.filter(kill_house__system_address__province=user.province, + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, + + ).order_by( + 'recive_date') + + excel_options = [ + 'ردیف', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'خریدار', + 'تلفن خریدار', + 'محل کشتار', + 'کشور مقصد', + 'مرغدار', + 'تلفن مرغدار', + 'تعداد درخواست (قطعه)', + 'میانگین وزنی (کیلوگرم)', + 'وزن کل (کیلوگرم)', + 'کد احراز', + 'وضعیت', + 'تاریخ تایید/رد', + 'دلیل رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد درخواست های تایید شده', + 'مجموع تعداد درخواست های تایید شده (قطعه)', + 'مجموع وزن کل تایید شده (کیلوگرم)', + + 'تعداد درخواست های رد شده', + 'مجموع تعداد درخواست های رد شده (قطعه)', + 'مجموع وزن کل رد شده (کیلوگرم)', + + 'تعداد درخواست های حذف شده', + 'مجموع تعداد درخواست های حذف شده (قطعه)', + 'مجموع وزن کل حذف شده (کیلوگرم)', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'گزارش صادرات از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_accepted = 0 + all_rejected = 0 + all_deleted = 0 + all_weight = 0 + accepted_weight = 0 + deleted_weight = 0 + rejected_weight = 0 + for kill in querysets: + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + kill_date = jdatetime.date.fromgregorian( + day=kill.recive_date.day, + month=kill.recive_date.month, + year=kill.recive_date.year + ) + if kill.accept_reject_date is not None: + del_accept_date = jdatetime.date.fromgregorian( + day=kill.accept_reject_date.day, + month=kill.accept_reject_date.month, + year=kill.accept_reject_date.year + ) + else: + del_accept_date = '-' + + if kill.slaughter_house is not None: + kill_place = kill.slaughter_house.name + else: + kill_place = kill.kill_house.name + Index_weight = round(kill.Index_weight, 1) + + if kill.export_state == 'accepted': + type = 'تایید شده' + all_accepted += 1 + accepted_weight += int(kill.kill_capacity * Index_weight) + elif kill.export_state == 'rejected': + type = 'رد شده' + all_rejected += 1 + rejected_weight += int(kill.kill_capacity * Index_weight) + elif kill.export_state == 'deleted': + type = 'حذف شده' + all_deleted += 1 + deleted_weight += int(kill.kill_capacity * Index_weight) + else: + type = 'در انتظار تایید' + all_weight += int(kill.kill_capacity * Index_weight) + list1 = [ + m, + str(create_date), + str(kill_date), + kill.kill_house.name, + kill.kill_house.kill_house_operator.user.mobile, + kill_place, + kill.export_country, + kill.poultry.unit_name, + kill.poultry.user.mobile, + kill.kill_capacity, + Index_weight, + int(kill.kill_capacity * Index_weight), + kill.direct_buying_code if kill.direct_buying_code else '-', + type, + str(del_accept_date), + kill.direct_buying_message if kill.direct_buying_message else '-' + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[13] == 'رد شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + if list1[13] == 'حذف شده': + cell.fill = PatternFill(start_color="F7A49B", fill_type="solid") + + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + cell.alignment = Alignment(horizontal='center') + + export_quantity = querysets.aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + + export_accepted_quantity = querysets.filter(export_state='accepted').aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + export_rejected_quantity = querysets.filter(export_state='rejected').aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + export_deleted_quantity = querysets.filter(export_state='deleted').aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + + value_header_list = [ + all_accepted, + export_accepted_quantity, + accepted_weight, + + all_rejected, + export_rejected_quantity, + rejected_weight, + + all_deleted, + export_deleted_quantity, + deleted_weight + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + export_quantity, + '', + all_weight, + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش درخواست های صادرات.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def monitor_loads_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + 'کشور مقصد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + + excel_options1 = { + 'آمار کلی': [], + 'مدیریت بارها': [], + 'بارهای حذف شده': [], + 'فروش به خارج از استان': [], + 'بارهای زنجیره': [], + 'خرید زنده خارج از استان': [], + 'خرید لاشه خارج از استان': [], + + } + + output = BytesIO() + workbook = Workbook() + for name, options in excel_options1.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + if sheet_name == 'آمار کلی': + filtered_kill_request = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__kill_house_price', + 'price', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer').values( + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'province_kill_request__kill_house_price', + 'price', + 'killer', + 'province_request__poultry_request__Index_weight', + ) + + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_reqs.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_reqs.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_reqs + else: + filtered_kill_reqs = filtered_kill_reqs + worksheet['H1'] = f'اطلاعات کل بارها' + worksheet['H1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['H1'].font = Font(color='FF0000', size=11) + merge_range1 = 'H1:L1' + worksheet.merge_cells(merge_range1) + + worksheet['H6'] = f'گزارش بارهای حذف شده' + merge_range1 = 'H6:L6' + worksheet.merge_cells(merge_range1) + worksheet['H6'].font = Font(color='FF0000', size=11) + worksheet['H6'].alignment = Alignment(horizontal='center', vertical='center') + + worksheet['H11'] = f'گزارش فروش به خارج از استان' + worksheet['H11'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['H11'].font = Font(color='FF0000', size=11) + merge_range1 = 'H11:L11' + worksheet.merge_cells(merge_range1) + + worksheet['H16'] = f'گزارش کشتار شرکت های زنجیره ای' + worksheet['H16'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['H16'].font = Font(color='FF0000', size=11) + merge_range1 = 'H16:L16' + worksheet.merge_cells(merge_range1) + + worksheet['H21'] = f'گزارش خرید زنده خارج از استان' + worksheet['H21'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['H21'].font = Font(color='FF0000', size=11) + merge_range1 = 'H21:L21' + worksheet.merge_cells(merge_range1) + + worksheet['H26'] = f'گزارش خرید لاشه خارج از استان' + worksheet['H26'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['H26'].font = Font(color='FF0000', size=11) + merge_range1 = 'H26:L26' + worksheet.merge_cells(merge_range1) + + for col_num, option in enumerate(header_list, 9): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet.column_dimensions[col_letter].width = 13 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list2, 6): + col_letter = get_column_letter(col_num) + + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet.column_dimensions[col_letter].width = 13 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list, 9): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=7, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[7].height = 20.8 + worksheet.column_dimensions[col_letter].width = 13 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list2, 6): + col_letter = get_column_letter(col_num) + + cell = worksheet.cell(row=7, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[7].height = 20.8 + worksheet.column_dimensions[col_letter].width = 13 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + filtered_kill_reqs1 = filtered_kill_reqs.filter(trash=False) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs1.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + all_age = [] + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_weighte1 = 0 + all_vet_state_accepted = len( + filtered_kill_reqs1.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs1.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs1.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs1.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_quantity = filtered_kill_reqs1.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs1.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs1.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = filtered_kill_reqs1.aggregate( + total_quantity=Count('id', filter=Q(ware_house_confirmation=True))).get( + 'total_quantity') or 0 + if filtered_kill_reqs1: + for kill in filtered_kill_reqs1: + if kill.get('killer') != None: + killer_exclusive += 1 + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + weight = kill.get('quantity') * kill.get( + 'province_request__poultry_request__Index_weight') + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + all_weighte1 += weight + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs1.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs1.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs1.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs1.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity', filter=Q(ware_house_confirmation=True))).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs1.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight', filter=Q(ware_house_confirmation=True))).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs1.aggregate( + total_quantity=Sum('weight_loss', filter=Q(ware_house_confirmation=True))).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_state_ware_house_confirmation > 0 else 0 + has_code1 = filtered_kill_reqs1.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code1.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + hasnt_code = filtered_kill_reqs1.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + difference_bar = len(filtered_kill_reqs1.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 8): + cell = worksheet.cell(row=12, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[12].height = 20.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + value_header_list = [ + len(filtered_kill_reqs1), + killer_exclusive, + all_quantity, + int(all_weighte1), + round(all_weighte1 / all_quantity, 1) if all_weighte1 > 0 and all_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + filtered_kill_reqs2 = filtered_kill_reqs.filter(trash=True) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs2.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + all_age = [] + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs2.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs2.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs2.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs2.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_quantity = filtered_kill_reqs2.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs2.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs2.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs2: + for kill in filtered_kill_reqs2: + if kill.get('killer') != None: + killer_exclusive += 1 + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs2.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs2.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs2.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs2.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs2.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs2.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + has_code1 = filtered_kill_reqs2.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code1.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + hasnt_code = filtered_kill_reqs2.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + difference_bar = len(filtered_kill_reqs2.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + value_header_list = [ + len(filtered_kill_reqs2), + killer_exclusive, + all_quantity, + int(all_weighte), + round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=8, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=8, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + state = 'accepted' + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + poultry_requests_accepted = poultry_requests.filter(province_state='accepted') + + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + state='accepted').exists(): + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + + if poultry_request.quarantine_code: + has_code += 1 + + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=13, column=item + 8, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + ).order_by('id') + if request.GET['role'] == "ChainCompany": + chain_allocations = chain_allocations.filter(chain_company__user=user, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__address__city=user.city, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + city_operator = CityOperator.objects.get(user=user, trash=False) + chain_allocations = chain_allocations.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "VetFarm": + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__in=poultry, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + else: + chain_allocations = chain_allocations.filter(state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 8): + cell = worksheet.cell(row=17, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[17].height = 20.8 + + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + all_age = [] + + all_quantity = chain_allocations.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_weighte = chain_allocations.aggregate( + total=Sum('weight'))[ + 'total'] or 0 + has_code = 0 + if chain_allocations: + for chain_allocation in chain_allocations: + age = (chain_allocation.poultry_hatching.chicken_age) + all_age.append(age) + + if chain_allocation.quarantine_code: + has_code += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(chain_allocations), + all_quantity, + all_weighte, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=18, column=item + 8, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=22, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type='live', + trash=False).order_by('-date') + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=23, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=27, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass', + trash=False).order_by('-date') + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=28, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + elif sheet_name == 'مدیریت بارها': + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + + 'تعداد قطعه وارد شده در قرنطینه', + 'عملیات', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت سند', + 'وضعیت بار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + 'کشور مقصد', + 'اختلاف مجوز', + + ] + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list, 9, 2, border_style='thin') + create_header(worksheet, header_list2, 6, 2, border_style='thin') + filtered_kill_request = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'province_kill_request__kill_house_price', + 'price', + 'killhouse_user__type', 'killer', 'entered_message', + 'bar_document_status__title').values( + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'province_kill_request__kill_house_price', + 'price', + 'killer', 'entered_message', 'bar_document_status__title' + ) + + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_reqs.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_reqs.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_reqs + else: + filtered_kill_reqs = filtered_kill_reqs + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_age = [] + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + if kill['entered_message'] is not None and kill[ + 'entered_message'] == 'ورود به انبار توسط سیستم': + state_ware_house_confirmation = 'ورود به انبار(سیستمی)' + else: + state_ware_house_confirmation = 'ورود به انبار(دستی)' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = 'در انتظار ورود به انبار' + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + kill['bar_document_status__title'] if kill['bar_document_status__title'] != None else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{weight_loss}', + export_country, + kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else quarantine_quantity + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code1.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + hasnt_code = filtered_kill_reqs.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + int(all_weighte), + round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای حذف شده': + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + 'کشور مقصد', + + ] + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + filtered_kill_request = KillHouseRequest.objects.filter(trash=True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'province_kill_request__kill_house_price', + 'price', + 'killhouse_user__type', 'killer').values( + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'province_kill_request__kill_house_price', + 'price', + 'killer', + ) + + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_request.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_request.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['B1'] = f'گزارش بارهای حذف شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_age = [] + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['document_status'] if kill['document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{weight_loss}', + export_country, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code1.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + hasnt_code = filtered_kill_reqs.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + int(all_weighte), + round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'فروش به خارج از استان': + + state = 'accepted' + user = SystemUserProfile.objects.get(key=request.GET['key']) + name_bar = '' + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + if state == 'pending': + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + name_bar = 'حذف/رد شده' + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + name_bar = 'حذف/رد شده' + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + name_bar = 'رد شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + poultry_requests_accepted = poultry_requests.filter(province_state='accepted') + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {name_bar} خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + age = poultry_request.hatching.chicken_age + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info != None else '-', + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای زنجیره': + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + ).order_by('id') + if request.GET['role'] == "ChainCompany": + user = SystemUserProfile.objects.get(key=request.GET['key']) + chain_allocations = chain_allocations.filter(chain_company__user=user, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key']) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__address__city=user.city, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + user = SystemUserProfile.objects.get(key=request.GET['key']) + city_operator = CityOperator.objects.get(user=user, trash=False) + chain_allocations = chain_allocations.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "VetFarm": + user = SystemUserProfile.objects.get(key=request.GET['key']) + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__in=poultry, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + else: + chain_allocations = chain_allocations.filter(state__in=('accepted', 'pending'), + trash=False).order_by('-id') + state1 = 'تایید شده' + + excel_options = [ + 'ردیف', + 'وضعیت', + ' تاریخ سفارش', + 'نوع فروش', + 'ثبت کننده سفارش', + 'تلفن ثبت کننده سفارش', + 'خریدار', + 'تلفن خریدار', + 'مرغداری', + 'تلفن مرغداری', + 'شرکت زنجیره', + ' تلفن شرکت زنجیره', + 'کد بهداشتی', + 'کد قرنطینه', + 'راننده ', + 'تلفن راننده ', + 'خودرو', + 'پلاک', + 'حجم', + 'میانگین وزن', + 'وزن', + 'سن', + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if state1 == 'تایید شده': + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + else: + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {state1} شرکت زنجیره' + if chain_allocations.exists(): + name = chain_allocations.first().poultry_hatching.poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_age = [] + + all_quantity = chain_allocations.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_weighte = chain_allocations.aggregate( + total=Sum('weight'))[ + 'total'] or 0 + has_code = 0 + if chain_allocations: + for chain_allocation in chain_allocations: + age = chain_allocation.poultry_hatching.chicken_age + all_age.append(age) + chain_date = jdatetime.date.fromgregorian( + day=chain_allocation.date.day, + month=chain_allocation.date.month, + year=chain_allocation.date.year + ) + + if chain_allocation.quarantine_code: + has_code += 1 + + remover_fullname = '-' + remover_mobile = '-' + if chain_allocation.state == 'accepted': + state = 'تایید شده' + elif chain_allocation.state == 'rejected': + state = 'رد شده' + remover_fullname = chain_allocation.seconder['fullname'] if chain_allocation.seconder else None + remover_mobile = chain_allocation.seconder['mobile'] if chain_allocation.seconder else None + elif chain_allocation.state == 'pending': + state = 'در انتظار تایید' + else: + state = 'حذف شده' + remover_fullname = chain_allocation.remover['fullname'] if chain_allocation.remover else None + remover_mobile = chain_allocation.remover['mobile'] if chain_allocation.remover else None + out_province = 'خارج استان' if chain_allocation.out_province == True else 'داخل استان' + + full_name_registerer = chain_allocation.registerer[ + 'fullname'] if chain_allocation.registerer else '-' + mobile_registerer = chain_allocation.registerer['mobile'] if chain_allocation.registerer else '-' + + if chain_allocation.kill_house is not None: + buyer_fullname = chain_allocation.kill_house.name + buyer_mobile = chain_allocation.kill_house.kill_house_operator.user.mobile + else: + buyer_fullname = chain_allocation.buyer_name + buyer_mobile = chain_allocation.buyer_mobile + + list1 = [ + m, + state, + str(chain_date), + out_province, + full_name_registerer, + mobile_registerer, + buyer_fullname, + buyer_mobile, + chain_allocation.poultry_hatching.poultry.unit_name, + chain_allocation.poultry_hatching.poultry.user.mobile, + chain_allocation.company_name, + chain_allocation.company_user_mobile, + chain_allocation.health_code if chain_allocation.health_code else '-', + chain_allocation.quarantine_code if chain_allocation.quarantine_code else '-', + chain_allocation.driver_name if chain_allocation.driver_name else '-', + chain_allocation.driver_mobile if chain_allocation.driver_mobile else '-', + chain_allocation.type_car if chain_allocation.type_car else '-', + chain_allocation.pelak if chain_allocation.pelak else '-', + chain_allocation.quantity, + chain_allocation.index_weight, + chain_allocation.weight, + age, + ] + m += 1 + if state1 == 'تایید شده': + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(chain_allocations), + all_quantity, + all_weighte, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + '', + all_weighte, + '', + '', + '', + + ] + if state1 == 'تایید شده': + for item in range(len(list2) - 2): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'خرید زنده خارج از استان': + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'live' + if request.GET['role'] in ['KillHouse', 'KillHouseVet']: + if request.GET['role'] == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + + excel_options = [ + 'ردیف', + 'کدسفارش', + 'تاریخ ثبت در سامانه', + 'تاریخ خرید', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'نوع خرید', + 'استان/شهر', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'وضعیت', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده ', + 'مجموع وزن زنده (کیلوگرم)', + 'مجموع وزن لاشه (کیلوگرم)', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.ware_house == True: + if kill.register_type == 'automatic': + state = 'ورود به انبار (سیستمی)' + else: + state = 'ورود به انبار (دستی)' + else: + if kill.register_type == 'automatic': + state = 'در انتظار ورود به انبار (سیستمی)' + else: + state = ' در انتظار ورود به انبار (دستی)' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + if kill.exclusive_killer: + killer_type = f'کشتارکن اختصاصی {kill.kill_house.name}' + kill_house_name = kill.exclusive_killer.name + kill_house_mobile = kill.exclusive_killer.kill_house_operator.user.mobile + + elif kill.kill_house.killer == True and kill.kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + + else: + killer_type = 'کشتارگاه' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + bar_code = str(kill.bar_code) if kill.bar_code else '-' + list1 = [ + m, + bar_code, + str(shamsi_date(kill.register_date, in_value=True)) if kill.register_date else '-', + str(date_of_buy), + killer_type, + kill_house_name, + kill_house_mobile, + kill.poultry_name, + kill.poultry_mobile, + buy_type, + f'{kill.province} / {kill.city}', + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + bar_pending = kill_house_free_bar_info + bar_pending_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_weight_of_carcasses), + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + bar_pending_quantity, + bar_pending_weight_of_carcasses, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'خرید لاشه خارج از استان': + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'carcass' + if request.GET['role'] in ['KillHouse', 'KillHouseVet']: + if request.GET['role'] == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + + excel_options = [ + 'ردیف', + 'وضعیت دامپزشک', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'حجم تایید شده', + 'وزن تایید شده', + 'تایید/رد کننده', + 'تاریخ تایید/ رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + + list1 = [ + m, + state, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.vet_farm_name, + kill.vet_farm_mobile, + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + kill.kill_house_vet_quantity, + kill.kill_house_vet_weight, + kill.acceptor_rejector, + str(date_of_reject_accepted) + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + m - 1, + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + int(bar_number_of_carcasses), + int(bar_weight_of_carcasses), + int(bar_kill_house_vet_quantity), + bar_kill_house_vet_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_free_bar_excel(request): + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = request.GET.get('type') + date_type = request.GET.get('date_type') + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = 'create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if date_type == 'buy': + + filters = { + 'register_date__date__gte': date1, + 'register_date__date__lte': date2, + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + else: + order_by_type = '-date' + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + + else: + filters = { + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by( + order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + excel_options = [ + 'ردیف', + 'کدسفارش', + 'تاریخ ثبت در سامانه', + 'تاریخ خرید', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'کشتارکن', + 'فروشنده', + 'تلفن فروشنده', + 'نوع خرید', + 'استان/شهر', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'وضعیت', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده ', + 'مجموع وزن زنده (کیلوگرم)', + 'مجموع وزن لاشه (کیلوگرم)', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if request.GET['type'] == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name \ + if kill_house_free_bar_info.first() else '' + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.ware_house == True: + if kill.register_type == 'automatic': + state = 'ورود به انبار (سیستمی)' + else: + state = 'ورود به انبار (دستی)' + else: + if kill.register_type == 'automatic': + state = 'در انتظار ورود به انبار (سیستمی)' + else: + state = ' در انتظار ورود به انبار (دستی)' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + # date_of_buy = jdatetime.date.fromgregorian( + # day=kill.date.day, + # month=kill.date.month, + # year=kill.date.year + # ) + date_of_buy = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + if kill.exclusive_killer: + killer_type = f'کشتارکن اختصاصی {kill.kill_house.name}' + kill_house_name = kill.exclusive_killer.name + kill_house_mobile = kill.exclusive_killer.kill_house_operator.user.mobile + + elif kill.kill_house.killer == True and kill.kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + + else: + killer_type = 'کشتارگاه' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + bar_code = str(kill.bar_code) if kill.bar_code else '-' + if kill.exclusive_killer: + exclusive_killer = f'{kill.exclusive_killer.name}({kill.exclusive_killer.kill_house_operator.user.mobile})' + else: + exclusive_killer = '-' + list1 = [ + m, + bar_code, + str(shamsi_date(kill.register_date, in_value=True)) if kill.register_date else '-', + str(date_of_buy), + killer_type, + kill_house_name, + kill_house_mobile, + exclusive_killer, + kill.poultry_name, + kill.poultry_mobile, + buy_type, + f'{kill.province} / {kill.city}', + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_weight_of_carcasses), + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + bar_pending_quantity, + bar_pending_weight_of_carcasses, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if request.GET['role'] == 'KillHouse': + name = kill_house_free_bar_info.first().kill_house.name + response[ + 'Content-Disposition'] = f'attachment; filename=" مدیریت بار {type} کشتارگاه {name} خرید از استان.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بار {type} خرید از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def comprehensive_report_of_the_slaughterhouse_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date2' in request.GET else now + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + img = Image('assets/img/img-min.png') + img.width = 180 + img.height = 160 + worksheet.add_image(img, 'M1') + + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + abc_list = [] + for letter in string.ascii_uppercase: + abc_list.append(letter) + a = ['AA', 'AB', 'AC', 'AD', 'AE', 'AF', 'AG', 'AH'] + abc_list.extend(a) + for abc in abc_list[8:18]: + worksheet[f'{abc}14'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'ware_house_accepted_real_weight', 'ware_house_accepted_real_quantity') + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first().killhouse_user.kill_house_operator.user.province.name + worksheet[ + 'E13'] = f'گزارش جامع خریداران در فرآیند کشتار مرغ گوشتی استان {name} از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + else: + worksheet[ + 'E13'] = f'گزارش جامع خریداران در فرآیند کشتار مرغ گوشتی از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['I14'] = 'حجم کل بارهای ایجاد شده ( زنده)' + worksheet['K14'] = 'حجم کل بارهای تحویلی کشتارگاه( زنده)' + worksheet['M14'] = 'وزن نهایی با افت 25%' + worksheet['N14'] = 'ورودی به انبار کشتارگاه(لاشه)' + worksheet['P14'] = 'درصد لاشه ورودی به انبار کشتارگاه نسبت به بار تحویلی کشتارگاه(با افت 25 %)' + worksheet['R14'] = 'درصد بار تحویلی نسبت به بار ایجاد شده' + worksheet['M10'] = 'سامانه رصدیار' + if filtered_kill_reqs: + first = filtered_kill_reqs.first().killhouse_user.kill_house_operator.user.province.name + worksheet['M11'] = f'استان {first}' + merge_range111 = 'M11:O11' + worksheet.merge_cells(merge_range111) + + worksheet.row_dimensions[14].height = 42 + + worksheet['E13'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['K14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['N14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['P14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['R14'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M11'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M10'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'E13:X13' + merge_range2 = 'I14:J15' + merge_range3 = 'K14:L15' + merge_range4 = 'M14:M16' + merge_range5 = 'N14:O15' + merge_range6 = 'P14:Q15' + merge_range7 = 'R14:S15' + merge_range8 = 'M10:O10' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + + worksheet['E13'].font = Font(size=18, bold=True) + worksheet['P14'].font = Font(size=9, bold=True) + worksheet['M10'].font = Font(size=12, bold=True) + + worksheet['I14'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + worksheet['K14'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + worksheet['N14'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + worksheet['M14'].fill = PatternFill(start_color="FCE4D6", fill_type="solid") + worksheet['P14'].fill = PatternFill(start_color="F8CBAD", fill_type="solid") + worksheet['R14'].fill = PatternFill(start_color="F8CBAD", fill_type="solid") + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + for item in range(4): + cell = worksheet.cell(row=16, column=item + 9, value=list1[item]) + worksheet.row_dimensions[16].height = 24 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for item in range(6): + cell = worksheet.cell(row=16, column=item + 14, value=list1[item]) + worksheet.row_dimensions[16].height = 24 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + all_kill_req_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity' or 0) + + weight = filtered_kill_reqs.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] + + all_kill_req_quantity_reciver = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity' or 0) + all_kill_req_weight_reciver = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity' or 0) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity' or 0) + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity' or 0) + if all_kill_req_quantity: + list_1 = [ + all_kill_req_quantity, + weight, + all_kill_req_quantity_reciver, + all_kill_req_weight_reciver, + (int(all_kill_req_weight_reciver) * 75) / 100, + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + f'{int(all_ware_house_accepted_real_quantity * 100 / all_kill_req_quantity_reciver)}%', + f"{int(all_ware_house_accepted_real_weight * 100 / all_kill_req_weight_reciver)}%", + f"{int(all_kill_req_quantity_reciver * 100 / all_kill_req_quantity)}%", + f'{int((all_kill_req_weight_reciver * 100) / weight)}%' + ] + for item in range(len(list_1)): + cell = worksheet.cell(row=17, column=item + 9, value=list_1[item]) + value = list_1[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' + else: + cell.value = value + + cell.alignment = Alignment(horizontal='center', vertical='center', ) + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + tomorrow_date1 = date1 + timedelta(days=1) + tomorrow_date2 = date2 + timedelta(days=1) + from_date = jdatetime.date.fromgregorian( + year=tomorrow_date1.year, + month=tomorrow_date1.month, + day=tomorrow_date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + tommorow_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=tomorrow_date2.year, + month=tomorrow_date2.month, + day=tomorrow_date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + tomorrow_date_2 = separate.join(reversed_date) + + worksheet.row_dimensions[21].height = 36 + for abc in abc_list[5:21]: + worksheet[f'{abc}20'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + worksheet['F19'] = f'اطلاعات کلی توزیع و پخش مرغ گرم از تاریخ {tommorow_date_1} تا {tomorrow_date_2}' + worksheet['F20'] = f'تعداد خریداران' + worksheet['G20'] = f'کشتار داخل استان' + worksheet['I20'] = f'خرید خارج از استان' + worksheet['K20'] = f'جمع کل انبار' + worksheet['M20'] = f'توزیع شده' + worksheet['O20'] = f'توزیع / تحویل شده' + worksheet['Q20'] = f'مانده انبار' + worksheet['S20'] = f'درصد توزیع نسبت به وردی به انبار' + worksheet['T20'] = f'تعداد مباشر تخصیص داده شده' + worksheet['U20'] = f'تعداد صنف تخصیص داده شده' + + worksheet['F19'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['F20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['K20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['O20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['Q20'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['S20'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['T20'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['U20'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range = 'F19:U19' + merge_range1 = 'F20:F22' + merge_range2 = 'G20:H21' + merge_range3 = 'I20:J21' + merge_range4 = 'K20:L21' + merge_range5 = 'M20:N21' + merge_range6 = 'O20:P21' + merge_range7 = 'Q20:R21' + merge_range8 = 'S20:S22' + merge_range9 = 'T20:T22' + merge_range10 = 'U20:U22' + + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + + worksheet['F19'].font = Font(size=18, bold=True, color='FF0000') + worksheet['F20'].font = Font(size=9) + + worksheet['F20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['G20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['I20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['K20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['M20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['O20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['Q20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['S20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['T20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + worksheet['U20'].fill = PatternFill(start_color="DDEBF7", fill_type="solid") + for item in range(12): + cell = worksheet.cell(row=22, column=item + 7, value=list1[item]) + worksheet.row_dimensions[22].height = 24 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + filtered_kill_reqs_tommorow = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'ware_house_accepted_real_weight', 'ware_house_accepted_real_quantity', + 'killhouse_user__kill_house_operator__user__city__name') + + number_of_kill_house_tommorow = filtered_kill_reqs_tommorow.values( + 'killhouse_user').distinct().count() if filtered_kill_reqs_tommorow else 0 + + kill_free_info_tommorow = KillHouseFreeBarInformation.objects.filter(trash=False, date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2).only( + 'weight_of_carcasses', 'number_of_carcasses') + all_quantity_out_false_tommorow = filtered_kill_reqs_tommorow.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity' or 0) + + weight_tommorow = filtered_kill_reqs_tommorow.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] + all_quantity_out_true_tommorow = kill_free_info_tommorow.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity' or 0) + all_weight_out_true_tomorow = kill_free_info_tommorow.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + kill_house_ware_houses_tommorow = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2, trash=False) + final_total_number_of_carcasses_tommorow = \ + kill_house_ware_houses_tommorow.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses_tommorow.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + steward_allocations_tommorow = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses_tommorow, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + total_allocated_quantity = \ + steward_allocations_tommorow.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations_tommorow.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations_tommorow.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations_tommorow.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses_tommorow.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses_tommorow.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses_tommorow.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + steward_allocations_for_number_of_steward = steward_allocations_tommorow.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + guild_allocations_tommorow = steward_allocations_tommorow.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations_tommorow.values( + 'guilds').distinct().count() if guild_allocations_tommorow else 0 + if filtered_kill_reqs_tommorow: + list_1 = [ + number_of_kill_house_tommorow, + all_quantity_out_false_tommorow if all_quantity_out_false_tommorow != None else 0, + weight_tommorow, + all_quantity_out_true_tommorow if all_quantity_out_true_tommorow != None else 0, + all_weight_out_true_tomorow, + final_total_number_of_carcasses_tommorow if final_total_number_of_carcasses_tommorow != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight, + total_accepted_allocated_quantity, + total_accepted_allocated_weight, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + f"{int((total_allocated_quantity * 100) / final_total_number_of_carcasses) if total_allocated_quantity and final_total_number_of_carcasses != None else 0}%", + number_of_steward, + number_of_guild, + + ] + for item in range(len(list_1)): + cell = worksheet.cell(row=23, column=item + 6, value=list_1[item]) + value = list_1[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' + else: + cell.value = value + + cell.alignment = Alignment(horizontal='center', vertical='center', ) + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + for abc in abc_list: + worksheet[f'{abc}27'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + worksheet.row_dimensions[27].height = 42 + for item in range(4): + cell = worksheet.cell(row=29, column=item + 4, value=list1[item]) + worksheet.row_dimensions[29].height = 24 + + cell.fill = PatternFill(start_color="92D050", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + for item in range(4): + cell = worksheet.cell(row=29, column=item + 10, value=list1[item]) + worksheet.row_dimensions[29].height = 24 + + cell.fill = PatternFill(start_color="92D050", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for item in range(10): + cell = worksheet.cell(row=29, column=item + 14, value=list1[item]) + worksheet.row_dimensions[29].height = 24 + + cell.fill = PatternFill(start_color="9BC2E6", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for item in range(2): + cell = worksheet.cell(row=29, column=item + 27, value=list1[item]) + worksheet.row_dimensions[29].height = 24 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for item in range(5): + cell = worksheet.cell(row=29, column=item + 28, value=list1[item]) + worksheet.row_dimensions[29].height = 24 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + worksheet['I26'] = 'اطلاعات کلی بارها و توزیع خریداران ' + worksheet['A27'] = 'ردیف' + worksheet['B27'] = 'خریدار' + worksheet['C27'] = 'شهرستان' + worksheet['D27'] = 'حجم کل بارهای ایجاد شده توسط کشتارگاه ( زنده)' + worksheet['F27'] = 'حجم کل بارهای تحویلی توسط کشتارگاه( زنده)' + worksheet['H27'] = 'وزن تحویلی با افت 25%' + worksheet['I27'] = 'درصد تعداد قطعه بار ایجاد شده به تحویلی' + worksheet['J27'] = 'ورودی به انبار کشتارگاه(لاشه)' + worksheet['L27'] = 'درصد لاشه ورودی به انبار کشتارگاه نسبت به بارتحویلی کشتارگاه(با افت 25 %)' + worksheet['N27'] = 'خرید خارج از استان' + worksheet['P27'] = 'جمع کل انبار' + worksheet['R27'] = 'توزیع شده' + worksheet['T27'] = 'توزیع/تحویل شده' + worksheet['V27'] = 'مانده انبار' + worksheet['X27'] = 'درصد وزن مانده در انبار به ورودی انبار' + worksheet['Y27'] = 'تعداد مباشر/ صنف ' + worksheet['Z27'] = 'بارهای تخلیه شده و عدم تکمیل(تحویل)' + worksheet['Z29'] = 'تعداد بار' + worksheet['AC27'] = 'ورودی به انبار' + worksheet['AC29'] = 'تعداد بار' + worksheet['AD29'] = 'حجم بار' + worksheet['AE29'] = 'وزن بار' + worksheet['AF29'] = 'درصد افت' + worksheet['AG27'] = 'بارهای فاقد قرنطینه و تخلیه شده' + worksheet['AG29'] = 'تعداد بار' + worksheet['AH29'] = 'درصد' + worksheet['I27'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A27'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B27'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['C27'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['D27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['H27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['I27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['J27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['L27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['N27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['P27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['R27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['T27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['V27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['X27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Y27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Z27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Z29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AF29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AE29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AD29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AC29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AC27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AG27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AG29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['AH29'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range = 'A27:A29' + merge_range1 = 'B27:B29' + merge_range2 = 'C27:C29' + merge_range3 = 'D27:E28' + merge_range4 = 'F27:G28' + merge_range5 = 'H27:H29' + merge_range6 = 'I27:I29' + merge_range7 = 'J27:K28' + merge_range8 = 'L27:M28' + merge_range9 = 'N27:O28' + merge_range10 = 'P27:Q28' + merge_range11 = 'R27:S28' + merge_range12 = 'T27:U28' + merge_range13 = 'V27:W28' + merge_range14 = 'I26:R26' + merge_range15 = 'X27:X29' + merge_range16 = 'Y27:Y29' + merge_range17 = 'Z27:AB28' + merge_range18 = 'M1:O9' + merge_range19 = 'AC27:AF28' + merge_range20 = 'AG27:AH28' + + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + worksheet.merge_cells(merge_range11) + worksheet.merge_cells(merge_range12) + worksheet.merge_cells(merge_range13) + worksheet.merge_cells(merge_range14) + worksheet.merge_cells(merge_range15) + worksheet.merge_cells(merge_range16) + worksheet.merge_cells(merge_range17) + worksheet.merge_cells(merge_range18) + worksheet.merge_cells(merge_range19) + worksheet.merge_cells(merge_range20) + + worksheet['A27'].fill = PatternFill(start_color="8EA9DB", fill_type="solid") + worksheet['B27'].fill = PatternFill(start_color="8EA9DB", fill_type="solid") + worksheet['C27'].fill = PatternFill(start_color="8EA9DB", fill_type="solid") + worksheet['D27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['F27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['H27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['I27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['J27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['L27'].fill = PatternFill(start_color="FFE699", fill_type="solid") + worksheet['N27'].fill = PatternFill(start_color="C9C9C9", fill_type="solid") + worksheet['P27'].fill = PatternFill(start_color="C9C9C9", fill_type="solid") + worksheet['R27'].fill = PatternFill(start_color="C9C9C9", fill_type="solid") + worksheet['T27'].fill = PatternFill(start_color="C9C9C9", fill_type="solid") + worksheet['V27'].fill = PatternFill(start_color="C9C9C9", fill_type="solid") + worksheet['X27'].fill = PatternFill(start_color="F8CBAD", fill_type="solid") + worksheet['Y27'].fill = PatternFill(start_color="F8CBAD", fill_type="solid") + worksheet['Z27'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + worksheet['Z29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AC29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AD29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AE29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AF29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AC27'].fill = PatternFill(start_color="92CDDC", fill_type="solid") + worksheet['AG27'].fill = PatternFill(start_color="00B050", fill_type="solid") + worksheet['AH29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + worksheet['AG29'].fill = PatternFill(start_color="FFD966", fill_type="solid") + + worksheet['L27'].font = Font(size=8) + worksheet['X27'].font = Font(size=9) + worksheet['I26'].font = Font(size=17) + + l = 30 + m = 1 + all_all_kill_req_quantity = 0 + all_weight = 0 + all_all_kill_req_quantity_reciver = 0 + all_all_kill_req_weight_reciver = 0 + all_twenty_five_percent = 0 + all_reciver_percent = 0 + all_final_total_number_of_carcasses = 0 + all_final_total_weight_of_carcasses = 0 + all_lashe_25_percent = 0 + all_weight_lashe_25_percent = 0 + all_all_quantity_out_true = 0 + all_all_weight_out_true = 0 + all_total_allocated_quantity = 0 + all_total_allocated_weight = 0 + all_total_accepted_allocated_quantity = 0 + all_total_accepted_allocated_weight = 0 + all_total_remain_quantity = 0 + all_total_remain_weight = 0 + all_all_num = 0 + all_remain_percent = 0 + all_len_tomorrow_kill_request_not_assigment = 0 + all_all_kill_req_quantity_not_assigment = 0 + all_all_kill_req_weight_not_assigment = 0 + all_all_ware_house_accepted_real_quantity = 0 + all_len_kill_req1 = 0 + all_ware_house_accepted_real_weight = 0 + all_ware_house_accepted_real_quantity = 0 + all_weight_loss = 0 + all_hasnt_code = 0 + all_percent_hasnt_code = 0 + kill_houses = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user__city').exclude( + out_province=True) + for kill_house in kill_houses: + kill_free_information = kill_free_info_tommorow.filter(kill_house=kill_house) + tomorrow_kill_request = filtered_kill_reqs_tommorow.filter(killhouse_user=kill_house) + if tomorrow_kill_request: + tomorrow_kill_request_not_assigment = tomorrow_kill_request.filter(assignment_state_archive='pending', + vet_state='accepted') + all_kill_req_quantity = tomorrow_kill_request.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity' or 0) + all_len_tomorrow_kill_request_not_assigment += len(tomorrow_kill_request_not_assigment) + all_all_kill_req_quantity += all_kill_req_quantity + + all_kill_req_quantity_reciver = tomorrow_kill_request.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity' or 0) + all_all_kill_req_quantity_reciver += all_kill_req_quantity_reciver + all_kill_req_weight_reciver = tomorrow_kill_request.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity' or 0) + all_all_kill_req_weight_reciver += all_kill_req_weight_reciver + all_ware_house_accepted_real_quantity = tomorrow_kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity' or 0) + weight = tomorrow_kill_request.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] + all_weight += weight + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2, kill_house=kill_house, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + all_total_allocated_quantity += total_allocated_quantity if total_allocated_quantity != None else 0 + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + all_total_allocated_weight += total_allocated_weight if total_allocated_weight != None else 0 + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + all_total_accepted_allocated_quantity += total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0 + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + all_total_accepted_allocated_weight += total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0 + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + all_total_remain_quantity += total_remain_quantity if total_remain_quantity != None else 0 + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + all_total_remain_weight += total_remain_weight if total_remain_weight != None else 0 + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] or 0 + all_final_total_number_of_carcasses += final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0 + + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] or 0 + all_final_total_weight_of_carcasses += final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0 + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + all_kill_req_quantity_not_assigment = tomorrow_kill_request_not_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + all_all_kill_req_quantity_not_assigment += all_kill_req_quantity_not_assigment if all_kill_req_quantity_not_assigment != None else 0 + all_kill_req_weight_not_assigment = tomorrow_kill_request_not_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + all_all_kill_req_weight_not_assigment += all_kill_req_weight_not_assigment if all_kill_req_weight_not_assigment != None else 0 + all_quantity_out_true = kill_free_information.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + all_all_quantity_out_true += all_quantity_out_true if all_quantity_out_true != None else 0 + all_weight_out_true = kill_free_information.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity' or 0) + all_all_weight_out_true += all_weight_out_true if all_weight_out_true != None else 0 + twenty_five_percent = (int(all_kill_req_weight_reciver) * 75) / 100 + all_twenty_five_percent += twenty_five_percent if twenty_five_percent > 0 else 0 + reciver_percent = ( + int(all_kill_req_quantity_reciver) * 100) / all_kill_req_quantity if all_kill_req_quantity_reciver != None else 0 + all_reciver_percent += reciver_percent if reciver_percent > 0 else 0 + lashe_25_percent = int( + final_total_number_of_carcasses * 100 / all_kill_req_quantity_reciver) if final_total_number_of_carcasses != None else 0 + all_lashe_25_percent += lashe_25_percent if lashe_25_percent > 0 else 0 + weight_lashe_25_percent = int( + final_total_weight_of_carcasses * 100 / all_kill_req_weight_reciver) if final_total_weight_of_carcasses != None else 0 + all_weight_lashe_25_percent += weight_lashe_25_percent if weight_lashe_25_percent > 0 else 0 + remain_percent = int(( + total_remain_quantity * 100) / all_ware_house_accepted_real_quantity) if total_remain_quantity != None and all_ware_house_accepted_real_quantity > 0 else 0 + all_remain_percent += remain_percent if remain_percent > 0 else 0 + all_num = number_of_steward + number_of_guild + all_all_num += all_num if all_num > 0 else 0 + + kill_req = filtered_kill_reqs_tommorow.filter(ware_house_confirmation=True, + killhouse_user=kill_house) + all_len_kill_req1 += len(kill_req) + ware_house_accepted_real_quantity = kill_req.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + + ware_house_accepted_real_weight = kill_req.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity') or 0 + weight_loss1 = kill_req.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity') or 0 + weight_loss = weight_loss1 / len(kill_req) if len(kill_req) > 0 else 0 + all_ware_house_accepted_real_weight += ware_house_accepted_real_weight + all_ware_house_accepted_real_quantity += ware_house_accepted_real_quantity + all_weight_loss += int(weight_loss1) + all_all_ware_house_accepted_real_quantity += ware_house_accepted_real_quantity + hasnt_code = len(tomorrow_kill_request.filter(assignment_state_archive='True', clearance_code__isnull=True)) + percent_hasnt_code = round(hasnt_code * 100 / len(tomorrow_kill_request)) if len( + tomorrow_kill_request) > 0 else 0 + + all_hasnt_code += hasnt_code + all_percent_hasnt_code += percent_hasnt_code + list_1 = [ + m, + kill_house.name, + kill_house.city_name, + all_kill_req_quantity, + weight, + all_kill_req_quantity_reciver, + all_kill_req_weight_reciver, + twenty_five_percent, + f'{int(reciver_percent)}%', + final_total_number_of_carcasses, + final_total_weight_of_carcasses, + f'{lashe_25_percent}%', + f"{weight_lashe_25_percent}%", + all_quantity_out_true, + all_weight_out_true, + final_total_number_of_carcasses, + final_total_weight_of_carcasses, + total_allocated_quantity, + total_allocated_weight, + total_accepted_allocated_quantity, + total_accepted_allocated_weight, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + f'{remain_percent}%', + all_num, + len(tomorrow_kill_request_not_assigment), + all_kill_req_quantity_not_assigment, + all_kill_req_weight_not_assigment, + len(kill_req), + ware_house_accepted_real_quantity, + ware_house_accepted_real_weight, + f"{int(weight_loss)}%", + hasnt_code, + f"{percent_hasnt_code}%", + + ] + for item in range(len(list_1)): + cell = worksheet.cell(row=l, column=item + 1, value=list_1[item]) + value = list_1[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' + else: + cell.value = value + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + l += 1 + m += 1 + + for abc in abc_list[:1]: + worksheet[f'{abc}{l}'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + worksheet.row_dimensions[int(f'{l}')].height = 24 + + worksheet[f'A{l}'] = 'جمع کل' + + worksheet[f'A{l}'].alignment = Alignment(horizontal='center', vertical='center') + merge_range = f'A{l}:C{l}' + worksheet[f'A{l}'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + all_reciver_percent2 = ( + int(all_all_kill_req_quantity_reciver) * 100) / all_all_kill_req_quantity if all_all_kill_req_quantity_reciver and all_all_kill_req_quantity > 0 else 0 + all_all_lashe_25_percent = int( + all_final_total_number_of_carcasses * 100 / all_all_kill_req_quantity_reciver) if all_final_total_number_of_carcasses > 0 else 0 + all_all_weight_lashe_25_percent = int( + all_final_total_weight_of_carcasses * 100 / all_all_kill_req_weight_reciver) if all_final_total_weight_of_carcasses > 0 else 0 + all_all_all_remain_percent = int(( + all_total_remain_quantity * 100) / all_all_ware_house_accepted_real_quantity) if all_total_remain_quantity > 0 and all_all_ware_house_accepted_real_quantity > 0 else 0 + worksheet.merge_cells(merge_range) + list2 = [ + all_all_kill_req_quantity, + all_weight, + all_all_kill_req_quantity_reciver, + all_all_kill_req_weight_reciver, + all_twenty_five_percent, + f'{int(all_reciver_percent2)}%', + all_final_total_number_of_carcasses, + all_final_total_weight_of_carcasses, + f'{all_all_lashe_25_percent}%', + f'{all_all_weight_lashe_25_percent}%', + all_all_quantity_out_true, + all_all_weight_out_true, + all_final_total_number_of_carcasses, + all_final_total_weight_of_carcasses, + all_total_allocated_quantity, + all_total_allocated_weight, + all_total_accepted_allocated_quantity, + all_total_accepted_allocated_weight, + all_total_remain_quantity, + all_total_remain_weight, + f'{all_all_all_remain_percent}%', + all_all_num, + all_len_tomorrow_kill_request_not_assigment, + all_all_kill_req_quantity_not_assigment, + all_all_kill_req_weight_not_assigment, + all_len_kill_req1, + all_all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + f"{int(all_weight_loss / all_len_kill_req1 if all_len_kill_req1 > 0 else 0)}%", + all_hasnt_code, + f"{int(all_hasnt_code / all_len_kill_req1 if all_len_kill_req1 > 0 else 0)}%", + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 4, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="FFFF00", fill_type="solid") + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش جامع کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def out_province_carcasses_buyer_kill_house_excel(request): + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + buyers = OutProvinceCarcassesBuyer.objects.filter(trash=False, Kill_house=kill_house).order_by('id') + + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + buyers = buyers.filter( + build_query(filterset_class, value) + ) + + excel_options = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'تعداد درخواست ها', + 'حجم درخواست ها', + 'وزن درخواست ها', + + ] + + header_list = [ + 'تعداد خریداران', + 'تعداد کل درخواست ها', + 'حجم کل درخواست ها', + 'وزن کل درخواست ها', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + + excel_description(worksheet, 'A1', f' خریداران لاشه خارج استان کشتارگاه {kill_house.name}', color='red', row2='B1') + + if kill_house: + province = kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer__in=buyers) + + for buyer in buyers: + free_sale = free_sales.filter(buyer=buyer) + + total_quantity = free_sale.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sale.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + list1 = [ + m, + buyer.fullname, + buyer.mobile, + buyer.unit_name, + buyer.province, + buyer.city, + len(free_sale), + total_quantity, + total_weight + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer__in=buyers) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + value_list = [ + len(buyers), + len(free_sales), + total_quantity, + total_weight, + ] + create_value(worksheet, value_list, 3, 3) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + len(free_sales), + total_quantity, + total_weight, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" خریداران لاشه خارج استان کشتارگاه {kill_house.name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_free_sale_bar_information_for_excel_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date2' in request.GET else now + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + len_buyers = [] + sheet_names2 = [ + 'فروش لاشه خارج استان', + 'خریداران', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + if sheet_name == 'فروش لاشه خارج استان': + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + buyers = buyers.filter( + build_query(filterset_class, value) + ) + + excel_options = [ + 'ردیف', + 'نام کشتارگاه', + 'موبایل کشتارگاه', + 'تاریخ', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'حجم لاشه(تقریبی)', + 'وزن لاشه(کیلوگرم)', + + ] + + header_list = [ + 'تعداد کل فروش', + 'تعداد خریداران', + 'حجم لاشه(تقریبی)', + 'وزن لاشه(کیلوگرم)', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + + excel_description(worksheet, 'A1', f'فروش لاشه خارج استان کشتارگاه {kill_house.name}', color='red', + row2='B1') + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='B3') + + if kill_house: + province = kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + + for buyer in buyers: + date = jdatetime.date.fromgregorian( + day=buyer.date.day, + month=buyer.date.month, + year=buyer.date.year + ) + if buyer.buyer_name not in len_buyers: + len_buyers.append(buyer.buyer_name) + list1 = [ + m, + buyer.kill_house.name, + buyer.kill_house.kill_house_operator.user.mobile, + str(date), + buyer.buyer_name, + buyer.buyer_mobile, + buyer.buyer_name, + buyer.province, + buyer.city, + buyer.number_of_carcasses, + buyer.weight_of_carcasses, + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + + total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + value_list = [ + len(buyers), + len(len_buyers), + total_quantity, + total_weight, + ] + create_value(worksheet, value_list, 3, 3) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + total_weight, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + else: + out_buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=kill_house, trash=False).order_by('id') + excel_options = [ + 'ردیف', + 'نام خریدار', + 'موبایل خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'تعداد درخواست ها', + 'حجم تقریبی(قطعه)', + 'وزن(کلوگرم)', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + excel_description(worksheet, 'A1', f'خریداران کشتارگاه {kill_house.name}', color='red', + row2='B1') + + if kill_house: + province = kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + + for buyer in out_buyers: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer=buyer) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + list1 = [ + m, + buyer.buyer.fullname, + buyer.buyer.mobile, + buyer.buyer.unit_name, + buyer.buyer.province, + + buyer.buyer.city, + len(free_sales), + total_quantity, + total_weight, + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + + # total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + # 'total'] or 0 + # total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + # 'total'] or 0 + + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # total_quantity, + # total_weight, + # + # ] + # create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="فروش لاشه خارج استان کشتارگاه {kill_house.name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_free_sale_bar_information_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date2' in request.GET else now + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + # user = SystemUserProfile.objects.get(key=request.GET['key'],trash=False) + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user,trash=False).first() + buyers = KillHouseFreeSaleBarInformation.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + buyers = buyers.filter( + build_query(filterset_class, value) + ) + + excel_options = [ + 'ردیف', + 'نام کشتارگاه', + 'موبایل کشتارگاه', + 'تاریخ', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'حجم لاشه', + 'وزن لاشه', + + ] + + header_list = [ + 'تعداد کل لاشه', + 'حجم کل لاشه', + 'وزن کل لاشه', + + ] + + kill_houses = buyers.values_list('kill_house__name', flat=True).distinct() + sheet_name = 'اطلاعات کلی' + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + worksheet = workbook.create_sheet(sheet_name) + kill_houses = set(kill_houses) + date_1 = shamsi_date(date1) + date_2 = shamsi_date(date2) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + province = buyers.first().kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'F2', + f'اطلاعات کلی فروش لاشه به خارج استان {province} از تاریخ {date_1} تا {date_2}', color='red', + row2='K2') + excel_description(worksheet, 'E5', f'اطلاعات کلی', color='red', row2='F5') + create_header(worksheet, header_list, 7, 5, height=21, width=16.01) + total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + general_list = [ + len(buyers), + total_quantity, + total_weight + ] + create_value(worksheet, general_list, 6, 7, border_style='thin') + l = 10 + for kill_house in list(kill_houses): + excel_description(worksheet, f'E{l}', f'کشتار گاه {kill_house}', color='red', row2=f'F{l}') + create_header(worksheet, header_list, 7, l, height=21, width=16.01) + free_sales = buyers.filter(trash=False, kill_house__name=kill_house) + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + general_list = [ + len(free_sales), + total_quantity, + total_weight + ] + create_value(worksheet, general_list, l + 1, 7, border_style='thin') + l += 4 + + for kill_house in list(kill_houses): + sheet_name = kill_house + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + + excel_description(worksheet, 'A1', f' فروش لاشه خارج استان کشتارگاه {kill_house} ', color='red', row2='B1') + excel_description(worksheet, 'A3', f'از تاریخ {date_1} تا {date_2}', color='red', row2='B3') + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + free_sales = buyers.filter(trash=False, kill_house__name=kill_house) + + for buyer in free_sales: + date = jdatetime.date.fromgregorian( + day=buyer.date.day, + month=buyer.date.month, + year=buyer.date.year + ) + list1 = [ + m, + buyer.kill_house.name, + buyer.kill_house.kill_house_operator.user.mobile, + str(date), + buyer.buyer_name, + buyer.buyer_mobile, + buyer.buyer_name, + buyer.province, + buyer.city, + buyer.number_of_carcasses, + buyer.weight_of_carcasses, + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + value_list = [ + len(free_sales), + total_quantity, + total_weight, + ] + create_value(worksheet, value_list, 3, 3) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + total_weight, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="فروش لاشه خارج استان کشتارگاه ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def notentered_bars_for_kill_house_excel(request): + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + if 'search' in request.GET: + filtered_kill_reqs = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + filtered_kill_reqs = [] if len(filtered_kill_reqs) == 0 else filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list2, 6, 4, height=21.8, color='green') + + create_header(worksheet, header_list, 9, 4, height=21.8) + + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 6, 1, height=21.8, color='FF0000') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 2 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 6) + q += 1 + w += 1 + + kill_house_name = '' + if filtered_kill_reqs.exists(): + kill_house_name = filtered_kill_reqs.first()['killhouse_user__name'] + excel_description(worksheet, 'A1', f'بارهای {kill_house_name} در انتظار ورود به انبار (کشتار داخل استان)', size=11, + color='red', row2='E1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 7, 8, 20) + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + l = 7 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 5, 6) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" (کشتار داخل استان)بارهای در انتظار ورود به انبار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def entered_bars_for_kill_house_excel(request): + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + if 'search' in request.GET: + filtered_kill_reqs = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + filtered_kill_reqs = [] if len(filtered_kill_reqs) == 0 else filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list2, 6, 4, height=21.8, color='green') + + create_header(worksheet, header_list, 9, 4, height=21.8) + + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 6, 1, height=21.8, color='FF0000') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 2 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 6) + q += 1 + w += 1 + + kill_house_name = '' + if filtered_kill_reqs.exists(): + kill_house_name = filtered_kill_reqs.first()['killhouse_user__name'] + excel_description(worksheet, 'A1', f'بارهای {kill_house_name} وارد شده به انبار (کشتار داخل استان)', size=11, + color='red', row2='E1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 7, 8, 20) + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + l = 7 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 5, 6) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" (کشتار داخل استان)بارهای وارد شده به انبار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_free_bar_entered_for_warehouse_excel(request): + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = request.GET.get('type') + date_type = request.GET.get('date_type') + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if date_type: + if date_type == 'buy': + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + order_by_type = '-date' + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + excel_options = [ + 'ردیف', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تاریخ ورود به انبار', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'درصد افت', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد کل بار زنده', + 'حجم کل بار زنده', + 'وزن کل بار زنده', + 'تعداد کل بارهای وارد شده به انبار', + 'حجم کل بارهای زنده وارد شده به انبار', + 'وزن کل بارهای زنده وارد شده به انبار', + 'وزن لاشه وارد شده به انبار', + 'کل بار وارد نشده به انبار', + 'حجم کل بار وارد نشده به انبار', + 'وزن کل بار وارد نشده به انبار', + + ] + + for col_num, option in enumerate(header_list2, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if request.GET['type'] == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید خارج از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['A2'] = f'استان {name}' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['A2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + date_of_enter = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + list1 = [ + m, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + str(date_of_enter), + kill.number_of_carcasses, + int(kill.weight_of_carcasses), + + kill.weight_loss, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + # if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + quantity, + live_weight, + + len(entered_bars), + + entered_quantity, + entered_live_weight, + weight_of_carcasses, + len(not_entered_bars), + not_entered_quantity, + not_entered_live_weight, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + quantity, + live_weight, + '', + number_of_carcasses, + weight_of_carcasses, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if kill_house_free_bar_info.exists(): + if request.GET['role'] == 'KillHouse': + name = kill_house_free_bar_info.first().kill_house.name + response[ + 'Content-Disposition'] = f'attachment; filename=" مدیریت بار {type} کشتارگاه {name} خرید از استان.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بار {type} خرید از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_free_bar_carcasses_for_warehouse_excel(request): + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = request.GET.get('type') + date_type = request.GET.get('date_type') + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if date_type: + if date_type == 'buy': + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + order_by_type = '-date' + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + excel_options = [ + 'ردیف', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'کدقرنطینه', + + 'تاریخ ورود به انبار', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد کل بار', + 'حجم لاشه', + 'وزن لاشه', + + ] + + for col_num, option in enumerate(header_list2, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if request.GET['type'] == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید خارج از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['A2'] = f'استان {name}' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['A2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + date_of_enter = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + list1 = [ + m, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.bar_clearance_code, + str(date_of_enter), + kill.number_of_carcasses, + int(kill.weight_of_carcasses), + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + # if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + number_of_carcasses, + weight_of_carcasses, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + number_of_carcasses, + weight_of_carcasses, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if kill_house_free_bar_info.exists(): + if request.GET['role'] == 'KillHouse': + name = kill_house_free_bar_info.first().kill_house.name + response[ + 'Content-Disposition'] = f'attachment; filename=" مدیریت بار {type} کشتارگاه {name} خرید از استان.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بار {type} خرید از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def steward_allocation_for_warehouse_excel(request): + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = filterset_class(data=query, queryset=allocations) + allocations = ps.filter() + allocations = [] if len( + allocations) == 0 else allocations + + excel_options = [ + 'ردیف', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + kill_house_name = '' + if allocations.exists(): + kill_house_name = allocations.first().kill_house.name + excel_description(worksheet, 'A1', f'تخصیصات داخل استان کشتارگاه {kill_house_name}', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + elif allocation.allocation_type == 'killhouse_guild': + allocation_type = 'کشتارگاه به صنف' + buyer_name = allocation.to_guilds.guilds_name + buyer_mobile = allocation.to_guilds.user.mobile + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = '' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + str(shamsi_date((allocation.date))), + allocation_type, + buyer_name, + buyer_mobile, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.number_of_carcasses, + allocation.weight_of_carcasses, + allocation.receiver_real_number_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + allocation.registration_code, + system_registration_code, + state, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + number_of_carcasses_allocations, + weight_of_carcasses_allocations, + receiver_real_number_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + number_of_carcasses_allocations, + weight_of_carcasses_allocations, + receiver_real_number_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="تخصیصات صورت گرفته داخل استان کشتارگاه {kill_house_name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_inventory_data(request): + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + sheet_names2 = [ + 'اطلاعات کلی', + 'بارهای در انتظار ورود به انبار', + 'بارهای وارد شده به انبار', + 'فروش به داخل استان', + 'فروش به خارج استان', + 'خریداران(خارج استان)', + 'بار زنده (خرید خارج استان)', + 'بار لاشه (خرید خارج استان)', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + if sheet_name == 'اطلاعات کلی': + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from1 = shamsi_date(date1) + from2 = shamsi_date(date2) + excel_description(worksheet, 'A7', + f'گزارش جامع انبار کشتارگاه {kill_house.name} از تاریخ {from1} تا تاریخ {from2}', + size=11, color='red', row2='C9') + else: + excel_description(worksheet, 'A7', f'گزارش جامع انبار کشتارگاه {kill_house.name}', + size=11, color='red', row2='C8') + excel_description(worksheet, 'D2', f'مدیریت انبار', + size=11, color='red', row2='G2') + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='FF0000', border_style='thin') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 4 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 3, border_style='thin') + q += 1 + w += 1 + + excel_description(worksheet, 'D6', f'اطلاعات پخش', + size=11, color='red', row2='G6') + header_list2 = [ + 'فروش و توزیع داخل استان(کیلوگرم)', + 'فروش و توزیع خارج استان(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 5, 7, height=21.8, width=20, color='C00000', border_style='thin') + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + steward_allocations = StewardAllocation.objects.filter(kill_house=kill_house, + receiver_state__in=('pending', 'accepted'), + calculate_status=True, trash=False) + steward_allocations_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + calculate_status=True) + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + value_header_list = [ + steward_allocations_weight, + free_sales_weight, + + ] + create_value(worksheet, value_header_list, 8, 5, border_style='thin') + + excel_description(worksheet, 'D11', f'بارهای در انتظار ورود به انبار', + size=11, color='red', row2='G11') + header_list = [ + 'تعداد بار', + 'حجم بار', + 'وزن بار', + 'میانگین وزن ', + + 'تعداد بارهای تکمیل شده', + + ] + + # برای بالای هدر + # header_list2 = [ + # 'تعداد درخواست مرغداران', + # ' مجموع تعداد قطعه درخواست مرغداران', + # ' مجموع وزن درخواست مرغداران', + # + # ] + # create_header(worksheet, header_list2, 1, 12, height=21.8, color='green',border_style='thin') + + create_header(worksheet, header_list, 3, 12, height=21.8, border_style='thin') + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + key = kill.get('key') + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + all_weighte += weight + + value_header_list = [ + + len(filtered_kill_reqs), + + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + + len(bar_complete), + + ] + create_value(worksheet, value_header_list, 13, 3, border_style='thin') + + excel_description(worksheet, 'D15', f'بارهای وارد شده به انبار', + size=11, color='red', row2='G15') + header_list = [ + 'تعداد بارهای ایجاد شده', + + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + + ' افت در لحظه', + ' افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + # header_list2 = [ + # 'تعداد درخواست مرغداران', + # ' مجموع تعداد قطعه درخواست مرغداران', + # ' مجموع وزن درخواست مرغداران', + # + # ] + # create_header(worksheet, header_list2, 1, 16, height=21.8, color='green', border_style='thin') + + create_header(worksheet, header_list, 3, 16, height=21.8, border_style='thin') + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_state_ware_house_confirmation > 0 else 0 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + all_total_weight_loss = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + key = kill.get('key') + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + all_weighte += weight + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if kill[ + 'accepted_real_weight'] != 0 else 0 + all_total_weight_loss += total_weight_loss + all_total_weight_loss = all_total_weight_loss / len(filtered_kill_reqs) if len( + filtered_kill_reqs) > 0 else 0 + value_header_list = [ + len(filtered_kill_reqs), + + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + + f'%{int(all_total_weight_loss)}', + f'%{all_weight_loss}', + + ] + create_value(worksheet, value_header_list, 17, 3, border_style='thin') + + excel_description(worksheet, 'D19', f'فروش به داخل استان', + size=11, color='red', row2='G19') + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + + ] + create_header(worksheet, header_list2, 4, 20, height=21, width=16.01, border_style='thin') + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + number_of_carcasses_allocations, + weight_of_carcasses_allocations, + receiver_real_number_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + create_value(worksheet, value_header_list2, 21, 4, border_style='thin') + + excel_description(worksheet, 'D23', f'فروش به خارج استان', + size=11, color='red', row2='G23') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + date__date__gte=date1, + date__date__lte=date2).order_by('-date') + else: + buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + ).order_by('-date') + + header_list = [ + 'تعداد کل فروش', + 'تعداد خریداران', + 'حجم لاشه(تقریبی)', + 'وزن لاشه(کیلوگرم)', + + ] + + create_header(worksheet, header_list, 4, 24, height=21, width=16.01, border_style='thin') + + total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + len_buyers = [] + for buyer in buyers: + + if buyer.buyer_name not in len_buyers: + len_buyers.append(buyer.buyer_name) + value_list = [ + len(buyers), + len(len_buyers), + total_quantity, + total_weight, + ] + create_value(worksheet, value_list, 25, 4, border_style='thin') + + excel_description(worksheet, 'D27', f'بار زنده (خرید خارج استان)', + size=11, color='red', row2='G27') + + type = 'live' + kill_houses = None + + role = request.GET.get('role') + order_by_type = '-create_date' + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + filters['buy_type'] = type + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters, calculate_status=True, + temporary_trash=False, + temporary_deleted=False).order_by( + order_by_type) + header_list2 = [ + 'تعداد کل بار زنده', + 'حجم کل بار زنده', + 'وزن کل بار زنده', + 'تعداد کل بارهای وارد شده به انبار', + 'حجم کل بارهای زنده وارد شده به انبار', + 'وزن کل بارهای زنده وارد شده به انبار', + 'وزن لاشه وارد شده به انبار', + 'کل بار وارد نشده به انبار', + 'حجم کل بار وارد نشده به انبار', + 'وزن کل بار وارد نشده به انبار', + + ] + create_header(worksheet, header_list2, 2, 28, height=21, width=16.01, border_style='thin') + + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + quantity, + live_weight, + + len(entered_bars), + + entered_quantity, + entered_live_weight, + weight_of_carcasses, + len(not_entered_bars), + not_entered_quantity, + not_entered_live_weight, + + ] + create_value(worksheet, value_header_list2, 29, 2, border_style='thin') + + excel_description(worksheet, 'D31', f'بار لاشه (خرید خارج استان)', + size=11, color='red', row2='G31') + type = 'carcasses' + bar_state = 'entered' + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters, calculate_status=True, + temporary_trash=False, + temporary_deleted=False).order_by( + order_by_type) + header_list2 = [ + 'تعداد کل بار', + 'حجم لاشه', + 'وزن لاشه', + + ] + create_header(worksheet, header_list2, 5, 32, height=21, width=16.01, border_style='thin') + + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + value_header_list2 = [ + len(kill_house_free_bar_info), + number_of_carcasses, + weight_of_carcasses, + + ] + create_value(worksheet, value_header_list2, 33, 5, border_style='thin') + elif sheet_name == 'بارهای در انتظار ورود به انبار': + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + if 'search' in request.GET: + filtered_kill_reqs = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + filtered_kill_reqs = [] if len(filtered_kill_reqs) == 0 else filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list2, 6, 4, height=21.8, color='green') + + create_header(worksheet, header_list, 9, 4, height=21.8) + + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 6, 1, height=21.8, color='FF0000') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 2 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 6) + q += 1 + w += 1 + + kill_house_name = '' + if filtered_kill_reqs.exists(): + kill_house_name = filtered_kill_reqs.first()['killhouse_user__name'] + excel_description(worksheet, 'A1', f'بارهای {kill_house_name} در انتظار ورود به انبار (کشتار داخل استان)', + size=11, color='red', row2='E1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 7, 8, 20) + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + l = 7 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 5, 6) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'بارهای وارد شده به انبار': + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + if 'search' in request.GET: + filtered_kill_reqs = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + filtered_kill_reqs = [] if len(filtered_kill_reqs) == 0 else filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + + ] + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list2, 6, 4, height=21.8, color='green') + + create_header(worksheet, header_list, 9, 4, height=21.8) + + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 6, 1, height=21.8, color='FF0000') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 2 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 6) + q += 1 + w += 1 + + kill_house_name = '' + if filtered_kill_reqs.exists(): + kill_house_name = filtered_kill_reqs.first()['killhouse_user__name'] + excel_description(worksheet, 'A1', f'بارهای {kill_house_name} وارد شده به انبار (کشتار داخل استان)', + size=11, color='red', row2='E1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 7, 8, 20) + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + l = 7 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if kill[ + 'accepted_real_weight'] != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_state_ware_house_confirmation > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 5, 6) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'فروش به داخل استان': + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = filterset_class(data=query, queryset=allocations) + allocations = ps.filter() + allocations = [] if len( + allocations) == 0 else allocations + + excel_options = [ + 'ردیف', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'شماره واسط خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'سهمیه', + 'نوع فروش', + 'وضعیت', + + ] + + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + kill_house_name = '' + if allocations.exists(): + kill_house_name = allocations.first().kill_house.name + excel_description(worksheet, 'A1', f'تخصیصات داخل استان کشتارگاه {kill_house_name}', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name if allocation.to_steward else '-' + buyer_mobile = allocation.to_steward.user.mobile if allocation.to_steward else '-' + elif allocation.allocation_type == 'killhouse_guild': + allocation_type = 'کشتارگاه به صنف' + buyer_name = allocation.to_guilds.guilds_name if allocation.to_guilds else '-' + buyer_mobile = allocation.to_guilds.user.mobile if allocation.to_guilds else '-' + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = '' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + str(shamsi_date(allocation.date, in_value=True)), + allocation_type, + buyer_name, + buyer_mobile, + allocation.interface_number or '-', + sell_type, + allocation.amount, + allocation.total_amount, + allocation.number_of_carcasses, + allocation.weight_of_carcasses, + allocation.receiver_real_number_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + str(allocation.logged_registration_code or '-'), + system_registration_code, + "دولتی" if allocation.quota == 'governmental' else 'آزاد', + "دولتی" if allocation.approved_price_status == True else 'آزاد', + state, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + number_of_carcasses_allocations, + weight_of_carcasses_allocations, + receiver_real_number_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + number_of_carcasses_allocations, + weight_of_carcasses_allocations, + receiver_real_number_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'فروش به خارج استان': + + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + date__date__gte=date1, + date__date__lte=date2).order_by('-date') + else: + buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + ).order_by('-date') + len_buyers = [] + + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + buyers = buyers.filter( + build_query(filterset_class, value) + ) + + excel_options = [ + 'ردیف', + 'نام کشتارگاه', + 'موبایل کشتارگاه', + 'تاریخ', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'حجم لاشه(تقریبی)', + 'وزن لاشه(کیلوگرم)', + + ] + + header_list = [ + 'تعداد کل فروش', + 'تعداد خریداران', + 'حجم لاشه(تقریبی)', + 'وزن لاشه(کیلوگرم)', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + + excel_description(worksheet, 'A1', f'فروش لاشه خارج استان کشتارگاه {kill_house.name}', color='red', + row2='B1') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='B3') + + if kill_house: + province = kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + + for buyer in buyers: + date = jdatetime.date.fromgregorian( + day=buyer.date.day, + month=buyer.date.month, + year=buyer.date.year + ) + if buyer.buyer_name not in len_buyers: + len_buyers.append(buyer.buyer_name) + list1 = [ + m, + buyer.kill_house.name, + buyer.kill_house.kill_house_operator.user.mobile, + str(date), + buyer.buyer_name, + buyer.buyer_mobile, + buyer.buyer_name, + buyer.province, + buyer.city, + buyer.number_of_carcasses, + buyer.weight_of_carcasses, + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + + total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + value_list = [ + len(buyers), + len(len_buyers), + total_quantity, + total_weight, + ] + create_value(worksheet, value_list, 3, 3) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + total_weight, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'خریداران(خارج استان)': + out_buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=kill_house, trash=False).order_by( + 'id') + excel_options = [ + 'ردیف', + 'نام خریدار', + 'موبایل خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'تعداد درخواست ها', + 'حجم تقریبی(قطعه)', + 'وزن(کلوگرم)', + + ] + + excel_description(worksheet, 'A1', f'خریداران کشتارگاه {kill_house.name}', color='red', + row2='B1') + + if kill_house: + province = kill_house.kill_house_operator.user.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 5 + m = 1 + + for buyer in out_buyers: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer=buyer) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + list1 = [ + m, + buyer.buyer.fullname, + buyer.buyer.mobile, + buyer.buyer.unit_name, + buyer.buyer.province, + + buyer.buyer.city, + len(free_sales), + total_quantity, + total_weight, + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + l += 1 + elif sheet_name == 'بار زنده (خرید خارج استان)': + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'live' + kill_houses = None + + role = request.GET.get('role') + order_by_type = '-create_date' + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + filters['buy_type'] = type + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters, calculate_status=True, + temporary_trash=False, + temporary_deleted=False).order_by( + order_by_type) + + excel_options = [ + 'ردیف', + 'وضعیت', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تاریخ ورود به انبار', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'درصد افت', + + ] + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد کل بار زنده', + 'حجم کل بار زنده', + 'وزن کل بار زنده', + 'تعداد کل بارهای وارد شده به انبار', + 'حجم کل بارهای زنده وارد شده به انبار', + 'وزن کل بارهای زنده وارد شده به انبار', + 'وزن لاشه وارد شده به انبار', + 'کل بار وارد نشده به انبار', + 'حجم کل بار وارد نشده به انبار', + 'وزن کل بار وارد نشده به انبار', + + ] + + for col_num, option in enumerate(header_list2, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['B1'] = f'گزارش بار زنده خرید خارج از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['A2'] = f'استان {name}' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['A2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.weight_of_carcasses > 0: + state = 'ورود به انبار' + else: + state = 'در انظار ورود به انبار' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + date_of_enter = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + list1 = [ + m, + state, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + str(date_of_enter), + kill.number_of_carcasses, + int(kill.weight_of_carcasses), + + kill.weight_loss, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + # if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + quantity, + live_weight, + + len(entered_bars), + + entered_quantity, + entered_live_weight, + weight_of_carcasses, + len(not_entered_bars), + not_entered_quantity, + not_entered_live_weight, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + quantity, + live_weight, + '', + number_of_carcasses, + weight_of_carcasses, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بار لاشه (خرید خارج استان)': + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'carcasses' + bar_state = 'entered' + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters, calculate_status=True, + temporary_trash=False, + temporary_deleted=False).order_by( + order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + excel_options = [ + 'ردیف', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'کدقرنطینه', + + 'تاریخ ورود به انبار', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + + ] + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد کل بار', + 'حجم لاشه', + 'وزن لاشه', + + ] + + for col_num, option in enumerate(header_list2, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['B1'] = f'گزارش بار لاشه خرید خارج از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['A2'] = f'استان {name}' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['A2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.create_date.day, + month=kill.create_date.month, + year=kill.create_date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + date_of_enter = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + list1 = [ + m, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.bar_clearance_code, + str(date_of_enter), + kill.number_of_carcasses, + int(kill.weight_of_carcasses), + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + # if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(kill_house_free_bar_info), + number_of_carcasses, + weight_of_carcasses, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + number_of_carcasses, + weight_of_carcasses, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش انبار کشتارگاه {kill_house.name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def all_kill_house_inventory_data(request): + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id').annotate( + allocation_count=Count( + 'kill_house_steward_allocation', + filter=Q(kill_house_steward_allocation__receiver_state__in=['pending', 'accepted']) + ) + ).order_by( + '-allocation_count' + ) + sheet_name = 'اطلاعات کلی' + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'اطلاعات کلی': + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + # + + serializer = KillHouseForProvinceWareHouseDashboardSerializer(kill_houses, many=True, + context={'request': request}).data + header_list2 = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'ماهیت', + 'شهر', + 'مانده انبار فعلی', + 'کل وزن ورودی به انبار', + 'کل وزن فروش رفته', + 'حجم تخصیصات بدون ماشین', + 'تعداد بار درون استان', + 'حجم بار درون استان', + 'وزن بار درون استان', + 'تعداد بار زنده خارج استان', + 'حجم بار زنده خارج استان', + 'وزن بار زنده خارج استان', + 'تعداد بار لاشه خارج استان', + 'حجم بار لاشه خارج استان', + 'وزن بار لاشه خارج استان', + 'تعداد کل بارها', + 'حجم کل بارها', + 'وزن کل بارها', + 'تعداد بار وارد شده به انبار', + 'تعداد بار وارد نشده به انبار', + 'حجم بار وارد نشده به انبار', + 'وزن بار وارد نشده به انبار', + 'وزن فروش داخل استان', + 'وزن فروش خارج استان', + + ] + create_header(worksheet, header_list2, 1, 12, height=21.8, width=20, border_style='thin') + excel_description(worksheet, 'A2', f'اطلاعات جامع انبار', + size=11, color='red', row2='B4') + if serializer: + l = 13 + m = 1 + + for data in serializer: + list1 = [ + m, + data.get('name', ''), + data.get('kill_house_operator', {}).get('user', {}).get('mobile', ''), + 'کشتارگاه' if not data.get('killer', False) else 'کشتارکن', + data.get('kill_house_operator', {}).get('user', {}).get('city', {}).get('name', ''), + data.get('ware_house_info', {}).get('product_remain_weight', 0), + data.get('ware_house_info', {}).get('warehouse_total_entered_carcasses_weight', 0), + data.get('ware_house_info', {}).get('total_sell', 0), + data.get('ware_house_info', {}).get('province_kill_requests_quantity', 0), + data.get('ware_house_info', {}).get('total_province_bars', 0), + data.get('ware_house_info', {}).get('total_province_bars_quantity', 0), + data.get('ware_house_info', {}).get('total_province_bars_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_quantity', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_carcasses_bar', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses_weight', 0), + data.get('ware_house_info', {}).get('total_bars', 0), + data.get('ware_house_info', {}).get('warehouse_total_quantity', 0), + data.get('ware_house_info', {}).get('warehouse_total_weight', 0), + int(data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0)), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars', 0), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_allocations_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_sale__bar_carcasses_weight', 0), + + ] + + create_value(worksheet, list1, l, 1, border_style='thin', m=m) + m += 1 + l += 1 + header_list2 = [ + 'حجم کل بارها', + 'وزن کل بارها', + 'وزن وارد شده به انبار', + 'وزن توزیع شده داخل استان', + 'وزن توزیع شده خارج استان', + 'مانده انبار', + + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='C00000', border_style='thin') + products = RolesProducts.objects.filter(kill_house__in=kill_houses, trash=False) + product_remain_weight = products.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + shamsi_date1 = shamsi_date(date1) + shamsi_date2 = shamsi_date(date2) + excel_description(worksheet, 'A2', + f' اطلاعات جامع انبار از تاریخ {shamsi_date1} تا تاریخ {shamsi_date2}', + size=11, color='red', row2='B4') + + else: + excel_description(worksheet, 'A2', f'اطلاعات جامع انبار', + size=11, color='red', row2='B4') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, trash=False, + receiver_state__in=('pending', 'accepted'), + date__date__gte=date1, + date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True) + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses), + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter( + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True) + total_kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_weight = \ + kill_house_requests.filter(ware_house_confirmation=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + kill_house_free_bar_informations_live = kill_house_free_bar_informations.filter(buy_type='live') + kill_house_free_bar_informations_carcasses = kill_house_free_bar_informations.filter(buy_type='carcass') + total_kill_house_free_bar_quantity = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('quantity'))['total'] or 0 + total_kill_house_free_bar_weight = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('live_weight'))['total'] or 0 + total_kill_house_free_bar_carcasses = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_entered_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_weight = \ + kill_house_free_Sale_bar_informations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + warehouse_total_weight = total_kill_house_requests_weight + total_kill_house_free_bar_weight + total_kill_house_free_bar_carcasses_weight + warehouse_total_entered_carcasses_weight = total_entered_kill_house_requests_carcasses_weight + total_entered_kill_house_free_bar_carcasses_weight + + result = { + "product_remain_weight": int(warehouse_total_entered_carcasses_weight - ( + total_kill_house_allocations_weight + total_kill_house_free_sale__bar_carcasses_weight)), + "warehouse_total_quantity": int( + total_kill_house_requests_quantity + total_kill_house_free_bar_quantity + total_kill_house_free_bar_carcasses), + "warehouse_total_weight": int(warehouse_total_weight), + "warehouse_total_entered_carcasses_weight": int(warehouse_total_entered_carcasses_weight), + "total_kill_house_allocations_weight": int(total_kill_house_allocations_weight), + "total_kill_house_free_sale_bar_carcasses_weight": int( + total_kill_house_free_sale__bar_carcasses_weight), + + } + + value_header_list = [ + result['warehouse_total_quantity'], # حجم کل بارها + result['warehouse_total_weight'], # وزن کل بارها + result['warehouse_total_entered_carcasses_weight'], # وزن وارد شده به انبار + result['total_kill_house_allocations_weight'], # وزن توزیع شده داخل استان + result['total_kill_house_free_sale_bar_carcasses_weight'], + result['product_remain_weight'] # مانده انبار + ] + create_value(worksheet, value_header_list, 4, 3, border_style='thin') + + # محاسبه مجموع هر یک از فیلدها + sum_product_remain_weight = sum( + data.get('ware_house_info', {}).get('product_remain_weight', 0) for data in serializer) + sum_previous_product_remain_weight = sum( + data.get('ware_house_info', {}).get('previous_product_remain_weight', 0) for data in serializer) + sum_province_kill_requests_quantity = sum( + data.get('ware_house_info', {}).get('province_kill_requests_quantity', 0) for data in serializer) + sum_total_province_bars = sum( + data.get('ware_house_info', {}).get('total_province_bars', 0) for data in serializer) + sum_total_province_bars_quantity = sum( + data.get('ware_house_info', {}).get('total_province_bars_quantity', 0) for data in serializer) + sum_total_province_bars_weight = sum( + data.get('ware_house_info', {}).get('total_province_bars_weight', 0) for data in serializer) + sum_total_kill_house_free_bar = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar', 0) for data in serializer) + sum_total_kill_house_free_live_bar_quantity = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_quantity', 0) for data in + serializer) + sum_total_kill_house_free_live_bar_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_weight', 0) for data in serializer) + sum_total_kill_house_free_carcasses_bar = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_carcasses_bar', 0) for data in serializer) + sum_total_kill_house_free_bar_carcasses = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses', 0) for data in serializer) + sum_total_kill_house_free_bar_carcasses_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses_weight', 0) for data in + serializer) + sum_total_bars = sum(data.get('ware_house_info', {}).get('total_bars', 0) for data in serializer) + sum_warehouse_total_quantity = sum( + data.get('ware_house_info', {}).get('warehouse_total_quantity', 0) for data in serializer) + sum_warehouse_total_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_weight', 0) for data in serializer) + sum_warehouse_total_entered_bars = sum( + int(data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0)) for data in serializer) + sum_warehouse_total_entered_carcasses_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_carcasses_weight', 0) for data in + serializer) + sum_warehouse_total_not_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars', 0) for data in serializer) + sum_warehouse_total_not_entered_bars_quantity = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0) for data in + serializer) + sum_warehouse_total_not_entered_bars_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0) for data in + serializer) + sum_total_kill_house_allocations_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_allocations_weight', 0) for data in serializer) + sum_total_kill_house_free_sale__bar_carcasses_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_sale__bar_carcasses_weight', 0) for data in + serializer) + sum_total_sell = sum( + data.get('ware_house_info', {}).get('total_sell', 0) for data in + serializer) + sum_warehouse_total_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0) for data in + serializer) + + # ایجاد لیست نهایی برای ردیف مجموع + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + sum_product_remain_weight, + sum_warehouse_total_entered_bars, + sum_total_sell, + sum_province_kill_requests_quantity, + sum_total_province_bars, + sum_total_province_bars_quantity, + sum_total_province_bars_weight, + sum_total_kill_house_free_bar, + sum_total_kill_house_free_live_bar_quantity, + sum_total_kill_house_free_live_bar_weight, + sum_total_kill_house_free_carcasses_bar, + sum_total_kill_house_free_bar_carcasses, + sum_total_kill_house_free_bar_carcasses_weight, + sum_total_bars, + sum_warehouse_total_quantity, + sum_warehouse_total_weight, + sum_warehouse_total_entered_bars, + sum_warehouse_total_not_entered_bars, + sum_warehouse_total_not_entered_bars_quantity, + sum_warehouse_total_not_entered_bars_weight, + sum_total_kill_house_allocations_weight, + sum_total_kill_house_free_sale__bar_carcasses_weight + ] + + # اضافه کردن ردیف مجموع به اکسل + create_value(worksheet, summary_list, l + 1, 1, color='green') + + # for kill_house in kill_houses: + # sheet_name = kill_house.name + # worksheet = workbook.create_sheet(sheet_name) + # worksheet.sheet_view.rightToLeft = True + # worksheet.insert_rows(1) + # + # + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from1 = shamsi_date(date1) + # from2 = shamsi_date(date2) + # excel_description(worksheet, 'A7', + # f'گزارش جامع انبار کشتارگاه {kill_house.name} از تاریخ {from1} تا تاریخ {from2}', + # size=11, color='red', row2='C9') + # else: + # excel_description(worksheet, 'A7', f'گزارش جامع انبار کشتارگاه {kill_house.name}', + # size=11, color='red', row2='C8') + # + # excel_description(worksheet, 'D2', f'مدیریت انبار', + # size=11, color='red', row2='G2') + # header_list2 = [ + # 'ردیف', + # 'نام محصول', + # 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + # 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + # 'وزن خریدهای خارج استان(کیلوگرم)', + # 'کل ورودی به انبار(کیلوگرم)', + # 'کل فروش(کیلوگرم)', + # 'مانده انبار(کیلوگرم)', + # + # ] + # create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='FF0000', border_style='thin') + # products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + # q = 4 + # w = 1 + # for product in products: + # value_header_list = [ + # w, + # product.name, + # product.province_governmental_carcasses_weight, + # product.province_free_carcasses_weight, + # product.free_buying_carcasses_weight, + # product.total_carcasses_weight, + # product.real_allocated_weight, + # product.total_remain_weight, + # + # ] + # create_value(worksheet, value_header_list, q, 3, border_style='thin') + # q += 1 + # w += 1 + # + # excel_description(worksheet, 'D6', f'اطلاعات پخش', + # size=11, color='red', row2='G6') + # header_list2 = [ + # 'فروش و توزیع داخل استان(کیلوگرم)', + # 'فروش و توزیع خارج استان(کیلوگرم)', + # + # ] + # create_header(worksheet, header_list2, 5, 7, height=21.8, width=20, color='C00000', border_style='thin') + # + # steward_allocations = StewardAllocation.objects.filter(kill_house=kill_house, + # receiver_state__in=('pending', 'accepted'), + # calculate_status=True, trash=False) + # steward_allocations_weight = \ + # steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + # + # free_sales = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + # temporary_trash=False, + # temporary_deleted=False, + # calculate_status=True) + # free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + # value_header_list = [ + # steward_allocations_weight, + # free_sales_weight, + # + # ] + # create_value(worksheet, value_header_list, 8, 5, border_style='thin') + # + # excel_description(worksheet, 'D11', f'بارهای در انتظار ورود به انبار', + # size=11, color='red', row2='G11') + # data = KillHouseForProvinceWareHouseDashboardSerializer(kill_house, context={'request': request}).data + # + # header_list = [ + # 'تعداد بار', + # 'حجم بار', + # 'وزن بار', + # 'میانگین وزن ', + # + # ] + # + # # برای بالای هدر + # # header_list2 = [ + # # 'تعداد درخواست مرغداران', + # # ' مجموع تعداد قطعه درخواست مرغداران', + # # ' مجموع وزن درخواست مرغداران', + # # + # # ] + # # create_header(worksheet, header_list2, 1, 12, height=21.8, color='green',border_style='thin') + # + # create_header(worksheet, header_list, 3, 12, height=21.8, border_style='thin') + # if 'date1' in request.GET and request.GET['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() + # + # filtered_kill_reqs = KillHouseRequest.objects.filter( + # Q(killhouse_user=kill_house) | Q(killer=kill_house), + # kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=date2, + # ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + # '-kill_request__recive_date').order_by( + # '-create_date').select_related( + # 'killhouse_user', 'province_request__poultry_request__poultry__user', + # 'province_request__poultry_request', + # 'province_request__poultry_request__poultry', 'add_car__driver', + # 'killhouse_user__system_address__city', + # 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', 'traffic_code', + # 'assignment_state_archive', + # 'province_request__poultry_request__hatching__chicken_age', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'killhouse_user', + # 'killhouse_user__name', + # 'province_request__poultry_request__amount', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_request__poultry_request__send_date', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', 'quarantine_quantity', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'province_kill_request__province_request__poultry_request__out', + # 'killer__name', + # 'killhouse_user__type', 'killer', 'bar_document_status', + # 'bar_document_status__title').values( + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_confirmation', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', + # 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', + # 'killhouse_user', + # 'killhouse_user__name', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__send_date', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', + # 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', + # 'quarantine_quantity', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'province_request__poultry_request__hatching__chicken_age', + # 'province_request__poultry_request__amount', + # 'assignment_state_archive', + # 'traffic_code', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'province_kill_request__province_request__poultry_request__out', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'killer__name', + # 'killhouse_user__type', + # 'killer', 'bar_document_status', + # 'bar_document_status__title' + # ) + # else: + # filtered_kill_reqs = KillHouseRequest.objects.filter( + # Q(killhouse_user=kill_house) | Q(killer=kill_house), + # ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + # '-kill_request__recive_date').order_by( + # '-create_date').select_related( + # 'killhouse_user', 'province_request__poultry_request__poultry__user', + # 'province_request__poultry_request', + # 'province_request__poultry_request__poultry', 'add_car__driver', + # 'killhouse_user__system_address__city', + # 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', 'traffic_code', + # 'assignment_state_archive', + # 'province_request__poultry_request__hatching__chicken_age', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'killhouse_user', + # 'killhouse_user__name', + # 'province_request__poultry_request__amount', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_request__poultry_request__send_date', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', 'quarantine_quantity', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'province_kill_request__province_request__poultry_request__out', + # 'killer__name', + # 'killhouse_user__type', 'killer', 'bar_document_status', + # 'bar_document_status__title').values( + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_confirmation', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', + # 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', + # 'killhouse_user', + # 'killhouse_user__name', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__send_date', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', + # 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', + # 'quarantine_quantity', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'province_request__poultry_request__hatching__chicken_age', + # 'province_request__poultry_request__amount', + # 'assignment_state_archive', + # 'traffic_code', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'province_kill_request__province_request__poultry_request__out', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'killer__name', + # 'killhouse_user__type', + # 'killer', 'bar_document_status', + # 'bar_document_status__title' + # ) + # + # + # + # + # + # all_age = [] + # + # all_real_quantity = 0 + # all_net_weighte = 0 + # all_weighte = 0 + # kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + # assignments = KillHouseAssignmentInformation.objects.filter( + # kill_house_request__key__in=kill_keys, trash=False + # ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + # assignment_mapping = { + # assignment.kill_house_request.key: ( + # int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + # for assignment in assignments + # } + # + # if filtered_kill_reqs: + # for kill in filtered_kill_reqs: + # age = (kill.get('province_request__poultry_request__send_date').date() - + # kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + # if age not in all_age: + # all_age.append(age) + # + # key = kill.get('key') + # net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + # all_real_quantity += real_quantity if real_quantity != '-' else 0 + # all_net_weighte += net_weighte if net_weighte != '-' else 0 + # + # weight = int(kill.get('quantity') * kill.get( + # 'province_kill_request__province_request__poultry_request__Index_weight')) + # + # if kill['message'] is not None: + # state_delete = 'بار حذف شده' + # else: + # all_weighte += weight + # + # value_header_list = [ + # + # data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars', 0), + # data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0), + # data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0), + # round(data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0) / data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0), + # 1) if data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0) > 0 and data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0) > 0 else 0, + # + # ] + # create_value(worksheet, value_header_list, 13, 3, border_style='thin') + # + # excel_description(worksheet, 'D15', f'بارهای وارد شده به انبار', + # size=11, color='red', row2='G15') + # header_list = [ + # 'تعداد بارهای ایجاد شده', + # + # 'مجموع حجم بارها', + # 'مجموع وزن بارها', + # 'میانگین وزن ', + # + # ' افت در لحظه', + # ' افت لاشه ورود به انبار', + # + # ] + # + # # برای بالای هدر + # # header_list2 = [ + # # 'تعداد درخواست مرغداران', + # # ' مجموع تعداد قطعه درخواست مرغداران', + # # ' مجموع وزن درخواست مرغداران', + # # + # # ] + # # create_header(worksheet, header_list2, 1, 16, height=21.8, color='green', border_style='thin') + # + # create_header(worksheet, header_list, 3, 16, height=21.8, border_style='thin') + # if 'date1' in request.GET and request.GET['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() + # + # filtered_kill_reqs = KillHouseRequest.objects.filter( + # Q(killhouse_user=kill_house) | Q(killer=kill_house), + # kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=date2, + # ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + # '-kill_request__recive_date').select_related( + # 'killhouse_user', 'province_request__poultry_request__poultry__user', + # 'province_request__poultry_request', + # 'province_request__poultry_request__poultry', 'add_car__driver', + # 'killhouse_user__system_address__city', + # 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', 'traffic_code', + # 'assignment_state_archive', + # 'province_request__poultry_request__hatching__chicken_age', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'killhouse_user', + # 'killhouse_user__name', + # 'province_request__poultry_request__amount', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_request__poultry_request__send_date', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', 'quarantine_quantity', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'province_kill_request__province_request__poultry_request__out', + # 'killer__name', + # 'killhouse_user__type', 'killer', 'bar_document_status', + # 'bar_document_status__title').values( + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_confirmation', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', + # 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', + # 'killhouse_user', + # 'killhouse_user__name', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__send_date', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', + # 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', + # 'quarantine_quantity', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'province_request__poultry_request__hatching__chicken_age', + # 'province_request__poultry_request__amount', + # 'assignment_state_archive', + # 'traffic_code', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'province_kill_request__province_request__poultry_request__out', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'killer__name', + # 'killhouse_user__type', + # 'killer', 'bar_document_status', + # 'bar_document_status__title' + # ) + # else: + # filtered_kill_reqs = KillHouseRequest.objects.filter( + # Q(killhouse_user=kill_house) | Q(killer=kill_house), + # ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + # '-kill_request__recive_date').select_related( + # 'killhouse_user', 'province_request__poultry_request__poultry__user', + # 'province_request__poultry_request', + # 'province_request__poultry_request__poultry', 'add_car__driver', + # 'killhouse_user__system_address__city', + # 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', 'traffic_code', + # 'assignment_state_archive', + # 'province_request__poultry_request__hatching__chicken_age', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'killhouse_user', + # 'killhouse_user__name', + # 'province_request__poultry_request__amount', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_request__poultry_request__send_date', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', 'quarantine_quantity', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'province_kill_request__province_request__poultry_request__out', + # 'killer__name', + # 'killhouse_user__type', 'killer', 'bar_document_status', + # 'bar_document_status__title').values( + # 'province_request__poultry_request__poultry__user__fullname', + # 'province_kill_request__kill_house_price', + # 'kill_request__export_country', + # 'province_request__poultry_request__direct_buying', + # 'province_request__poultry_request__export', + # 'province_request__poultry_request__freezing', + # 'document_status', + # 'ware_house_confirmation', + # 'ware_house_accepted_real_quantity', + # 'ware_house_accepted_real_weight', + # 'weight_loss', 'message', + # 'province_request__poultry_request__freezing', + # 'province_request__poultry_request', + # 'killhouse_user', + # 'killhouse_user__name', + # 'killhouse_user__kill_house_operator__user__mobile', + # 'killhouse_user__system_address__city__name', + # 'killhouse_user__killer', + # 'kill_request__slaughter_house', + # 'kill_request__slaughter_house__name', + # 'province_request__poultry_request__poultry', + # 'province_request__poultry_request__order_code', + # 'province_request__poultry_request__chicken_breed', + # 'province_request__poultry_request__poultry__user__city__name', + # 'province_request__poultry_request__poultry__unit_name', + # 'province_request__poultry_request__poultry__user__mobile', + # 'province_request__poultry_request__send_date', + # 'add_car__driver__driver_name', + # 'add_car__driver__driver_mobile', + # 'add_car__driver__type_car', + # 'add_car__driver__health_code', + # 'key', + # 'province_kill_request__province_request__poultry_request__Index_weight', + # 'clearance_code', + # 'quantity', + # 'bar_code', + # 'accepted_real_weight', + # 'accepted_real_quantity', + # 'vet_state', + # 'vet_accepted_real_quantity', + # 'vet_accepted_real_weight', + # 'quarantine_quantity', + # 'killhouse_user__kill_house_operator__user__province__name', + # 'province_request__poultry_request__hatching__chicken_age', + # 'province_request__poultry_request__amount', + # 'assignment_state_archive', + # 'traffic_code', + # 'province_kill_request__province_request__poultry_request__free_sale_in_province', + # 'province_kill_request__province_request__poultry_request__union', + # 'province_kill_request__province_request__poultry_request__direct_buying', + # 'province_kill_request__province_request__poultry_request__out', + # 'quarantine_code_state', + # 'province_request__poultry_request__send_date', + # 'province_request__poultry_request__hatching__date', + # 'killer__kill_house_operator__user__mobile', + # 'killer__name', + # 'killhouse_user__type', + # 'killer', 'bar_document_status', + # 'bar_document_status__title' + # ) + # + # all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + # + # aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + # total_accepted_real_quantity=Sum('accepted_real_quantity'), + # total_accepted_real_weight=Sum('accepted_real_weight'), + # total_quantity=Sum('quantity'), + # total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + # total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + # total_quarantine_quantity=Sum('quarantine_quantity'), + # total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + # total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + # total_weight_loss=Sum('weight_loss'), + # + # ) + # + # all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + # + # all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + # + # all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + # 2) if all_weight_loss > 0 else 0 + # all_age = [] + # + # all_real_quantity = 0 + # all_net_weighte = 0 + # all_weighte = 0 + # kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + # assignments = KillHouseAssignmentInformation.objects.filter( + # kill_house_request__key__in=kill_keys, trash=False + # ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + # assignment_mapping = { + # assignment.kill_house_request.key: ( + # int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + # for assignment in assignments + # } + # all_total_weight_loss = 0 + # if filtered_kill_reqs: + # for kill in filtered_kill_reqs: + # age = (kill.get('province_request__poultry_request__send_date').date() - + # kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + # if age not in all_age: + # all_age.append(age) + # + # key = kill.get('key') + # net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + # all_real_quantity += real_quantity if real_quantity != '-' else 0 + # all_net_weighte += net_weighte if net_weighte != '-' else 0 + # + # weight = int(kill.get('quantity') * kill.get( + # 'province_kill_request__province_request__poultry_request__Index_weight')) + # + # if kill['message'] is not None: + # state_delete = 'بار حذف شده' + # else: + # all_weighte += weight + # weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + # + # if kill['ware_house_confirmation'] == True: + # state_ware_house_confirmation = 'ورود به انبار' + # + # else: + # state_ware_house_confirmation = '-' + # + # weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + # 'ware_house_accepted_real_weight'] > 0 else 0 + # if weight_loss1 < 0: + # weight_loss1 = weight_loss1 * -1 + # total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if kill['accepted_real_weight'] > 0 else 0 + # all_total_weight_loss += total_weight_loss + # all_total_weight_loss = all_total_weight_loss / len(filtered_kill_reqs) if len(filtered_kill_reqs) > 0 else 0 + # value_header_list = [ + # data.get('ware_house_info', {}).get('total_bars', 0), + # data.get('ware_house_info', {}).get('warehouse_total_quantity', 0), + # data.get('ware_house_info', {}).get('warehouse_total_weight', 0), + # round(data.get('ware_house_info', {}).get('warehouse_total_weight', 0) / data.get('ware_house_info', {}).get('warehouse_total_quantity', 0), + # 1) if data.get('ware_house_info', {}).get('warehouse_total_weight', 0) > 0 and data.get('ware_house_info', {}).get('warehouse_total_quantity', 0) > 0 else 0, + # + # f'%{int(all_total_weight_loss)}', + # f'%{all_weight_loss}', + # + # ] + # create_value(worksheet, value_header_list, 17, 3, border_style='thin') + # + # excel_description(worksheet, 'D19', f'فروش به داخل استان', + # size=11, color='red', row2='G19') + # if 'date1' in request.GET and request.GET['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() + # + # allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + # trash=False, date__date__gte=date1, + # date__date__lte=date2).order_by('id') + # else: + # allocations = StewardAllocation.objects.filter(Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + # trash=False).order_by('id') + # + # header_list2 = [ + # 'تعداد تخصیصات', + # 'قیمت کل', + # 'حجم تخصیصی', + # 'وزن تخصیصی', + # 'حجم تایید شده', + # 'وزن تایید شده', + # + # ] + # create_header(worksheet, header_list2, 4, 20, height=21, width=16.01, border_style='thin') + # total_amount_allocations = allocations.aggregate( + # total_quantity=Sum('total_amount')).get( + # 'total_quantity') or 0 + # number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('number_of_carcasses')).get( + # 'total_quantity') or 0 + # weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('weight_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_number_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + # 'total_quantity') or 0 + # + # value_header_list2 = [ + # len(allocations), + # total_amount_allocations, + # number_of_carcasses_allocations, + # weight_of_carcasses_allocations, + # receiver_real_number_of_carcasses_allocations, + # receiver_real_weight_of_carcasses_allocations, + # + # ] + # create_value(worksheet, value_header_list2, 21, 4, border_style='thin') + # + # excel_description(worksheet, 'D23', f'فروش به خارج استان', + # size=11, color='red', row2='G23') + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), + # '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), + # '%Y-%m-%d').date() + # buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + # date__date__gte=date1, + # date__date__lte=date2).order_by('-date') + # else: + # buyers = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + # ).order_by('-date') + # + # header_list = [ + # 'تعداد کل فروش', + # 'تعداد خریداران', + # 'حجم لاشه(تقریبی)', + # 'وزن لاشه(کیلوگرم)', + # + # ] + # + # create_header(worksheet, header_list, 4, 24, height=21, width=16.01, border_style='thin') + # + # total_quantity = buyers.aggregate(total=Sum('number_of_carcasses'))[ + # 'total'] or 0 + # total_weight = buyers.aggregate(total=Sum('weight_of_carcasses'))[ + # 'total'] or 0 + # len_buyers = [] + # for buyer in buyers: + # + # if buyer.buyer_name not in len_buyers: + # len_buyers.append(buyer.buyer_name) + # value_list = [ + # len(buyers), + # len(len_buyers), + # total_quantity, + # total_weight, + # ] + # create_value(worksheet, value_list, 25, 4, border_style='thin') + # + # excel_description(worksheet, 'D27', f'بار زنده (خرید خارج استان)', + # size=11, color='red', row2='G27') + # + # type = 'live' + # + # role = request.GET.get('role') + # order_by_type = '-create_date' + # + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # + # filters = { + # 'create_date__date__gte': date1, + # 'create_date__date__lte': date2, + # 'trash': False, + # } + # else: + # filters = { + # 'trash': False + # } + # + # filters['buy_type'] = type + # + # kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + # header_list2 = [ + # 'تعداد کل بار زنده', + # 'حجم کل بار زنده', + # 'وزن کل بار زنده', + # 'تعداد کل بارهای وارد شده به انبار', + # 'حجم کل بارهای زنده وارد شده به انبار', + # 'وزن کل بارهای زنده وارد شده به انبار', + # 'وزن لاشه وارد شده به انبار', + # 'کل بار وارد نشده به انبار', + # 'حجم کل بار وارد نشده به انبار', + # 'وزن کل بار وارد نشده به انبار', + # + # ] + # create_header(worksheet, header_list2, 2, 28, height=21, width=16.01, border_style='thin') + # + # quantity = kill_house_free_bar_info.aggregate( + # total_quantity=Sum('quantity')).get( + # 'total_quantity') or 0 + # live_weight = kill_house_free_bar_info.aggregate( + # total_quantity=Sum('live_weight')).get( + # 'total_quantity') or 0 + # + # weight_of_carcasses = kill_house_free_bar_info.aggregate( + # total_quantity=Sum('weight_of_carcasses')).get( + # 'total_quantity') or 0 + # + # entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + # + # entered_quantity = entered_bars.aggregate( + # total_quantity=Sum('quantity')).get( + # 'total_quantity') or 0 + # entered_live_weight = entered_bars.aggregate( + # total_quantity=Sum('live_weight')).get( + # 'total_quantity') or 0 + # + # not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + # + # not_entered_quantity = not_entered_bars.aggregate( + # total_quantity=Sum('quantity')).get( + # 'total_quantity') or 0 + # not_entered_live_weight = not_entered_bars.aggregate( + # total_quantity=Sum('live_weight')).get( + # 'total_quantity') or 0 + # + # value_header_list2 = [ + # len(kill_house_free_bar_info), + # quantity, + # live_weight, + # + # len(entered_bars), + # + # entered_quantity, + # entered_live_weight, + # weight_of_carcasses, + # len(not_entered_bars), + # not_entered_quantity, + # not_entered_live_weight, + # + # ] + # create_value(worksheet, value_header_list2, 29, 2, border_style='thin') + # + # excel_description(worksheet, 'D31', f'بار لاشه (خرید خارج استان)', + # size=11, color='red', row2='G31') + # type = 'carcasses' + # bar_state = 'entered' + # + # kill_houses = None + # order_by_type = '-create_date' + # + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # + # filters = { + # 'create_date__date__gte': date1, + # 'create_date__date__lte': date2, + # 'trash': False, + # } + # else: + # filters = { + # 'trash': False + # } + # + # if kill_houses is not None: + # filters['kill_house__in'] = kill_houses + # + # if type: + # filters['buy_type'] = type + # if type == 'live': + # if bar_state: + # if bar_state == 'entered': + # filters['weight_of_carcasses__gt'] = 0 + # else: + # filters['weight_of_carcasses'] = 0 + # + # kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + # header_list2 = [ + # 'تعداد کل بار', + # 'حجم لاشه', + # 'وزن لاشه', + # + # ] + # create_header(worksheet, header_list2, 5, 32, height=21, width=16.01, border_style='thin') + # + # number_of_carcasses = kill_house_free_bar_info.aggregate( + # total_quantity=Sum('number_of_carcasses')).get( + # 'total_quantity') or 0 + # weight_of_carcasses = kill_house_free_bar_info.aggregate( + # total_quantity=Sum('weight_of_carcasses')).get( + # 'total_quantity') or 0 + # + # value_header_list2 = [ + # len(kill_house_free_bar_info), + # number_of_carcasses, + # weight_of_carcasses, + # + # ] + # create_value(worksheet, value_header_list2, 33, 5, border_style='thin') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش جامع انبار کشتارگاه ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def cold_house_excel(request): + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + cold_house = ColdHouse.objects.filter(key=request.GET['cold_house_key'], trash=False).first() + + else: + cold_house = ColdHouse.objects.filter(live_stock_support__isnull=False, trash=False).first() + + if request.GET['type'] == 'output': + type = 'بارهای خارج شده' + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(kill_house=kill_house, trash=False) + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + else: + type = 'بارهای وارد شده' + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.filter(kill_house=kill_house, trash=False).first() + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.filter(key=request.GET['cold_house_key'], trash=False).first() + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = filterset_class(data=query, queryset=allocations) + allocations = ps.filter() + allocations = [] if len( + allocations) == 0 else allocations + + excel_options = [ + 'ردیف', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'حجم تخصیصی', + 'وزن تخصیصی', + 'حجم تایید شده', + 'وزن تایید شده', + # 'کد احراز', + # 'وضعیت کد احراز', + 'وضعیت', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + excel_description(worksheet, 'A5', type, color='red', row2='C5') + header_list2 = [ + 'وزن کل', + 'وزن خارج شده', + 'وزن باقیمانده', + 'تعداد کل بار وارد شده', + 'وزن کل بار وارد شده', + 'تعداد کل بار خارج شده', + 'وزن کل بار خارج شده', + + ] + + create_header(worksheet, header_list2, 5, 2, height=20.8, border_style='thin') + cell_color_changer(worksheet, 2, 5, 8, 'FF0000') + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + kill_house_name = '' + if allocations.exists(): + kill_house_name = allocations.first().kill_house.name + excel_description(worksheet, 'A1', f'سردخانه {kill_house_name}', size=11, color='red', + row2='D1') + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'A3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + elif allocation.allocation_type == 'killhouse_guild': + allocation_type = 'کشتارگاه به صنف' + buyer_name = allocation.to_guilds.guilds_name + buyer_mobile = allocation.to_guilds.user.mobile + elif allocation.allocation_type == 'ColdHouse': + allocation_type = 'کشتارگاه به سردخانه' + if allocation.to_cold_house.kill_house: + buyer_name = allocation.to_cold_house.kill_house.name + buyer_mobile = allocation.to_cold_house.kill_house.kill_house_operator.user.mobile + else: + buyer_name = allocation.to_cold_house.live_stock_support.user.name + buyer_mobile = allocation.to_cold_house.live_stock_support.user.mobile + elif allocation.allocation_type == 'killhouse_killhouse': + allocation_type = 'کشتارگاه به کشتارگاه' + buyer_name = allocation.to_kill_house.kill_house.name + buyer_mobile = allocation.to_kill_house.kill_house_operator.user.mobile + else: + allocation_type = '-' + buyer_name = '-' + buyer_mobile = '-' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = 'آزاد' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + str(shamsi_date((allocation.date))), + allocation_type, + buyer_name, + buyer_mobile, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.number_of_carcasses, + allocation.weight_of_carcasses, + allocation.receiver_real_number_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + # allocation.registration_code, + # system_registration_code, + state, + + ] + m += 1 + + create_value(worksheet, list1, l + 1, 1) + total_input_bars_weight = allocations.aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_number_of_carcasses = allocations.aggregate( + total=Sum('number_of_carcasses'))['total'] or 0 + total_weight_of_carcasses = allocations.aggregate( + total=Sum('weight_of_carcasses'))['total'] or 0 + total_receiver_real_number_of_carcasses = allocations.aggregate( + total=Sum('receiver_real_number_of_carcasses'))['total'] or 0 + total_receiver_real_weight_of_carcasses = allocations.aggregate( + total=Sum('receiver_real_weight_of_carcasses'))['total'] or 0 + + value_header_list2 = [ + cold_house.total_input_weight, + cold_house.total_allocated_weight, + cold_house.total_remain_weight, + len(allocations), + total_input_bars_weight, + 0, + 0, + + ] + + create_value(worksheet, value_header_list2, 3, 5, border_style='thin') + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_number_of_carcasses, + total_weight_of_carcasses, + total_receiver_real_number_of_carcasses, + total_receiver_real_weight_of_carcasses, + # '', + # '', + '', + + ] + # for item in range(len(list2)): + # cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + # value = list2[item] + # if isinstance(value, (int, float)): + # cell.number_format = '#,###' # Apply general number format + # else: + # cell.value = value # Keep as text for other values + # + # cell.alignment = Alignment(horizontal='center') + # cell.font = Font(size=10, bold=True) + # cell.font = Font(bold=True) + # cell.fill = PatternFill(start_color="00B050", fill_type="solid") + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="سردخانه {kill_house_name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def management_cold_house_excel(request): + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + excel_options = [ + 'ردیف', + 'نام سردخانه', + 'شهر', + 'آدرس', + 'وزن کل', + 'وزن خارج شده', + 'وزن باقیمانده', + 'وضعیت', + 'اجازه پخش', + 'اجازه جابه جایی', + 'ظرفیت', + + ] + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + sheet_name = 'اطلاعات کلی' + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + header_list2 = [ + 'ردیف', + 'نام کشتارگاه', + 'نام مالک', + 'موبایل', + 'شهر', + 'تعداد سرد خانه ها', + 'وزن وارد شده', + 'وزن خارج شده', + 'وزن باقیمانده', + + ] + + create_header(worksheet, header_list2, 3, 8, height=25.8, border_style='thin', width=15) + + header_list3 = [ + 'تعداد کل سردخانه', + 'تعداد کل سردخانه کشتارگاه', + 'تعداد کل سردخانه مباشرین', + 'کل وزن وارد شده', + 'کل وزن خارج شده', + 'کل وزن باقیمانده', + + ] + create_header(worksheet, header_list3, 5, 3, height=25.8, border_style='thin', width=15, color='FF0000') + cold_houses = ColdHouse.objects.filter(trash=False) + kill_house_cold_houses = cold_houses.filter(kill_house__isnull=False) + steward_cold_houses = cold_houses.filter(steward__isnull=False) + total_input_weight = cold_houses.aggregate( + total=Sum('total_input_weight'))['total'] or 0 + + total_allocated_weight = cold_houses.aggregate( + total=Sum('total_allocated_weight'))['total'] or 0 + + total_remain_weight = cold_houses.aggregate( + total=Sum('total_remain_weight'))['total'] or 0 + + result = { + "total_cold_houses": len(cold_houses), + "total_kill_house_cold_house": len(kill_house_cold_houses), + "total_steward_cold_house": len(steward_cold_houses), + "total_input_weight": total_input_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + list1 = [ + len(cold_houses), + len(kill_house_cold_houses), + len(steward_cold_houses), + total_input_weight, + total_allocated_weight, + total_remain_weight, + + ] + create_header(worksheet, list1, 5, 4, height=25.8, border_style='thin', color='D9D9D9', text_color='000000') + + excel_description(worksheet, 'A3', f'مدیریت سرد خانه ها', color='red', row2='C4') + + l = 8 + m = 1 + for kill_house in kill_houses: + cold_houses = ColdHouse.objects.filter(kill_house=kill_house, trash=False) + if cold_houses: + total_input_weight = cold_houses.aggregate(total=Sum('total_input_weight'))[ + 'total'] or 0 + total_allocated_weight = cold_houses.aggregate(total=Sum('total_allocated_weight'))[ + 'total'] or 0 + total_remain_weight = cold_houses.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + list1 = [ + m, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + kill_house.kill_house_operator.user.city.name, + len(cold_houses), + total_input_weight, + total_allocated_weight, + total_remain_weight, + + ] + m += 1 + l += 1 + create_header(worksheet, list1, 3, l, height=25.8, border_style='thin', color='B8CCE4', + text_color='000000') + + for kill_house in kill_houses: + cold_houses = ColdHouse.objects.filter(kill_house=kill_house, trash=False) + if cold_houses: + sheet_name = kill_house.name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list2 = [ + 'تعداد سرد خانه', + 'وزن وارد شده', + 'وزن خارج شده', + 'وزن باقیمانده', + + ] + + create_header(worksheet, header_list2, 5, 2, height=20.8, border_style='thin') + + total_input_weight = cold_houses.aggregate(total=Sum('total_input_weight'))[ + 'total'] or 0 + total_allocated_weight = cold_houses.aggregate(total=Sum('total_allocated_weight'))[ + 'total'] or 0 + total_remain_weight = cold_houses.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + + value_header_list2 = [ + len(cold_houses), + total_input_weight, + total_allocated_weight, + total_remain_weight, + + ] + + create_value(worksheet, value_header_list2, 3, 5, border_style='thin') + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + excel_description(worksheet, 'A5', f'سردخانه های {kill_house.name}', color='red', row2='C5') + l = 5 + m = 1 + for cold_house in cold_houses: + l += 1 + + status = 'فعال' if cold_house.active == True else 'غیر فعال' + broadcast = 'دارد' if cold_house.broadcast == True else 'ندارد' + relocate = 'دارد' if cold_house.relocate == True else 'ندارد' + + list1 = [ + m, + cold_house.name, + cold_house.city, + cold_house.address, + cold_house.total_input_weight, + cold_house.total_allocated_weight, + cold_house.total_remain_weight, + status, + broadcast, + relocate, + cold_house.capacity + + ] + m += 1 + + create_value(worksheet, list1, l + 1, 1) + total_input_weight = cold_houses.aggregate( + total=Sum('total_input_weight'))['total'] or 0 + total_allocated_weight = cold_houses.aggregate( + total=Sum('total_allocated_weight'))['total'] or 0 + total_remain_weight = cold_houses.aggregate( + total=Sum('total_remain_weight'))['total'] or 0 + capacity = cold_houses.aggregate( + total=Sum('capacity'))['total'] or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + total_input_weight, + total_allocated_weight, + total_remain_weight, + '', + '', + '', + capacity + + ] + + create_value(worksheet, list2, l + 3, 1, color='yellow') + + # blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + # red_font = Font(color="C00000", bold=True) + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from_date_1 = shamsi_date(date1) + # to_date_1 = shamsi_date(date2) + # worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + # header_list2 = [ + # 'وزن کل', + # 'وزن خارج شده', + # 'وزن باقیمانده', + # 'تعداد کل بار وارد شده', + # 'وزن کل بار وارد شده', + # 'تعداد کل بار خارج شده', + # 'وزن کل بار خارج شده', + # + # ] + # + # create_header(worksheet, header_list2, 5, 2, height=20.8, border_style='thin') + # cell_color_changer(worksheet, 2, 5, 8, 'FF0000') + # create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + # + # kill_house_name = '' + # if allocations.exists(): + # kill_house_name = allocations.first().kill_house.name + # excel_description(worksheet, 'A1', f'سردخانه {kill_house_name}', size=11, color='red', + # row2='D1') + # + # worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + # merge_range1 = 'B1:D1' + # merge_range2 = 'B2:D2' + # merge_range = 'A3:D3' + # worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range) + # worksheet.merge_cells(merge_range2) + # worksheet['B1'].font = red_font + # worksheet['A3'].font = Font(size=11) + # worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + # + # l = 5 + # m = 1 + # + # if allocations: + # for allocation in allocations: + # l += 1 + # + # if allocation.allocation_type == 'killhouse_steward': + # allocation_type = 'کشتارگاه به مباشر' + # buyer_name = allocation.to_steward.guilds_name + # buyer_mobile = allocation.to_steward.user.mobile + # elif allocation.allocation_type == 'killhouse_guild': + # allocation_type = 'کشتارگاه به صنف' + # buyer_name = allocation.to_guilds.guilds_name + # buyer_mobile = allocation.to_guilds.user.mobile + # elif allocation.allocation_type == 'ColdHouse': + # allocation_type = 'کشتارگاه به سردخانه' + # if allocation.to_cold_house.kill_house: + # buyer_name = allocation.to_cold_house.kill_house.name + # buyer_mobile = allocation.to_cold_house.kill_house.kill_house_operator.user.mobile + # else: + # buyer_name = allocation.to_cold_house.live_stock_support.user.name + # buyer_mobile = allocation.to_cold_house.live_stock_support.user.mobile + # elif allocation.allocation_type == 'killhouse_killhouse': + # allocation_type = 'کشتارگاه به کشتارگاه' + # buyer_name = allocation.to_kill_house.kill_house.name + # buyer_mobile = allocation.to_kill_house.kill_house_operator.user.mobile + # else: + # allocation_type = '-' + # buyer_name = '-' + # buyer_mobile = '-' + # + # if allocation.sell_type == 'exclusive': + # sell_type = 'اختصاصی' + # else: + # sell_type = 'آزاد' + # system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + # state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + # list1 = [ + # m, + # str(shamsi_date((allocation.date))), + # allocation_type, + # buyer_name, + # buyer_mobile, + # sell_type, + # allocation.amount, + # allocation.total_amount, + # allocation.number_of_carcasses, + # allocation.weight_of_carcasses, + # allocation.receiver_real_number_of_carcasses, + # allocation.receiver_real_weight_of_carcasses, + # # allocation.registration_code, + # # system_registration_code, + # state, + # + # ] + # m += 1 + # + # create_value(worksheet, list1, l + 1, 1) + # total_input_bars_weight = allocations.aggregate( + # total=Sum('real_weight_of_carcasses'))['total'] or 0 + # total_number_of_carcasses = allocations.aggregate( + # total=Sum('number_of_carcasses'))['total'] or 0 + # total_weight_of_carcasses = allocations.aggregate( + # total=Sum('weight_of_carcasses'))['total'] or 0 + # total_receiver_real_number_of_carcasses = allocations.aggregate( + # total=Sum('receiver_real_number_of_carcasses'))['total'] or 0 + # total_receiver_real_weight_of_carcasses = allocations.aggregate( + # total=Sum('receiver_real_weight_of_carcasses'))['total'] or 0 + # + # value_header_list2 = [ + # cold_house.total_input_weight, + # cold_house.total_allocated_weight, + # cold_house.total_remain_weight, + # len(allocations), + # total_input_bars_weight, + # 0, + # 0, + # + # ] + # + # create_value(worksheet, value_header_list2, 3, 5, border_style='thin') + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # total_number_of_carcasses, + # total_weight_of_carcasses, + # total_receiver_real_number_of_carcasses, + # total_receiver_real_weight_of_carcasses, + # # '', + # # '', + # '', + # + # ] + # + # create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="سرد خانه ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def create_guilds_or_stewards_from_excel(request): + pass + # file = request.FILES['file'].read() + # read = openpyxl.load_workbook(BytesIO(file), data_only=True) + # sheet = read.active + # group = Group.objects.get(name__exact="Guilds") + # steward_role = Group.objects.get(name__exact="Steward") + # password = '123456' + # result_list=[] + # yesterday= datetime.datetime.now().date() + # birth_day=convert_to_shamsi(day=yesterday.day, + # month=yesterday.month, + # year=yesterday.year).replace('-','/') + # for i, row in enumerate(sheet.iter_rows(values_only=True)): + # if i <= 1: + # continue + # kill_house_name = row[1] + # first_name = row[2] + # last_name = row[3] + # national_id = row[4] + # mobile = row[5] + # city_name = row[6] + # postal_code = row[7] + # address = row[8] + # guild_name = row[9] + # type_activity = row[10] + # area_activity = row[11] + # guilds_id = row[12] + # license_number = row[13] + # is_steward = row[14] + # + # + # is_steward = True if is_steward == 'مباشر' else 'صنف' + # mobile = str(mobile) + # + # if len(mobile) < 10: + # continue + # if len(mobile) == 10: + # mobile = '0' + mobile + # + # try: + # city = City.objects.get(name=city_name) + # province = Province.objects.get(key=city.province.key) + # + # system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + # if system_profile: + # if not Guilds.objects.filter(user=system_profile, trash=False).exists(): + # hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + # data = { + # "username": mobile, + # "first_name": first_name, + # "last_name": last_name, + # "password": hashed_password, + # "national_code": national_id, + # "role": "Rancher", + # "api_key": PROJECT_API_KEY + # } + # req = requests.post( + # url=ARTA_REGISTER, + # data=data, + # verify=False + # ) + # + # if req.status_code == 200: + # province = Province.objects.filter(trash=False).first() + # user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + # user.save() + # base_id = SystemUserProfile.objects.all() + # if base_id.count() > 0: + # base_id = int(base_id.last().base_order) + 1 + # else: + # base_id = 1000 + # city_id = City.objects.filter(trash=False, name=city).first() + # + # system_profile = SystemUserProfile( + # mobile=mobile, + # first_name=first_name, + # last_name=last_name, + # fullname=first_name+' ' + last_name, + # user=user, + # base_order=base_id, + # password=password, + # birthday=datetime.datetime.now().date(), + # city=city_id, + # province=province + # ) + # system_profile.save() + # system_profile.role.add(group) + # address = SystemAddress( + # province=province, + # city=city_id, + # address='', + # + # ) + # address.save() + # + # cooperative = Cooperative.objects.filter(trash=False, address__city=city_id).first() + # rancher = Rancher( + # user=system_profile, + # address=address, + # cooperative=cooperative, + # name=rancher_name, + # mobile=mobile, + # fullname=first_name + ' ' + last_name, + # city=city, + # herd_name=rancher_name, + # postal_code=postal_code, + # epidemiological_code=epidemiological_code, + # herd_code=herd_code, + # national_id=national_id, + # type='rural' if type_rancher == 'روستایی' else 'industrial' + # + # + # ) + # rancher.save() + # + # for _i in range(range_live_stock): + # live_stock = LiveStock( + # herd_code=herd_code, + # type=type_live_stock, + # birth_day=birth_day, + # birth_day_gh=yesterday, + # gender=gender, + # + # ) + # live_stock.save() + # except: + # result_list.append(rancher_name) + # + # return Response(result_list) + + +def non_receipt_request_excel(request): + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + user = SystemUserProfile.objects.get(key=request.GET['key']) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house = [] + kill_house_requests_list = [] + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + for kill_house_vet in kill_house_vets: + kill_house.append(kill_house_vet.kill_house) + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if request.GET['role'] in ['CityOperator', 'CityJahad', 'CityPoultry']: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True, + province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True + + ).order_by('-kill_request__recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_requests) + kill_house_requests_list = ps.filter() + kill_house_requests = [] if len(kill_house_requests_list) == 0 else kill_house_requests_list + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True).data + excel_options = [ + "ردیف", + "کدبار", + "کد بهداشتی حمل و نقل", + "تاریخ کشتار", + "خریدار", + " تلفن خریدار", + "کشتارکن اختصاصی", + "تلفن کشتارکن اختصاصی", + "مرغدار", + "تلفن مرغدار", + "تعداد اولیه", + "وزن اولیه بار (کیلوگرم)", + "قیمت مرغدار", + "قیمت کشتارگاه", + "ماشین", + "راننده", + "تحویلی دامپزشک (قطعه)", + "وزن تحویلی دامپزشک (کیلوگرم)", + "کدسفارش کشتار", + "نوع کشتار", + "وضعیت عدم وصول", + "پیغام عدم وصول", + "بررسی کننده", + "تاریخ تایید/رد", + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + "تعداد اولیه", + "وزن اولیه بار (کیلوگرم)", + "تحویلی دامپزشک (قطعه)", + "وزن تحویلی دامپزشک (کیلوگرم)", + + ] + + create_header(worksheet, header_list2, 5, 2, height=20.8, border_style='thin') + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'عدم وصول', size=11, color='red', + row2='D1') + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'A3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if serializer: + for data in serializer: + l += 1 + non_receipt_state_type = 'رد شده' + non_receipt_state = data.get('non_receipt_state') + if non_receipt_state: + if non_receipt_state == 'pending': + non_receipt_state_type = 'در انتظار تایید' + if non_receipt_state == 'accepted': + non_receipt_state_type = 'تایید شده' + non_receipt_check_date = data.get('non_receipt_check_date') + if non_receipt_check_date: + try: + non_receipt_check_date = datetime.datetime.strptime(str(non_receipt_check_date), + '%Y-%m-%dT%H:%M:%S.%f').date() + except ValueError: + non_receipt_check_date = datetime.datetime.strptime(str(non_receipt_check_date), + '%Y-%m-%dT%H:%M:%S').date() + non_receipt_check_date = shamsi_date(non_receipt_check_date, in_value=True) + else: + non_receipt_check_date = '-' + recive_date = data.get('kill_request', {}).get('recive_date') + if recive_date: + try: + recive_date = datetime.datetime.strptime(str(recive_date), '%Y-%m-%dT%H:%M:%S.%f').date() + except ValueError: + recive_date = datetime.datetime.strptime(str(recive_date), '%Y-%m-%dT%H:%M:%S').date() + recive_date = shamsi_date(recive_date, in_value=True) + else: + recive_date = '-' + + if data.get('poultry_request', {}).get('export') == False: + export_type = 'عادی' + else: + export_type = 'صادرات' + list1 = [ + m, + str(data.get('bar_code')) or "-", + data.get('traffic_code') or "-", + str(recive_date), + data.get('killhouse_user', {}).get('name') if data.get( + 'killhouse_user') else "-", + data.get('killhouse_user', {}).get('kill_house_operator', {}).get('user', {}).get('mobile') if data.get( + 'killhouse_user') else "-", + data.get('killer', {}).get('name') if data.get( + 'killer') else "-", + data.get('killer', {}).get('kill_house_operator', {}).get('user', {}).get('mobile') if data.get( + 'killer') else "-", + data.get('poultry_request', {}).get('poultry', {}).get('unit_name') if data.get( + 'poultry_request') else "-", + data.get('poultry_request', {}).get('poultry', {}).get('user', {}).get('mobile') if data.get( + 'poultry_request') else "-", + data.get('quantity') or "-", + data.get('weight_info', {}).get('weight') if data.get('weight_info') else "-", + data.get('price') or 0, + data.get('weight_info', {}).get('kill_house_price') if data.get('weight_info') else 0, + data.get('car', {}).get('type_car') if data.get('car') else "-", + data.get('car', {}).get('driver_name') if data.get('car') else "-", + data.get('vet_accepted_real_quantity') or 0, + data.get('vet_accepted_real_weight') or 0, + str(data.get('poultry_request', {}).get('order_code')) if data.get('poultry_request') else "-", + export_type, + non_receipt_state_type, + data.get('message') or "-", + data.get('non_receipt_checker') or "-", + str(non_receipt_check_date), + ] + m += 1 + + create_value(worksheet, list1, l + 1, 1) + total_quantity = sum( + data.get('quantity', 0) if data.get('quantity') != "-" else 0 + for data in serializer + ) + + total_weight = sum( + data.get('weight_info', {}).get('weight', 0) if data.get('weight_info') and data.get('weight_info', {}).get( + 'weight') != "-" else 0 + for data in serializer + ) + + total_price = sum( + data.get('price', 0) + for data in serializer + ) + + total_vet_accepted_real_quantity = sum( + data.get('vet_accepted_real_quantity', 0) + for data in serializer + ) + + total_vet_accepted_real_weight = sum( + data.get('vet_accepted_real_weight', 0) + for data in serializer + ) + + value_header_list2 = [ + total_quantity, + total_weight, + total_vet_accepted_real_quantity, + total_vet_accepted_real_weight + + ] + # + create_value(worksheet, value_header_list2, 3, 5, border_style='thin') + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + total_weight, + '', + '', + '', + '', + total_vet_accepted_real_quantity, + total_vet_accepted_real_weight, + '', + '', + '', + '', + '', + '', + + ] + + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="عدم وصول.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def return_kill_house_request_excel(request): + serializer_class = KillHouseRequestForBarManagementSerializer + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'KillHouse': + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True)) + + else: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True)) + + if 'search' in request.GET: + kill_house_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_requests) + kill_house_request_list = ps.filter() + kill_house_requests = [] if len(kill_house_request_list) == 0 else kill_house_request_list + + serializer = serializer_class(kill_house_requests, many=True).data + + header_list2 = [ + "ردیف", + "کد بار", + "کدسفارش", + "نوع درخواست", + "نوع کشتار", + "نام فارم", + "نام مرغدار", + "شهر مرغدار", + "تاریخ درخواست کشتار", + "تعداد بار", + "تاریخ ثبت بار", + "نام کشتارگاه", + "شهر کشتارگاه", + "وزن", + "میانگین وزنی", + "تعداد نهایی", + "وزن نهایی", + "قیمت مرغدار", + "قیمت کشتارگاه", + "وضعیت تایید", + "پلاک خودرو", + "نام راننده", + "عدم دریافت", + "پیام عدم دریافت", + "نوع برگشت" + ] + create_header(worksheet, header_list2, 1, 12, height=21.8, width=20, border_style='thin') + excel_description(worksheet, 'A2', f'بارهای بازگشتی', + size=11, color='red', row2='B4') + if serializer: + l = 13 + m = 1 + + for item in serializer: + state = "" + if item.get('state') == "pending": + state = "در انتظار تایید" + elif item.get('state') == "accepted": + state = "تایید شده" + elif item.get('state') == "rejected": + state = "رد شده" + + request_type = "" + if item.get('poultry_request', {}).get('market'): + request_type = "پنل معاملات" + elif item.get('poultry_request', {}).get('direct_buying'): + request_type = "خرید مستقیم" + elif item.get('warehouse'): + request_type = "انبار" + else: + request_type = "اتحادیه" + + kill_type = "" + if item.get('poultry_request', {}).get('freezing'): + kill_type = "انجماد" + elif item.get('poultry_request', {}).get('export'): + kill_type = "صادرات" + else: + kill_type = "عادی" + + list1 = [ + m, + str(item.get('bar_code') or "-"), + str(item.get('poultry_request', {}).get('order_code')) or "-", + request_type, + kill_type, + item.get('poultry_request', {}).get('poultry', {}).get('unit_name') or "-", + f"{item.get('poultry_request', {}).get('poultry', {}).get('user', {}).get('fullname') or '-'} ({item.get('poultry_request', {}).get('poultry', {}).get('user', {}).get('mobile') or '-'})", + item.get('poultry_request', {}).get('poultry', {}).get('address', {}).get('city', {}).get( + 'name') or "-", + str(shamsi_date(convert_str_to_date(item.get('kill_request', {}).get('recive_date')), in_value=True)), + item.get('quantity', 0), + str(shamsi_date(convert_str_to_date(item.get('create_date')), in_value=True)), + item.get('killhouse_user', {}).get('name') or item.get('killer', {}).get('name') or "-", + item.get('killhouse_user', {}).get('kill_house_operator', {}).get('user', {}).get('city', {}).get( + 'name') or item.get('killer', {}).get('kill_house_operator', {}).get('user', {}).get('city', + {}).get( + 'name') or "-", + item.get('weight_info', {}).get('weight', 0) if item.get('weight_info', {}).get( + 'weight') else "-", + item.get('weight_info', {}).get('index_weight', 0) if item.get('weight_info', {}).get( + 'index_weight') else "-", + item.get('accepted_real_quantity', 0), + item.get('accepted_real_weight', 0), + item.get('poultry_request', {}).get('amount', 0) if item.get('poultry_request', {}).get( + 'amount') else "-", + item.get('weight_info', {}).get('kill_house_price', 0) if item.get('weight_info', {}).get( + 'kill_house_price') else "-", + state, + item.get('car', {}).get('pelak') or "-", + item.get('car', {}).get('driver_name') or "-", + "دارد" if item.get('non_receipt') else "ندارد", + item.get('non_receipt_message') or "-", + ("کاربر" if item.get('non_receipt') and item.get('main_non_receipt') else "سیستم") + " " + str( + shamsi_date(convert_str_to_date(item.get('modify_date')))) + ] + + create_value(worksheet, list1, l, 1, border_style='thin', m=m) + m += 1 + l += 1 + header_list2 = [ + "تعداد کل تخصیصات", + "تعداد تخصیصات بازگشتی کاربر", + "تعداد تخصیصات بازگشتی سیستم", + "حجم کل تخصیصات", + "حجم تخصیصات بازگشتی کاربر", + "حجم تخصیصات بازگشتی سیستم", + "وزن کل تخصیصات", + "وزن بازگشتی کاربر", + "وزن بازگشتی سیستم", + "تعداد کل بارها", + "تعداد بارهای عدم وصول", + "تعداد بارهای بازگشتی سیستمی", + "حجم کل بارها", + "حجم بارهای عدم وصول", + "حجم بارهای بازگشتی سیستمی", + "وزن کل بارها", + "وزن بارهای عدم وصول", + "وزن بارهای بازگشتی سیستمی", + "وزن خریدهای بازگشتی با کارمزد", + "کارمزد خریدهای بازگشتی" + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='C00000', border_style='thin') + + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + + province_kill_request_filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + + kill_house_request_filters = {} + if 'date1' in request.GET: + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + province_kill_request_filters['kill_request__recive_date__date__gte'] = date1 + province_kill_request_filters['kill_request__recive_date__date__lte'] = date2 + kill_house_request_filters['kill_request__recive_date__date__gte'] = date1 + kill_house_request_filters['kill_request__recive_date__date__lte'] = date2 + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + province_kill_request_filters['killhouse_user'] = kill_house + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + else: + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), + **province_kill_request_filters).order_by('id') + + return_province_kill_requests_aggregates = return_province_kill_requests.aggregate( + total_count=Count('id'), + total_operator_return_count=Count('id', filter=Q(trash=False, return_to_province=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('total_killed_quantity'), + total_operator_return_quantity=Sum('main_quantity', filter=Q(trash=False, return_to_province=True)), + total_system_return_quantity=Sum('total_killed_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('total_killed_weight'), + total_operator_return_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight'), + filter=Q(trash=False, return_to_province=True)), + total_system_return_weight=Sum('total_killed_weight', filter=Q(trash=True, return_trash=True)), + + ) + return_kill_house_requests_aggregates = return_kill_house_requests.aggregate( + total_count=Count('id'), + total_non_receipt_count=Count('id', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('accepted_real_quantity'), + total_non_receipt_quantity=Sum('accepted_real_quantity', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_quantity=Sum('accepted_real_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('accepted_real_weight'), + total_non_receipt_weight=Sum('accepted_real_weight', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_weight=Sum('accepted_real_weight', filter=Q(trash=True, return_trash=True)), + ) + province_kill_request_total_operator_return_quantity = return_province_kill_requests_aggregates[ + 'total_operator_return_quantity'] or 0 + province_kill_request_total_system_return_quantity = return_province_kill_requests_aggregates[ + 'total_system_return_quantity'] or 0 + province_kill_request_total_quantity = province_kill_request_total_operator_return_quantity + province_kill_request_total_system_return_quantity + province_kill_request_total_operator_return_weight = return_province_kill_requests_aggregates[ + 'total_operator_return_weight'] or 0 + province_kill_request_total_system_return_weight = return_province_kill_requests_aggregates[ + 'total_system_return_weight'] or 0 + province_kill_request_total_weight = province_kill_request_total_operator_return_weight + province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight = return_kill_house_requests_aggregates[ + 'total_system_return_weight'] or 0 + total_return_weight_with_wage = province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight + result = { + "province_kill_request_total_count": return_province_kill_requests_aggregates['total_count'] or 0, + "province_kill_request_total_operator_return_count": return_province_kill_requests_aggregates[ + 'total_operator_return_count'] or 0, + "province_kill_request_total_system_return_count": return_province_kill_requests_aggregates[ + 'total_system_return_count'] or 0, + "province_kill_request_total_quantity": province_kill_request_total_quantity, + "province_kill_request_total_operator_return_quantity": province_kill_request_total_operator_return_quantity, + "province_kill_request_total_system_return_quantity": province_kill_request_total_system_return_quantity, + "province_kill_request_total_weight": province_kill_request_total_weight, + "province_kill_request_total_operator_return_weight": province_kill_request_total_operator_return_weight, + "province_kill_request_total_system_return_weight": province_kill_request_total_system_return_weight, + "kill_house_request_total_count": return_kill_house_requests_aggregates['total_count'] or 0, + "kill_house_request_total_non_receipt_count": return_kill_house_requests_aggregates[ + 'total_non_receipt_count'] or 0, + "kill_house_request_total_system_return_count": return_kill_house_requests_aggregates[ + 'total_system_return_count'] or 0, + "kill_house_request_total_quantity": return_kill_house_requests_aggregates['total_quantity'] or 0, + "kill_house_request_total_non_receipt_quantity": return_kill_house_requests_aggregates[ + 'total_non_receipt_quantity'] or 0, + "kill_house_request_total_system_return_quantity": return_kill_house_requests_aggregates[ + 'total_system_return_quantity'] or 0, + "kill_house_request_total_weight": return_kill_house_requests_aggregates['total_weight'] or 0, + "kill_house_request_total_non_receipt_weight": return_kill_house_requests_aggregates[ + 'total_non_receipt_weight'] or 0, + "kill_house_request_total_system_return_weight": kill_house_request_total_system_return_weight, + "total_return_weight_with_wage": total_return_weight_with_wage, + "total_return_wage": total_return_weight_with_wage * province_live_wage_type_amount, + } + value_header_list = [ + result.get('province_kill_request_total_count') or 0, + result.get('province_kill_request_total_operator_return_count') or 0, + result.get('province_kill_request_total_system_return_count') or 0, + result.get('province_kill_request_total_quantity') or 0, + result.get('province_kill_request_total_operator_return_quantity') or 0, + result.get('province_kill_request_total_system_return_quantity') or 0, + result.get('province_kill_request_total_weight') or 0, + result.get('province_kill_request_total_operator_return_weight') or 0, + result.get('province_kill_request_total_system_return_weight') or 0, + result.get('kill_house_request_total_count') or 0, + result.get('kill_house_request_total_non_receipt_count') or 0, + result.get('kill_house_request_total_system_return_count') or 0, + result.get('kill_house_request_total_quantity') or 0, + result.get('kill_house_request_total_non_receipt_quantity') or 0, + result.get('kill_house_request_total_system_return_quantity') or 0, + result.get('kill_house_request_total_weight') or 0, + result.get('kill_house_request_total_non_receipt_weight') or 0, + result.get('kill_house_request_total_system_return_weight') or 0, + result.get('total_return_weight_with_wage') or 0, + result.get('total_return_wage') or 0, + + ] + create_value(worksheet, value_header_list, 4, 3, border_style='thin') + + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + + create_value(worksheet, summary_list, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="بارهای بازگشتی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def warehouse_archive_combined_excel(request): + # Filters for list + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + + list_filters = {"trash": False} + if date1: + list_filters['date__date__gte'] = date1 + list_filters['date__date__lte'] = date2 + + archives = WarehouseArchive.objects.filter(**list_filters).order_by('-create_date') + list_data = WarehouseArchiveSerializer(archives, many=True).data + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and str(value).strip(): + archives = archives.filter( + build_query(WarehouseArchiveFilterSet.Meta.fields, value) + ) + + # Build dashboard queryset like TotalKillHouseWarehouseArchiveDashboardViewSet + dash_filters = {"trash": False, "kill_house__isnull": False} + if date1: + dash_filters['create_date__date__gte'] = date1 + dash_filters['create_date__date__lte'] = date2 + dash_archives = WarehouseArchive.objects.filter(**dash_filters) + kill_houses = KillHouse.objects.filter(id__in=dash_archives.values_list('kill_house__id', flat=True), trash=False) + + if search == 'filter' and value not in ("", None, 'undefined'): + kh_list = [] + for item in [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name', + ]: + query = QueryDict('{0}__contains={1}'.format(item, value)) + ps = KillHouseFilterSet(data=query, queryset=kill_houses) + if ps.filter().exists(): + kh_list = ps.filter() + kill_houses = kh_list if kh_list else kill_houses.none() + + dash_data = TotalKillHouseWarehouseArchiveDashboardSerializer( + kill_houses, many=True, context={'date1': date1, 'date2': date2} + ).data + + # Headers + excel_options = [ + 'ردیف', + 'تاریخ بایگانی', + 'تاریخ انبار', + 'نام کشتارگاه', + 'شهر', + 'وزن (کیلوگرم)', + 'نوع سهمیه', + 'ثبت کننده', + 'شماره تماس', + 'توضیحات', + ] + + header_list2 = [ + 'ردیف', + 'نام کشتارگاه', + 'تعداد کل', + 'تعداد دولتی', + 'تعداد آزاد', + 'وزن کل (کیلوگرم)', + 'وزن دولتی (کیلوگرم)', + 'وزن آزاد (کیلوگرم)', + ] + + # Workbook setup (single sheet) + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + # Title and date range (like sample) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if date1 and date2: + try: + d1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + d2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + from_date_1 = shamsi_date(d1) + to_date_1 = shamsi_date(d2) + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + except Exception: + pass + + # Render dashboard header (to the top area, columns start at 5 like sample) + create_header(worksheet, header_list2, 5, 2, height=20.8, border_style='thin') + + # Compute where the list should start based on dashboard rows + dash_count = len(dash_data) if dash_data else 0 + list_header_row = 6 + dash_count + + # Render list header with freeze and filter below dashboard block + create_header_freez(worksheet, excel_options, 1, list_header_row, list_header_row + 1, 20) + + excel_description(worksheet, 'A1', f'مانده انبار کشتارگاه', size=11, color='red', row2='D1') + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'A3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + # Fill dashboard rows under header_list2 + # header_list2 is at row 5, so start values at row 6 + dash_row = 3 + for i, item in enumerate(dash_data, start=1): + vals = [ + i, + item.get('name', '-'), + (item.get('info') or {}).get('total_count', 0) or 0, + (item.get('info') or {}).get('total_governmental_count', 0) or 0, + (item.get('info') or {}).get('total_free_count', 0) or 0, + (item.get('info') or {}).get('total_weight', 0) or 0, + (item.get('info') or {}).get('total_governmental_weight', 0) or 0, + (item.get('info') or {}).get('total_free_weight', 0) or 0, + ] + create_value(worksheet, vals, dash_row, 5, border_style='thin') + dash_row += 1 + + # Fill list rows starting from computed list header (data starts at header_row + 1) + l = list_header_row + total_count = 0 + total_weight = 0 + governmental_count = 0 + governmental_weight = 0 + free_count = 0 + free_weight = 0 + + for idx, arc in enumerate(list_data, start=1): + l += 1 + cd = convert_str_to_date(arc.get('create_date')) + create_date_sh = str(shamsi_date(cd, in_value=True)) if cd else '-' + d = convert_str_to_date(arc.get('date')) + date_sh = str(shamsi_date(d, in_value=True)) if d else '-' + kh = arc.get('kill_house') or {} + kh_name = kh.get('name', '-') + city = kh.get('city', '-') + quota_val = arc.get('quota') + quota = 'آزاد' if quota_val == 'free' else ('دولتی' if quota_val == 'governmental' else (quota_val or '-')) + weight_val = arc.get('weight') or 0 + + # accumulate totals + total_count += 1 + total_weight += weight_val or 0 + if quota_val == 'governmental': + governmental_count += 1 + governmental_weight += weight_val or 0 + if quota_val == 'free': + free_count += 1 + free_weight += weight_val or 0 + + row_vals = [ + idx, + create_date_sh, + date_sh, + kh_name, + city, + weight_val, + quota, + arc.get('registerer') or '-', + arc.get('registerer_mobile') or '-', + arc.get('description') or '-', + ] + create_value(worksheet, row_vals, l, 1, border_style='thin') + + # summary row after list + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + total_weight, + '', + '', + '', + '', + ] + + create_value(worksheet, summary_list, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="ترکیبی مانده انبار کشتارگاه.xlsx"'.encode('utf-8') + response.write(output.getvalue()) + return response + diff --git a/panel/KillHouse/helpers.py b/panel/KillHouse/helpers.py new file mode 100644 index 0000000..5d93938 --- /dev/null +++ b/panel/KillHouse/helpers.py @@ -0,0 +1,2034 @@ +import datetime +import jdatetime +import requests +import uuid +from django.db.models import Sum, Q, Case, When, F, FloatField +from django.http import HttpResponse +from rest_framework.response import Response + +from deposit_id import wage_counting_type, province_id, out_selling_ignore, new_out_selling_count_wage, \ + new_out_selling_count_wage_date, before_out_buying_count_wage_amount, market_code_state +from general_urls import base_url_for_sms_report +from panel.models import KillHouseRequest, KillHouseFreeBarInformation, ColdHouseAllocations, \ + KillHouseFreeSaleBarInformation, StewardAllocation, ProvinceKillRequest, WageType, InternalTransaction, KillHouse, \ + BarDifferenceRequest, PercentageOfWageType, RolesProducts, KillHouseWareHouse, KillRequest, \ + ProvinceCheckOperatorRequest, PoultryRequest, KillHousePercentage, IndexWeightCategory, PosSegmentation, \ + WarehouseArchive +from ticket.models import TicketSupport, MessageSupport + + +def kill_house_requests_product_warehousing(product): + # kill_house_requests = KillHouseRequest.objects.filter(killhouse_user=product.kill_house,input_warehouse=product.kill_house, + # ware_house_confirmation=True, trash=False, + # calculate_status=True,warehouse=True) + kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=product.kill_house, + ware_house_confirmation=True, trash=False, + calculate_status=True, warehouse=True) + governmental_kill_house_requests = kill_house_requests.filter( + province_request__poultry_request__free_sale_in_province=False) + free_kill_house_requests = kill_house_requests.filter(province_request__poultry_request__free_sale_in_province=True) + # Q(province_request__poultry_request__free_sale_in_province=True) | Q( + # province_request__poultry_request__direct_buying=True)) + product.province_governmental_carcasses_quantity = \ + governmental_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_quantity'))['total'] or 0 + product.province_governmental_carcasses_weight = \ + governmental_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + product.province_free_carcasses_quantity = \ + free_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_quantity'))['total'] or 0 + product.province_free_carcasses_weight = \ + free_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + product.save() + + governmental_commitment_weight = \ + governmental_kill_house_requests.aggregate(total=Sum('warehouse_commitment_weight'))[ + 'total'] or 0 + free_commitment_weight = \ + free_kill_house_requests.aggregate(total=Sum('warehouse_commitment_weight'))['total'] or 0 + + product.kill_house.total_in_province_governmental_bars_weight = product.province_governmental_carcasses_weight + product.kill_house.total_in_province_free_bars_weight = product.province_free_carcasses_weight + product.kill_house.total_in_province_governmental_bars_commitment_weight = governmental_commitment_weight + product.kill_house.total_in_province_free_bars_commitment_weight = free_commitment_weight + product.kill_house.save() + + +def kill_house_free_buying_product_warehousing(product): + # kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(kill_house=product.kill_house, trash=False, + # calculate_status=True,warehouse=True,input_warehouse=product.kill_house) \ + # .exclude(entered_message='ورود به انبار مجازی') + + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(trash=False, + calculate_status=True, warehouse=True, + input_warehouse=product.kill_house) \ + .exclude(entered_message='ورود به انبار مجازی') + product.free_buying_carcasses_quantity = \ + kill_house_free_buying_bars.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + product.free_buying_carcasses_weight = \ + kill_house_free_buying_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + product.save() + free_commitment_weight = \ + kill_house_free_buying_bars.aggregate(total=Sum('warehouse_commitment_weight'))[ + 'total'] or 0 + product.kill_house.total_out_province_buying_bars_weight = product.free_buying_carcasses_weight + product.kill_house.total_out_province_buying_bars_commitment_weight = free_commitment_weight + product.kill_house.save() + + +def kill_house_archive_warehousing(kill_house): + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False,warehouse=True) + + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + product.ware_house_archive_weight = archives_weight + product.save() + kill_house.ware_house_archive_governmental_weight = archives_governmental_weight + kill_house.ware_house_archive_free_weight = archives_free_weight + kill_house.save() + + +def kill_house_cold_house_allocations_product_warehousing(product): + cold_house_allocations = ColdHouseAllocations.objects.filter(kill_house=product.kill_house, + state__in=('pending', 'accepted'), + trash=False) + + product.freezing_quantity = cold_house_allocations.aggregate(total=Sum('real_quantity'))[ + 'total'] or 0 + product.freezing_weight = cold_house_allocations.aggregate(total=Sum('real_weight'))[ + 'total'] or 0 + product.save() + + +def kill_house_cold_house_allocations(cold_house): + cold_house_allocations = StewardAllocation.objects.filter(kill_house=cold_house.kill_house, + to_cold_house=cold_house, receiver_state='accepted', + trash=False, warehouse=True) + + cold_house.total_input_weight = cold_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.save() + cold_house.kill_house.total_cold_house_governmental_weight = \ + cold_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.kill_house.total_cold_house_free_weight = \ + cold_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.kill_house.save() + + +def cold_house_warehousing(cold_house): + cold_house_allocations = StewardAllocation.objects.filter( + Q(to_cold_house=cold_house) | Q(other_cold_house=cold_house), receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + input_allocations = cold_house_allocations.filter( + Q(kill_house__isnull=False, to_cold_house=cold_house) | Q( + kill_house__isnull=True, other_cold_house=cold_house), + receiver_state='accepted') + output_allocations = cold_house_allocations.filter( + Q(to_steward__isnull=False) | Q(to_guilds__isnull=False) | Q(other_cold_house__isnull=False), + kill_house__isnull=True, to_cold_house=cold_house) + + cold_house.total_input_weight = input_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.total_allocated_weight = output_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.save() + cold_house.kill_house.total_cold_house_governmental_weight = \ + output_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.kill_house.total_cold_house_free_weight = \ + output_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house.kill_house.save() + + +def kill_house_allocations_product_warehousing(product): + kill_house_allocations = StewardAllocation.objects.filter( + Q(kill_house=product.kill_house) | Q(to_kill_house=product.kill_house), trash=False, calculate_status=True, + warehouse=True) + kill_house_allocated = kill_house_allocations.filter(kill_house__isnull=False, to_cold_house__isnull=True) + kill_house_governmental_allocated = kill_house_allocations.filter(kill_house__isnull=False, + to_cold_house__isnull=True, quota='governmental') + kill_house_free_allocated = kill_house_allocations.filter(kill_house__isnull=False, to_cold_house__isnull=True, + quota='free') + kill_house_allocated_from = kill_house_allocations.filter(kill_house__isnull=True, to_cold_house__isnull=True) + governmental_kill_house_allocated_from = kill_house_allocated_from.filter(approved_price_status=True) + free_kill_house_allocated_from = kill_house_allocated_from.filter(approved_price_status=False) + cold_house_allocations = kill_house_allocations.filter(to_cold_house__isnull=False, + receiver_state__in=('pending', 'accepted')) + + product.province_allocated_quantity = \ + kill_house_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + product.province_allocated_weight = \ + kill_house_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + product.province_governmental_allocated_weight = \ + kill_house_governmental_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + product.province_free_allocated_weight = \ + kill_house_free_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + product.receive_governmental_carcasses_quantity = \ + governmental_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + product.receive_governmental_carcasses_weight = \ + governmental_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + product.receive_free_carcasses_quantity = \ + free_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + product.receive_free_carcasses_weight = \ + free_kill_house_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + product.cold_house_allocated_weight = cold_house_allocations.aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + product.save() + product.kill_house.total_selling_in_province_governmental_weight = product.province_governmental_allocated_weight + product.kill_house.total_selling_in_province_free_weight = product.province_free_allocated_weight + product.kill_house.save() + + +def kill_house_free_sale_product_warehousing(product): + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=product.kill_house, + + trash=False, calculate_status=True, + warehouse=True) + + product.out_province_allocated_quantity = \ + kill_house_free_sale_bars.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + product.out_province_allocated_weight = kill_house_free_sale_bars.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + # return ({"len(1)":product.out_province_allocated_quantity,"2":product.out_province_allocated_weight}) + product.save() + product.kill_house.total_selling_out_province_governmental_weight = \ + kill_house_free_sale_bars.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + product.kill_house.total_selling_out_province_free_weight = \ + kill_house_free_sale_bars.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + product.kill_house.save() + + +def get_new_wage_for_free_buying(kill_house_free_sale_bar_info): + final_date = '2025-05-28' + after_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=new_out_selling_count_wage_date, + quarantine_weight_of_carcasses=0).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + after_new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=new_out_selling_count_wage_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + + # before_total_out_selling_province_carcasses_weight = \ + # kill_house_free_sale_bar_info.filter(date__date__lte=final_date).filter(date__date__lte=new_out_selling_count_wage_date, + # quarantine_weight_of_carcasses=0).aggregate( + # total=Sum('real_weight_of_carcasses'))['total'] or 0 + + before_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__lte=final_date).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + # before_new_total_out_selling_province_carcasses_weight = \ + # kill_house_free_sale_bar_info.filter(date__date__gt=final_date).filter(date__date__lte=new_out_selling_count_wage_date, + # quarantine_weight_of_carcasses__gt=0).aggregate( + # total_weight=Sum( + # Case( + # When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + # then=F('real_weight_of_carcasses')), + # default=F('quarantine_weight_of_carcasses'), + # output_field=FloatField() + # ) + # ) + # ) + before_new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gte=final_date, date__date__lt=new_out_selling_count_wage_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + before_new_out_selling = before_new_total_out_selling_province_carcasses_weight['total_weight'] or 0 + before_total_out_selling_province_carcasses_weight += before_new_out_selling + after_new_out_selling = after_new_total_out_selling_province_carcasses_weight['total_weight'] or 0 + after_total_out_selling_province_carcasses_weight += after_new_out_selling + + return { + "before_new_out_selling": before_new_out_selling, + "before_total_out_selling_province_carcasses_weight": before_total_out_selling_province_carcasses_weight, + "after_new_out_selling": after_new_out_selling, + "after_total_out_selling_province_carcasses_weight": after_total_out_selling_province_carcasses_weight, + } + + +def get_finance_info(kill_house, date1=None, date2=None): + before_total_out_live_buying_province_carcasses_weight = 0 + after_total_out_live_buying_province_carcasses_weight = 0 + before_new_out_selling = 0 + after_new_out_selling = 0 + extra_company_amount = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-buy', trash=False).first() + free_sell_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-sell', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + free_buying_carcesses_weight_wage_type_amount = free_buying_carcesses_weight_wage_type.amount if free_buying_carcesses_weight_wage_type.status == True else 0 + free_sell_carcesses_weight_wage_type_amount = free_sell_carcesses_weight_wage_type.amount if free_sell_carcesses_weight_wage_type.status == True else 0 + + if date1: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + archive_wage=False, return_to_province=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=True, + return_trash=True, + archive_wage=False, return_to_province=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + kill_request__recive_date__date__gte=date1, kill_request__recive_date__date__lte=date2, + trash=False, calculate_status=True + ) + + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + kill_request__recive_date__date__gte=date1, kill_request__recive_date__date__lte=date2, + trash=True, return_trash=True, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house=kill_house) | Q(exclusive_killer=kill_house), + archive_wage=False, + calculate_status=True, date__date__gte=date1, date__date__lte=date2, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, date__date__gte=date1, date__date__lte=date2, + trash=False) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', date__date__gte=date1, date__date__lte=date2, + trash=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, state='accepted', + create_date__date__gte=date1, + create_date__date__lte=date2) + else: + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=True, + return_trash=True, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=False, calculate_status=True + ) + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=True, return_trash=True, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house=kill_house) | Q(exclusive_killer=kill_house), + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', + trash=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, state='accepted') + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + difference_requests_weight = \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + return_total_province_live_weight = return_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + return_total_province_live_weight += return_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + final_date = '2025-05-28' + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__lte=final_date).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=final_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + new_out_selling = new_total_out_selling_province_carcasses_weight['total_weight'] or 0 + + total_out_selling_province_carcasses_weight += new_out_selling + + if wage_counting_type == 'live': + total_province_carcasses_weight = total_province_live_weight + total_pure_province_carcasses_weight = total_province_carcasses_weight + else: + return_total_province_live_weight = int(return_total_province_live_weight * 0.75) + total_province_carcasses_weight = total_province_live_weight * 0.75 + difference_requests_weight = difference_requests_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - out_selling_out_carcasses_buying_difference + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + real_total_out_live_buying_province_carcasses_weight = total_out_live_buying_province_carcasses_weight + if new_out_selling_count_wage: + if out_selling_ignore: + before_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__lt=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + after_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__gte=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + get_new_wage = get_new_wage_for_free_buying(kill_house_free_sale_bar_info) + + before_new_out_selling = get_new_wage['before_new_out_selling'] + after_new_out_selling = get_new_wage['after_new_out_selling'] + max_amount = before_total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= before_new_out_selling: + before_total_out_live_buying_province_carcasses_weight -= max_amount + else: + before_total_out_live_buying_province_carcasses_weight -= before_new_out_selling + + if after_total_out_live_buying_province_carcasses_weight > after_new_out_selling: + extra_company_amount = int(after_new_out_selling * extra_company_amount) + after_total_out_live_buying_province_carcasses_weight -= after_new_out_selling + + else: + extra_company_amount = int(after_total_out_live_buying_province_carcasses_weight * extra_company_amount) + + after_total_out_live_buying_province_carcasses_weight = 0 + + total_out_live_buying_province_carcasses_weight = before_total_out_live_buying_province_carcasses_weight + after_total_out_live_buying_province_carcasses_weight + + else: + if out_selling_ignore: + max_amount = total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= new_out_selling: + total_out_live_buying_province_carcasses_weight -= max_amount + else: + total_out_live_buying_province_carcasses_weight -= new_out_selling + + # else: + # total_out_live_buying_province_carcasses_weight -= total_out_selling_province_quarantine_carcasses_weight + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_type_amount + difference_requests_price = difference_requests_weight * province_live_wage_type_amount + total_return_pure_province_carcasses_price = return_total_province_live_weight * province_live_wage_type_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_wage_type_amount + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (before_total_out_live_buying_province_carcasses_weight * before_out_buying_count_wage_amount) + ( + after_total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount)) + else: + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount + + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_wage_type_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + extra_company_amount + total_return_pure_province_carcasses_price + + return { + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "total_out_selling_province_carcasses_weight": total_out_selling_province_carcasses_weight, + "total_pure_province_carcasses_weight": total_pure_province_carcasses_weight, + "total_pure_province_carcasses_price": total_pure_province_carcasses_price, + "total_out_selling_province_carcasses_price": total_out_selling_province_carcasses_price, + "total_out_carcasses_buying_province_carcasses_weight": total_out_carcasses_buying_province_carcasses_weight, + "total_out_carcasses_buying_province_carcasses_price": total_out_carcasses_buying_province_carcasses_price, + "total_out_live_buying_province_carcasses_weight": real_total_out_live_buying_province_carcasses_weight, + "total_out_live_buying_province_carcasses_price": total_out_live_buying_province_carcasses_price, + "total_paid_wage": total_paid_wage, + "total_price": total_price, + "province_live_wage_amount": province_live_wage_type_amount, + "free_buying_live_weight_amount": free_buying_live_weight_wage_type_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_wage_type_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_wage_type_amount, + "extra_company_amount": extra_company_amount, + "before_total_out_live_buying_province_carcasses_weight": before_total_out_live_buying_province_carcasses_weight, + "after_total_out_live_buying_province_carcasses_weight": after_total_out_live_buying_province_carcasses_weight, + "before_new_out_selling": before_new_out_selling, + "after_new_out_selling": after_new_out_selling, + "return_total_province_live_weight": return_total_province_live_weight, + "total_return_pure_province_carcasses_price": total_return_pure_province_carcasses_price, + "difference_requests_weight": difference_requests_weight, + "difference_requests_price": difference_requests_price, + + } + + +def get_kill_house_finance_info(kill_house, date1=None, date2=None): + before_total_out_live_buying_province_carcasses_weight = 0 + after_total_out_live_buying_province_carcasses_weight = 0 + before_new_out_selling = 0 + after_new_out_selling = 0 + extra_company_amount = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-buy', trash=False).first() + free_sell_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-sell', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + free_buying_carcesses_weight_wage_type_amount = free_buying_carcesses_weight_wage_type.amount if free_buying_carcesses_weight_wage_type.status == True else 0 + free_sell_carcesses_weight_wage_type_amount = free_sell_carcesses_weight_wage_type.amount if free_sell_carcesses_weight_wage_type.status == True else 0 + + if date1: + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0).order_by('id') + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=True, + return_trash=True, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ) + kill_house_requests = kill_house_requests.filter( + Q(killhouse_user=kill_house, killer__isnull=True) | Q(killhouse_user=kill_house, killer=kill_house) | Q( + killer=kill_house)) + + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=True, return_trash=True, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ) + return_kill_house_requests = return_kill_house_requests.filter( + Q(killhouse_user=kill_house, killer__isnull=True) | Q(killhouse_user=kill_house, killer=kill_house) | Q( + killer=kill_house)) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house=kill_house, exclusive_killer__isnull=True) | Q(exclusive_killer=kill_house), + archive_wage=False, + calculate_status=True, create_date__date__gte=date1, create_date__date__lte=date2, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, date__date__gte=date1, date__date__lte=date2, + trash=False) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', date__date__gte=date1, date__date__lte=date2, + trash=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, state='accepted', + create_date__date__gte=date1, + create_date__date__lte=date2, ) + + + else: + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=True, + return_trash=True, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=False, calculate_status=True + ) + kill_house_requests = kill_house_requests.filter( + Q(killhouse_user=kill_house, killer__isnull=True) | Q(killhouse_user=kill_house, killer=kill_house) | Q( + killer=kill_house)) + + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=True, return_trash=True, calculate_status=True + ) + return_kill_house_requests = return_kill_house_requests.filter( + Q(killhouse_user=kill_house, killer__isnull=True) | Q(killhouse_user=kill_house, killer=kill_house) | Q( + killer=kill_house)) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house=kill_house, exclusive_killer__isnull=True) | Q(exclusive_killer=kill_house), + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', + trash=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, state='accepted') + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + # total_out_selling_province_carcasses_weight = \ + # kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + # sum_quarantine_carcasses_weight = \ + # kill_house_free_sale_bar_info.filter(quarantine_weight_of_carcasses__gt=0).aggregate( + # total_weight=Sum( + # Case( + # When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + # then=F('real_weight_of_carcasses')), + # default=F('quarantine_weight_of_carcasses'), + # output_field=FloatField() + # ) + # ) + # ) + # total_out_selling_province_quarantine_carcasses_weight = sum_quarantine_carcasses_weight['total_weight'] or 0 + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + difference_requests_weight = \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + return_total_province_live_weight = return_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + return_total_province_live_weight += return_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + final_date = '2025-05-28' + + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__lte=final_date).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=final_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + new_out_selling = new_total_out_selling_province_carcasses_weight['total_weight'] or 0 + + total_out_selling_province_carcasses_weight += new_out_selling + + if wage_counting_type == 'live': + total_province_carcasses_weight = total_province_live_weight + total_pure_province_carcasses_weight = total_province_carcasses_weight + else: + return_total_province_live_weight = int(return_total_province_live_weight * 0.75) + total_province_carcasses_weight = total_province_live_weight * 0.75 + difference_requests_weight = difference_requests_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - out_selling_out_carcasses_buying_difference + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + real_total_out_live_buying_province_carcasses_weight = total_out_live_buying_province_carcasses_weight + if new_out_selling_count_wage: + if out_selling_ignore: + before_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__lt=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + after_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__gte=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + get_new_wage = get_new_wage_for_free_buying(kill_house_free_sale_bar_info) + + before_new_out_selling = get_new_wage['before_new_out_selling'] + after_new_out_selling = get_new_wage['after_new_out_selling'] + max_amount = before_total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= before_new_out_selling: + before_total_out_live_buying_province_carcasses_weight -= max_amount + else: + before_total_out_live_buying_province_carcasses_weight -= before_new_out_selling + + if after_total_out_live_buying_province_carcasses_weight > after_new_out_selling: + extra_company_amount = int(after_new_out_selling * extra_company_amount) + after_total_out_live_buying_province_carcasses_weight -= after_new_out_selling + + else: + extra_company_amount = int(after_total_out_live_buying_province_carcasses_weight * extra_company_amount) + + after_total_out_live_buying_province_carcasses_weight = 0 + + total_out_live_buying_province_carcasses_weight = before_total_out_live_buying_province_carcasses_weight + after_total_out_live_buying_province_carcasses_weight + + else: + if out_selling_ignore: + max_amount = total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= new_out_selling: + total_out_live_buying_province_carcasses_weight -= max_amount + else: + total_out_live_buying_province_carcasses_weight -= new_out_selling + + # else: + # total_out_live_buying_province_carcasses_weight -= total_out_selling_province_quarantine_carcasses_weight + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_type_amount + difference_requests_price = difference_requests_weight * province_live_wage_type_amount + total_return_pure_province_carcasses_price = return_total_province_live_weight * province_live_wage_type_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_wage_type_amount + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (before_total_out_live_buying_province_carcasses_weight * before_out_buying_count_wage_amount) + ( + after_total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount)) + else: + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount + + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_wage_type_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + extra_company_amount + total_return_pure_province_carcasses_price + + return { + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "total_out_selling_province_carcasses_weight": total_out_selling_province_carcasses_weight, + "total_pure_province_carcasses_weight": total_pure_province_carcasses_weight, + "total_pure_province_carcasses_price": total_pure_province_carcasses_price, + "total_out_selling_province_carcasses_price": total_out_selling_province_carcasses_price, + "total_out_carcasses_buying_province_carcasses_weight": total_out_carcasses_buying_province_carcasses_weight, + "total_out_carcasses_buying_province_carcasses_price": total_out_carcasses_buying_province_carcasses_price, + "total_out_live_buying_province_carcasses_weight": real_total_out_live_buying_province_carcasses_weight, + "total_out_live_buying_province_carcasses_price": total_out_live_buying_province_carcasses_price, + "total_paid_wage": total_paid_wage, + "total_price": total_price, + "province_live_wage_amount": province_live_wage_type_amount, + "free_buying_live_weight_amount": free_buying_live_weight_wage_type_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_wage_type_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_wage_type_amount, + "extra_company_amount": extra_company_amount, + "before_total_out_live_buying_province_carcasses_weight": before_total_out_live_buying_province_carcasses_weight, + "after_total_out_live_buying_province_carcasses_weight": after_total_out_live_buying_province_carcasses_weight, + "before_new_out_selling": before_new_out_selling, + "after_new_out_selling": after_new_out_selling, + "return_total_province_live_weight": return_total_province_live_weight, + "total_return_pure_province_carcasses_price": total_return_pure_province_carcasses_price, + "difference_requests_weight": difference_requests_weight, + "difference_requests_price": difference_requests_price, + + } + + +def get_difference_carcasses_weight(kill_houses, date1=None, date2=None): + difference_weight = 0 + for kill_house in kill_houses: + if date1: + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False, date__date__gte=date1, + date__date__lte=date2) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False, date__date__gte=date1, date__date__lte=date2) + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + # total_out_selling_province_carcasses_weight = \ + # kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + final_date = '2025-05-28' + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__lte=final_date).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=final_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + total_out_selling_province_carcasses_weight += new_total_out_selling_province_carcasses_weight[ + 'total_weight'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + + difference_weight += out_selling_out_carcasses_buying_difference + + return difference_weight + + +def get_difference_carcasses_percent(date1=None, date2=None): + different_percent = 0 + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + if date1: + total_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0).order_by('id') + total_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ) + else: + total_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + total_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + + total_province_live_weight = total_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += total_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += total_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, state='accepted') + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses, date1, date2) + + different_percent = total_pure_province_carcasses_weight / total_province_carcasses_weight + + return different_percent + + +def generate_unique_bar_code(): + shamsi_year = jdatetime.date.fromgregorian(year=datetime.datetime.now().year, month=1, day=1).year + last_digit = str(shamsi_year)[-1] + while True: + code = int(province_id + last_digit + str(uuid.uuid4().int)[:5]) + + if not KillHouseFreeBarInformation.objects.filter(bar_code=code, trash=False).exists(): + return code + + +def send_ticket_for_bar_difference_request(user, kill_house, quantity, poultry): + new_ticket = TicketSupport( + user=user, + title="پیام سیستمی:درخواست رسیدگی اختلاف کشتار", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(kill_house) + + message = 'با سلام و احترام این پیام از طرف سامانه میباشد.' \ + '\n' \ + f'کاربر گرامی برای شما حجم {quantity} قطعه اختلاف کشتار از مرغدار {poultry} ثبت گردیده لطفا جهت تعیین تکلیف به بخش مدیریت بار قسمت اختلاف کشتار مراجعه نمایید.باتشکر سامانه رصدیار ' + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + + +def get_difference_carcasses_weight_kill(kill_house, date1=None, date2=None): + if date1: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + archive_wage=False, date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, date__date__gte=date1, date__date__lte=date2, + trash=False) + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + + difference_weight = out_selling_out_carcasses_buying_difference + + return difference_weight + + +def get_calculate_shares(kill_house): + before_total_out_live_buying_province_carcasses_price = 0 + total_wage_type = WageType.objects.filter(trash=False) + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + wage_info = get_finance_info(kill_house) + + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False) + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + # total_pure_province_carcasses_price = wage_info['total_pure_province_carcasses_price'] + wage_info[ + # 'total_return_pure_province_carcasses_price'] + total_pure_province_carcasses_price = wage_info['total_pure_province_carcasses_price'] + total_out_selling_province_carcasses_price = wage_info['total_out_selling_province_carcasses_price'] + difference_requests_price = wage_info['difference_requests_price'] + total_return_pure_province_carcasses_price = wage_info['total_return_pure_province_carcasses_price'] + + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (wage_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount) + ( + wage_info[ + 'after_total_out_live_buying_province_carcasses_weight'] * free_buying_live_weight_wage_type_amount)) + + before_total_out_live_buying_province_carcasses_price = wage_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount + else: + total_out_live_buying_province_carcasses_price = wage_info[ + 'total_out_live_buying_province_carcasses_price'] + total_out_carcasses_buying_province_carcasses_price = wage_info[ + 'total_out_carcasses_buying_province_carcasses_price'] + total_price = wage_info['total_price'] + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + return_union_province_kill_request_wage = total_return_pure_province_carcasses_price * union_province_kill_request_percent + + union_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + return_union_province_kill_request_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + guilds_difference_requests_price = difference_requests_price * guilds_province_kill_request_percent + other_difference_requests_price = difference_requests_price * other_province_kill_request_percent + guild_return_province_kill_request_wage = total_return_pure_province_carcasses_price * guilds_province_kill_request_percent + other_return_province_kill_request_wage = total_return_pure_province_carcasses_price * other_province_kill_request_percent + + # company_province_kill_request_wage = ( + # total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + # guilds_difference_requests_price + other_difference_requests_price + guild_return_province_kill_request_wage + other_return_province_kill_request_wage) + + company_province_kill_request_wage = ( + total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guilds_difference_requests_price + other_difference_requests_price) + return_company_province_kill_request_wage = ( + total_return_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guild_return_province_kill_request_wage + other_return_province_kill_request_wage) + company_free_buying_live_wage = (( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * company_free_buying_live_percent) + before_total_out_live_buying_province_carcasses_price + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + return_company_province_kill_request_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_wage = (total_pure_province_carcasses_price * guilds_province_kill_request_percent) - ( + guilds_difference_requests_price + guild_return_province_kill_request_wage) + guilds_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_wage = (total_pure_province_carcasses_price * other_province_kill_request_percent) - ( + other_difference_requests_price + other_return_province_kill_request_wage) + other_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + return [ + { + "name": "اتحادیه", + "province_kill_request_wage": union_province_kill_request_wage, + "free_buying_live_wage": union_free_buying_live_wage, + "free_buying_carcasses_wage": union_free_buying_carcasses_wage, + "free_sell_carcasses_wage": union_free_sell_carcasses_wage, + "total_wage": union_total_wage, + "total_paid_wage": union_total_paid_wage, + "total_unpaid_wage": union_total_unpaid_wage, + "total_unpaid": total_price - total_paid_wage, + }, + { + "name": "شرکت", + "province_kill_request_wage": company_province_kill_request_wage, + "free_buying_live_wage": company_free_buying_live_wage, + "free_buying_carcasses_wage": company_free_buying_carcasses_wage, + "free_sell_carcasses_wage": company_free_sell_carcasses_wage, + "total_wage": company_total_wage, + "total_paid_wage": company_total_paid_wage, + "total_unpaid_wage": company_total_unpaid_wage, + "total_unpaid": total_price - total_paid_wage, + + }, + { + "name": "صنف پروتئین", + "province_kill_request_wage": guilds_province_kill_request_wage, + "free_buying_live_wage": guilds_free_buying_live_wage, + "free_buying_carcasses_wage": guilds_free_buying_carcasses_wage, + "free_sell_carcasses_wage": guilds_free_sell_carcasses_wage, + "total_wage": guilds_total_wage, + "total_paid_wage": guilds_total_paid_wage, + "total_unpaid_wage": guilds_total_unpaid_wage, + "total_unpaid": total_price - total_paid_wage, + + }, + { + "name": "دامپزشک", + "province_kill_request_wage": other_province_kill_request_wage, + "free_buying_live_wage": other_free_buying_live_wage, + "free_buying_carcasses_wage": other_free_buying_carcasses_wage, + "free_sell_carcasses_wage": other_free_sell_carcasses_wage, + "total_wage": other_total_wage, + "total_paid_wage": other_total_paid_wage, + "total_unpaid_wage": other_total_unpaid_wage, + "total_unpaid": total_price - total_paid_wage, + + }] + + +def get_kill_house_percent(kill_house): + shares = get_calculate_shares(kill_house) + union = shares[0]['total_unpaid_wage'] if shares[0]['total_unpaid_wage'] > 0 else 0 + company = shares[1]['total_unpaid_wage'] if shares[1]['total_unpaid_wage'] > 0 else 0 + guilds = shares[2]['total_unpaid_wage'] if shares[2]['total_unpaid_wage'] > 0 else 0 + vet = shares[3]['total_unpaid_wage'] if shares[3]['total_unpaid_wage'] > 0 else 0 + + # if union >= company: + # return None + # else: + total = union + company + guilds + vet + if total == 0 : + return { + "union": union, + "company": company, + "guilds": guilds, + "vet": vet, + "total_percent": total, + } + union = int((union / total) * 100) + company = int((company / total) * 100) + guilds = int((guilds / total) * 100) + vet = int((vet / total) * 100) + total_percent = union + company + guilds + vet + + if total_percent < 100: + if base_url_for_sms_report == 'ma': + if union >= company: + union += 100 - total_percent + else: + company += 100 - total_percent + + else: + company += 100 - total_percent + + return { + "union": union, + "company": company, + "guilds": guilds, + "vet": vet, + "total_percent": total_percent, + } + + +def create_kill_house_free_bar(request): + kill = KillHouse.objects.filter(trash=False, unique_identifier__isnull=False).order_by('id').values_list( + 'unique_identifier', flat=True) + kill_house_list = { + "kill_house": list(kill) + } + bars = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) + for bar in bars.json(): + kill_house = KillHouse.objects.filter(trash=False, unique_identifier=bar['jihadi_destination']).first() + if kill_house: + if not KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar['tracking']): + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + date = bar['date'] + + kill_house_free_bar_info = KillHouseFreeBarInformation( + kill_house=kill_house, + product=product, + ) + kill_house_free_bar_info.driver_name = 'سیستمی' + kill_house_free_bar_info.input_warehouse = kill_house + kill_house_free_bar_info.driver_mobile = '0' + kill_house_free_bar_info.poultry_name = bar['hatching']['poultry']['UnitName'] + kill_house_free_bar_info.poultry_mobile = bar['hatching']['poultry']['Mobile'] + kill_house_free_bar_info.province = bar['hatching']['poultry']['Province'] + kill_house_free_bar_info.city = bar['hatching']['poultry']['City'] + kill_house_free_bar_info.bar_clearance_code = bar['tracking'] + kill_house_free_bar_info.bar_clearance_code = bar['tracking'] + kill_house_free_bar_info.quantity = bar['quantity'] + kill_house_free_bar_info.live_weight = int(int(bar['quantity']) * 2.5) + kill_house_free_bar_info.buy_type = 'live' + kill_house_free_bar_info.car = '0' + kill_house_free_bar_info.register_type = 'automatic' + + kill_house_free_bar_info.date = datetime.datetime.now() + + kill_house_free_bar_info.bar_code = generate_unique_bar_code() + kill_house_free_bar_info.save() + wage = 0 + type = 'live-buy' if kill_house_free_bar_info.buy_type == 'live' else 'carcasse-buy' + wage_type = WageType.objects.filter(en_name=type, trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + kill_house_free_bar_info.wage = wage + kill_house_free_bar_info.total_wage_amount = wage * int( + kill_house_free_bar_info.live_weight) if kill_house_free_bar_info.buy_type == 'live' else wage * int( + kill_house_free_bar_info.weight_of_carcasses) + kill_house_free_bar_info.save() + kill_house_free_bar_info.create_date = date + kill_house_free_bar_info.register_date = datetime.datetime.now() + kill_house_free_bar_info.save() + kill_house_free_buying_product_warehousing(product) + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + kill_house_free_bar_info.union_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.union_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'company': + kill_house_free_bar_info.company_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.company_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + kill_house_free_bar_info.guilds_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.guilds_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'city': + kill_house_free_bar_info.city_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.city_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + kill_house_free_bar_info.wallet_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.wallet_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + else: + kill_house_free_bar_info.other_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.other_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + return HttpResponse('ok') + + +def create_kill_house_free_bar_cron(): + kill = KillHouse.objects.filter(trash=False, unique_identifier__isnull=False).order_by('id').values_list( + 'unique_identifier', flat=True) + kill_house_list = { + "kill_house": list(kill) + } + bars = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) + for bar in bars.json(): + kill_house = KillHouse.objects.filter(trash=False, unique_identifier=bar['DesPartIdCode']).first() + if kill_house: + if not KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar['TrackingCode']): + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + formatted_str = str(bar['Date']).replace('T', ' ').replace('Z', '') + + date = datetime.datetime.strptime(formatted_str, '%Y-%m-%d %H:%M:%S').date() + date = datetime.datetime(year=date.year, month=date.month, day=date.day, hour=10, + minute=1, + second=1) + + kill_house_free_bar_info = KillHouseFreeBarInformation( + kill_house=kill_house, + product=product, + ) + kill_house_free_bar_info.driver_name = 'سیستمی' + kill_house_free_bar_info.driver_mobile = '0' + kill_house_free_bar_info.input_warehouse = kill_house + kill_house_free_bar_info.poultry_name = bar['hatching']['poultry']['UnitName'] + kill_house_free_bar_info.poultry_mobile = bar['hatching']['poultry']['Mobile'] + kill_house_free_bar_info.province = bar['hatching']['poultry']['Province'] + kill_house_free_bar_info.city = bar['hatching']['poultry']['City'] + kill_house_free_bar_info.bar_clearance_code = bar['TrackingCode'] + kill_house_free_bar_info.bar_clearance_code = bar['TrackingCode'] + kill_house_free_bar_info.quantity = bar['GoodAmount'] + kill_house_free_bar_info.live_weight = int(int(bar['GoodAmount']) * 2.5) + kill_house_free_bar_info.buy_type = 'live' + kill_house_free_bar_info.car = '0' + kill_house_free_bar_info.register_type = 'automatic' + + kill_house_free_bar_info.date = datetime.datetime.now() + + kill_house_free_bar_info.bar_code = generate_unique_bar_code() + kill_house_free_bar_info.save() + wage = 0 + type = 'live-buy' if kill_house_free_bar_info.buy_type == 'live' else 'carcasse-buy' + wage_type = WageType.objects.filter(en_name=type, trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + kill_house_free_bar_info.wage = wage + kill_house_free_bar_info.total_wage_amount = wage * int( + kill_house_free_bar_info.live_weight) if kill_house_free_bar_info.buy_type == 'live' else wage * int( + kill_house_free_bar_info.weight_of_carcasses) + kill_house_free_bar_info.save() + kill_house_free_bar_info.create_date = date + kill_house_free_bar_info.register_date = datetime.datetime.now() + kill_house_free_bar_info.save() + kill_house_free_buying_product_warehousing(product) + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + kill_house_free_bar_info.union_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.union_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'company': + kill_house_free_bar_info.company_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.company_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + kill_house_free_bar_info.guilds_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.guilds_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'city': + kill_house_free_bar_info.city_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.city_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + kill_house_free_bar_info.wallet_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.wallet_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + else: + kill_house_free_bar_info.other_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.other_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + +def create_kill_house_free_barss(request): + kill = KillHouse.objects.filter(trash=False, unique_identifier__isnull=False).order_by('id').values_list( + 'unique_identifier', flat=True) + kill_house_list = { + "kill_house": list(kill) + } + bars = requests.post('https://rsibackend.rasadyar.com/app/get_bar_info/', data=kill_house_list) + for bar in bars.json(): + kill_house = KillHouse.objects.filter(trash=False, unique_identifier=bar['DesPartIdCode']).first() + if kill_house: + mm = KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=bar['TrackingCode']).first() + if mm: + mm.province = bar['hatching']['poultry']['Province'] + mm.city = bar['hatching']['poultry']['City'] + + mm.save() + + return HttpResponse('ok') + + +def market_poultry_request_remain_quantity(poultry_request): + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_kill_reqs = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request=poultry_request, + market=False, + return_to_province=False, + state__in=('pending', 'accepted'), + temporary_trash=False).only('total_killed_quantity') \ + .aggregate(total=Sum('total_killed_quantity')) + kill_requests = KillRequest.objects.filter(trash=False, market=True, market_state__in=('pending', 'accepted'), + poultry_request=poultry_request).only('kill_capacity') \ + .aggregate(total=Sum('kill_capacity')) + new_remain = poultry_request.quantity - ((kill_requests['total'] or 0) + (province_kill_reqs['total'] or 0)) + new_quantity = poultry_request.quantity - ((kill_requests['total'] or 0) + (province_kill_reqs['total'] or 0)) + poultry_request.remain_quantity = new_remain if new_remain > 0 else 0 + poultry_request.save() + province_check.quantity = new_quantity if new_quantity > 0 else 0 + province_check.save() + + +# def market_calculate_light_weight(kill_house, total_poultry_requests_quantity, +# total_poultry_requests_quantity_light_weight): +# real_total_light_weight_quantity = 0 +# kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( +# 'kill_house', flat=True) +# kill_houses = KillHouse.objects.filter(out_province=False, market_buying=True, market_light_capacity=True, +# trash=False).exclude( +# id__in=kill_house_ids).order_by('id', 'killer') +# for kill_house_obj in kill_houses: +# kill_house_share = int((kill_house_obj.market_capacity_percent / 100) * total_poultry_requests_quantity) +# kill_house_light_weight_quantity = int(kill_house_share * (kill_house_obj.market_light_capacity_percent / 100)) +# real_total_light_weight_quantity += kill_house_light_weight_quantity +# kill_house_share = 0 +# kill_house_light_weight_quantity = 0 +# +# kill_house_share = int((kill_house.market_capacity_percent / 100) * total_poultry_requests_quantity) +# +# kill_house_light_weight_quantity = int(kill_house_share * (kill_house.market_light_capacity_percent / 100)) +# +# kill_house_real_percent = int(( +# kill_house_light_weight_quantity / real_total_light_weight_quantity) * 100) if real_total_light_weight_quantity > 0 else 0 +# +# kill_house_real_light_weight = int((kill_house_real_percent / 100) * total_poultry_requests_quantity_light_weight) +# +# return kill_house_real_light_weight +# +# +# def market_kill_request_share_quantity(kill_house, date1=None, date2=None): +# if kill_house.market_buying: +# now = datetime.datetime.now().date() +# market_light_capacity = kill_house.market_light_capacity +# market_light_capacity_percent = kill_house.market_light_capacity_percent +# market_light_share = 0 +# +# index_weight_category = IndexWeightCategory.objects.filter(trash=False).order_by('id') +# light = index_weight_category.filter(name='سبک').first() +# heavy = index_weight_category.filter(name='سنگین').first() +# +# if date1: +# poultry_requests = PoultryRequest.objects.filter( +# send_date__date__gte=date1, +# send_date__date__lte=date2, +# state_process='accepted', +# province_state='accepted', +# temporary_trash=False, +# trash=False, +# out=False, +# final_state__in=('pending', 'accepted'), +# market=True, +# ) +# +# kill_house_market_kill_requests = KillRequest.objects.filter(trash=False, recive_date__date__gte=date1, +# recive_date__date__lte=date2, +# kill_house=kill_house, market=True, +# market_state__in=('pending', 'accepted')) +# else: +# poultry_requests = PoultryRequest.objects.filter( +# send_date__date=now, +# state_process='accepted', +# province_state='accepted', +# temporary_trash=False, +# trash=False, +# out=False, +# final_state__in=('pending', 'accepted'), +# market=True, +# ) +# +# kill_house_market_kill_requests = KillRequest.objects.filter(trash=False, recive_date__date=now, +# kill_house=kill_house, market=True, +# market_state__in=('pending', 'accepted')) +# +# total_poultry_requests_quantity = poultry_requests.aggregate(total=Sum('quantity'))['total'] or 0 +# +# total_poultry_requests_quantity_light_weight = \ +# poultry_requests.filter(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value).aggregate( +# total=Sum('quantity'))['total'] or 0 +# total_remain_poultry_requests_quantity_light_weight = \ +# poultry_requests.filter(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value).aggregate( +# total=Sum('remain_quantity'))['total'] or 0 +# +# light_real_quantity = market_calculate_light_weight(kill_house, total_poultry_requests_quantity, +# total_poultry_requests_quantity_light_weight) +# +# if kill_house.market_buying_limitation: +# if kill_house.market_buying_capacity_percent_status: +# kill_house_today_share = int( +# (kill_house.market_capacity_percent / 100) * total_poultry_requests_quantity) +# +# else: +# kill_house_today_share = int( +# kill_house.total_kill_capacity * (kill_house.total_kill_capacity_percent / 100)) +# +# +# +# else: +# kill_house_today_share = total_poultry_requests_quantity +# +# kill_house_market_kill_requests_quantity = \ +# kill_house_market_kill_requests.aggregate(total=Sum('kill_capacity'))[ +# 'total'] or 0 +# kill_house_market_kill_requests_quantity_weight = \ +# kill_house_market_kill_requests.aggregate(total=Sum(F('kill_capacity') * F('Index_weight')))[ +# 'total'] or 0 +# kill_house_market_kill_requests_quantity_first = \ +# kill_house_market_kill_requests.filter(market_final_accept=False).aggregate(total=Sum('kill_capacity'))[ +# 'total'] or 0 +# +# kill_house_market_kill_requests_quantity_first_weight = \ +# kill_house_market_kill_requests.filter(market_final_accept=False).aggregate( +# total=Sum(F('kill_capacity') * F('Index_weight')))[ +# 'total'] or 0 +# kill_house_market_kill_requests_quantity_final = \ +# kill_house_market_kill_requests.filter(market_final_accept=True).aggregate(total=Sum('kill_capacity'))[ +# 'total'] or 0 +# kill_house_market_kill_requests_quantity_final_weight = \ +# kill_house_market_kill_requests.filter(market_final_accept=True).aggregate( +# total=Sum(F('kill_capacity') * F('Index_weight')))[ +# 'total'] or 0 +# +# total_kill_house_market_kill_requests_quantity_agreement_light_weight = \ +# kill_house_market_kill_requests.filter(Index_weight__lt=light.min_value).aggregate( +# total=Sum('kill_capacity'))[ +# 'total'] or 0 +# +# total_kill_house_market_kill_requests_quantity_light_weight = \ +# kill_house_market_kill_requests.filter(Index_weight__gte=light.min_value, +# Index_weight__lt=light.max_value).aggregate( +# total=Sum('kill_capacity'))[ +# 'total'] or 0 +# +# total_kill_house_market_kill_requests_quantity_heavy_weight = \ +# kill_house_market_kill_requests.filter(Index_weight__gte=heavy.min_value, +# Index_weight__lte=heavy.max_value).aggregate( +# total=Sum('kill_capacity'))[ +# 'total'] or 0 +# +# if market_code_state: +# kill_house_market_kill_requests_quantity_light_weight = \ +# kill_house_market_kill_requests.filter(market_final_accept=True, market_code_status=True, +# input_market_code__isnull=False, +# Index_weight__lt=light.max_value).aggregate( +# total=Sum('kill_capacity'))[ +# 'total'] or 0 +# else: +# kill_house_market_kill_requests_quantity_light_weight = \ +# kill_house_market_kill_requests.filter(market_final_accept=True, +# Index_weight__lt=light.max_value).aggregate( +# total=Sum('kill_capacity'))[ +# 'total'] or 0 +# +# if market_light_capacity: +# # market_light_share = int(kill_house_today_share * (market_light_capacity_percent / 100)) +# market_light_share = light_real_quantity +# +# kill_house_today_left_share = kill_house_today_share - kill_house_market_kill_requests_quantity if ( +# kill_house_today_share - kill_house_market_kill_requests_quantity) > 0 else 0 +# +# else: +# total_poultry_requests_quantity = 0 +# total_poultry_requests_quantity_light_weight = 0 +# total_remain_poultry_requests_quantity_light_weight = 0 +# kill_house_today_share = 0 +# market_light_share = 0 +# kill_house_market_kill_requests_quantity_light_weight = 0 +# kill_house_market_kill_requests_quantity = 0 +# kill_house_today_left_share = 0 +# kill_house_market_kill_requests_quantity_first = 0 +# kill_house_market_kill_requests_quantity_final = 0 +# light_real_quantity = 0 +# kill_house_market_kill_requests_quantity_weight = 0 +# kill_house_market_kill_requests_quantity_first_weight = 0 +# kill_house_market_kill_requests_quantity_final_weight = 0 +# total_kill_house_market_kill_requests_quantity_agreement_light_weight = 0 +# total_kill_house_market_kill_requests_quantity_light_weight = 0 +# total_kill_house_market_kill_requests_quantity_heavy_weight = 0 +# +# result = { +# "total_poultry_requests_quantity": total_poultry_requests_quantity, +# "total_poultry_requests_quantity_light_weight": total_poultry_requests_quantity_light_weight, +# "total_remain_poultry_requests_quantity_light_weight": total_remain_poultry_requests_quantity_light_weight, +# "kill_house_today_share": kill_house_today_share, +# "market_light_share": market_light_share, +# "kill_house_market_kill_requests_quantity_light_weight": kill_house_market_kill_requests_quantity_light_weight, +# "kill_house_market_kill_requests_quantity": kill_house_market_kill_requests_quantity, +# "kill_house_market_kill_requests_quantity_first": kill_house_market_kill_requests_quantity_first, +# "kill_house_market_kill_requests_quantity_final": kill_house_market_kill_requests_quantity_final, +# "kill_house_today_left_share": kill_house_today_left_share, +# "light_real_quantity": light_real_quantity, +# "kill_house_market_kill_requests_quantity_weight": kill_house_market_kill_requests_quantity_weight, +# "kill_house_market_kill_requests_quantity_first_weight": kill_house_market_kill_requests_quantity_first_weight, +# "kill_house_market_kill_requests_quantity_final_weight": kill_house_market_kill_requests_quantity_final_weight, +# "total_kill_house_market_kill_requests_quantity_agreement_light_weight": total_kill_house_market_kill_requests_quantity_agreement_light_weight, +# "total_kill_house_market_kill_requests_quantity_light_weight": total_kill_house_market_kill_requests_quantity_light_weight, +# "total_kill_house_market_kill_requests_quantity_heavy_weight": total_kill_house_market_kill_requests_quantity_heavy_weight, +# } +# +# return result + + +def market_calculate_light_weight(kill_house, total_kill_houses, total_poultry_requests_quantity, + total_poultry_requests_quantity_light_weight): + shares = total_kill_houses.annotate( + kill_share=F('market_capacity_percent') * total_poultry_requests_quantity / 100.0, + light_share=F('market_capacity_percent') * total_poultry_requests_quantity / 100.0 * F( + 'market_light_capacity_percent') / 100.0 + ).values_list('id', 'light_share') + + real_total_light_weight_quantity = sum([ls[1] for ls in shares]) + + kill_house_light_share = next((ls[1] for ls in shares if ls[0] == kill_house.id), 0) + + kill_house_real_percent = int(( + kill_house_light_share / real_total_light_weight_quantity) * 100) if real_total_light_weight_quantity > 0 else 0 + + kill_house_real_light_weight = int((kill_house_real_percent / 100) * total_poultry_requests_quantity_light_weight) + + return kill_house_real_light_weight + + +# def market_kill_request_share_quantity(kill_house, date1=None, date2=None, total_kill_houses=None): +# result = { +# "total_poultry_requests_quantity": 0, +# "total_poultry_requests_quantity_light_weight": 0, +# "total_remain_poultry_requests_quantity_light_weight": 0, +# "kill_house_today_share": 0, +# "market_light_share": 0, +# "kill_house_market_kill_requests_quantity_light_weight": 0, +# "kill_house_market_kill_requests_quantity": 0, +# "kill_house_market_kill_requests_quantity_first": 0, +# "kill_house_market_kill_requests_quantity_final": 0, +# "kill_house_today_left_share": 0, +# "light_real_quantity": 0, +# "kill_house_market_kill_requests_quantity_weight": 0, +# "kill_house_market_kill_requests_quantity_first_weight": 0, +# "kill_house_market_kill_requests_quantity_final_weight": 0, +# "total_kill_house_market_kill_requests_quantity_agreement_light_weight": 0, +# "total_kill_house_market_kill_requests_quantity_light_weight": 0, +# "total_kill_house_market_kill_requests_quantity_heavy_weight": 0, +# } +# +# if not kill_house.market_buying: +# return result +# +# now = datetime.datetime.now().date() +# date_filter = Q(send_date__date=now) +# kill_request_date_filter = Q(recive_date__date=now) +# +# if date1: +# date_filter = Q(send_date__date__gte=date1, send_date__date__lte=date2) +# kill_request_date_filter = Q(recive_date__date__gte=date1, recive_date__date__lte=date2) +# +# weights = IndexWeightCategory.objects.filter(trash=False) +# light = weights.filter(name='سبک').first() +# heavy = weights.filter(name='سنگین').first() +# +# poultry_requests = PoultryRequest.objects.filter( +# date_filter, +# state_process='accepted', +# province_state='accepted', +# temporary_trash=False, +# trash=False, +# out=False, +# final_state__in=('pending', 'accepted'), +# market=True, +# ) +# +# total_poultry_requests_quantity = poultry_requests.aggregate(total=Sum('quantity'))['total'] or 0 +# total_light_quantity = poultry_requests.filter( +# Index_weight__gte=light.min_value, +# Index_weight__lt=light.max_value +# ).aggregate(total=Sum('quantity'))['total'] or 0 +# total_remain_light_quantity = poultry_requests.filter( +# Index_weight__gte=light.min_value, +# Index_weight__lt=light.max_value +# ).aggregate(total=Sum('remain_quantity'))['total'] or 0 +# +# kill_requests = KillRequest.objects.filter( +# kill_request_date_filter, +# trash=False, +# kill_house=kill_house, +# market=True, +# market_state__in=('pending', 'accepted') +# ) +# +# kill_house_today_share = total_poultry_requests_quantity +# if kill_house.market_buying_limitation: +# if kill_house.market_buying_capacity_percent_status: +# kill_house_today_share = int(kill_house.market_capacity_percent / 100 * total_poultry_requests_quantity) +# else: +# kill_house_today_share = int(kill_house.total_kill_capacity * kill_house.total_kill_capacity_percent / 100) +# +# agg = kill_requests.aggregate( +# total_kill_capacity=Sum('kill_capacity') or 0, +# total_weight=Sum(F('kill_capacity') * F('Index_weight')) or 0, +# total_first=Sum('kill_capacity', filter=Q(market_final_accept=False)) or 0, +# total_first_weight=Sum(F('kill_capacity') * F('Index_weight'), filter=Q(market_final_accept=False)) or 0, +# total_final=Sum('kill_capacity', filter=Q(market_final_accept=True)) or 0, +# total_final_weight=Sum(F('kill_capacity') * F('Index_weight'), filter=Q(market_final_accept=True)) or 0, +# total_agreement_light=Sum('kill_capacity', filter=Q(Index_weight__lt=light.min_value)) or 0, +# total_light=Sum('kill_capacity', +# filter=Q(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value)) or 0, +# total_heavy=Sum('kill_capacity', +# filter=Q(Index_weight__gte=heavy.min_value, Index_weight__lte=heavy.max_value)) or 0, +# ) +# +# light_real_quantity = market_calculate_light_weight(kill_house, total_kill_houses, total_poultry_requests_quantity, +# total_light_quantity) +# market_light_share = light_real_quantity if kill_house.market_light_capacity else 0 +# kill_house_today_left_share = max(0, kill_house_today_share - (agg['total_kill_capacity'] or 0)) +# +# result.update({ +# "total_poultry_requests_quantity": total_poultry_requests_quantity or 0, +# "total_poultry_requests_quantity_light_weight": total_light_quantity or 0, +# "total_remain_poultry_requests_quantity_light_weight": total_remain_light_quantity or 0, +# "kill_house_today_share": kill_house_today_share or 0, +# "market_light_share": market_light_share or 0, +# "kill_house_market_kill_requests_quantity_light_weight": agg['total_light'] or 0, +# "kill_house_market_kill_requests_quantity": agg['total_kill_capacity'] or 0, +# "kill_house_market_kill_requests_quantity_first": agg['total_first'] or 0, +# "kill_house_market_kill_requests_quantity_final": agg['total_final'] or 0, +# "kill_house_today_left_share": kill_house_today_left_share or 0, +# "light_real_quantity": light_real_quantity or 0, +# "kill_house_market_kill_requests_quantity_weight": agg['total_weight'] or 0, +# "kill_house_market_kill_requests_quantity_first_weight": agg['total_first_weight'] or 0, +# "kill_house_market_kill_requests_quantity_final_weight": agg['total_final_weight'] or 0, +# "total_kill_house_market_kill_requests_quantity_agreement_light_weight": agg['total_agreement_light'] or 0, +# "total_kill_house_market_kill_requests_quantity_light_weight": agg['total_light'] or 0, +# "total_kill_house_market_kill_requests_quantity_heavy_weight": agg['total_heavy'] or 0, +# }) +# +# return result + + +def market_kill_request_share_quantity( + kill_house, + date1=None, + date2=None, + total_kill_houses=None, + weights=None, + precomputed_poultry=None +): + result = { + "total_poultry_requests_quantity": 0, + "total_poultry_requests_quantity_light_weight": 0, + "total_remain_poultry_requests_quantity_light_weight": 0, + "kill_house_today_share": 0, + "market_light_share": 0, + "kill_house_market_kill_requests_quantity_light_weight": 0, + "kill_house_market_kill_requests_quantity": 0, + "kill_house_market_kill_requests_quantity_first": 0, + "kill_house_market_kill_requests_quantity_final": 0, + "kill_house_today_left_share": 0, + "light_real_quantity": 0, + "kill_house_market_kill_requests_quantity_weight": 0, + "kill_house_market_kill_requests_quantity_first_weight": 0, + "kill_house_market_kill_requests_quantity_final_weight": 0, + "total_kill_house_market_kill_requests_quantity_agreement_light_weight": 0, + "total_kill_house_market_kill_requests_quantity_light_weight": 0, + "total_kill_house_market_kill_requests_quantity_heavy_weight": 0, + } + + if not kill_house.market_buying: + return result + + now = datetime.date.today() + date_filter = Q(send_date__date=now) + kill_request_date_filter = Q(recive_date__date=now) + + if date1: + date_filter = Q(send_date__date__gte=date1, send_date__date__lte=date2) + kill_request_date_filter = Q(recive_date__date__gte=date1, recive_date__date__lte=date2) + + if weights is None: + weights = IndexWeightCategory.objects.filter(trash=False) + light = weights.filter(name='سبک').first() + heavy = weights.filter(name='سنگین').first() + + poultry_requests = PoultryRequest.objects.filter( + date_filter, + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state__in=('pending', 'accepted'), + market=True, + ) + + poultry_agg = poultry_requests.aggregate( + total=Sum('quantity'), + total_light=Sum('quantity', filter=Q(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value)), + total_remain_light=Sum('remain_quantity', + filter=Q(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value)), + ) + + total_poultry_requests_quantity = poultry_agg['total'] or 0 + total_light_quantity = poultry_agg['total_light'] or 0 + total_remain_light_quantity = poultry_agg['total_remain_light'] or 0 + + kill_requests = KillRequest.objects.filter( + kill_request_date_filter, + trash=False, + kill_house=kill_house, + market=True, + market_state__in=('pending', 'accepted') + ) + + agg = kill_requests.aggregate( + total_kill_capacity=Sum('kill_capacity'), + total_weight=Sum(F('kill_capacity') * F('Index_weight')), + total_first=Sum('kill_capacity', filter=Q(market_final_accept=False)), + total_first_weight=Sum(F('kill_capacity') * F('Index_weight'), filter=Q(market_final_accept=False)), + total_final=Sum('kill_capacity', filter=Q(market_final_accept=True)), + total_final_weight=Sum(F('kill_capacity') * F('Index_weight'), filter=Q(market_final_accept=True)), + total_agreement_light=Sum('kill_capacity', filter=Q(Index_weight__lt=light.min_value)), + total_light=Sum('kill_capacity', filter=Q(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value)), + total_heavy=Sum('kill_capacity', + filter=Q(Index_weight__gte=heavy.min_value, Index_weight__lte=heavy.max_value)), + ) + + kill_house_today_share = total_poultry_requests_quantity + if kill_house.market_buying_limitation: + if kill_house.market_buying_capacity_percent_status: + kill_house_today_share = int(kill_house.market_capacity_percent / 100 * total_poultry_requests_quantity) + else: + kill_house_today_share = int(kill_house.total_kill_capacity * kill_house.total_kill_capacity_percent / 100) + + light_real_quantity = market_calculate_light_weight( + kill_house, total_kill_houses, total_poultry_requests_quantity, total_light_quantity + ) + market_light_share = light_real_quantity if kill_house.market_light_capacity else 0 + kill_house_today_left_share = max(0, kill_house_today_share - (agg['total_kill_capacity'] or 0)) + + result.update({ + "total_poultry_requests_quantity": total_poultry_requests_quantity, + "total_poultry_requests_quantity_light_weight": total_light_quantity, + "total_remain_poultry_requests_quantity_light_weight": total_remain_light_quantity, + "kill_house_today_share": kill_house_today_share, + "market_light_share": market_light_share, + "kill_house_market_kill_requests_quantity_light_weight": agg['total_light'] or 0, + "kill_house_market_kill_requests_quantity": agg['total_kill_capacity'] or 0, + "kill_house_market_kill_requests_quantity_first": agg['total_first'] or 0, + "kill_house_market_kill_requests_quantity_final": agg['total_final'] or 0, + "kill_house_today_left_share": kill_house_today_left_share, + "light_real_quantity": light_real_quantity, + "kill_house_market_kill_requests_quantity_weight": agg['total_weight'] or 0, + "kill_house_market_kill_requests_quantity_first_weight": agg['total_first_weight'] or 0, + "kill_house_market_kill_requests_quantity_final_weight": agg['total_final_weight'] or 0, + "total_kill_house_market_kill_requests_quantity_agreement_light_weight": agg['total_agreement_light'] or 0, + "total_kill_house_market_kill_requests_quantity_light_weight": agg['total_light'] or 0, + "total_kill_house_market_kill_requests_quantity_heavy_weight": agg['total_heavy'] or 0, + }) + + return result + + +def calculate_governmental_quota(kill_house): + kill_house_governmental_share = 0 + if kill_house.quota: + now = datetime.datetime.now().date() + + if kill_house.quota_max_kill_limit: + kill_house_governmental_share = int((kill_house.governmental_quota / 100) * kill_house.total_kill_capacity) + elif kill_house.quota_request: + poultry_requests = PoultryRequest.objects.filter( + send_date__date=now, + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + free_sale_in_province=False, + final_state__in=('pending', 'accepted') + ) + poultry_requests_quantity = poultry_requests.aggregate(total=Sum('remain_quantity'))['total'] or 0 + kill_house_governmental_share = int((kill_house.governmental_quota / 100) * poultry_requests_quantity) + + else: + if kill_house.quota_custom: + kill_house_governmental_share = kill_house.quota_custom_quantity + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, temporary_trash=False, + killhouse_user=kill_house, + return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=now) + kill_house_market_kill_requests = KillRequest.objects.filter(trash=False, recive_date__date=now, + kill_house=kill_house, market=True, + market_state__in=('pending', 'accepted')) + + province_kill_requests_governmental_quantity = \ + province_kill_requests.filter(province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('total_killed_quantity'))['total'] or 0 + kill_house_market_kill_requests_governmental_quantity = \ + kill_house_market_kill_requests.filter(poultry_request__free_sale_in_province=False).aggregate( + total=Sum('kill_capacity'))['total'] or 0 + total_governmental_quantity = province_kill_requests_governmental_quantity + kill_house_market_kill_requests_governmental_quantity + + if total_governmental_quantity < kill_house_governmental_share: + return 'not_allowed' + + return None + + +# def check_kill_house_remain_limitation_weight(kill_house): +# yesterday = datetime.datetime.now() - datetime.timedelta(days=1) +# today = datetime.datetime.now().date() +# kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, +# province_request__poultry_request__free_sale_in_province=False, +# kill_request__recive_date__date=yesterday.date(), +# ware_house_confirmation=True, trash=False, +# calculate_status=True, warehouse=True) +# +# kill_house_allocations = StewardAllocation.objects.filter( +# kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, system_registration_code=True, +# receiver_state__in=('pending', 'accepted'), date__date=today, quota='governmental') +# +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, +# quota='governmental', +# date__date=today, trash=False, +# calculate_status=True, warehouse=True) +# segmentations = PosSegmentation.objects.filter(kill_house=kill_house, date__date=today, trash=False, warehouse=True, +# quota='governmental') +# +# kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ +# 'total'] or 0 +# kill_house_allocations_weight = \ +# kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 +# kill_house_free_sale_bars_weight = kill_house_free_sale_bars.aggregate(total=Sum('real_weight_of_carcasses'))[ +# 'total'] or 0 +# +# segmentation_weight = \ +# segmentations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# +# total_input = kill_house_requests_weight +# total_output = kill_house_allocations_weight + kill_house_free_sale_bars_weight + segmentation_weight +# total_remain = total_input - total_output +# +# if total_remain <= 0: +# return True +# else: +# if kill_house.ware_house_remaining_percent_limitation_status: +# if (total_input * (kill_house.ware_house_remaining_percent_limitation / 100)) > total_remain: +# return True +# else: +# return False +# else: +# return True +def check_kill_house_remain_limitation_weight(kill_house): + production_date = (datetime.datetime.now() - datetime.timedelta(days=3)).date() + kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, + province_request__poultry_request__free_sale_in_province=False, + kill_request__recive_date__date=production_date, + ware_house_confirmation=True, trash=False, + calculate_status=True, warehouse=True) + + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, system_registration_code=True, + receiver_state__in=('pending', 'accepted'), production_date__date=production_date, quota='governmental') + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + quota='governmental', + production_date__date=production_date, trash=False, + calculate_status=True, warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, production_date__date=production_date, trash=False, warehouse=True, + quota='governmental') + + kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + kill_house_free_sale_bars_weight = kill_house_free_sale_bars.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentation_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + + archives = WarehouseArchive.objects.filter(kill_house=kill_house,date__date=production_date,quota='governmental', trash=False) + + archives_governmental_weight = \ + archives.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + total_input = kill_house_requests_weight + total_output = kill_house_allocations_weight + kill_house_free_sale_bars_weight + segmentation_weight + archives_governmental_weight + total_remain = total_input - total_output + + if total_remain <= 0: + return True + else: + if kill_house.ware_house_remaining_percent_limitation_status: + if (total_input * (kill_house.ware_house_remaining_percent_limitation / 100)) > total_remain: + return True + else: + return False + else: + return True diff --git a/panel/KillHouse/serializers.py b/panel/KillHouse/serializers.py new file mode 100644 index 0000000..7e1a79f --- /dev/null +++ b/panel/KillHouse/serializers.py @@ -0,0 +1,6036 @@ +import datetime +from datetime import timedelta +from django.db.models import Sum, Q, F, Count +from rest_framework import serializers + +# import panel.KillHouse.serializers +from authentication.models import SystemUserProfile +from authentication.serializer.serializer import SystemUserProfileSerializer, BankCardSerializer, \ + SystemUserProfileForAutoAllocationSerializer, SystemUserProfileForGuildSerializer, \ + SystemUserProfileForPoultryLocSerializer, SystemUserProfileForInspectionSerializer +from authentication.serializers import UserProfileSerializer, SystemAddressSerializer +from deposit_id import wage_counting_type, new_out_selling_count_wage, before_out_buying_count_wage_amount +from deposit_percent import wage_percent, carcases_sell +from panel.KillHouse.helpers import get_finance_info, get_kill_house_finance_info, get_difference_carcasses_weight, \ + get_difference_carcasses_weight_kill, market_kill_request_share_quantity +from panel.models import \ + KillHouse, \ + KillHouseRequest, \ + KillRequest, \ + KillHouseCheckRequest, KillHouseAssignmentInformation, PoultryAssignmentInformation, \ + ProvinceCheckOperatorRequest, KillHouseADDCAR, Vet, VetCheckRequest, ProvinceKillRequest, KillHouseRequestExchange, \ + KillHouseRequestExchangeReserve, KillHouseRequestExchangeAddCar, PoultryRequestExchangeAccept, KillHouseDriver, \ + KillHouseOperator, KillHouseRequestAction, KillHouseRequestActionWinner, DriverRequestCancel, KillHouseVet, \ + KillHouseComplaint, CheckKillHouseComplaint, CheckUnusualCasualties, KillHouseAssignmentImages, KillRequestFactor, \ + KillRequestFactorPayment, AutomaticKillRequest, VetFarm, KillHouseCreditors, KillHouseAllowVet, Poultry, \ + ProvinceAllowKillHouseRegisterCar, KillHousePercentage, KillHouseDailyQuota, KillHouseFactorToProvince, \ + KillHouseWareHouse, KillHouseFreeBarInformation, PoultryRequest, ShareOfAllocation, \ + ProvinceAllowKillHouseDirectBuying, Pricing, KillHousePurchaseRequest, StewardAllocation, ProvinceOperator, \ + CityOperatorCheckRequest, CityOperator, StewardWareHouse, Steward, PoultryHatching, KillHouseFreeSaleBarInformation, \ + PaymentGatewayPercentage, SlaughterHouseTransaction, InternalTransaction, BarDocumentStatus, \ + KillHouseStewardGuildRelation, OutProvinceCarcassesBuyer, TypeActivity, WageType, RolesProducts, ColdHouse, \ + BarDifferenceRequest, PercentageOfWageType, PoultryRequestQuarantineCode, DirectBuyingPayment, PosSegmentation, \ + ProductsTransactions, WarehouseArchive + +from panel.poultry.serializers import PoultryRequestExchangeSerializer, PoultryRequestSerializer, \ + PoultryRequestForBarMangementSerializer, PoultrySerializer, PoultryForBarManagementSerializer, \ + PoultryForPoultryRequestLetterSerializer, OutProvincePoultryRequestBuyerSerializer, PoultryHatchingSerializer, \ + PoultryHatchingForBarDifferenceRequestSerializer, PoultryForPredictionSerializer, PoultryRequestForMarketSerializer, \ + PoultryHatchingForLocSerializer + + +class BarDocumentStatusSerializer(serializers.ModelSerializer): + class Meta: + model = BarDocumentStatus + fields = ['id', 'key', 'title', 'sms', 'is_error', 'priority_id'] + + +class KillHouseOperatorForAutoAllocationsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user'] + + +class KillHouseOperatorForColdHouseSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user'] + + +# سریالایزر مربوط به اپراتور شهرستان +class KillHouseOperatorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = KillHouseOperator + fields = '__all__' + + +class KillHouseOperatorForKillHouseDriverSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user'] + + +class KillHouseOperatorForAllUserSerializer(serializers.ModelSerializer): + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = KillHouseOperator + fields = ['user_bank_info'] + + +class KillHouseForKillHouseDriverSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForKillHouseDriverSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'killer'] + + +class VetForKillHouseVetSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['user'] + + +class KillHouseVetForKillHouseSerializer(serializers.ModelSerializer): + vet = VetForKillHouseVetSerializer(read_only=True) + + class Meta: + model = KillHouseVet + fields = ['vet'] + + +class KillHouseForKillHouseVetKillHouseSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForKillHouseDriverSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'name'] + + +class KillHouseForAllUserSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAllUserSerializer(read_only=True) + system_address = SystemAddressSerializer(read_only=True) + killers = serializers.SerializerMethodField('get_killers') + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + + class Meta: + model = KillHouse + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + 'address', + 'car', + 'create_date', + 'modify_date', + 'killing_race', + 'phone', + 'shift_work_from', + 'shift_work_to', + 'user', + 'userprofile', + ) + + def get_killers(self, obj): + killers = KillHousePercentage.objects.filter(kill_house_for_killer__exact=obj) + return KillHousePercentageForKillerKillHousseSerializer(killers, many=True).data + + def get_kill_house_vet(self, obj): + kill_house_vet = KillHouseVet.objects.filter(kill_house__exact=obj, trash=False) + return KillHouseVetForKillHouseSerializer(kill_house_vet, many=True).data + + +class KillHouseForAutoAllocationSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'name', 'killer', 'key', 'maximum_load_volume_increase', + 'maximum_load_volume_reduction'] + + +class KillHouseForKillHouseGuildRelationSerializer(serializers.ModelSerializer): + # kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + allocation_limit = serializers.SerializerMethodField('get_allocation_limit') + + class Meta: + model = KillHouse + fields = ['name', 'city', 'fullname', 'mobile', 'killer', 'key', 'allocation_limit'] + + def get_allocation_limit(self, obj): + guild = self.context.get('guild') + if guild: + relation = KillHouseStewardGuildRelation.objects.filter(kill_house=obj, guild=guild).first() + if relation: + return { + "allocation_limit": relation.allocation_limit, + "allocation_type": relation.allocation_type + } + return None + + +class KillHouseForKillHouseStewardRelationSerializer(serializers.ModelSerializer): + # kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + allocation_limit = serializers.SerializerMethodField('get_allocation_limit') + + class Meta: + model = KillHouse + fields = ['name', 'city', 'fullname', 'mobile', 'killer', 'key', 'allocation_limit'] + + def get_allocation_limit(self, obj): + guild = self.context.get('guild') + if guild: + relation = KillHouseStewardGuildRelation.objects.filter(kill_house=obj, steward=guild).first() + if relation: + return { + "allocation_limit": relation.allocation_limit, + "allocation_type": relation.allocation_type + } + return None + + +class KillHouseForCommonlyUsedSerializer(serializers.ModelSerializer): + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + + class Meta: + model = KillHouse + fields = ['name', 'city', 'fullname', 'mobile', 'killer', 'key', 'market_capacity_percent', + 'market_light_capacity', 'market_light_capacity_percent', 'market_buying', 'market_buying_limitation', + 'total_kill_capacity', 'total_kill_capacity_percent', 'max_kill_limit', + 'market_buying_capacity_percent_status', + 'governmental_selling_permission', 'free_selling_permission', + 'in_province_governmental_selling_percent', + 'out_province_governmental_selling_percent', 'segmentation_governmental_percent', + 'in_province_free_selling_percent', 'out_province_free_selling_percent', + 'segmentation_free_selling_percent', + 'cold_house_governmental_percent', + 'cold_house_free_percent', + 'free_sale_form_governmental_quota', + 'out_province_free_buying_commitment_percent', + 'free_sale_from_free_quota_in_province', + ] + + +class KillHouseForReturnBuyingSerializer(serializers.ModelSerializer): + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + + class Meta: + model = KillHouse + fields = ['name', 'city', 'fullname', 'mobile', 'killer', 'key'] + + +class KillHouseForColdHouseAllocationSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + if date1: + + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False) + + else: + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False) + + self_allocations = cold_house_allocations.filter(kill_house=obj, to_cold_house__kill_house=obj) + other_allocations = cold_house_allocations.filter(kill_house=obj).exclude(to_cold_house__kill_house=obj) + + cold_house_allocations_weight = \ + cold_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + self_allocations_weight = \ + self_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + other_allocations_weight = \ + other_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + result = { + "total_allocations_count": cold_house_allocations.count(), + "total_allocations_weight": cold_house_allocations_weight, + "total_self_allocations_count": self_allocations.count(), + "total_self_allocations_weight": self_allocations_weight, + "total_other_allocations_count": other_allocations.count(), + "total_other_allocations_weight": other_allocations_weight, + + } + return result + + +class KillHouseForSegmentationSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + if date1: + + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False, date__date__gte=date1, + date__date__lte=date2) + + else: + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False) + + segmentations_aggregates = segmentations.aggregate( + total_count=Count('id'), + total_self_count=Count('id', filter=Q(to_guild__isnull=True)), + total_other_count=Count('id', filter=Q(to_guild__isnull=False)), + total_weight=Sum('weight'), + total_self_weight=Sum('weight', filter=Q(to_guild__isnull=True)), + total_other_weight=Sum('weight', filter=Q(to_guild__isnull=False)), + + ) + + result = { + "total_count": segmentations_aggregates['total_count'] or 0, + "total_weight": segmentations_aggregates['total_weight'] or 0, + "total_self_count": segmentations_aggregates['total_self_count'] or 0, + "total_self_weight": segmentations_aggregates['total_self_weight'] or 0, + "total_other_count": segmentations_aggregates['total_other_count'] or 0, + "total_other_weight": segmentations_aggregates['total_other_weight'] or 0 + + } + return result + + +# class TotalKillHouseRemainWeightViewSetSerializer(serializers.ModelSerializer): +# info = serializers.SerializerMethodField('get_info') +# +# class Meta: +# model = KillHouse +# fields = ['key', 'name', 'info'] +# +# def get_info(self, obj): +# product = RolesProducts.objects.filter(kill_house=obj, trash=False, name='مرغ گرم').first() +# archives = WarehouseArchive.objects.filter(kill_house=obj, trash=False,warehouse=True) +# today = datetime.datetime.now().date() +# yesterday = today - timedelta(days=1) +# two_days_ago = yesterday - timedelta(days=1) +# date_list=[two_days_ago,yesterday,two_days_ago] +# +# all_dates = set() +# +# all_dates.update( +# KillHouseRequest.objects.filter( +# input_warehouse=obj, +# ware_house_confirmation=True, trash=False, calculate_status=True, warehouse=True +# ).values_list('kill_request__recive_date__date', flat=True) +# ) +# +# all_dates.update( +# KillHouseFreeBarInformation.objects.filter( +# input_warehouse=obj, trash=False, calculate_status=True, warehouse=True +# ).exclude(entered_message='ورود به انبار مجازی') +# .values_list('date__date', flat=True) +# ) +# +# all_dates.update( +# StewardAllocation.objects.filter( +# kill_house=obj, trash=False, calculate_status=True, warehouse=True, +# receiver_state__in=('pending', 'accepted') +# ).values_list('production_date__date', flat=True) +# ) +# +# all_dates.update( +# KillHouseFreeSaleBarInformation.objects.filter( +# kill_house=obj, trash=False, calculate_status=True, warehouse=True +# ).values_list('production_date__date', flat=True) +# ) +# +# all_dates.update( +# PosSegmentation.objects.filter( +# kill_house=obj, trash=False, warehouse=True +# ).values_list('production_date__date', flat=True) +# ) +# +# all_dates.update( +# ProductsTransactions.objects.filter( +# product=product, transaction__paid=True, trash=False, warehouse=True +# ).values_list('transaction__date__date', flat=True) +# ) +# +# days = sorted([d for d in all_dates if d is not None]) +# +# if not days: +# return None +# +# kill_house_requests = KillHouseRequest.objects.filter( +# input_warehouse=obj, +# ware_house_confirmation=True, trash=False, calculate_status=True, warehouse=True +# ) +# +# kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( +# input_warehouse=obj, trash=False, calculate_status=True, warehouse=True +# ).exclude(entered_message='ورود به انبار مجازی') +# +# kill_house_allocations = StewardAllocation.objects.filter( +# kill_house=obj, trash=False, calculate_status=True, warehouse=True, +# receiver_state__in=('pending', 'accepted') +# ) +# +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( +# kill_house=obj, trash=False, calculate_status=True, warehouse=True +# ) +# +# segmentations = PosSegmentation.objects.filter( +# kill_house=obj, trash=False, warehouse=True +# ) +# +# transactions = ProductsTransactions.objects.filter( +# product=product, transaction__paid=True, trash=False, warehouse=True +# ) +# +# governmental_list = [] +# free_list = [] +# +# for day in days: +# kill_house_requests_info = kill_house_requests.aggregate( +# total_kill_house_request_governmental_weight=Sum( +# 'ware_house_accepted_real_weight', +# filter=Q( +# province_request__poultry_request__free_sale_in_province=False, +# kill_request__recive_date__date=day +# ) +# ), +# total_kill_house_request_free_weight=Sum( +# 'ware_house_accepted_real_weight', +# filter=Q( +# province_request__poultry_request__free_sale_in_province=True, +# kill_request__recive_date__date=day +# ) +# ), +# ) +# +# kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( +# total_kill_house_free_buying_bars_weight=Sum('weight_of_carcasses', filter=Q(date__date=day)) +# ) +# +# kill_house_allocations_info = kill_house_allocations.aggregate( +# total_kill_house_allocations_governmental_weight=Sum( +# 'real_weight_of_carcasses', filter=Q(quota='governmental', production_date__date=day) +# ), +# total_kill_house_allocations_free_weight=Sum( +# 'real_weight_of_carcasses', filter=Q(quota='free', production_date__date=day) +# ), +# ) +# +# kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( +# total_kill_house_free_sale_bars_governmental_weight=Sum( +# 'real_weight_of_carcasses', filter=Q(quota='governmental', production_date__date=day) +# ), +# total_kill_house_free_sale_bars_free_weight=Sum( +# 'real_weight_of_carcasses', filter=Q(quota='free', production_date__date=day) +# ), +# ) +# +# segmentations_info = segmentations.aggregate( +# segmentations_governmental_weight=Sum('weight', +# filter=Q(quota='governmental', production_date__date=day)), +# segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), +# ) +# +# pos_allocated_weight_info = transactions.aggregate( +# pos_governmental_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=True, transaction__date__date=day)), +# pos_free_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=False, transaction__date__date=day)), +# ) +# archives_info = archives.aggregate( +# total_archive_governmental_weight=Sum('weight', filter=Q(date__date=day, quota='governmental')), +# total_archive_free_weight=Sum('weight', filter=Q(date__date=day, quota='free')), +# ) +# +# total_kill_house_request_governmental_weight = kill_house_requests_info[ +# 'total_kill_house_request_governmental_weight'] or 0 +# total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 +# total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ +# 'total_kill_house_free_buying_bars_weight'] or 0 +# total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_governmental_weight'] or 0 +# total_kill_house_allocations_free_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_free_weight'] or 0 +# total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_governmental_weight'] or 0 +# total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_free_weight'] or 0 +# segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 +# segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 +# pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 +# pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 +# total_archive_governmental_weight = archives_info['total_archive_governmental_weight'] or 0 +# total_archive_free_weight = archives_info['total_archive_free_weight'] or 0 +# +# total_governmental_input = total_kill_house_request_governmental_weight +# total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight +# total_governmental_output = ( +# total_kill_house_allocations_governmental_weight + +# total_kill_house_free_sale_bars_governmental_weight + +# segmentations_governmental_weight + +# int(pos_governmental_allocated_weight / 1000) +# ) +# total_free_output = ( +# total_kill_house_allocations_free_weight + +# total_kill_house_free_sale_bars_free_weight + +# segmentations_free_weight + +# int(pos_free_allocated_weight / 1000) +# ) +# governmental_amount = ( +# total_governmental_input - total_governmental_output) - total_archive_governmental_weight +# free_amount = (total_free_input - total_free_output) - total_archive_free_weight +# governmental_data = { +# 'day': day, +# 'amount': governmental_amount, +# } +# free_data = { +# 'day': day, +# 'amount': free_amount, +# } +# if day not in date_list: +# +# if governmental_amount > 0: +# governmental_list.append(governmental_data) +# if free_amount > 0: +# free_list.append(free_data) +# +# final_dict = { +# 'governmental': governmental_list, +# 'free': free_list +# } +# return final_dict +class TotalKillHouseRemainWeightViewSetSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_info(self, obj): + product = RolesProducts.objects.filter(kill_house=obj, trash=False, name='مرغ گرم').first() + archives = WarehouseArchive.objects.filter(kill_house=obj, trash=False,warehouse=True) + today = datetime.datetime.now().date() + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + date_list=[two_days_ago,yesterday,two_days_ago] + + all_dates = set() + + all_dates.update( + KillHouseRequest.objects.filter( + input_warehouse=obj, + ware_house_confirmation=True, trash=False, calculate_status=True, warehouse=True + ).values_list('kill_request__recive_date__date', flat=True) + ) + + all_dates.update( + KillHouseFreeBarInformation.objects.filter( + input_warehouse=obj, trash=False, calculate_status=True, warehouse=True + ).exclude(entered_message='ورود به انبار مجازی') + .values_list('date__date', flat=True) + ) + + all_dates.update( + StewardAllocation.objects.filter( + kill_house=obj, trash=False, calculate_status=True, warehouse=True, + receiver_state__in=('pending', 'accepted') + ).values_list('production_date__date', flat=True) + ) + + all_dates.update( + KillHouseFreeSaleBarInformation.objects.filter( + kill_house=obj, trash=False, calculate_status=True, warehouse=True + ).values_list('production_date__date', flat=True) + ) + + all_dates.update( + PosSegmentation.objects.filter( + kill_house=obj, trash=False, warehouse=True + ).values_list('production_date__date', flat=True) + ) + + all_dates.update( + ProductsTransactions.objects.filter( + product=product, transaction__paid=True, trash=False, warehouse=True + ).values_list('transaction__date__date', flat=True) + ) + + days = sorted([d for d in all_dates if d is not None]) + + if not days: + return None + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse=obj, + ware_house_confirmation=True, trash=False, calculate_status=True, warehouse=True + ) + + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( + input_warehouse=obj, trash=False, calculate_status=True, warehouse=True + ).exclude(entered_message='ورود به انبار مجازی') + + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, trash=False, calculate_status=True, warehouse=True, + receiver_state__in=('pending', 'accepted') + ) + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=obj, trash=False, calculate_status=True, warehouse=True + ) + + segmentations = PosSegmentation.objects.filter( + kill_house=obj, trash=False, warehouse=True + ) + + transactions = ProductsTransactions.objects.filter( + product=product, transaction__paid=True, trash=False, warehouse=True + ) + + governmental_list = [] + free_list = [] + + for day in days: + kill_house_requests_info = kill_house_requests.aggregate( + total_kill_house_request_governmental_weight=Sum( + 'ware_house_accepted_real_weight', + filter=Q( + province_request__poultry_request__free_sale_in_province=False, + kill_request__recive_date__date=day + ) + ), + total_kill_house_request_free_weight=Sum( + 'ware_house_accepted_real_weight', + filter=Q( + province_request__poultry_request__free_sale_in_province=True, + kill_request__recive_date__date=day + ) + ), + ) + + kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( + total_kill_house_free_buying_bars_weight=Sum('weight_of_carcasses', filter=Q(date__date=day)) + ) + + kill_house_allocations_info = kill_house_allocations.aggregate( + total_kill_house_allocations_governmental_weight=Sum( + 'real_weight_of_carcasses', filter=Q(quota='governmental', production_date__date=day) + ), + total_kill_house_allocations_free_weight=Sum( + 'real_weight_of_carcasses', filter=Q(quota='free', production_date__date=day) + ), + ) + + kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( + total_kill_house_free_sale_bars_governmental_weight=Sum( + 'real_weight_of_carcasses', filter=Q(quota='governmental', production_date__date=day) + ), + total_kill_house_free_sale_bars_free_weight=Sum( + 'real_weight_of_carcasses', filter=Q(quota='free', production_date__date=day) + ), + ) + + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental', production_date__date=day)), + segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), + ) + + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True, transaction__date__date=day)), + pos_free_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=False, transaction__date__date=day)), + ) + archives_info = archives.aggregate( + total_archive_governmental_weight=Sum('weight', filter=Q(date__date=day, quota='governmental')), + total_archive_free_weight=Sum('weight', filter=Q(date__date=day, quota='free')), + ) + + total_kill_house_request_governmental_weight = kill_house_requests_info[ + 'total_kill_house_request_governmental_weight'] or 0 + total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 + total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ + 'total_kill_house_free_buying_bars_weight'] or 0 + total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_governmental_weight'] or 0 + total_kill_house_allocations_free_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_free_weight'] or 0 + total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_governmental_weight'] or 0 + total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + total_archive_governmental_weight = archives_info['total_archive_governmental_weight'] or 0 + total_archive_free_weight = archives_info['total_archive_free_weight'] or 0 + + total_governmental_input = total_kill_house_request_governmental_weight + total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight + total_governmental_output = ( + total_kill_house_allocations_governmental_weight + + total_kill_house_free_sale_bars_governmental_weight + + segmentations_governmental_weight + + int(pos_governmental_allocated_weight / 1000) + ) + total_free_output = ( + total_kill_house_allocations_free_weight + + total_kill_house_free_sale_bars_free_weight + + segmentations_free_weight + + int(pos_free_allocated_weight / 1000) + ) + governmental_amount = ( + total_governmental_input - total_governmental_output) - total_archive_governmental_weight + free_amount = (total_free_input - total_free_output) - total_archive_free_weight + governmental_data = { + 'day': day, + 'amount': governmental_amount, + } + free_data = { + 'day': day, + 'amount': free_amount, + } + if day not in date_list: + + if governmental_amount > 0: + governmental_list.append(governmental_data) + if free_amount > 0: + free_list.append(free_data) + + final_dict = { + 'governmental': governmental_list, + 'free': free_list + } + return final_dict + +class TotalKillHouseWarehouseArchiveDashboardSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + if date1: + archives = WarehouseArchive.objects.filter(trash=False, kill_house=obj, create_date__date__gte=date1, + create_date__date__lte=date2) + + else: + archives = WarehouseArchive.objects.filter(trash=False, kill_house=obj) + + archives_info = archives.aggregate( + total_count=Count('id'), + total_governmental_count=Count('id', filter=Q(quota='governmental')), + total_free_count=Count('id', filter=Q(quota='free')), + total_weight=Sum('weight'), + total_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_free_weight=Sum('weight', filter=Q(quota='free')), + ) + + total_count = archives_info['total_count'] or 0 + total_governmental_count = archives_info['total_governmental_count'] or 0 + total_free_count = archives_info['total_free_count'] or 0 + total_weight = archives_info['total_weight'] or 0 + total_governmental_weight = archives_info['total_governmental_weight'] or 0 + total_free_weight = archives_info['total_free_weight'] or 0 + + result = { + 'total_count': total_count, + 'total_governmental_count': total_governmental_count, + 'total_free_count': total_free_count, + 'total_weight': total_weight, + 'total_governmental_weight': total_governmental_weight, + 'total_free_weight': total_free_weight, + } + return result + + +class KillHouseComparativeInformationSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_ware_house_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def _calculate_info(self, obj, date1=None, date2=None): + product = RolesProducts.objects.filter(kill_house=obj, trash=False, name='مرغ گرم').first() + + if date1: + bars_date1 = date1 + bars_date2 = date2 + # bars_date1 = date1 - timedelta(days=1) + # bars_date2 = date2 - timedelta(days=1) + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + trash=False, + temporary_trash=False, + temporary_deleted=False, + kill_request__recive_date__date__gte=bars_date1, + kill_request__recive_date__date__lte=bars_date2) + + kill_house_requests = KillHouseRequest.objects.filter( + killhouse_user=obj, + non_receipt=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=bars_date1, + kill_request__recive_date__date__lte=bars_date2 + ) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), kill_house=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + + kill_house_allocations = StewardAllocation.objects.filter(kill_house=obj, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, date__date__gte=date1, + date__date__lte=date2) + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False, date__date__gte=date1, + date__date__lte=date2) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house=obj,date__date__gte=date1,date__date__lte=date2, trash=False) + + + else: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + trash=False, + temporary_trash=False, + temporary_deleted=False) + + kill_house_requests = KillHouseRequest.objects.filter(killhouse_user=obj, + trash=False, + non_receipt=False, + calculate_status=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(kill_house=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + + kill_house_allocations = StewardAllocation.objects.filter(kill_house=obj, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True) + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house=obj, trash=False) + + + province_kill_request_info = province_kill_requests.aggregate( + total_province_kill_request_count=Count('id'), + total_province_kill_request_quantity=Sum('total_killed_quantity'), + total_province_kill_request_weight=Sum('total_killed_weight'), + + ) + kill_house_request_info = kill_house_requests.aggregate( + total_kill_house_request_quantity=Sum('accepted_real_quantity'), + total_kill_house_request_governmental_quantity=Sum('accepted_real_quantity', + filter=Q( + province_request__poultry_request__free_sale_in_province=False)), + total_kill_house_request_free_quantity=Sum('accepted_real_quantity', + filter=Q( + province_request__poultry_request__free_sale_in_province=True)), + total_kill_house_request_warehouse_entered_quantity=Sum('accepted_real_quantity', + filter=Q(ware_house_confirmation=True)), + total_kill_house_request_warehouse_entered_weight=Sum('accepted_real_weight', + filter=Q(ware_house_confirmation=True)), + total_kill_house_request_warehouse_cacasses_entered_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True)), + + total_kill_house_request_warehouse_entered_governmental_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=False)), + total_kill_house_request_warehouse_entered_free_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=True)), + ) + kill_house_free_bar_info = kill_house_free_bar_informations.aggregate( + total_kill_house_free_bar_carcass_total_weight=Sum('weight_of_carcasses'), + total_kill_house_free_bar_live_total_quantity=Sum('quantity', filter=Q(buy_type='live')), + total_kill_house_entered_free_bar_live_total_weight=Sum('live_weight', + filter=Q(buy_type='live', ware_house=True)), + total_kill_house_entered_free_bar_live_carcasses_total_weight=Sum('weight_of_carcasses', + filter=Q(buy_type='live', + ware_house=True)), + total_kill_house_entered_free_bar_live_total_quantity=Sum('quantity', + filter=Q(buy_type='live', ware_house=True)), + ) + + kill_house_free_Sale_bar_info = kill_house_free_Sale_bar_informations.aggregate( + total_kill_house_free_Sale_bar_weight=Sum('real_weight_of_carcasses'), + total_kill_house_free_Sale_bar_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_free_Sale_bar_free_weight=Sum('real_weight_of_carcasses', filter=Q(quota='free')), + ) + + kill_house_allocations_info = kill_house_allocations.aggregate( + total_kill_house_allocations_weight=Sum('real_weight_of_carcasses'), + total_kill_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + ) + + segmentations_aggregates_info = segmentations.aggregate( + total_segmentations_weight=Sum('weight'), + total_segmentations_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_segmentations_free_weight=Sum('weight', filter=Q(quota='free')), + ) + cold_house_allocations_info = cold_house_allocations.aggregate( + total_cold_house_allocations_weight=Sum('real_weight_of_carcasses'), + total_cold_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_cold_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + ) + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + total_archive_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_archive_free_weight=Sum('weight', filter=Q(quota='free')), + ) + + return {**province_kill_request_info, **kill_house_request_info, **kill_house_free_bar_info, + **kill_house_free_Sale_bar_info, **kill_house_allocations_info, **segmentations_aggregates_info,**pos_allocated_weight_info, + **cold_house_allocations_info,**archives_info} + + def get_ware_house_info(self, obj): + product_remain_weight = RolesProducts.objects.filter(kill_house=obj, trash=False).only( + 'total_remain_weight').first() + product_remain_weight = product_remain_weight.total_remain_weight if product_remain_weight else 0 + date1 = self.context.get('date1') + date2 = self.context.get('date2') + rsi_data = self.context.get('rsi_data') + kill_house_rsi_info = next( + (obj_info for obj_info in rsi_data if obj_info["PartIdCode"] == obj.unique_identifier), None) + if date1 and date2: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + total_info = self._calculate_info(obj, date1, date2) if date1 else self._calculate_info(obj) + + total_province_kill_requests_quantity = total_info['total_province_kill_request_quantity'] or 0 + total_kill_house_request_governmental_quantity = total_info[ + 'total_kill_house_request_governmental_quantity'] or 0 + total_kill_house_request_free_quantity = total_info['total_kill_house_request_free_quantity'] or 0 + total_kill_house_free_bar_live_total_quantity = total_info['total_kill_house_free_bar_live_total_quantity'] or 0 + total_live_bars_quantity = total_kill_house_request_governmental_quantity + total_kill_house_request_free_quantity + total_kill_house_free_bar_live_total_quantity + total_kill_house_request_warehouse_entered_quantity = total_info[ + 'total_kill_house_request_warehouse_entered_quantity'] or 0 + total_kill_house_entered_free_bar_live_total_quantity = total_info[ + 'total_kill_house_entered_free_bar_live_total_quantity'] or 0 + total_entered_warehouse_bars_quantity = total_kill_house_request_warehouse_entered_quantity + total_kill_house_entered_free_bar_live_total_quantity + total_kill_house_request_warehouse_entered_weight = total_info[ + 'total_kill_house_request_warehouse_entered_weight'] or 0 + total_kill_house_entered_free_bar_live_total_weight = total_info[ + 'total_kill_house_entered_free_bar_live_total_weight'] or 0 + total_entered_warehouse_bars_weight = total_kill_house_request_warehouse_entered_weight + total_kill_house_entered_free_bar_live_total_weight + total_kill_house_request_warehouse_cacasses_entered_weight = total_info[ + 'total_kill_house_request_warehouse_cacasses_entered_weight'] or 0 + total_kill_house_entered_free_bar_live_carcasses_total_weight = total_info[ + 'total_kill_house_entered_free_bar_live_carcasses_total_weight'] or 0 + total_kill_house_free_bar_carcass_total_weight = total_info[ + 'total_kill_house_free_bar_carcass_total_weight'] or 0 + total_kill_house_request_warehouse_entered_governmental_weight = total_info[ + 'total_kill_house_request_warehouse_entered_governmental_weight'] or 0 + total_kill_house_request_warehouse_entered_free_weight = total_info[ + 'total_kill_house_request_warehouse_entered_free_weight'] or 0 + total_kill_house_warehouse_cacasses_entered_weight = total_kill_house_request_warehouse_cacasses_entered_weight + total_kill_house_free_bar_carcass_total_weight + total_kill_house_warehouse_govermental_cacasses_entered_weight = total_kill_house_request_warehouse_entered_governmental_weight + total_kill_house_warehouse_free_cacasses_entered_weight = total_kill_house_request_warehouse_entered_free_weight + total_kill_house_entered_free_bar_live_carcasses_total_weight + total_kill_house_free_Sale_bar_weight = total_info['total_kill_house_free_Sale_bar_weight'] or 0 + total_kill_house_free_Sale_bar_governmental_weight = total_info[ + 'total_kill_house_free_Sale_bar_governmental_weight'] or 0 + total_kill_house_free_Sale_bar_free_weight = total_info['total_kill_house_free_Sale_bar_free_weight'] or 0 + total_kill_house_allocations_weight = total_info['total_kill_house_allocations_weight'] or 0 + total_kill_house_allocations_governmental_weight = total_info[ + 'total_kill_house_allocations_governmental_weight'] or 0 + total_kill_house_allocations_free_weight = total_info['total_kill_house_allocations_free_weight'] or 0 + total_segmentations_weight = total_info['total_segmentations_weight'] or 0 + total_segmentations_governmental_weight = total_info['total_segmentations_governmental_weight'] or 0 + total_segmentations_free_weight = total_info['total_segmentations_free_weight'] or 0 + total_cold_house_allocations_weight = total_info['total_cold_house_allocations_weight'] or 0 + total_cold_house_allocations_governmental_weight = total_info[ + 'total_cold_house_allocations_governmental_weight'] or 0 + total_cold_house_allocations_free_weight = total_info['total_cold_house_allocations_free_weight'] or 0 + pos_allocated_weight = total_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = total_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = total_info['pos_free_allocated_weight'] or 0 + total_archive_governmental_weight = total_info['total_archive_governmental_weight'] or 0 + total_archive_free_weight = total_info['total_archive_free_weight'] or 0 + total_input_weight = total_kill_house_warehouse_cacasses_entered_weight + total_governmental_input_weight = total_kill_house_request_warehouse_entered_governmental_weight + total_free_input_weight = total_kill_house_request_warehouse_entered_free_weight + total_kill_house_free_bar_carcass_total_weight + total_output_weight = total_kill_house_free_Sale_bar_weight + total_kill_house_allocations_weight + total_segmentations_weight + total_cold_house_allocations_weight + total_output_governmental_weight = total_kill_house_free_Sale_bar_governmental_weight + total_kill_house_allocations_governmental_weight + total_segmentations_governmental_weight + total_cold_house_allocations_governmental_weight + int(pos_governmental_allocated_weight / 1000) + total_output_free_weight = total_kill_house_free_Sale_bar_free_weight + total_kill_house_allocations_free_weight + total_segmentations_free_weight + total_cold_house_allocations_free_weight + int(pos_free_allocated_weight / 1000) + # total_remain_weight = total_input_weight - total_output_weight + total_remain_governmental_weight = (total_governmental_input_weight - total_output_governmental_weight) - total_archive_governmental_weight if ( + total_governmental_input_weight - total_output_governmental_weight) - total_archive_governmental_weight> 0 else 0 + last_total_remain_governmental_weight = ( + (total_governmental_input_weight - total_output_governmental_weight) - total_archive_governmental_weight) * -1 if ( + total_governmental_input_weight - total_output_governmental_weight) - total_archive_governmental_weight < 0 else 0 + total_remain_free_weight = (total_free_input_weight - total_output_free_weight) - total_archive_free_weight if ( + total_free_input_weight - total_output_free_weight) - total_archive_free_weight > 0 else 0 + last_total_remain_free_weight = ((total_free_input_weight - total_output_free_weight) - total_archive_free_weight) * -1 if ( + total_free_input_weight - total_output_free_weight) - total_archive_free_weight < 0 else 0 + total_remain_weight = total_remain_governmental_weight + total_remain_free_weight + last_total_remain_weight = last_total_remain_governmental_weight + last_total_remain_free_weight + + return { + "kill_house_rsi_info": kill_house_rsi_info, + "total_killing_quantity": total_province_kill_requests_quantity + total_kill_house_free_bar_live_total_quantity, + "total_kill_house_request_governmental_quantity": total_kill_house_request_governmental_quantity, + "total_kill_house_request_free_quantity": total_kill_house_request_free_quantity, + "total_kill_house_free_bar_live_total_quantity": total_kill_house_free_bar_live_total_quantity, + "total_live_bars_quantity": total_live_bars_quantity, + "total_entered_warehouse_bars_quantity": total_entered_warehouse_bars_quantity, + "total_entered_warehouse_bars_weight": total_entered_warehouse_bars_weight, + "total_kill_house_request_warehouse_entered_quantity": total_kill_house_request_warehouse_entered_quantity, + "total_kill_house_request_warehouse_entered_weight": total_kill_house_request_warehouse_entered_weight, + "total_kill_house_warehouse_cacasses_entered_weight": total_kill_house_warehouse_cacasses_entered_weight, + "total_kill_house_warehouse_govermental_cacasses_entered_weight": total_kill_house_warehouse_govermental_cacasses_entered_weight, + "total_kill_house_warehouse_free_cacasses_entered_weight": total_kill_house_warehouse_free_cacasses_entered_weight, + "total_kill_house_request_warehouse_entered_governmental_weight": total_kill_house_request_warehouse_entered_governmental_weight, + "total_kill_house_request_warehouse_entered_free_weight": total_kill_house_request_warehouse_entered_free_weight, + "total_output_weight": total_output_weight, + "total_kill_house_allocations_weight": total_kill_house_allocations_weight, + "total_kill_house_free_Sale_bar_weight": total_kill_house_free_Sale_bar_weight, + "total_other_output_weight": total_segmentations_weight + total_cold_house_allocations_weight, + "total_remain_weight": total_remain_weight, + "total_remain_governmental_weight": total_remain_governmental_weight, + "total_remain_free_weight": total_remain_free_weight, + "last_total_remain_governmental_weight": last_total_remain_governmental_weight, + "last_total_remain_free_weight": last_total_remain_free_weight, + "last_total_remain_weight": last_total_remain_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "total_archive_governmental_weight": total_archive_governmental_weight, + "total_archive_free_weight": total_archive_free_weight, + + } + + +class KillHouseMarketInfoSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + kill_houses = self.context.get('kill_houses') + if date1: + kill_house_info = market_kill_request_share_quantity(obj, date1, date2, total_kill_houses=kill_houses) + else: + kill_house_info = market_kill_request_share_quantity(obj, total_kill_houses=kill_houses) + + result = { + "total_poultry_requests_quantity": kill_house_info['total_poultry_requests_quantity'], + "kill_house_today_share": kill_house_info['kill_house_today_share'], + "market_light_share": kill_house_info['market_light_share'], + "kill_house_market_kill_requests_quantity": kill_house_info['kill_house_market_kill_requests_quantity'], + "kill_house_market_kill_requests_quantity_first": kill_house_info[ + 'kill_house_market_kill_requests_quantity_first'], + "kill_house_market_kill_requests_quantity_final": kill_house_info[ + 'kill_house_market_kill_requests_quantity_final'], + "kill_house_today_left_share": kill_house_info['kill_house_today_left_share'], + "kill_house_market_kill_requests_quantity_weight": kill_house_info[ + 'kill_house_market_kill_requests_quantity_weight'], + "kill_house_market_kill_requests_quantity_first_weight": kill_house_info[ + 'kill_house_market_kill_requests_quantity_first_weight'], + "kill_house_market_kill_requests_quantity_final_weight": kill_house_info[ + 'kill_house_market_kill_requests_quantity_final_weight'], + "total_kill_house_market_kill_requests_quantity_agreement_light_weight": kill_house_info[ + 'total_kill_house_market_kill_requests_quantity_agreement_light_weight'], + "total_kill_house_market_kill_requests_quantity_light_weight": kill_house_info[ + 'total_kill_house_market_kill_requests_quantity_light_weight'], + "total_kill_house_market_kill_requests_quantity_heavy_weight": kill_house_info[ + 'total_kill_house_market_kill_requests_quantity_heavy_weight'], + } + return result + + +class KillHouseForKillHousePercentageSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + system_address = SystemAddressSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'system_address', 'kill_house_operator', 'name', 'active', 'killer', 'type'] + + +class KillHouseForTotalReportAutomaticStewardAllocationSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + quantity_info = serializers.SerializerMethodField('get_quantity_info') + + class Meta: + model = KillHouse + fields = ['name', 'killer', 'kill_house_operator', 'quantity_info'] + + def get_quantity_info(self, obj): + from django.db.models import F, Sum, DecimalField + date = datetime.datetime.strptime(str(self.context.get('request').GET['date']), '%Y-%m-%d').date() + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=date + ).select_related( + 'province_request__poultry_request') + allocations = StewardAllocation.objects.filter(kill_house=obj, date__date=date) + + total_quantity = province_kill_requests.aggregate(total_quantity=Sum('main_quantity')).get( + 'total_quantity', 0) + total_allocations = allocations.aggregate(total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity', 0) + if total_quantity == None: + total_quantity = 0 + if total_allocations == None: + total_allocations = 0 + + if total_quantity == None: + total_quantity = 0 + if total_allocations == None: + total_allocations = 0 + remain_quantity = total_quantity - total_allocations + + return { + "total_quantity": total_quantity, + "total_allocations": total_allocations, + "remain_quantity": remain_quantity + } + + +class KillHouseWageForTotalDashbordSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'wage_info'] + + def get_wage_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + return_to_province=False, + trash=False) + + unpaid_province_kill_requests = province_kill_requests.filter( + wage_pay=False, + archive_by_province=False, + return_to_province=False, + trash=False) + + paid_province_kill_requests = province_kill_requests.filter( + wage_pay=True, + archive_by_province=False, + return_to_province=False, + + trash=False) + + archive_province_kill_requests = province_kill_requests.filter( + wage_pay=False, + archive_by_province=True, + return_to_province=False, + trash=False) + + return { + "total_count": len(province_kill_requests), + "paid_count": len(paid_province_kill_requests), + "unpaid_count": len(unpaid_province_kill_requests), + "archive_count": len(archive_province_kill_requests), + "total_quantity": province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0, + "total_weight": province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0, + "total_wage": province_kill_requests.aggregate(total=Sum(F('total_killed_weight') * F('wage')))[ + 'total'], + "total_paid_quantity": paid_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0, + "total_weight_paid": + paid_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0, + "total_paid_wage": paid_province_kill_requests.aggregate(total=Sum(F('total_killed_weight') * F('wage')))[ + 'total'] or 0, + "total_unpaid_quantity": unpaid_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0, + "total_weight_unpaid": unpaid_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0, + "total_unpaid_wage": + unpaid_province_kill_requests.aggregate(total=Sum(F('total_killed_weight') * F('wage')))[ + 'total'], + "total_archive_quantity": archive_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0, + "total_weight_archive": archive_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0, + "total_archive_wage": + archive_province_kill_requests.aggregate(total=Sum(F('total_killed_weight') * F('wage')))[ + 'total'], + + } + + +class KillHouseForAutomaticStewardAllocationSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + system_address = SystemAddressSerializer(read_only=True) + province_kill_request_information = serializers.SerializerMethodField('get_province_kill_request_information') + date = serializers.SerializerMethodField('get_date') + + class Meta: + model = KillHouse + fields = ['key', 'system_address', 'kill_house_operator', 'name', 'active', 'killer', + 'province_kill_request_information', 'date' + ] + + def get_province_kill_request_information(self, obj): + from datetime import datetime, timedelta + date = datetime.strptime(str(self.context.get('request').GET['date']), '%Y-%m-%d').date() + ware_house = KillHouseWareHouse.objects.filter(kill_house=obj, date__date=date).first() + if not ware_house: + ware_house_date = datetime(year=date.year, month=date.month, day=date.day, hour=1, minute=12, second=20) + ware_house = KillHouseWareHouse( + kill_house=obj, + date=ware_house_date + ) + ware_house.save() + + total_number_of_carcasses_temp = ware_house.update_total_number_of_carcasses + ware_house.pre_cold_number_of_carcasses_to_ware_house if ware_house.update_total_number_of_carcasses > 0 else ware_house.total_number_of_carcasses + ware_house.pre_cold_number_of_carcasses_to_ware_house + total_weight_of_carcasses_temp = ware_house.update_total_weight_of_carcasses + ware_house.pre_cold_weight_of_carcasses_to_ware_house if ware_house.update_total_weight_of_carcasses > 0 else ware_house.total_weight_of_carcasses + ware_house.pre_cold_weight_of_carcasses_to_ware_house + return { + "total_number_of_carcasses": total_number_of_carcasses_temp, + "total_weight_of_carcasses": total_weight_of_carcasses_temp, + "allocated_total_number_of_carcasses": ware_house.allocated_total_number_of_carcasses, + "pre_cold_number_of_carcasses_self_ware_house": ware_house.pre_cold_number_of_carcasses_self_ware_house, + "pre_cold_weight_of_carcasses_self_ware_house": ware_house.pre_cold_weight_of_carcasses_self_ware_house, + "allocated_total_weight_of_carcasses": ware_house.allocated_total_weight_of_carcasses, + "remain_total_number_of_carcasses": total_number_of_carcasses_temp - ware_house.allocated_total_number_of_carcasses if ware_house.pre_cold_number_of_carcasses_self_ware_house == 0 else 0, + "remain_total_weight_of_carcasses": total_weight_of_carcasses_temp - ware_house.allocated_total_weight_of_carcasses if ware_house.pre_cold_weight_of_carcasses_to_ware_house == 0 else 0, + + } + + def get_date(self, obj): + return datetime.datetime.strptime(str(self.context.get('request').GET['date']), '%Y-%m-%d').date() + + +class KillHousePurchaseRequestSerializer(serializers.ModelSerializer): + kill_house = KillHouseForKillHousePercentageSerializer(read_only=True) + + class Meta: + model = KillHousePurchaseRequest + fields = '__all__' + + +class KillHouseforPurchaseRequestSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + system_address = SystemAddressSerializer(read_only=True) + allow_purchase_request = serializers.SerializerMethodField('get_allow_purchase_request') + wage_info = serializers.SerializerMethodField('get_wage_info') + kill_house_for_killer = serializers.SerializerMethodField('get_kill_house_for_killer') + + class Meta: + model = KillHouse + fields = ['key', 'max_kill_limit', 'extra_bar_kill_percent', 'total_kill_capacity', 'kill_house_operator', + 'name', 'killer', 'system_address', 'allow_purchase_request', 'wage_info', 'type', 'killer', + 'kill_house_for_killer', 'out_province_selling_limitation', 'out_province_selling_limitation_percent', + 'in_province_selling_limitation', 'in_province_selling_limitation_percent', 'quota', 'free_quota', + 'governmental_quota', 'quota_max_kill_limit', 'quota_request', 'quota_custom', + 'quota_custom_quantity', 'maximum_load_volume_increase', 'maximum_load_volume_reduction', + 'ware_house_remaining_percent_limitation', 'ware_house_remaining_percent_limitation_status', + 'ware_house_remaining_weight_limitation', 'ware_house_remaining_weight_limitation_status','ware_house_remaining_weight_archive_percent'] + + def get_allow_purchase_request(self, obj): + allow = True + limitation = False + total_limitation = False + limitation_number = 0 + purchase_request = KillHousePurchaseRequest.objects.filter(kill_house=obj).first() + if purchase_request: + allow = purchase_request.allow + limitation = purchase_request.limitation + limitation_number = purchase_request.limitation_number + total_limitation = purchase_request.total_limitation + + return { + "allow": allow, + "limitation": limitation, + "limitation_number": limitation_number, + "total_limitation": total_limitation, + } + + def get_wage_info(self, obj): + total_unpaid_wage = 0 + total_paid_wage = 0 + kill_house_kill_requests_wage = 0 + real_free_sale_wage = 0 + # role = self.context.get('request').GET['role'] + total_unpaid_wage = get_finance_info(obj)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter(Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "user_token": 'k' + obj.kill_house_operator.user.user_gate_way_id, + "total_amount": total_unpaid_wage - (total_paid_wage + obj.off) + } + + def get_kill_house_for_killer(self, obj): + kill_house_for_killer_info = None + kill_house_for_killer = KillHousePercentage.objects.filter(kill_house=obj, kill_house_for_killer__isnull=False, + kill_house__killer=True).first() + + if kill_house_for_killer: + kill_house_for_killer_info = { + "kill_house_name": kill_house_for_killer.kill_house_for_killer.name, + "fullname": kill_house_for_killer.kill_house_for_killer.kill_house_operator.user.fullname, + "mobile": kill_house_for_killer.kill_house_for_killer.kill_house_operator.user.mobile, + } + + return kill_house_for_killer_info + + +class KillHouseForKillingInformationDiscrepancyReportSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'kill_house_operator', 'name', 'killer'] + + +class PosKillHouseForKillingInformationDiscrepancyReportSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouse + fields = ['key', 'name'] + + +class KillHouseForProvinceSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForColdHouseSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'name', 'killer', 'kill_house_operator'] + + +class KillHouseForProvinceWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + role = self.context.get('request').GET['role'] + + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + union_share__gt=0, + return_to_province=False, + archive_wage=False, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'Company': + wage_type = 'company_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + company_share__gt=0, + return_to_province=False, + archive_wage=False, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'Guilds': + wage_type = 'guilds_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + guilds_share__gt=0, + return_to_province=False, + archive_wage=False, + trash=False).select_related( + 'province_request__poultry_request') + else: + wage_type = 'wallet_share' + + total_quantity += province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + + total_weight += province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + total_wage += province_kill_requests.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(province_kill_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_wage": total_wage, + + } + + +class KillHouseForKillHouseRequestWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + role = self.context.get('request').GET['role'] + if role == 'ProvinceOperator': + kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), + province_kill_request__union_share__gt=0, + archive_wage=False, trash=False) + elif role == 'Company': + kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), + province_kill_request__company_share__gt=0, + archive_wage=False, trash=False) + elif role == 'Guilds': + + kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), + province_kill_request__guilds_share__gt=0, + archive_wage=False, trash=False) + else: + kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), + archive_wage=False, trash=False) + + total_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + + total_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(kill_house_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + + } + + +class KillHouseForNewWageInormationSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + shares = serializers.SerializerMethodField('get_shares') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'wage_info', 'shares'] + + def get_wage_info(self, obj): + date1 = None + date2 = None + if self.context.get('request').GET.get('date1'): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + total_paid_wage = 0 + if date1: + # finance_info = get_kill_house_finance_info(obj,date1,date2) + finance_info = get_finance_info(obj, date1, date2) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), status='completed', date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + # finance_info = get_kill_house_finance_info(obj) + finance_info = get_finance_info(obj) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "wage_counting_type": wage_counting_type, + "total_wage": finance_info['total_price'], + "total_paid_wage": total_paid_wage, + "off": obj.off, + "total_unpaid_wage": finance_info['total_price'] - (total_paid_wage + obj.off), + "province_kill_requests_total_wage": finance_info['total_pure_province_carcasses_price'], + "province_kill_requests_total_weight": finance_info['total_pure_province_carcasses_weight'], + "free_bars_live_total_wage": finance_info['total_out_live_buying_province_carcasses_price'], + "free_bars_live_total_weight": finance_info['total_out_live_buying_province_carcasses_weight'], + "free_bars_carcases_total_wage": finance_info['total_out_carcasses_buying_province_carcasses_price'], + "free_bars_carcases_total_weight": finance_info['total_out_carcasses_buying_province_carcasses_weight'], + "free_bars_out_province_carcases_total_wage": finance_info['total_out_selling_province_carcasses_price'], + "free_bars_out_province_carcases_total_weight": finance_info['total_out_selling_province_carcasses_weight'], + "total_province_live_weight": finance_info['total_province_live_weight'], + "total_province_carcasses_weight": finance_info['total_province_carcasses_weight'], + "province_live_wage_amount": finance_info['province_live_wage_amount'], + "free_buying_live_weight_amount": finance_info['free_buying_live_weight_amount'], + "free_buying_carcesses_weight_amount": finance_info['free_buying_carcesses_weight_amount'], + "free_sell_carcesses_weight_amount": finance_info['free_sell_carcesses_weight_amount'], + "return_total_province_live_weight": finance_info['return_total_province_live_weight'], + "total_return_pure_province_carcasses_price": finance_info['total_return_pure_province_carcasses_price'], + } + + def get_shares(self, kill_house): + date1 = None + date2 = None + before_total_out_live_buying_province_carcasses_price = 0 + total_wage_type = WageType.objects.filter(trash=False) + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + + if self.context.get('request').GET.get('date1'): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + + finance_info = get_finance_info(kill_house, date1, date2) if date1 else get_finance_info(kill_house) + if date1: + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False) + + total_pure_province_carcasses_price = finance_info['total_pure_province_carcasses_price'] + return_total_pure_province_carcasses_price = finance_info['total_return_pure_province_carcasses_price'] + total_out_selling_province_carcasses_price = finance_info['total_out_selling_province_carcasses_price'] + difference_requests_price = finance_info['difference_requests_price'] + + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (finance_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount) + ( + finance_info[ + 'after_total_out_live_buying_province_carcasses_weight'] * free_buying_live_weight_wage_type_amount)) + + before_total_out_live_buying_province_carcasses_price = finance_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount + else: + total_out_live_buying_province_carcasses_price = finance_info[ + 'total_out_live_buying_province_carcasses_price'] + total_out_carcasses_buying_province_carcasses_price = finance_info[ + 'total_out_carcasses_buying_province_carcasses_price'] + total_price = finance_info['total_price'] + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + guilds_difference_requests_price = difference_requests_price * guilds_province_kill_request_percent + other_difference_requests_price = difference_requests_price * other_province_kill_request_percent + guild_return_province_kill_request_wage = return_total_pure_province_carcasses_price * guilds_province_kill_request_percent + other_return_province_kill_request_wage = return_total_pure_province_carcasses_price * other_province_kill_request_percent + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + return_union_province_kill_request_wage = return_total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + return_union_province_kill_request_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + company_province_kill_request_wage = ( + total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guilds_difference_requests_price + other_difference_requests_price) + return_company_province_kill_request_wage = ( + return_total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guild_return_province_kill_request_wage + other_return_province_kill_request_wage) + company_free_buying_live_wage = (( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * company_free_buying_live_percent) + before_total_out_live_buying_province_carcasses_price + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + return_company_province_kill_request_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_wage = ( + total_pure_province_carcasses_price * guilds_province_kill_request_percent) - guilds_difference_requests_price + return_guilds_province_kill_request_wage = 0 + guilds_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_wage = ( + total_pure_province_carcasses_price * other_province_kill_request_percent) - other_difference_requests_price + return_other_province_kill_request_wage = 0 + other_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + return [ + { + "name": "اتحادیه", + "province_kill_request_wage": union_province_kill_request_wage, + "return_province_kill_request_wage": return_union_province_kill_request_wage, + "free_buying_live_wage": union_free_buying_live_wage, + "free_buying_carcasses_wage": union_free_buying_carcasses_wage, + "free_sell_carcasses_wage": union_free_sell_carcasses_wage, + "total_wage": union_total_wage, + "total_paid_wage": union_total_paid_wage, + "total_unpaid_wage": union_total_unpaid_wage, + }, + { + "name": "شرکت", + "province_kill_request_wage": company_province_kill_request_wage, + "return_province_kill_request_wage": return_company_province_kill_request_wage, + "free_buying_live_wage": company_free_buying_live_wage, + "free_buying_carcasses_wage": company_free_buying_carcasses_wage, + "free_sell_carcasses_wage": company_free_sell_carcasses_wage, + "total_wage": company_total_wage, + "total_paid_wage": company_total_paid_wage, + "total_unpaid_wage": company_total_unpaid_wage, + }, + { + "name": "صنف پروتئین", + "province_kill_request_wage": guilds_province_kill_request_wage, + "return_province_kill_request_wage": return_guilds_province_kill_request_wage, + "free_buying_live_wage": guilds_free_buying_live_wage, + "free_buying_carcasses_wage": guilds_free_buying_carcasses_wage, + "free_sell_carcasses_wage": guilds_free_sell_carcasses_wage, + "total_wage": guilds_total_wage, + "total_paid_wage": guilds_total_paid_wage, + "total_unpaid_wage": guilds_total_unpaid_wage, + }, + { + "name": "دامپزشک", + "province_kill_request_wage": other_province_kill_request_wage, + "return_province_kill_request_wage": return_other_province_kill_request_wage, + "free_buying_live_wage": other_free_buying_live_wage, + "free_buying_carcasses_wage": other_free_buying_carcasses_wage, + "free_sell_carcasses_wage": other_free_sell_carcasses_wage, + "total_wage": other_total_wage, + "total_paid_wage": other_total_paid_wage, + "total_unpaid_wage": other_total_unpaid_wage, + }] + + +class KillHouseColdHouseSerializer(serializers.ModelSerializer): + kill_house = KillHouseForProvinceSerializer(read_only=True) + + class Meta: + model = ColdHouse + fields = ['key', 'kill_house', 'total_input_weight', 'total_allocated_weight', + 'total_remain_weight', 'name', 'province', 'city', 'address', 'capacity', 'active', 'broadcast', + 'relocate'] + + +class KillHouseColdHousesSerializer(serializers.ModelSerializer): + cold_houses = serializers.SerializerMethodField('get_cold_houses') + + class Meta: + model = KillHouse + fields = ['key', 'cold_houses'] + + def get_cold_houses(self, obj): + cold_houses = ColdHouse.objects.filter(kill_house=obj, trash=False) + serializer = KillHouseColdHouseSerializer(cold_houses, many=True) + return serializer.data + + +class KillHouseForColdHouseSerializer(serializers.ModelSerializer): + cold_houses_info = serializers.SerializerMethodField('get_cold_houses_info') + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + province = serializers.CharField(source='kill_house_operator.user.province.name', read_only=True) + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'name', 'fullname', 'mobile', 'cold_houses_info', 'province', 'city'] + + def get_cold_houses_info(self, obj): + cold_houses = ColdHouse.objects.filter(kill_house=obj, trash=False) + + total_input_weight = cold_houses.aggregate(total=Sum('total_input_weight'))[ + 'total'] or 0 + total_allocated_weight = cold_houses.aggregate(total=Sum('total_allocated_weight'))[ + 'total'] or 0 + total_remain_weight = cold_houses.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + + return { + "total_cold_houses": len(cold_houses), + "total_input_weight": total_input_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + +class ParentCompanyKillHouseForNewWageInormationSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'wage_info'] + + def get_wage_info(self, obj): + total_paid_wage = 0 + finance_info = get_kill_house_finance_info(obj) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "wage_counting_type": wage_counting_type, + "total_wage": finance_info['total_price'], + "total_paid_wage": total_paid_wage, + "off": obj.off, + "total_unpaid_wage": finance_info['total_price'] - (total_paid_wage + obj.off), + "province_kill_requests_total_wage": finance_info['total_pure_province_carcasses_price'], + "province_kill_requests_total_weight": finance_info['total_pure_province_carcasses_weight'], + "free_bars_live_total_wage": finance_info['total_out_live_buying_province_carcasses_price'], + "free_bars_live_total_weight": finance_info['total_out_live_buying_province_carcasses_weight'], + "free_bars_carcases_total_wage": finance_info['total_out_carcasses_buying_province_carcasses_price'], + "free_bars_carcases_total_weight": finance_info['total_out_carcasses_buying_province_carcasses_weight'], + "free_bars_out_province_carcases_total_wage": finance_info['total_out_selling_province_carcasses_price'], + "free_bars_out_province_carcases_total_weight": finance_info['total_out_selling_province_carcasses_weight'], + "total_province_live_weight": finance_info['total_province_live_weight'], + "total_province_carcasses_weight": finance_info['total_province_carcasses_weight'], + "province_live_wage_amount": finance_info['province_live_wage_amount'], + "free_buying_live_weight_amount": finance_info['free_buying_live_weight_amount'], + "free_buying_carcesses_weight_amount": finance_info['free_buying_carcesses_weight_amount'], + "free_sell_carcesses_weight_amount": finance_info['free_sell_carcesses_weight_amount'], + } + + +class KillHouseForProvinceWareHouseDashboardSerializer(serializers.ModelSerializer): + ware_house_info = serializers.SerializerMethodField('get_ware_house_info') + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'name', 'killer', 'kill_house_operator', 'ware_house_info'] + + def _calculate_info(self, obj, date1=None, date2=None): + product = RolesProducts.objects.filter(kill_house=obj, trash=False, name='مرغ گرم').first() + if date1: + bars_date1 = date1 + bars_date2 = date2 + # bars_date1 = date1 - timedelta(days=1) + # bars_date2 = date1 - timedelta(days=1) + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, trash=False, + temporary_trash=False, + temporary_deleted=False, + kill_request__recive_date__date__gte=bars_date1, + kill_request__recive_date__date__lte=bars_date2, + warehouse=True) + + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(killhouse_user=obj) | Q(killer=obj), + # trash=False, calculate_status=True, + # archive_wage=False, + # temporary_trash=False, + # temporary_deleted=False, + # kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=date2 + # ) + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse=obj, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=bars_date1, + kill_request__recive_date__date__lte=bars_date2, warehouse=True + ) + # kill_house_requests = kill_house_requests.filter( + # Q(killhouse_user=obj, killer__isnull=True) | Q(killhouse_user=obj, killer=obj) | Q( + # killer=obj)) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), input_warehouse=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True).exclude( + entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True) + + kill_house_allocations = StewardAllocation.objects.filter(kill_house=obj, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, date__date__gte=date1, + date__date__lte=date2, warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False, date__date__gte=date1, + date__date__lte=date2, warehouse=True) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house=obj,date__date__gte=date1,date__date__lte=date2, trash=False,warehouse=True) + + + else: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + first_car_allocated_quantity=0, trash=False, + warehouse=True) + + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(killhouse_user=obj) | Q(killer=obj), + # temporary_trash=False, + # temporary_deleted=False, + # trash=False, calculate_status=True) + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse=obj, + # Q(killhouse_user=obj)|Q(killer=obj), + trash=False, calculate_status=True, warehouse=True + ) + # kill_house_requests = kill_house_requests.filter( + # Q(killhouse_user=obj, killer__isnull=True) | Q(killhouse_user=obj, killer=obj) | Q( + # killer=obj)) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(input_warehouse=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True).exclude( + entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house=obj, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=obj, trash=False, warehouse=True) + + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=obj, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, trash=False, warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house=obj, trash=False,warehouse=True) + + + province_kill_request_info = province_kill_requests.aggregate( + total_province_kill_request_count=Count('id'), + total_province_kill_request_quantity=Sum('total_killed_quantity'), + total_province_kill_request_weight=Sum('total_killed_weight'), + + ) + kill_house_request_info = kill_house_requests.aggregate( + total_kill_house_request_count=Count('id'), + total_kill_house_request_warehouse_entered_count=Count('id', filter=Q(ware_house_confirmation=True)), + total_kill_house_request_warehouse_not_entered_count=Count('id', filter=Q(ware_house_confirmation=False)), + total_kill_house_request_quantity=Sum('accepted_real_quantity'), + total_kill_house_request_weight=Sum('accepted_real_weight'), + total_kill_house_request_warehouse_not_entered_quantity=Sum('accepted_real_quantity', + filter=Q(ware_house_confirmation=False)), + total_kill_house_request_warehouse_not_entered_weight=Sum('accepted_real_weight', + filter=Q(ware_house_confirmation=False)), + kill_house_request_warehouse_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True)), + kill_house_request_warehouse_governmental_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=False)), + kill_house_request_warehouse_free_weight=Sum('ware_house_accepted_real_weight', + filter=Q(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=True)), + + ) + kill_house_free_bar_info = kill_house_free_bar_informations.aggregate( + total_kill_house_free_bar_live_count=Count('id', filter=Q(buy_type='live')), + total_kill_house_free_bar_carcass_count=Count('id', filter=Q(buy_type='carcass')), + total_kill_house_free_bar_warehouse_entered_count=Count('id', filter=Q(weight_of_carcasses__gt=0)), + total_kill_house_free_bar_warehouse_not_entered_count=Count('id', filter=Q(weight_of_carcasses=0)), + total_kill_house_free_bar_live_quantity=Sum('quantity', filter=Q(buy_type='live')), + total_kill_house_free_bar_live_weight=Sum('live_weight', filter=Q(buy_type='live')), + total_kill_house_free_bar_carcass_quantity=Sum('number_of_carcasses', filter=Q(buy_type='carcass')), + total_kill_house_free_bar_carcass_weight=Sum('weight_of_carcasses', filter=Q(buy_type='carcass')), + total_kill_house_free_bar_carcass_total_weight=Sum('weight_of_carcasses'), + total_kill_house_free_bar_live_warehouse_not_entered_quantity=Sum('quantity', + filter=Q(weight_of_carcasses=0)), + total_kill_house_free_bar_warehouse_not_entered_weight=Sum('live_weight', filter=Q(weight_of_carcasses=0)), + + ) + + kill_house_free_Sale_bar_info = kill_house_free_Sale_bar_informations.aggregate( + total_kill_house_free_Sale_bar_weight=Sum('real_weight_of_carcasses'), + total_kill_house_free_Sale_bar_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_free_Sale_bar_free_weight=Sum('real_weight_of_carcasses', filter=Q(quota='free')), + ) + + kill_house_allocations_info = kill_house_allocations.aggregate( + total_kill_house_allocations_weight=Sum('real_weight_of_carcasses'), + total_kill_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + ) + + segmentations_aggregates_info = segmentations.aggregate( + total_segmentations_weight=Sum('weight'), + total_segmentations_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_segmentations_free_weight=Sum('weight', filter=Q(quota='free')), + ) + cold_house_allocations_info = cold_house_allocations.aggregate( + total_cold_house_allocations_weight=Sum('real_weight_of_carcasses'), + total_cold_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_cold_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + ) + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + total_archive_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_archive_free_weight=Sum('weight', filter=Q(quota='free')), + ) + + return {**province_kill_request_info, **kill_house_request_info, **kill_house_free_bar_info, + **kill_house_free_Sale_bar_info, **kill_house_allocations_info, **segmentations_aggregates_info, + **cold_house_allocations_info, **pos_allocated_weight_info, **archives_info} + + def get_ware_house_info(self, obj): + product_remain_weight = RolesProducts.objects.filter(kill_house=obj, trash=False).only( + 'total_remain_weight').first() + product_remain_weight = product_remain_weight.total_remain_weight if product_remain_weight else 0 + request = self.context.get('request') + date1 = request.GET.get('date1', None) + date2 = request.GET.get('date2', None) + + if date1 and date2: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + total_info = self._calculate_info(obj, date1, date2) if date1 else self._calculate_info(obj) + + total_kill_house_requests_quantity = total_info['total_kill_house_request_quantity'] if total_info[ + 'total_kill_house_request_quantity'] else 0 + total_kill_house_free_bar_quantity = total_info['total_kill_house_free_bar_live_quantity'] if total_info[ + 'total_kill_house_free_bar_live_quantity'] else 0 + total_kill_house_free_bar_carcasses = total_info['total_kill_house_free_bar_carcass_quantity'] if total_info[ + 'total_kill_house_free_bar_carcass_quantity'] else 0 + + total_kill_house_requests_weight = total_info['total_kill_house_request_weight'] if total_info[ + 'total_kill_house_request_weight'] else 0 + total_kill_house_free_bar_weight = total_info['total_kill_house_free_bar_live_weight'] if total_info[ + 'total_kill_house_free_bar_live_weight'] else 0 + total_kill_house_free_bar_carcasses_weight = total_info['total_kill_house_free_bar_carcass_weight'] if \ + total_info['total_kill_house_free_bar_carcass_weight'] else 0 + + total_province_bars = total_info['total_kill_house_request_count'] if total_info[ + 'total_kill_house_request_count'] else 0 + kill_house_free_bar_informations_live = total_info['total_kill_house_free_bar_live_count'] if total_info[ + 'total_kill_house_free_bar_live_count'] else 0 + kill_house_free_bar_informations_carcasses = total_info['total_kill_house_free_bar_carcass_count'] if \ + total_info['total_kill_house_free_bar_carcass_count'] else 0 + total_entered_kill_house_requests_carcasses_weight = total_info['kill_house_request_warehouse_weight'] if \ + total_info['kill_house_request_warehouse_weight'] else 0 + total_entered_kill_house_free_bar_carcasses_weight = total_info[ + 'total_kill_house_free_bar_carcass_total_weight'] if total_info[ + 'total_kill_house_free_bar_carcass_total_weight'] else 0 + + entered_kill_house_request = total_info['total_kill_house_request_warehouse_entered_count'] if total_info[ + 'total_kill_house_request_warehouse_entered_count'] else 0 + entered_free_buying_bars = total_info['total_kill_house_free_bar_warehouse_entered_count'] if total_info[ + 'total_kill_house_free_bar_warehouse_entered_count'] else 0 + + not_entered_kill_house_request = total_info['total_kill_house_request_warehouse_not_entered_count'] if \ + total_info['total_kill_house_request_warehouse_not_entered_count'] else 0 + not_entered_free_buying_bars = total_info['total_kill_house_free_bar_warehouse_not_entered_count'] if \ + total_info['total_kill_house_free_bar_warehouse_not_entered_count'] else 0 + + not_entered_kill_house_request_quantity = total_info[ + 'total_kill_house_request_warehouse_not_entered_quantity'] if total_info[ + 'total_kill_house_request_warehouse_not_entered_quantity'] else 0 + not_entered_free_buying_bars_quantity = total_info[ + 'total_kill_house_free_bar_live_warehouse_not_entered_quantity'] if total_info[ + 'total_kill_house_free_bar_live_warehouse_not_entered_quantity'] else 0 + + not_entered_kill_house_request_weight = total_info['total_kill_house_request_warehouse_not_entered_weight'] if \ + total_info['total_kill_house_request_warehouse_not_entered_weight'] else 0 + not_entered_free_buying_bars_weight = total_info['total_kill_house_free_bar_warehouse_not_entered_weight'] if \ + total_info['total_kill_house_free_bar_warehouse_not_entered_weight'] else 0 + + total_kill_house_allocations_weight = total_info['total_kill_house_allocations_weight'] if \ + total_info['total_kill_house_allocations_weight'] else 0 + + total_kill_house_free_Sale_bar_weight = total_info['total_kill_house_free_Sale_bar_weight'] if \ + total_info['total_kill_house_free_Sale_bar_weight'] else 0 + + total_kill_house_segmentations_weight = total_info['total_segmentations_weight'] if \ + total_info['total_segmentations_weight'] else 0 + total_kill_house_cold_house_allocations_weight = total_info['total_cold_house_allocations_weight'] if \ + total_info['total_cold_house_allocations_weight'] else 0 + + kill_house_request_warehouse_governmental_weight = total_info[ + 'kill_house_request_warehouse_governmental_weight'] if \ + total_info['kill_house_request_warehouse_governmental_weight'] else 0 + + kill_house_request_warehouse_free_weight = total_info['kill_house_request_warehouse_free_weight'] if \ + total_info['kill_house_request_warehouse_free_weight'] else 0 + + total_kill_house_free_Sale_bar_governmental_weight = total_info[ + 'total_kill_house_free_Sale_bar_governmental_weight'] if \ + total_info['total_kill_house_free_Sale_bar_governmental_weight'] else 0 + + total_kill_house_free_Sale_bar_free_weight = total_info['total_kill_house_free_Sale_bar_free_weight'] if \ + total_info['total_kill_house_free_Sale_bar_free_weight'] else 0 + + total_kill_house_allocations_governmental_weight = total_info[ + 'total_kill_house_allocations_governmental_weight'] if \ + total_info['total_kill_house_allocations_governmental_weight'] else 0 + + total_kill_house_allocations_free_weight = total_info['total_kill_house_allocations_free_weight'] if \ + total_info['total_kill_house_allocations_free_weight'] else 0 + + total_segmentations_governmental_weight = total_info['total_segmentations_governmental_weight'] if \ + total_info['total_segmentations_governmental_weight'] else 0 + + total_segmentations_free_weight = total_info['total_segmentations_free_weight'] if \ + total_info['total_segmentations_free_weight'] else 0 + + total_cold_house_allocations_governmental_weight = total_info[ + 'total_cold_house_allocations_governmental_weight'] if \ + total_info['total_cold_house_allocations_governmental_weight'] else 0 + + total_cold_house_allocations_free_weight = total_info['total_cold_house_allocations_free_weight'] if \ + total_info['total_cold_house_allocations_free_weight'] else 0 + + pos_allocated_weight = total_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = total_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = total_info['pos_free_allocated_weight'] or 0 + + total_archive_governmental_weight = total_info['total_archive_governmental_weight'] or 0 + total_archive_free_weight = total_info['total_archive_free_weight'] or 0 + + total_governmental_input_weight = kill_house_request_warehouse_governmental_weight + total_free_input_weight = kill_house_request_warehouse_free_weight + total_entered_kill_house_free_bar_carcasses_weight + total_governmental_output_weight = total_kill_house_free_Sale_bar_governmental_weight + total_kill_house_allocations_governmental_weight + total_segmentations_governmental_weight + total_cold_house_allocations_governmental_weight + int(pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_kill_house_free_Sale_bar_free_weight + total_kill_house_allocations_free_weight + total_segmentations_free_weight + total_cold_house_allocations_free_weight + int(pos_free_allocated_weight / 1000) + total_governmental_remain_weight = (total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight if ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight > 0 else 0 + last_total_governmental_remain_weight = ( + (total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight) * -1 if ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight < 0 else 0 + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - total_archive_free_weight if ( + total_free_input_weight - total_free_output_weight) - total_archive_free_weight > 0 else 0 + last_total_free_remain_weight = ((total_free_input_weight - total_free_output_weight) - total_archive_free_weight) * -1 if ( + total_free_input_weight - total_free_output_weight) - total_archive_free_weight < 0 else 0 + last_total_remain_weight = last_total_governmental_remain_weight + last_total_free_remain_weight + warehouse_total_weight = total_kill_house_requests_weight + total_kill_house_free_bar_weight + total_kill_house_free_bar_carcasses_weight + warehouse_total_entered_carcasses_weight = total_entered_kill_house_requests_carcasses_weight + total_entered_kill_house_free_bar_carcasses_weight + difference_weight = warehouse_total_entered_carcasses_weight - ( + total_kill_house_allocations_weight + total_kill_house_free_Sale_bar_weight + total_kill_house_segmentations_weight + total_kill_house_cold_house_allocations_weight) + final_difference_weight = difference_weight if difference_weight > 0 else (-1) * difference_weight + total_sell = total_kill_house_allocations_weight + total_kill_house_free_Sale_bar_weight + total_kill_house_segmentations_weight + total_kill_house_cold_house_allocations_weight + + return { + "product_remain_weight": product_remain_weight, + "previous_product_remain_weight": int(product_remain_weight + final_difference_weight) if date1 else 0, + "total_sell": total_sell, + "total_province_bars": total_province_bars, + "total_province_bars_quantity": total_info['total_kill_house_request_quantity'] if total_info[ + 'total_kill_house_request_quantity'] else 0, + "total_province_bars_weight": total_info['total_kill_house_request_weight'] if total_info[ + 'total_kill_house_request_weight'] else 0, + "total_kill_house_free_bar": total_info['total_kill_house_free_bar_live_count'] if total_info[ + 'total_kill_house_free_bar_live_count'] else 0, + "total_kill_house_free_live_bar_quantity": total_info['total_kill_house_free_bar_live_quantity'] if + total_info['total_kill_house_free_bar_live_quantity'] else 0, + "total_kill_house_free_live_bar_weight": total_info['total_kill_house_free_bar_live_weight'] if total_info[ + 'total_kill_house_free_bar_live_weight'] else 0, + "total_kill_house_free_carcasses_bar": total_info['total_kill_house_free_bar_carcass_count'] if total_info[ + 'total_kill_house_free_bar_carcass_count'] else 0, + "total_kill_house_free_bar_carcasses": total_info['total_kill_house_free_bar_carcass_quantity'] if + total_info['total_kill_house_free_bar_carcass_quantity'] else 0, + "total_kill_house_free_bar_carcasses_weight": total_info['total_kill_house_free_bar_carcass_weight'] if + total_info['total_kill_house_free_bar_carcass_weight'] else 0, + "province_kill_requests": total_info['total_province_kill_request_count'] if total_info[ + 'total_province_kill_request_count'] else 0, + "province_kill_requests_quantity": total_info['total_province_kill_request_quantity'] if total_info[ + 'total_province_kill_request_quantity'] else 0, + "province_kill_requests_weight": total_info['total_province_kill_request_weight'] if total_info[ + 'total_province_kill_request_weight'] else 0, + + "total_bars": total_province_bars + kill_house_free_bar_informations_live + kill_house_free_bar_informations_carcasses, + "warehouse_total_quantity": total_kill_house_requests_quantity + total_kill_house_free_bar_quantity + total_kill_house_free_bar_carcasses, + "warehouse_total_weight": warehouse_total_weight, + "warehouse_total_entered_bars": entered_kill_house_request + entered_free_buying_bars, + "warehouse_total_entered_carcasses_weight": warehouse_total_entered_carcasses_weight, + "warehouse_total_not_entered_bars": not_entered_kill_house_request + not_entered_free_buying_bars, + + "warehouse_total_not_entered_bars_quantity": not_entered_kill_house_request_quantity + not_entered_free_buying_bars_quantity, + "warehouse_total_not_entered_bars_weight": not_entered_kill_house_request_weight + not_entered_free_buying_bars_weight, + "total_kill_house_allocations_weight": total_info['total_kill_house_allocations_weight'] if total_info[ + 'total_kill_house_allocations_weight'] else 0, + "total_kill_house_free_sale__bar_carcasses_weight": total_info['total_kill_house_free_Sale_bar_weight'] if + total_info['total_kill_house_free_Sale_bar_weight'] else 0, + "total_kill_house_segmentations_weight": total_kill_house_segmentations_weight, + "total_kill_house_cold_house_allocations_weight": total_kill_house_cold_house_allocations_weight, + "total_governmental_input_weight": total_governmental_input_weight, + "total_free_input_weight": total_free_input_weight, + "total_governmental_output_weight": total_governmental_output_weight, + "total_free_output_weight": total_free_output_weight, + "total_governmental_remain_weight": total_governmental_remain_weight, + "total_free_remain_weight": total_free_remain_weight, + "last_total_governmental_remain_weight": last_total_governmental_remain_weight, + "last_total_free_remain_weight": last_total_free_remain_weight, + "last_total_remain_weight": last_total_remain_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "total_archive_governmental_weight": total_archive_governmental_weight, + "total_archive_free_weight": total_archive_free_weight, + + } + + +class KillHouseForFreeBarWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_weight = 0 + total_wage = 0 + total_quantity = 0 + type = self.context.get('request').GET['type'] + role = self.context.get('request').GET['role'] + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, buy_type=type, + trash=False) + + elif role == 'ProvinceOperator': + wage_type = 'union_share' + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, buy_type=type, + union_share__gt=0, trash=False) + + elif role == 'Company': + wage_type = 'company_share' + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, buy_type=type, + company_share__gt=0, trash=False) + + elif role == 'Guilds': + wage_type = 'guilds_share' + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, buy_type=type, + guilds_share__gt=0, trash=False) + + else: + wage_type = 'wallet_share' + + if type == 'live': + + total_weight += free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_quantity += free_bars.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_wage += free_bars.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + else: + + total_weight += free_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_quantity += free_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + + total_wage += free_bars.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(free_bars), + "total_weight": total_weight, + "total_quantity": total_quantity, + "total_wage": total_wage, + + } + + +class KillHouseForProvinceWageWithDateSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + role = self.context.get('request').GET['role'] + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + union_share__gt=0, + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'Company': + wage_type = 'company_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + company_share__gt=0, + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).select_related( + 'province_request__poultry_request') + elif role == 'Guilds': + wage_type = 'guilds_share' + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + guilds_share__gt=0, + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).select_related( + 'province_request__poultry_request') + else: + wage_type = 'wallet_share' + + total_quantity += province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + + total_weight += province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + total_wage += province_kill_requests.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(province_kill_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_wage": total_wage, + + } + + +class KillHouseForKillHouseRequestWageWithDateSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + # role = self.context.get('request').GET['role'] + kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + archive_wage=False, + trash=False) + + total_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + + total_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(kill_house_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + + } + + +# class KillHouseForProvinceWageWithDateSerializer(serializers.ModelSerializer): +# info = serializers.SerializerMethodField('get_info') +# +# class Meta: +# model = KillHouse +# fields = ['key', 'info'] +# +# def get_info(self, obj): +# total_count = 0 +# paid_count = 0 +# unpaid_count = 0 +# archive_count = 0 +# total_quantity = 0 +# total_weight_unpaid = 0 +# total_weight_archive = 0 +# total_weight_paid = 0 +# total_unpaid_wage = 0 +# total_archive_wage = 0 +# total_paid_wage = 0 +# total_paid_quantity = 0 +# total_unpaid_quantity = 0 +# total_archive_quantity = 0 +# total_quantity_sale_free = 0 +# total_quantity_sale_government = 0 +# total_weight_sale_free = 0 +# total_wage = 0 +# total_weight_sale_government = 0 +# date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() +# role = self.context.get('request').GET['role'] +# province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, +# state__in=('pending', 'accepted'), +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).select_related( +# 'province_request__poultry_request') +# # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, +# # state__in=('pending', 'accepted'), +# # return_to_province=False, +# # trash=False).select_related( +# # 'province_request__poultry_request') +# total_count = len(province_kill_requests) +# total_quantity = province_kill_requests.aggregate(total_quantity=Sum('total_killed_quantity')).get( +# 'total_quantity', 0) +# +# for province_kill_request in province_kill_requests: +# if province_kill_request.wage_pay == True: +# paid_count += 1 +# total_paid_quantity += province_kill_request.total_killed_quantity +# total_paid_wage += province_kill_request.total_killed_weight * province_kill_request.wage +# # total_paid_wage += int(province_kill_request.depositor['total_amount']) +# total_weight_paid += province_kill_request.total_killed_weight +# elif province_kill_request.wage_pay == False and province_kill_request.archive_by_province == False: +# unpaid_count += 1 +# total_unpaid_quantity += province_kill_request.total_killed_quantity +# total_unpaid_wage += province_kill_request.total_killed_weight * province_kill_request.wage +# total_weight_unpaid += province_kill_request.total_killed_weight +# +# else: +# archive_count += 1 +# total_archive_quantity += province_kill_request.total_killed_quantity +# total_archive_wage += province_kill_request.total_killed_weight * province_kill_request.wage +# total_weight_archive += province_kill_request.total_killed_weight +# if province_kill_request.province_request.poultry_request.free_sale_in_province == True: +# total_quantity_sale_free += province_kill_request.total_killed_quantity +# total_weight_sale_free += province_kill_request.total_killed_weight +# +# else: +# total_quantity_sale_government += province_kill_request.total_killed_quantity +# total_weight_sale_government += province_kill_request.total_killed_weight +# total_wage = total_paid_wage + total_unpaid_wage +# +# gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) +# union = gate_way_percentage.union / 100 if gate_way_percentage.union > 0 else 0 +# +# if role == 'ProvinceOperator': +# total_wage = (total_paid_wage + total_unpaid_wage) * union +# total_paid_wage = total_paid_wage * union +# total_unpaid_wage = total_unpaid_wage * union +# total_archive_wage = total_archive_wage * union +# +# return { +# "killer": obj.killer, +# "kill_house_fullname": obj.kill_house_operator.user.fullname, +# "kill_house_name": obj.name, +# "kill_house_mobile": obj.kill_house_operator.user.mobile, +# "kill_house_city": obj.kill_house_operator.user.city.name, +# "total_count": total_count, +# "paid_count": paid_count, +# "unpaid_count": unpaid_count, +# "archive_count": archive_count, +# "total_quantity": total_quantity, +# "total_weight": int(total_weight_paid + total_weight_unpaid), +# "total_weight_paid": int(total_weight_paid), +# "total_weight_archive": int(total_weight_archive), +# "total_weight_unpaid": int(total_weight_unpaid), +# "total_paid_wage": total_paid_wage, +# "total_unpaid_wage": total_unpaid_wage, +# "total_archive_wage": total_archive_wage, +# # "total_wage": total_paid_wage + total_unpaid_wage, +# "total_wage": total_wage, +# "total_unpaid_quantity": total_unpaid_quantity, +# "total_paid_quantity": total_paid_quantity, +# "total_archive_quantity": total_archive_quantity, +# "total_quantity_sale_free": total_quantity_sale_free, +# "total_weight_sale_free": total_weight_sale_free, +# "total_quantity_sale_government": total_quantity_sale_government, +# "total_weight_sale_government": total_weight_sale_government, +# +# } +class KillHouseForTotalProvinceWageTransactionWithDAteSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_paid_wage = 0 + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + role = self.context.get('request').GET['role'] + if role in ['KillHouse', 'AdminX', 'Supporter']: + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('id') + elif role == 'SuperAdmin': + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + company_share__gt=0, + date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + guilds_share__gt=0, + date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + + total_paid_wage += transactions.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + if role == 'SuperAdmin': + total_paid_wage -= transactions.aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_paid_count": len(transactions), + "total_paid_wage": total_paid_wage, + + } + + +class KillHouseForTotalProvinceWageTransactionSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_paid_wage = 0 + role = self.context.get('request').GET['role'] + # transactions = InternalTransaction.objects.filter( + # Q(kill_house=obj) | Q(parent_kill_house=obj), + # status='completed', + # trash=False).order_by('id') + if role in ['KillHouse', 'AdminX', 'Supporter']: + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + trash=False).order_by('id') + elif role == 'SuperAdmin': + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + union_share__gt=0, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + company_share__gt=0, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + guilds_share__gt=0, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + + total_paid_wage += transactions.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + if role == 'SuperAdmin': + total_paid_wage -= transactions.aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_paid_count": len(transactions), + "total_paid_wage": total_paid_wage, + + } + + +class KillHouseForFreeBarWageWithDateSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'info'] + + def get_info(self, obj): + total_weight = 0 + total_wage = 0 + total_quantity = 0 + type = self.context.get('request').GET['type'] + role = self.context.get('request').GET['role'] + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + elif role == 'ProvinceOperator': + wage_type = 'union_share' + elif role == 'Company': + wage_type = 'company_share' + elif role == 'Company': + wage_type = 'company_share' + else: + wage_type = 'wallet_share' + + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + trash=False) + if type == 'live': + + total_weight += free_bars.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_quantity += free_bars.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_wage += free_bars.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + else: + + total_weight += free_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_quantity += free_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + + total_wage += free_bars.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "killer": obj.killer, + "kill_house_fullname": obj.kill_house_operator.user.fullname, + "kill_house_name": obj.name, + "kill_house_mobile": obj.kill_house_operator.user.mobile, + "kill_house_city": obj.kill_house_operator.user.city.name, + "total_count": len(free_bars), + "total_weight": total_weight, + "total_quantity": total_quantity, + "total_wage": total_wage, + + } + + +class KillHouseForFreeSaleBarInformationViewSetWithDateSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'kill_house_operator', 'info'] + + def get_info(self, obj): + role = self.context.get('request').GET['role'] + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=obj, trash=False) + + total_carcasses = free_sale_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sale_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + return { + "number_of_buyers": len(buyers), + "total_number_of_carcasses": total_carcasses, + "total_weight_of_carcasses": total_weight, + + } + + +class KillHouseForFreeSaleBarInformationViewSetSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'kill_house_operator', 'info'] + + def get_info(self, obj): + free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=obj, + trash=False) + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=obj, trash=False) + + total_carcasses = free_sale_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sale_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + return { + "number_of_buyers": len(buyers), + "total_number_of_carcasses": total_carcasses, + "total_weight_of_carcasses": total_weight, + + } + + +class GeneralKillHouseSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForKillHouseDriverSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'name', 'killer', 'kill_house_operator', 'union_gateway_percent', 'company_gateway_percent', + 'guilds_gateway_percent', 'other_gateway_percent'] + + +class PosGeneralKillHouseSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouse + fields = ['key', 'name', 'killer'] + + +# سریالایزر مربوط به کشتارگاه +class KillHouseSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorSerializer(read_only=True) + system_address = SystemAddressSerializer(read_only=True) + allow_state = serializers.SerializerMethodField('get_register_state') + allow_direct_buying = serializers.SerializerMethodField('get_allow_direct_buying') + kill_place = serializers.SerializerMethodField('get_kill_place') + debt = serializers.SerializerMethodField('get_debt') + + # kill_request_quantity = serializers.SerializerMethodField('get_kill_request_remain_quantity') + + class Meta: + model = KillHouse + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + ) + + def get_kill_place(self, instance): + place = None + percentage = KillHousePercentage.objects.filter(kill_house=instance) + if percentage.count() > 0: + percentage = percentage.last() + if percentage.kill_house_for_killer != None: + place = percentage.kill_house_for_killer.name + else: + place = percentage.kill_house.name + + return place + + def get_allow_direct_buying(self, obj): + allow_state = False + allow = ProvinceAllowKillHouseDirectBuying.objects.filter(kill_house=obj) + if allow.count() > 0: + allow_state = allow.last().allow + + return allow_state + + def get_register_state(self, instance): + allow_state = None + allow = ProvinceAllowKillHouseRegisterCar.objects.filter(kill_house=instance) + if allow.count() > 0: + allow_state = allow.last().allow + + return allow_state + + def get_debt(self, instance): + debt = False + if KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__killhouse_user=instance, + state='pending').exists(): + debt = True + + return debt + + # def get_kill_request_remain_quantity(self, obj): + # quantity_sum = 0 + # kill_req_key = None + # now = datetime.datetime.now().date() + # kill_request = KillRequest.objects.filter(kill_house=obj, recive_date__year=now.year, + # recive_date__month=now.month, recive_date__day=now.day, + # trash=False).last() + # + # if kill_request: + # quantity_sum = kill_request.remain_quantity_for_poultry + # kill_req_key = kill_request.key + # + # return { + # "quantity_sum": quantity_sum, + # "kill_req_key": kill_req_key, + # } + + +class PosKillHouseSerializer(serializers.ModelSerializer): + shop_name = serializers.CharField(source='name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'shop_name', 'fullname', 'mobile'] + + +class PspKillHouseSerializer(serializers.ModelSerializer): + unit_name = serializers.CharField(source='name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + city = serializers.CharField(source='kill_house_operator.user.city.name', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'unit_name', 'fullname', 'mobile','city','killer'] + + +class distributionKillHouseSerializer(serializers.ModelSerializer): + shop_name = serializers.CharField(source='name', read_only=True) + fullname = serializers.CharField(source='kill_house_operator.user.fullname', read_only=True) + mobile = serializers.CharField(source='kill_house_operator.user.mobile', read_only=True) + shop_type = serializers.SerializerMethodField('get_type') + + class Meta: + model = KillHouse + fields = ['key', 'shop_name', 'fullname', 'mobile', 'shop_type'] + + def get_type(self, obj): + obj_type = 'کشتارکن' if obj.killer else 'کشتارگاه' + + return obj_type + + +class KillHouseAllowVetSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseAllowVet + fields = '__all__' + + +class KillHousePercentageSerializer(serializers.ModelSerializer): + kill_house = KillHouseForKillHousePercentageSerializer(read_only=True) + kill_house_for_killer = KillHouseForProvinceSerializer(read_only=True) + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + + # kill_house = KillHouseSerializer(read_only=True) + # kill_house_for_killer = KillHouseSerializer(read_only=True) + + class Meta: + model = KillHousePercentage + fields = ['key', 'guilds_quantity', 'guilds_weight', 'kill_house', 'kill_house_for_killer', 'percent', + 'last_guilds_update_date', 'kill_house_vet'] + # fields = '__all__' + + def get_kill_house_vet(self, obj): + if obj.kill_house_for_killer != None: + kill_house_vet = KillHouseVet.objects.filter(kill_house=obj.kill_house_for_killer, trash=False).last() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=obj.kill_house, trash=False).last() + + if kill_house_vet != None: + serializer = KillHouseVetForKillHousePercentageSerializer(kill_house_vet) + return serializer.data + return None + + +class KillHousePercentageForKillerKillHousseSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + + # kill_house_for_killer = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHousePercentage + fields = ['kill_house'] + # fields = ['kill_house_for_killer'] + + +class KillHouseADDCARForKillHouseDriverSerializer(serializers.ModelSerializer): + kill_house = KillHouseForKillHouseDriverSerializer(read_only=True) + + class Meta: + model = KillHouseADDCAR + fields = ['kill_house'] + + +class KillHouseDriverForAllUserSerializer(serializers.ModelSerializer): + user_bank_info = BankCardSerializer(read_only=True, required=False) + byers = serializers.SerializerMethodField('get_buyers') + + class Meta: + model = KillHouseDriver + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date', + 'status', + 'wallet', + 'wallet_amount', + 'registrar', + 'user', + 'weight_without_load', + ) + + def get_buyers(self, obj): + cars = KillHouseADDCAR.objects.filter(driver__exact=obj) + return KillHouseADDCARForKillHouseDriverSerializer(cars, many=True).data + + +# سریالایزر مربوط به اضافه کردن راننده به کشتارگاه +class KillHouseDriverSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True, required=False) + user_bank_info = BankCardSerializer(read_only=True, required=False) + first_name_last_name = serializers.SerializerMethodField('get_first_name_last_name') + + class Meta: + model = KillHouseDriver + fields = '__all__' + extra_kwargs = { + 'capocity': {'required': False}, + 'weight_without_load': {'required': False} + } + + def get_first_name_last_name(self, instance): + user_dict = {} + user = SystemUserProfile.objects.get( + key=instance.user.key) + user_dict = { + "first_name": user.first_name, + "last_name": user.last_name, + } + + return user_dict + + +class KillHouseDriverForBarManagementSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouseDriver + fields = ['driver_name', 'driver_mobile', 'type_car', 'pelak', 'health_code'] + + +# سریالایزر مربوط به اضافه کردن خودرو به کشتارگاه +class KillHouseADDCARSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + driver = KillHouseDriverSerializer(read_only=True) + + class Meta: + model = KillHouseADDCAR + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + ) + + +class KillHouseADDCARForBarManagementSerializer(serializers.ModelSerializer): + driver = KillHouseDriverForBarManagementSerializer(read_only=True) + + class Meta: + model = KillHouseADDCAR + fields = ['driver'] + + +class VetForBarManagementSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['user'] + + +class VetFarmForBarManagementSerializer(serializers.ModelSerializer): + vet = VetForBarManagementSerializer(read_only=True) + + class Meta: + model = VetFarm + fields = ['vet'] + + +# سریالایزر مربوط به ثبت نماینده کشتارگاه +class VetSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True) + farms = serializers.SerializerMethodField('get_farms') + kill_houses = serializers.SerializerMethodField('get_kill_houses') + + class Meta: + model = Vet + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by', + ) + + def get_farms(self, instance): + farms_list = [] + farms = VetFarm.objects.filter(vet=instance, trash=False).select_related('poultry', 'vet') + if farms.count() > 0: + for farm in farms: + internal_dict = { + "poultry_name": farm.poultry.unit_name, + "poultry_full_name": farm.poultry.user.fullname, + "poultry_mobile": farm.poultry.user.mobile, + "poultry_hall": farm.hall, + "vet_id": farm.vet.id, + "vet_farm_key": farm.key, + } + farms_list.append(internal_dict) + + return farms_list + + def get_kill_houses(self, instance): + kill_houses_list = [] + kill_house_vets = KillHouseVet.objects.filter(vet=instance, trash=False).select_related( + 'kill_house__kill_house_operator__user') + if kill_house_vets.count() > 0: + for kill_house_vet in kill_house_vets: + internal_dict = { + "Kill_house_key": kill_house_vet.kill_house.key, + "Kill_house_name": kill_house_vet.kill_house.name, + "Kill_house_user_full_name": kill_house_vet.kill_house.kill_house_operator.user.fullname, + "Kill_house_user_mobile": kill_house_vet.kill_house.kill_house_operator.user.mobile, + } + kill_houses_list.append(internal_dict) + + return kill_houses_list + + +class KillHouseVetSerializer(serializers.ModelSerializer): + vet = VetSerializer(read_only=True) + kill_house = KillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseVet + fields = '__all__' + + +class VetForKillRequestSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['user'] + + +class KillHouseVetForKillRequestSerializer(serializers.ModelSerializer): + vet = VetForKillRequestSerializer(read_only=True) + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseVet + fields = '__all__' + + +class KillHouseVetForKillHousePercentageSerializer(serializers.ModelSerializer): + vet = VetForKillRequestSerializer(read_only=True) + + class Meta: + model = KillHouseVet + fields = ['vet'] + + +class KillRequestForBarManagementSerializer(serializers.ModelSerializer): + class Meta: + model = KillRequest + fields = ['recive_date'] + + +# سریالایزر مربوط به ثبت درخواست کشتار توسط کشتارگاه +class KillRequestSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + poultry = PoultrySerializer(read_only=True) + slaughter_house = KillHouseForAutoAllocationSerializer(read_only=True) + # kill_house = KillHouseSerializer(read_only=True) + # slaughter_house = KillHouseSerializer(read_only=True) + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + number_of_allocated = serializers.SerializerMethodField('get_number_of_allocated') + poultry_hatching = PoultryHatchingSerializer(read_only=True) + + # kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + # number_of_allocated = serializers.SerializerMethodField('get_number_of_allocated') + + class Meta: + model = KillRequest + fields = '__all__' + + # def get_kill_house_vet(self, instance): + # vet = None + # kill_house_vet = KillHouseVet.objects.filter(kill_house=instance.kill_house, trash=False) + # if kill_house_vet.count() > 0: + # kill_house_vet = kill_house_vet.last() + # vet = { + # "kill_house_vet_full_name": kill_house_vet.vet.user.fullname, + # "kill_house_vet_mobile": kill_house_vet.vet.user.mobile, + # } + # + # return vet + + def get_kill_house_vet(self, obj): + kill_house_vet = KillHouseVet.objects.filter(kill_house__exact=obj.kill_house, trash=False).last() + if kill_house_vet: + return KillHouseVetForKillRequestSerializer(kill_house_vet).data + else: + return None + + # + # def get_number_of_allocated(self, instance): + # quantity = 0 + # province_kill_request = ProvinceKillRequest.objects.filter(kill_request=instance, + # state__in=('pending', 'accepted'), + # trash=False) + # if province_kill_request.count() > 0: + # quantity = province_kill_request.count() + # + # return quantity + + def get_number_of_allocated(self, instance): + return instance.kill_capacity - instance.remain_quantity + + +class KillHouseDailyQuotaSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + killer_kill_house = KillHouseSerializer(read_only=True) + kill_request = KillRequestSerializer(read_only=True) + + class Meta: + model = KillHouseDailyQuota + fields = '__all__' + + +class AutomaticKillRequestSerializer(serializers.ModelSerializer): + class Meta: + model = AutomaticKillRequest + fields = '__all__' + + +class KillRequestFactorSerializer(serializers.ModelSerializer): + kill_request = KillRequestSerializer(read_only=True) + + class Meta: + model = KillRequestFactor + fields = '__all__' + + +class KillRequestFactorPaymentSerializer(serializers.ModelSerializer): + kill_request_factor = KillRequestFactorSerializer(read_only=True) + + class Meta: + model = KillRequestFactorPayment + fields = '__all__' + + +class KillHouseRequestForColdHouseAllocationsSerializer(serializers.ModelSerializer): + kill_house_request_info = serializers.SerializerMethodField('get_kill_house_request_info') + + class Meta: + model = KillHouseRequest + fields = ['key', 'kill_house_request_info'] + + def get_kill_house_request_info(self, obj): + return { + "poultry_fullname": obj.province_request.poultry_request.poultry.user.fullname, + "poultry_mobile": obj.province_request.poultry_request.poultry.user.mobile, + "poultry_name": obj.province_request.poultry_request.poultry.unit_name, + "kill_house_name": obj.killhouse_user.name, + "kill_house_fullname": obj.killhouse_user.kill_house_operator.user.fullname, + "kill_house_mobile": obj.killhouse_user.kill_house_operator.user.mobile, + "quantity": obj.ware_house_accepted_real_quantity, + "weight": obj.ware_house_accepted_real_weight, + } + + +# سریالایزر مربوط به ثبت درخواست کشتار بعد از تخصیص استان +class KillHouseRequestSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseSerializer(read_only=True) + kill_request = KillRequestSerializer(read_only=True) + add_car = KillHouseADDCARSerializer(read_only=True) + poultry = serializers.SerializerMethodField('get_poultry') + + class Meta: + model = KillHouseRequest + fields = '__all__' + + def get_poultry(self, instance): + poultry = Poultry.objects.get( + key=instance.province_kill_request.province_request.poultry_request.poultry.key) + poultry_dict = { + "poultry_name": poultry.unit_name, + "poultry_mobile": poultry.user.mobile, + "poultry_address": poultry.address.address, + "poultry_city": poultry.address.city.name, + "poultry_province": poultry.address.province.name, + } + + return poultry_dict + + +class KillHouseRequestForDiffrentBarInfoSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + kill_request = KillRequestForBarManagementSerializer(read_only=True) + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + weight_info = serializers.SerializerMethodField('get_weight_info') + + class Meta: + model = KillHouseRequest + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + 'killhouse_user_id_foreign_key', + 'kill_request_id_foreign_key', + 'province_request_id_foreign_key', + 'province_kill_request_id_foreign_key', + 'add_car_id_foreign_key', + 'kill_house_request_id_key', + 'capacity', + 'kill_house_request_auction_winner', + 'city_number', + 'city_name', + 'province_number', + 'province_name', + 'province_request', + 'province_kill_request', + + ) + + def get_weight_info(self, obj): + index_weight = 0 + weight = 0 + assignment_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request=obj).last() + assingment_quantity = assignment_info.real_quantity + assingment_weight = assignment_info.net_weight + kill_house_vet_quantity = obj.vet_accepted_real_quantity + kill_house_vet_weight = obj.vet_accepted_real_weight + quantity = obj.quantity + weight = int(obj.quantity * obj.province_request.poultry_request.Index_weight) + + return {"assingment_quantity": assingment_quantity, + "assingment_weight": assingment_weight, + "kill_house_vet_quantity": kill_house_vet_quantity, + "kill_house_vet_weight": kill_house_vet_weight, + "quantity": quantity, + "weight": weight, + + } + + +class KillHouseRequestForBarManagementSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + killer = KillHouseForAutoAllocationSerializer(read_only=True) + bar_document_status = BarDocumentStatusSerializer(read_only=True) + kill_request = KillRequestForBarManagementSerializer(read_only=True) + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + real_add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + poultry_request = serializers.SerializerMethodField('get_poultry_request') + kill_place = serializers.SerializerMethodField('get_kill_place') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + weight_info = serializers.SerializerMethodField('get_weight_info') + assignment_info = serializers.SerializerMethodField('get_assignment_info') + final_bar_state = serializers.SerializerMethodField('get_final_bar_state') + + class Meta: + model = KillHouseRequest + exclude = ( + 'id', + # 'create_date', + # 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + 'killhouse_user_id_foreign_key', + 'kill_request_id_foreign_key', + 'province_request_id_foreign_key', + 'province_kill_request_id_foreign_key', + 'add_car_id_foreign_key', + 'kill_house_request_id_key', + 'capacity', + 'kill_house_request_auction_winner', + 'city_number', + 'city_name', + 'province_number', + 'province_name', + 'province_request', + 'province_kill_request', + + ) + + def get_poultry_request(self, obj): + poultry_request = PoultryRequest.objects.get( + key=obj.province_kill_request.province_request.poultry_request.key) + serializer = PoultryRequestForBarMangementSerializer(poultry_request) + return serializer.data + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_vet_farm(self, obj): + vet_farm = VetFarm.objects.filter( + poultry=obj.province_kill_request.province_request.poultry_request.poultry).last() + serializer = VetFarmForBarManagementSerializer(vet_farm) + return serializer.data + + def get_kill_house_vet(self, obj): + data = None + kill_request = KillRequest.objects.get(key=obj.kill_request.key) + if kill_request.slaughter_house != None: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.slaughter_house).select_related( + 'vet__user').first() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + 'vet__user').first() + if kill_house_vet: + data = { + "fullname": kill_house_vet.vet.user.fullname, + "mobile": kill_house_vet.vet.user.mobile, + } + return data + + def get_weight_info(self, obj): + first_index_weight = round((obj.quantity * obj.province_request.poultry_request.Index_weight) / obj.quantity, + 1) if obj.quantity > 0 else 0 + first_weight = int(obj.quantity * obj.province_request.poultry_request.Index_weight) + final_index_weight = round(obj.accepted_real_weight / obj.accepted_real_quantity, + 1) if obj.accepted_real_quantity > 0 else 0 + kill_house_price = obj.province_kill_request.kill_house_price + weight_loss = obj.accepted_real_weight - obj.ware_house_accepted_real_weight if obj.ware_house_accepted_real_weight \ + < obj.accepted_real_weight and obj.ware_house_accepted_real_weight != 0 else 0 + total_weight_loss = (weight_loss / obj.accepted_real_weight) * 100 if weight_loss != 0 else 0 + + initial_to_quarantine_ratio = round((obj.quarantine_quantity / obj.quantity) * 100, + 1) if obj.quantity > 0 and obj.quarantine_quantity else 0 + + quarantine_to_final_ratio = round((obj.quarantine_quantity / obj.accepted_real_quantity) * 100, + 1) if obj.accepted_real_quantity > 0 and obj.quarantine_quantity else 0 + + return {"index_weight": first_index_weight, + "weight": first_weight, + "final_index_weight": final_index_weight, + "kill_house_price": kill_house_price, + "weight_loss": round(total_weight_loss, 1), + "input_loss": obj.weight_loss, + "initial_to_quarantine_ratio": initial_to_quarantine_ratio, + "quarantine_to_final_ratio": quarantine_to_final_ratio, + } + + def get_assignment_info(self, obj): + assignment_state = False + state = None + assignment_key = None + net_weight = 0 + real_quantity = 0 + car_weight_without_load = 0 + car_weight_with_load = 0 + image_with_bar = image_without_bar = None + assignment = KillHouseAssignmentInformation.objects.filter(trash=False, kill_house_request=obj).first() + if assignment: + assignment_state = True + image_without_bar = assignment.car_weight_without_load_image + image_with_bar = assignment.car_weight_with_load_image + car_weight_without_load = assignment.car_weight_without_load + car_weight_with_load = assignment.car_weight_with_load + net_weight = assignment.net_weight + real_quantity = assignment.real_quantity + state = assignment.state + assignment_key = assignment.key + + return {"assignment_state": assignment_state, + "image_without_bar": image_without_bar, + "image_with_bar": image_with_bar, + "car_weight_without_load": car_weight_without_load, + "car_weight_with_load": car_weight_with_load, + "net_weight": net_weight, + "state": state, + "real_quantity": real_quantity, + "assignment_key": assignment_key + } + + def get_final_bar_state(self, obj): + final_state = 'در انتظار ورود اطلاعات' + if obj.ware_house_confirmation and obj.assignment_state_archive == 'True': + final_state = 'تکمیل شده' + elif obj.assignment_state_archive == 'True' and not obj.ware_house_confirmation: + final_state = 'در انتظار ورود به انبار' + elif obj.assignment_state_archive == 'pending' and obj.ware_house_confirmation: + final_state = 'در انتظار ورود اطلاعات بار' + else: + final_state = 'در انتظار ورود اطلاعات' + + return final_state + + +class KillHouseRequestForInputBarsSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + killer = KillHouseForAutoAllocationSerializer(read_only=True) + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + poultry_request = serializers.SerializerMethodField('get_poultry_request') + weight_info = serializers.SerializerMethodField('get_weight_info') + + class Meta: + model = KillHouseRequest + exclude = ( + 'id', + # 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + 'killhouse_user_id_foreign_key', + 'kill_request_id_foreign_key', + 'province_request_id_foreign_key', + 'province_kill_request_id_foreign_key', + 'add_car_id_foreign_key', + 'kill_house_request_id_key', + 'capacity', + 'kill_house_request_auction_winner', + 'city_number', + 'city_name', + 'province_number', + 'province_name', + 'province_request', + 'province_kill_request', + + ) + + def get_poultry_request(self, obj): + poultry_request = PoultryRequest.objects.get( + key=obj.province_kill_request.province_request.poultry_request.key) + return { + "poultry_req_order_code": poultry_request.order_code, + "poultry_name": poultry_request.poultry.unit_name, + "poultry_user_name": poultry_request.poultry.user.fullname, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_city": poultry_request.poultry.address.city.name, + "chicken_breed": poultry_request.chicken_breed, + "date": poultry_request.send_date, + "freezing": poultry_request.freezing, + "export": poultry_request.export, + "free_sale_in_province": poultry_request.free_sale_in_province, + "direct_buying": poultry_request.direct_buying, + } + + # def get_vet_info(self, obj): + # vet_farm_name = None + # vet_farm_mobile = None + # kill_house_vet_name = None + # kill_house_vet_mobile = None + # vet_farm = VetFarm.objects.filter( + # poultry=obj.province_kill_request.province_request.poultry_request.poultry).last() + # + # if vet_farm: + # vet_farm_name = vet_farm.vet.user.mobile + # vet_farm_mobile = vet_farm.vet.user.fullname + # kill_request = KillRequest.objects.get(key=obj.kill_request.key, trash=False) + # if kill_request.slaughter_house != None: + # kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.slaughter_house).select_related( + # 'vet__user').first() + # if kill_house_vet: + # kill_house_vet_name=kill_house_vet.vet.user.fullname + # kill_house_vet_mobile=kill_house_vet.vet.user.mobile + # else: + # kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + # 'vet__user').first() + # if kill_house_vet: + # kill_house_vet_name=kill_house_vet.vet.user.fullname + # kill_house_vet_mobile=kill_house_vet.vet.user.mobilee + # data = { + # "vet_farm_name": vet_farm_name, + # "vet_farm_mobile": vet_farm_mobile, + # "kill_house_vet_name": kill_house_vet_name, + # "kill_house_vet_mobile": kill_house_vet_mobile, + # } + # return data + + def get_weight_info(self, obj): + if obj.ware_house_confirmation == True: + state = 'ورود به انبار' + + elif obj.assignment_state_archive == 'pending': + state = 'در انتظار تکمیل اطلاعات' + + else: + state = 'تکمیل اطلاعات' + + first_index_weight = round((obj.quantity * obj.province_request.poultry_request.Index_weight) / obj.quantity, 1) + first_weight = int(obj.quantity * obj.province_request.poultry_request.Index_weight) + final_index_weight = round(obj.accepted_real_weight / obj.accepted_real_quantity, 1) + kill_house_price = obj.province_kill_request.kill_house_price + weight_loss = obj.accepted_real_weight - obj.ware_house_accepted_real_weight if obj.ware_house_accepted_real_weight \ + < obj.accepted_real_weight and obj.ware_house_accepted_real_weight != 0 else 0 + total_weight_loss = (weight_loss / obj.accepted_real_weight) * 100 if weight_loss != 0 else 0 + return {"index_weight": first_index_weight, + "weight": first_weight, + "final_index_weight": final_index_weight, + "kill_house_price": kill_house_price, + "weight_loss": round(total_weight_loss, 1), + "input_loss": obj.weight_loss, + "state": state, + } + + +# سریالایزر مربوط به تایید یا رد توسط کشتارگاه نسبت به تخصیص استان به کشتارگاه +class KillHouseCheckRequestSerializer(serializers.ModelSerializer): + kill_house_request = KillHouseRequestSerializer(read_only=True) + + class Meta: + model = KillHouseCheckRequest + fields = '__all__' + + +# سریالایزر مربوط به ثبت اطلاعات بار توسط کشتارگاه + +class KillHouseRequestForCompletedLoadsSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + real_add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + kill_place = serializers.SerializerMethodField('get_kill_place') + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + first_weight = serializers.SerializerMethodField('get_first_weight') + payment_remain_amount = serializers.SerializerMethodField('get_payment_remain_amount') + + class Meta: + model = KillHouseRequest + fields = ['key', 'killhouse_user', 'add_car', 'real_add_car', 'kill_place', + 'quantity', + 'bar_code', 'assignment_state_archive', 'clearance_code', 'traffic_code', 'accepted_real_quantity', + 'accepted_real_weight', 'vet_state', 'kill_house_vet', 'first_weight', 'payment_remain_amount'] + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_kill_house_vet(self, obj): + kill_house_vet_fullname = None + kill_house_vet_mobile = None + vet_check_date = None + if obj.vet_state == 'accepted': + vet_check = VetCheckRequest.objects.filter(kill_house_request=obj).only('kill_house_request', + 'create_date').first() + vet_check_date = vet_check.create_date + kill_house = obj.kill_request.slaughter_house if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_house, trash=False).select_related( + 'vet__user').first() + if kill_house_vet: + kill_house_vet_fullname = kill_house_vet.vet.user.fullname + kill_house_vet_mobile = kill_house_vet.vet.user.mobile + return { + "kill_house_vet_fullname": kill_house_vet_fullname, + "kill_house_vet_mobile": kill_house_vet_mobile, + "vet_check_date": vet_check_date, + } + + def get_first_weight(self, obj): + weight = obj.province_kill_request.province_request.poultry_request.Index_weight * obj.quantity + return weight + + def get_payment_remain_amount(self, obj): + kill_house_payment = KillRequestFactorPayment.objects.filter( + kill_request_factor__kill_request=obj.kill_request) + if kill_house_payment.count() > 0: + kill_request_payment_remain_amount = kill_house_payment.last().remain_amount + else: + kill_request_payment_remain_amount = 0 + return { + "kill_request_payment_remain_amount": kill_request_payment_remain_amount, + "sms_payment": obj.kill_request.sms_payment, + "buy_type": obj.province_kill_request.payment_type, + } + + +class KillHouseAssignmentInformationForCompletedLoadsSerializer(serializers.ModelSerializer): + kill_house_request = KillHouseRequestForCompletedLoadsSerializer(read_only=True) + poultry_request = serializers.SerializerMethodField('get_poultry_request') + banks_information = serializers.SerializerMethodField('get_banks_information') + + class Meta: + model = KillHouseAssignmentInformation + fields = ['kill_house_request', 'poultry_request', 'banks_information', 'car_weight_without_load', + 'car_weight_without_load_image', 'car_weight_with_load', 'car_weight_with_load_image', 'net_weight', + 'state', 'real_quantity', 'protest_time'] + + def get_poultry_request(self, obj): + poultry_request = PoultryRequest.objects.get( + key=obj.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.key) + return { + "poultry_province": poultry_request.poultry.user.province.name, + "poultry_city": poultry_request.poultry.user.city.name, + "order_code": poultry_request.order_code, + "poultry_name": poultry_request.poultry.user.fullname, + "unit_name": poultry_request.poultry.unit_name, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_request_quantity": poultry_request.quantity, + "poultry_request_id": poultry_request.id, + "age": (datetime.datetime.now() - poultry_request.hatching.date).days + 1, + + "index_weight": poultry_request.Index_weight, + "chicken_breed": poultry_request.chicken_breed, + "create_date": poultry_request.create_date, + "send_date": poultry_request.send_date, + "hatching_date": poultry_request.hatching.date, + "cell_type": poultry_request.cell_type, + "losses": poultry_request.hatching.losses, + } + + def get_banks_information(self, obj): + poultry_name_of_bank_user = None + poultry_bank_name = None + poultry_card = None + poultry_account = None + poultry_shaba = None + province_name_of_bank_user = None + province_bank_name = None + province_card = None + province_account = None + province_shaba = None + allocation = ShareOfAllocation.objects.all() + if allocation.count() > 0: + allocation = allocation.last().total + else: + allocation = 0 + + poultry = Poultry.objects.get( + key=obj.kill_house_request.province_request.poultry_request.poultry.key, + trash=False) + if poultry.user_bank_info != None: + poultry_name_of_bank_user = poultry.user_bank_info.name_of_bank_user + poultry_bank_name = poultry.user_bank_info.bank_name + poultry_card = poultry.user_bank_info.card + poultry_account = poultry.user_bank_info.account + poultry_shaba = poultry.user_bank_info.shaba + operator = ProvinceOperator.objects.filter(trash=False) + if operator.last().user_bank_info != None: + operator = operator.last() + province_name_of_bank_user = operator.user_bank_info.name_of_bank_user + province_bank_name = operator.user_bank_info.bank_name + province_card = operator.user_bank_info.shaba + province_account = operator.user_bank_info.account + province_shaba = operator.user_bank_info.shaba + + return { + "poultry_name_of_bank_user": poultry_name_of_bank_user, + "poultry_bank_name": poultry_bank_name, + "poultry_card": poultry_card, + "poultry_account": poultry_account, + "poultry_shaba": poultry_shaba, + "province_name_of_bank_user": province_name_of_bank_user, + "province_bank_name": province_bank_name, + "province_card": province_card, + "province_account": province_account, + "province_shaba": province_shaba, + "province_wage": allocation, + + } + + +class KillHouseAssignmentInformationSerializer(serializers.ModelSerializer): + kill_house_request = KillHouseRequestSerializer(read_only=True) + + class Meta: + model = KillHouseAssignmentInformation + fields = '__all__' + + +class KillHouseAssignmentInformationForAggregateLoadsSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouseAssignmentInformation + fields = ['key', 'car_weight_without_load', 'car_weight_without_load_image', 'car_weight_with_load', + 'car_weight_with_load_image', 'net_weight', 'real_quantity'] + + +class KillHouseRequestForAggregateLoadsSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + killer = KillHouseForAutoAllocationSerializer(read_only=True) + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + poultry_request = serializers.SerializerMethodField('get_poultry_request') + kill_place = serializers.SerializerMethodField('get_kill_place') + assingment_information = serializers.SerializerMethodField('get_assingment_information') + first_weight = serializers.SerializerMethodField('get_first_weight') + + class Meta: + model = KillHouseRequest + fields = ['key', 'killhouse_user', 'add_car', 'poultry_request', 'kill_place', 'assingment_information', + 'quantity', + 'bar_code', 'assignment_state_archive', 'clearance_code', 'traffic_code', 'accepted_real_quantity', + 'accepted_real_weight', 'vet_state', 'first_weight', 'killer'] + + def get_poultry_request(self, obj): + poultry_request = PoultryRequest.objects.get( + key=obj.province_kill_request.province_request.poultry_request.key) + serializer = PoultryRequestForBarMangementSerializer(poultry_request) + return serializer.data + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_assingment_information(self, obj): + assignment = KillHouseAssignmentInformation.objects.filter(kill_house_request=obj).first() + serializer = KillHouseAssignmentInformationForAggregateLoadsSerializer(assignment) + return serializer.data + + def get_first_weight(self, obj): + weight = obj.province_kill_request.province_request.poultry_request.Index_weight * obj.quantity + return weight + + +class KillHouseAssignmentImagesSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseAssignmentImages + fields = '__all__' + + +class VetForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['address', 'user_bank_info', 'identity_documents', 'active'] + + +class KillHouseVetForKillHouseVetSerializer(serializers.ModelSerializer): + kill_house = KillHouseForKillHouseVetKillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseVet + fields = ['kill_house'] + + +class KillHouseVetForAllUserSerializer(serializers.ModelSerializer): + vet = VetForAllUserSerializer(read_only=True) + # kill_house = KillHouseForAllUserSerializer(read_only=True) + kill_houses = serializers.SerializerMethodField('get_kill_houses') + + class Meta: + model = KillHouseVet + fields = ['vet', 'kill_houses'] + + def get_kill_houses(self, obj): + kill_houses = KillHouseVet.objects.filter(key=obj.key) + return KillHouseVetForKillHouseVetSerializer(kill_houses, many=True).data + + +# سریالایزر مربوط به ثبت اطلاعات بار توسط کشتارگاه +class VetCheckRequestSerializer(serializers.ModelSerializer): + class Meta: + model = VetCheckRequest + fields = '__all__' + + +class ProvinceKillRequestForAutoAllocationSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = ProvinceKillRequest + fields = ['killhouse_user', 'main_quantity'] + + +# سریالایزر مربوط به تخصیص استان به کشتارگاه +class ProvinceKillRequestSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseSerializer(read_only=True) + kill_request = KillRequestSerializer(read_only=True) + + class Meta: + model = ProvinceKillRequest + fields = '__all__' + + +class ProvinceKillRequestProvinceWageSerializer(serializers.ModelSerializer): + province_request = serializers.SerializerMethodField('get_province_request') + kill_house_requests = serializers.SerializerMethodField('get_kill_house_request') + + class Meta: + model = ProvinceKillRequest + fields = ['province_request', 'kill_house_requests', 'wage_pay', 'depositor', 'total_amount_editor', + 'archive_by_province', 'archive_message', 'archiver'] + + def get_province_request(self, obj): + role = self.context.get('request').GET['role'] + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + kill_house_user_full_name = obj.killhouse_user.kill_house_operator.user.fullname + kill_house_user_mobile = obj.killhouse_user.kill_house_operator.user.mobile + killer = obj.killhouse_user.killer + province_request = ProvinceCheckOperatorRequest.objects.filter(key=obj.province_request.key, + trash=False).select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').last() + + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + total_amount = obj.total_wage_amount + elif role == 'ProvinceOperator': + total_amount = obj.union_share + elif role == 'Company': + total_amount = obj.company_share + elif role == 'Company': + total_amount = obj.guilds_share + else: + total_amount = obj.total_wage_amount + + return { + "order_code": province_request.poultry_request.order_code, + "poultry_fullname": province_request.poultry_request.poultry.user.fullname, + "poultry_mobile": province_request.poultry_request.poultry.user.mobile, + "poultry_city": province_request.poultry_request.poultry.address.city.name, + "breed": province_request.poultry_request.chicken_breed, + "index_weight": province_request.poultry_request.Index_weight, + "send_date": province_request.poultry_request.send_date, + "wage": obj.wage, + "killer": killer, + "kill_place": kill_place, + "kill_house_user_full_name": kill_house_user_full_name, + "kill_house_user_mobile": kill_house_user_mobile, + "province_kill_request_quantity": obj.total_killed_quantity, + "province_kill_request_key": obj.key, + "province_kill_request_total_weight": obj.total_killed_weight, + "total_amount": total_amount, + "prev_total_amount": obj.prev_total_amount, + # "prev_total_amount": wage * (obj.main_quantity * province_request.poultry_request.Index_weight) + "free_sale": province_request.poultry_request.free_sale_in_province, + } + + def get_kill_house_request(self, obj): + kill_house_request = KillHouseRequest.objects.filter(province_kill_request=obj, + trash=False) + serializer = KillHouseRequestForBarManagementSerializer(kill_house_request, many=True) + return serializer.data + + +class KillRequestForDirectBuyingSerializer(serializers.ModelSerializer): + kill_house = KillHouseForCommonlyUsedSerializer(read_only=True) + slaughter_house = KillHouseForCommonlyUsedSerializer(read_only=True) + poultry = PoultryForPredictionSerializer(read_only=True) + poultry_request = PoultryRequestForMarketSerializer(read_only=True) + + # kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + + class Meta: + model = KillRequest + fields = ['key', 'create_date', 'recive_date', 'free_direct_buying', 'chicken_breed', 'kill_house', + 'slaughter_house', 'poultry', 'poultry_request', 'payment_deadline_date', 'payment_deadline_days', + 'kill_capacity', 'Index_weight', 'amount', 'market_final_accept', 'market_state', 'recive_time', + 'market_code_status', 'input_market_code', 'market_code','market_state_message'] + + # def get_kill_house_vet(self, obj): + # kill_house_vet = KillHouseVet.objects.filter(kill_house__exact=obj.kill_house, trash=False).last() + # if kill_house_vet: + # return KillHouseVetForKillRequestSerializer(kill_house_vet).data + # else: + # return None + + +class ProvinceKillRequestForDirectBuyingSerializer(serializers.ModelSerializer): + kill_request = KillRequestForDirectBuyingSerializer(read_only=True) + general_info = serializers.SerializerMethodField('get_general_info') + + class Meta: + model = ProvinceKillRequest + fields = ['key', 'kill_request', 'total_killed_quantity', 'total_killed_weight', 'general_info', + 'payment_deadline_days', 'payment_deadline_date', 'payment_deadline', 'payment_deadline_archive', + 'payment_deadline_state', 'payment_deadline_checker_fullname', 'payment_deadline_checker_mobile', + 'payment_deadline_check_date', 'payment_deadline_archive_message', 'final_accept', + 'extension_payment_deadline_days', 'payment_deadline_amount', 'extension_payment_deadline_days', + 'extension_payment_deadline_date'] + + def get_general_info(self, obj): + age = ((obj.kill_request.recive_date.date()) - (obj.kill_request.poultry_hatching.date.date())).days + 1 + total_amount = int(obj.kill_request.amount * obj.total_killed_weight) + payments = DirectBuyingPayment.objects.filter(province_kill_request=obj, trash=False) + total_paid_amount = payments.aggregate(total=Sum('amount'))['total'] or 0 + + return { + "age": age, + "total_amount": total_amount, + "Index_weight": round((obj.total_killed_weight / obj.total_killed_quantity), 2), + "total_paid_amount": total_paid_amount + + } + + +class ProvinceKillRequestForKillingInformationDiscrepancyReportSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForKillingInformationDiscrepancyReportSerializer(read_only=True) + total_info = serializers.SerializerMethodField('get_total_info') + + class Meta: + model = ProvinceKillRequest + fields = ['killhouse_user', 'total_info'] + + def get_total_info(self, obj): + province_kill_request_quantity = obj.main_quantity + province_kill_request_weight = int(obj.main_quantity * obj.province_request.poultry_request.Index_weight) + province_kill_request_remain_quantity = obj.quantity + province_kill_request_remain_weight = int(obj.quantity * obj.province_request.poultry_request.Index_weight) + kill_house_requests = KillHouseRequest.objects.filter(trash=False, province_kill_request=obj).annotate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight'), + + ) + kill_house_request_quantity = kill_house_requests.aggregate(total=Sum('total_quantity'))['total'] + kill_house_request_weight = kill_house_requests.aggregate(total=Sum('total_weight'))['total'] + + return { + "province_kill_request_quantity": province_kill_request_quantity, + "province_kill_request_weight": province_kill_request_weight, + "province_kill_request_remain_quantity": province_kill_request_remain_quantity, + "province_kill_request_remain_weight": province_kill_request_remain_weight, + "kill_house_requests_count": kill_house_requests.count(), + "kill_house_request_quantity": kill_house_request_quantity if kill_house_request_quantity != None else 0, + "kill_house_request_weight": kill_house_request_weight if kill_house_request_weight != None else 0, + "operator_fullname": obj.killhouse_user.kill_house_operator.user.fullname, + "operator_mobile": obj.killhouse_user.kill_house_operator.user.mobile, + "role": "KillHouse", + + } + + +# سریالایزر مربوط به ثبت درخواست بورسی کشتارگاه +class KillHouseRequestExchangeSerializer(serializers.ModelSerializer): + user = UserProfileSerializer(read_only=True) + + class Meta: + model = KillHouseRequestExchange + fields = '__all__' + + +# سریالایزر مربوط به ثبت درخواست رزرو بورسی کشتارگاه +class KillHouseRequestExchangeReserveSerializer(serializers.ModelSerializer): + poultry_exchange = PoultryRequestExchangeSerializer(read_only=True) + + class Meta: + model = KillHouseRequestExchangeReserve + fields = '__all__' + + +# سریالایزر مربوط به ثبت درخواست رزرو بورسی کشتارگاه +class KillHouseRequestActionSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + kill_house = KillHouseSerializer(read_only=True) + winner = serializers.SerializerMethodField('get_winner') + + class Meta: + model = KillHouseRequestAction + fields = '__all__' + + def get_winner(self, instance): + winners = KillHouseRequestActionWinner.objects.filter(kill_house_request_auction=instance) + if winners.count() > 0: + winners = winners.last() + internal_dict = { + "key": winners.key, + "fee": winners.fee, + "quantity": winners.quantity + } + + return internal_dict + + +# سریالایزر مربوط به ثبت درخواست رزرو بورسی کشتارگاه +class KillHouseRequestActionWinnerSerializer(serializers.ModelSerializer): + kill_house_request_auction = KillHouseRequestActionSerializer(read_only=True) + + class Meta: + model = KillHouseRequestActionWinner + fields = '__all__' + + +# سریالایزر مربوط به اضافه کردن خودرو به درخواست بورسی کشتارگاه +class KillHouseRequestExchangeAddCarSerializer(serializers.ModelSerializer): + kill_house_reserve = KillHouseRequestExchangeReserveSerializer(read_only=True) + + class Meta: + model = KillHouseRequestExchangeAddCar + fields = '__all__' + + +# سریالایزر مربوط به تایید یا رد درخواست بورسی کشتارگاه توسط مرغدار + +class PoultryRequestExchangeAcceptSerializer(serializers.ModelSerializer): + poultry_request_exchange = PoultryRequestExchangeSerializer(read_only=True) + kill_house_request_exchange_reserve = KillHouseRequestExchangeReserveSerializer(read_only=True) + + class Meta: + model = PoultryRequestExchangeAccept + fields = '__all__' + + +class DriverRequestCancelSerializer(serializers.ModelSerializer): + Kill_house_add_car = KillHouseADDCARSerializer(read_only=True) + kill_house_request = KillHouseRequestSerializer(read_only=True) + + class Meta: + model = DriverRequestCancel + fields = '__all__' + + +class KillHouseComplaintSerializer(serializers.ModelSerializer): + bar = KillHouseAssignmentInformationSerializer(read_only=True) + + class Meta: + model = KillHouseComplaint + fields = '__all__' + + +class CheckKillHouseComplaintSerializer(serializers.ModelSerializer): + complaint = KillHouseComplaintSerializer(read_only=True) + + class Meta: + model = CheckKillHouseComplaint + fields = '__all__' + + +class CheckUnusualCasualtiesSerializer(serializers.ModelSerializer): + killHousecomplaint = KillHouseComplaintSerializer(read_only=True) + + class Meta: + model = CheckUnusualCasualties + fields = '__all__' + + +class KillHouseCreditorsSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseCreditors + fields = '__all__' + + +class KillHouseWareHouseForDailyBroadCastOInDetailsSerializer(serializers.ModelSerializer): + informations = serializers.SerializerMethodField('get_informations') + + class Meta: + model = KillHouse + fields = ['informations', 'key'] + + def get_informations(self, obj): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, kill_house=obj, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + return { + "buyers": obj.name, + "city": obj.kill_house_operator.user.city.name, + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + "total_pre_cold_weight": total_pre_cold_weight if total_pre_cold_weight != None else 0, + "total_number_of_free_carcasses": total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + "total_free_weight_of_carcasses": total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "final_total_number_of_carcasses": final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + "final_total_weight_of_carcasses": final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + "total_allocated_quantity": total_allocated_quantity if total_allocated_quantity != None else 0, + "total_allocated_weight": total_allocated_weight if total_allocated_weight != None else 0, + "total_accepted_allocated_quantity": total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + "total_accepted_allocated_weight": total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + "total_remain_quantity": total_remain_quantity if total_remain_quantity != None else 0, + "total_remain_weight": total_remain_weight if total_remain_weight != None else 0, + "number_of_guild": number_of_guild, + "number_of_steward": number_of_steward, + + } + + +class KillHouseWareHouseSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseWareHouse + fields = '__all__' + + +class KillHouseFreeBarInformationSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + exclusive_killer = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseFreeBarInformation + fields = '__all__' + + +class KillHouseFreeBarInformationForWageTotalSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + total_amount = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouseFreeBarInformation + fields = '__all__' + + def get_info(self, obj): + role = self.context.get('request').GET['role'] + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + amount = obj.total_wage_amount + elif role == 'ProvinceOperator': + amount = obj.union_share + elif role == 'Company': + amount = obj.company_share + elif role == 'Guilds': + amount = obj.guilds_share + else: + amount = obj.total_wage_amount + return amount + + +class TypeActivityForKillHouseBuyerSerializer(serializers.ModelSerializer): + class Meta: + model = TypeActivity + fields = ['key', 'title'] + + +class OutProvinceCarcassesBuyerForKillHouseSerializer(serializers.ModelSerializer): + type_activity = TypeActivityForKillHouseBuyerSerializer(read_only=True) + Kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = OutProvinceCarcassesBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + +class KillHouseFreeSaleBarInformationSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + buyer = OutProvinceCarcassesBuyerForKillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseFreeSaleBarInformation + fields = '__all__' + + +class ProvinceKillRequestForLetterVetSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = ProvinceKillRequest + fields = ['killhouse_user', 'info'] + + def get_info(self, obj): + if obj.kill_request.slaughter_house == None: + kill_place = obj.kill_request.kill_house.name + else: + kill_place = obj.kill_request.slaughter_house.name + return { + "kill_place": kill_place, + "quantity": obj.main_quantity, + "weight": obj.main_quantity * obj.province_request.poultry_request.Index_weight, + } + + +class PoultryRequestoutProvinceSerializer(serializers.ModelSerializer): + poultry = PoultryForPoultryRequestLetterSerializer(read_only=True) + out_province_poultry_request_buyer = OutProvincePoultryRequestBuyerSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + out_state = serializers.SerializerMethodField('get_out_state') + total_system_quarantine_quantity = serializers.SerializerMethodField('get_total_system_quarantine_quantity') + + class Meta: + model = PoultryRequest + fields = ['key', 'out_state', 'hatching', 'create_date', 'poultry', 'order_code', 'quantity', 'remain_quantity', + 'send_date', + 'chicken_breed', 'financial_operation', 'Index_weight', 'amount', 'state_process', 'province_state', + 'order_code', 'registrar', 'buyer', 'out', 'quarantine_code', 'final_state', + 'out_province_request_cancel', 'out_province_request_canceller', 'out_province_driver_info', + 'hatching_left_over', 'freezing', 'total_wage_amount', 'wage_pay', 'has_wage', 'payer_type', + 'payer_fullname', 'out_province_poultry_request_buyer', 'buyer_mobile', 'buyer_fullname', + 'buyer_city', 'buyer_province', 'agent', 'killer_kill_house_unit_name', 'killer_kill_house_city', + 'killer_kill_house_province', 'kill_house_unique_id', 'payment_link', 'quarantine_quantity', + 'total_system_quarantine_quantity'] + + def get_hatching(self, obj): + + # if ProvinceKillRequest.objects.filter( + # province_request__city_request_Poultry__poultry_request=obj, + # state='accepted').exists(): + # age = (obj.send_date - obj.hatching.date).days + 1 + # else: + # age = (datetime.datetime.now() - obj.hatching.date).days + 1 + age = (obj.send_date - obj.hatching.date).days + 1 + + return { + "age": age, + "left_over": obj.hatching.left_over, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "hatching_quantity": obj.hatching.quantity, + } + + def get_out_state(self, obj): + state = None + if obj.province_state == 'rejected': + state = 'رد شده' + elif obj.province_state == 'pending' and obj.out_province_request_cancel == False: + state = 'در انتظار تایید' + + elif obj.province_state == 'accepted' and obj.has_wage == True and obj.wage_pay == False and obj.out_province_request_cancel == False and obj.out_province_request_cancel == False: + state = 'در انتظار پرداخت' + elif obj.province_state == 'accepted' and obj.has_wage == False and obj.wage_pay == False and obj.out_province_request_cancel == False and obj.out_province_request_cancel == False: + state = 'تایید شده' + elif obj.province_state == 'accepted' and obj.has_wage == True and obj.wage_pay == True and obj.out_province_request_cancel == False and obj.out_province_request_cancel == False: + state = 'پرداخت شده' + else: + state = 'لغو شده' + + return state + + def get_total_system_quarantine_quantity(self, obj): + code = PoultryRequestQuarantineCode.objects.filter(trash=False, poultry_request=obj).aggregate( + total=Sum('system_quarantine_quantity'))['total'] or 0 + return code + + +class PoultryRequestLetterTotalSerializer(serializers.ModelSerializer): + poultry = PoultryForPoultryRequestLetterSerializer(read_only=True) + + class Meta: + model = PoultryRequest + fields = ['poultry', 'order_code'] + + +class PoultryRequestLetterForProvinceVetSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + province_kill_requests = serializers.SerializerMethodField('get_province_kill_requests') + + class Meta: + model = PoultryRequest + fields = ['key', 'id', 'poultry', 'order_code', 'send_date', + 'province_kill_requests', 'quantity', 'Index_weight', 'hatching'] + + def get_hatching(self, obj): + vet_farm = VetFarm.objects.filter(trash=False, poultry=obj.poultry).first() + pricing = Pricing.objects.filter(trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else None + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else None + age = (datetime.datetime.now() - obj.hatching.date).days + 1 + return { + "vet_farm_name": vet_farm_name, + "vet_farm_mobile": vet_farm_mobile, + "age": age, + "hatching_quantity": obj.hatching.quantity, + "price": pricing.live_chicken_price if pricing else None, + } + + def get_province_kill_requests(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request=obj) + serializer = ProvinceKillRequestForLetterVetSerializer(province_kill_requests, many=True) + return serializer.data + + +class KillHouseRequestForTotalInformationSerializer(serializers.ModelSerializer): + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + kill_place = serializers.SerializerMethodField('get_kill_place') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + weight_info = serializers.SerializerMethodField('get_weight_info') + + class Meta: + model = KillHouseRequest + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + 'killhouse_user_id_foreign_key', + 'kill_request_id_foreign_key', + 'province_request_id_foreign_key', + 'province_kill_request_id_foreign_key', + 'add_car_id_foreign_key', + 'kill_house_request_id_key', + 'capacity', + 'kill_house_request_auction_winner', + 'city_number', + 'city_name', + 'province_number', + 'province_name', + 'province_request', + 'province_kill_request', + + ) + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_vet_farm(self, obj): + vet_farm = VetFarm.objects.filter( + poultry=obj.province_kill_request.province_request.poultry_request.poultry).last() + serializer = VetFarmForBarManagementSerializer(vet_farm) + return serializer.data + + def get_kill_house_vet(self, obj): + data = None + kill_request = KillRequest.objects.get(key=obj.kill_request.key, trash=False) + if kill_request.slaughter_house != None: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.slaughter_house).select_related( + 'vet__user').first() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + 'vet__user').first() + if kill_house_vet: + data = { + "fullname": kill_house_vet.vet.user.fullname, + "mobile": kill_house_vet.vet.user.mobile, + } + return data + + def get_weight_info(self, obj): + + return { + "weight": int(obj.quantity * obj.province_request.poultry_request.Index_weight), + "index_weight": round(int(obj.quantity * obj.province_request.poultry_request.Index_weight) / obj.quantity, + 2), + } + + +class KillHouseRequestForTotalInformationInTableSerializer(serializers.ModelSerializer): + add_car = KillHouseADDCARForBarManagementSerializer(read_only=True) + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + kill_place = serializers.SerializerMethodField('get_kill_place') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + kill_house_vet = serializers.SerializerMethodField('get_kill_house_vet') + weight_info = serializers.SerializerMethodField('get_weight_info') + vet_check = serializers.SerializerMethodField('get_vet_check') + assignment = serializers.SerializerMethodField('get_assignment') + + class Meta: + model = KillHouseRequest + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + 'killhouse_user_id_foreign_key', + 'kill_request_id_foreign_key', + 'province_request_id_foreign_key', + 'province_kill_request_id_foreign_key', + 'add_car_id_foreign_key', + 'kill_house_request_id_key', + 'capacity', + 'kill_house_request_auction_winner', + 'city_number', + 'city_name', + 'province_number', + 'province_name', + 'province_request', + 'province_kill_request', + + ) + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_vet_farm(self, obj): + vet_farm = VetFarm.objects.filter( + poultry=obj.province_kill_request.province_request.poultry_request.poultry).last() + serializer = VetFarmForBarManagementSerializer(vet_farm) + return serializer.data + + def get_kill_house_vet(self, obj): + data = None + kill_request = KillRequest.objects.get(key=obj.kill_request.key, trash=False) + if kill_request.slaughter_house != None: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.slaughter_house).select_related( + 'vet__user').first() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + 'vet__user').first() + if kill_house_vet: + data = { + "fullname": kill_house_vet.vet.user.fullname, + "mobile": kill_house_vet.vet.user.mobile, + } + return data + + def get_weight_info(self, obj): + + return { + "weight": int(obj.quantity * obj.province_request.poultry_request.Index_weight), + "index_weight": round(int(obj.quantity * obj.province_request.poultry_request.Index_weight) / obj.quantity, + 2), + } + + def get_vet_check(self, obj): + try: + vet_check = VetCheckRequest.objects.get(kill_house_request=obj) + vet_state = { + "date": vet_check.create_date, + "state": vet_check.state, + "kill_house_vet_fullname": vet_check.vet.user.fullname, + "kill_house_vet_mobile": vet_check.vet.user.mobile, + } + except: + vet_state = None + + return vet_state + + def get_assignment(self, obj): + try: + assignment = KillHouseAssignmentInformation.objects.get(kill_house_request=obj) + assignment_info = { + "net_weight": assignment.net_weight, + "real_quantity": assignment.real_quantity, + "car_weight_without_load_image": assignment.car_weight_without_load_image, + "car_weight_with_load_image": assignment.car_weight_with_load_image, + "state": assignment.state, + } + except: + assignment_info = None + + return assignment_info + + +class ProvinceKillRequestForTotalInformationSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + weight_info = serializers.SerializerMethodField('get_weight_info') + kill_place = serializers.SerializerMethodField('get_kill_place') + + class Meta: + model = ProvinceKillRequest + fields = ['killhouse_user', 'quantity', 'kill_place', 'main_quantity', 'total_killed_quantity', + 'first_car_allocated_quantity', 'total_killed_weight', 'automatic', 'weight_info', 'state'] + + def get_weight_info(self, obj): + province_kill_request_quantity = obj.main_quantity + province_kill_request_weight = int(obj.main_quantity * obj.province_request.poultry_request.Index_weight) + province_kill_request_index_weight = round((province_kill_request_weight / province_kill_request_quantity), 2) + + return { + "province_kill_request_quantity": province_kill_request_quantity, + "province_kill_request_weight": province_kill_request_weight, + "province_kill_request_index_weight": province_kill_request_index_weight, + } + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + +class ProvinceKillRequestForTotalInformationInTableSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForAutoAllocationSerializer(read_only=True) + weight_info = serializers.SerializerMethodField('get_weight_info') + kill_place = serializers.SerializerMethodField('get_kill_place') + kill_house_requests = serializers.SerializerMethodField('get_kill_house_requests') + + class Meta: + model = ProvinceKillRequest + fields = ['killhouse_user', 'quantity', 'kill_place', 'main_quantity', 'total_killed_quantity', + 'first_car_allocated_quantity', 'total_killed_weight', 'automatic', 'kill_house_requests', + 'weight_info', 'state'] + + def get_weight_info(self, obj): + province_kill_request_quantity = obj.main_quantity + province_kill_request_weight = int(obj.main_quantity * obj.province_request.poultry_request.Index_weight) + province_kill_request_index_weight = round((province_kill_request_weight / province_kill_request_quantity), 2) + + return { + "province_kill_request_quantity": province_kill_request_quantity, + "province_kill_request_weight": province_kill_request_weight, + "province_kill_request_index_weight": province_kill_request_index_weight, + } + + def get_kill_place(self, obj): + kill_place = obj.kill_request.slaughter_house.name if obj.kill_request.slaughter_house != None else obj.kill_request.kill_house.name + return kill_place + + def get_kill_house_requests(self, obj): + kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=obj) + kill_house_requests_serializer = KillHouseRequestForTotalInformationInTableSerializer(kill_house_requests, + many=True) + return kill_house_requests_serializer.data + + +class PoultryRequestForTotalInformationSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + city_state = serializers.SerializerMethodField('get_city_state') + province_state = serializers.SerializerMethodField('get_province_state') + province_kill_requests = serializers.SerializerMethodField('get_province_kill_requests') + kill_house_requests = serializers.SerializerMethodField('get_kill_house_requests') + + class Meta: + model = PoultryRequest + fields = ['key', 'create_date', 'poultry', 'quantity', 'send_date', 'direct_buying', 'union', 'state_process', + 'free_sale_in_province', 'hatching', + 'province_state', 'amount', 'financial_operation', + 'chicken_breed', 'order_code', 'city_state', 'province_state', 'Index_weight', + 'province_kill_requests', 'kill_house_requests', 'freezing', 'out', 'out_province_driver_info', + 'out_province_request_canceller', 'out_province_request_cancel', 'buyer'] + + def get_city_state(self, obj): + try: + if obj.out == True: + city_operator = CityOperator.objects.get(key=obj.city_operator.key, trash=False) + return { + "city_operator_fullname": city_operator.user.fullname, + "city_operator_mobile": city_operator.user.mobile, + "state": 'accept' if obj.state_process == 'accepted' else 'reject', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": obj.send_date.date(), + } + + else: + city = CityOperatorCheckRequest.objects.get(trash=False, poultry_request=obj) + return { + "city_operator_fullname": city.city_operator_system.user.fullname, + "city_operator_mobile": city.city_operator_system.user.mobile, + "state": city.state, + "poultry": city.poultry_request.poultry.unit_name, + "city": city.poultry_request.poultry.address.city.name, + "province": city.poultry_request.poultry.address.province.name, + "date": city.create_date.date(), + } + except: + city_operator = CityOperator.objects.get(key=obj.city_operator.key, trash=False) + return { + "city_operator_fullname": city_operator.user.fullname, + "city_operator_mobile": city_operator.user.mobile, + "state": 'pending', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": None, + } + + def get_hatching(self, obj): + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=obj, + state='accepted').exists(): + + age2 = (obj.send_date - obj.hatching.date).days + 1 + else: + age2 = (datetime.datetime.now() - obj.hatching.date).days + 1 + price = Pricing.objects.filter(trash=False).last() + price = price.live_chicken_price if price else None + try: + vet_farm = VetFarm.objects.get(poultry=obj.poultry, trash=False) + vet_farm_info = { + "vet_farm_fullname": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile + } + except: + vet_farm_info = None + + return { + "quantity": obj.hatching.quantity, + "left_over": obj.hatching.left_over, + "age": age2, + "price": price, + "vet_farm_info": vet_farm_info, + "weight": int(obj.quantity * obj.Index_weight) + + } + + def get_province_state(self, obj): + try: + if obj.out == True: + province_operator = ProvinceOperator.objects.get(user__role__name='ProvinceOperator', trash=False) + return { + "province_operator_fullname": province_operator.user.fullname, + "province_operator_mobile": province_operator.user.mobile, + "state": 'accept' if obj.province_state == 'accepted' else 'reject', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": obj.send_date.date(), + } + else: + province = ProvinceCheckOperatorRequest.objects.get(trash=False, poultry_request=obj) + return { + "province_operator_fullname": province.province_operator_system.user.fullname, + "province_operator_mobile": province.province_operator_system.user.mobile, + "state": province.state, + "poultry": province.poultry_request.poultry.unit_name, + "city": province.poultry_request.poultry.address.city.name, + "province": province.poultry_request.poultry.address.province.name, + "date": province.create_date.date(), + } + except: + province_operator = ProvinceOperator.objects.get(user__role__name='ProvinceOperator', trash=False) + return { + "province_operator_fullname": province_operator.user.fullname, + "province_operator_mobile": province_operator.user.mobile, + "state": 'pending', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": None, + } + + def get_province_kill_requests(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), trash=False, + province_request__poultry_request__key=obj.key) + province_kill_request_serializer = ProvinceKillRequestForTotalInformationSerializer(province_kill_requests, + many=True) + poultry_request_quantity = obj.quantity + poultry_request_remain_quantity = obj.remain_quantity + allocated_quantity = province_kill_requests.aggregate(total=Sum('main_quantity'))['total'] + + return { + "province_kill_request_serializer": province_kill_request_serializer.data, + "province_kill_requests_total_info": { + "poultry_request_quantity": poultry_request_quantity, + "poultry_request_remain_quantity": poultry_request_remain_quantity, + "allocated_quantity": allocated_quantity if allocated_quantity != None else 0, + } + } + + def get_kill_house_requests(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), trash=False, + province_request__poultry_request__key=obj.key) + allocated_quantity = province_kill_requests.aggregate(total=Sum('main_quantity'))['total'] + remain_quantity = province_kill_requests.aggregate(total=Sum('quantity'))['total'] + kill_house_requests = KillHouseRequest.objects.filter( + (Q(trash=False) | Q(trash=True, bar_remover__isnull=False)), province_request__poultry_request=obj) + kill_house_request_quantity = kill_house_requests.aggregate(total=Sum('quantity'))['total'] + + kill_house_request_vet_check = kill_house_requests.filter( + (Q(trash=False, vet_state='accepted', assignment_state_archive='pending') | Q(trash=False, + vet_state='pending', + assignment_state_archive='True'))) + kill_house_request_assignment = kill_house_requests.filter(trash=False, assignment_state_archive='True') + + kill_house_requests_serializer = KillHouseRequestForTotalInformationSerializer(kill_house_requests, + many=True) + kill_house_request_vet_check_serializer = KillHouseRequestForTotalInformationSerializer( + kill_house_request_vet_check, + many=True) + kill_house_request_assignment_serializer = KillHouseRequestForTotalInformationSerializer( + kill_house_request_assignment, + many=True) + + return { + "allocated_quantity": allocated_quantity, + "remain_quantity": remain_quantity, + "kill_house_request_quantity": kill_house_request_quantity if kill_house_request_quantity != None else 0, + "number_of_bars": len(kill_house_requests), + "vet_accepted_number_of_bars": len(kill_house_request_vet_check), + "vet_remain_number_of_bars": len(kill_house_requests) - len(kill_house_request_vet_check), + "kill_house_request_assignment": len(kill_house_request_assignment), + "assignment_remain_number_of_bars": len(kill_house_requests) - len(kill_house_request_assignment), + "kill_house_requests_serializer": kill_house_requests_serializer.data, + "kill_house_request_vet_check_serializer": kill_house_request_vet_check_serializer.data, + "kill_house_request_assignment_serializer": kill_house_request_assignment_serializer.data, + + } + + +class PoultryRequestForTotalInformationInTableSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + city_state = serializers.SerializerMethodField('get_city_state') + province_state = serializers.SerializerMethodField('get_province_state') + province_kill_requests = serializers.SerializerMethodField('get_province_kill_requests') + + class Meta: + model = PoultryRequest + fields = ['key', 'create_date', 'poultry', 'quantity', 'send_date', 'direct_buying', 'union', 'state_process', + 'free_sale_in_province', 'hatching', + 'province_state', 'amount', 'financial_operation', + 'chicken_breed', 'order_code', 'city_state', 'province_state', 'Index_weight', + 'province_kill_requests'] + + def get_city_state(self, obj): + try: + city = CityOperatorCheckRequest.objects.get(trash=False, poultry_request=obj) + return { + "city_operator_fullname": city.city_operator_system.user.fullname, + "city_operator_mobile": city.city_operator_system.user.mobile, + "state": city.state, + "poultry": city.poultry_request.poultry.unit_name, + "city": city.poultry_request.poultry.address.city.name, + "province": city.poultry_request.poultry.address.province.name, + "date": city.create_date.date(), + } + except: + city_operator = CityOperator.objects.get(key=obj.city_operator.key, trash=False) + return { + "city_operator_fullname": city_operator.user.fullname, + "city_operator_mobile": city_operator.user.mobile, + "state": 'pending', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": None, + } + + def get_hatching(self, obj): + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=obj, + state='accepted').exists(): + + age2 = (obj.send_date - obj.hatching.date).days + 1 + else: + age2 = (datetime.datetime.now() - obj.hatching.date).days + 1 + price = Pricing.objects.filter(trash=False).last() + price = price.live_chicken_price if price else None + try: + vet_farm = VetFarm.objects.get(poultry=obj.poultry, trash=False) + vet_farm_info = { + "vet_farm_fullname": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile + } + except: + vet_farm_info = None + + return { + "quantity": obj.hatching.quantity, + "left_over": obj.hatching.left_over, + "age": age2, + "price": price, + "vet_farm_info": vet_farm_info, + "weight": int(obj.quantity * obj.Index_weight) + + } + + def get_province_state(self, obj): + try: + province = ProvinceCheckOperatorRequest.objects.get(trash=False, poultry_request=obj) + return { + "province_operator_fullname": province.province_operator_system.user.fullname, + "province_operator_mobile": province.province_operator_system.user.mobile, + "state": province.state, + "poultry": province.poultry_request.poultry.unit_name, + "city": province.poultry_request.poultry.address.city.name, + "province": province.poultry_request.poultry.address.province.name, + "date": province.create_date.date(), + } + except: + province_operator = ProvinceOperator.objects.get(user__role__name='ProvinceOperator', trash=False) + return { + "province_operator_fullname": province_operator.user.fullname, + "province_operator_mobile": province_operator.user.mobile, + "state": 'pending', + "poultry": obj.poultry.unit_name, + "city": obj.poultry.address.city.name, + "province": obj.poultry.address.province.name, + "date": None, + } + + def get_province_kill_requests(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), trash=False, + province_request__poultry_request__key=obj.key) + province_kill_request_serializer = ProvinceKillRequestForTotalInformationInTableSerializer( + province_kill_requests, + many=True) + + return province_kill_request_serializer.data + + +class SlaughterHouseTransactionSerializer(serializers.ModelSerializer): + kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + parent_kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + + class Meta: + model = SlaughterHouseTransaction + fields = '__all__' + + +class KillHouseWageSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'wage_info'] + + def get_wage_info(self, obj): + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + total_unpaid_wage = 0 + kill_house_requests = KillHouseRequest.objects.filter(Q(killer=obj) | Q(killhouse_user=obj), trash=False) + total_wage += \ + kill_house_requests.aggregate(total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + total_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + first_car_allocated_quantity=0, + state__in=('pending', 'accepted'), trash=False, + return_to_province=False, archive_by_province=False) + total_wage += province_kill_requests.aggregate(total=Sum(F('total_killed_weight') * F('wage')))[ + 'total'] or 0 + total_weight += province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + transactions = SlaughterHouseTransaction.objects.filter(Q(kill_house=obj) | Q(parent_kill_house=obj), + state='completed', trash=False) + total_paid_wage = transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "total_weight": total_weight, + "total_wage": total_wage, + "total_paid_wage": total_paid_wage, + "total_unpaid_wage": total_wage - total_paid_wage, + } + + +class TotalWageInformationExclusiveKillerSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = KillHouse + fields = ['name', 'key', 'wage_info'] + + def get_wage_info(self, obj): + before_total_out_live_buying_province_carcasses_price = 0 + total_wage_type = WageType.objects.filter(trash=False) + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + finance_info = get_kill_house_finance_info(obj) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False) + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_pure_province_carcasses_price = finance_info['total_pure_province_carcasses_price'] + return_total_pure_province_carcasses_price = finance_info['total_return_pure_province_carcasses_price'] + total_out_selling_province_carcasses_price = finance_info['total_out_selling_province_carcasses_price'] + difference_requests_price = finance_info['difference_requests_price'] + + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (finance_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount) + ( + finance_info[ + 'after_total_out_live_buying_province_carcasses_weight'] * free_buying_live_weight_wage_type_amount)) + + before_total_out_live_buying_province_carcasses_price = finance_info[ + 'before_total_out_live_buying_province_carcasses_weight'] * before_out_buying_count_wage_amount + else: + total_out_live_buying_province_carcasses_price = finance_info[ + 'total_out_live_buying_province_carcasses_price'] + total_out_carcasses_buying_province_carcasses_price = finance_info[ + 'total_out_carcasses_buying_province_carcasses_price'] + total_price = finance_info['total_price'] + + # total_pure_province_carcasses_price = finance_info['total_pure_province_carcasses_price'] + # total_out_selling_province_carcasses_price = finance_info['total_out_selling_province_carcasses_price'] + # total_out_live_buying_province_carcasses_price = finance_info['total_out_live_buying_province_carcasses_price'] + # total_out_carcasses_buying_province_carcasses_price = finance_info[ + # 'total_out_carcasses_buying_province_carcasses_price'] + # total_price = finance_info['total_price'] + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + guilds_difference_requests_price = difference_requests_price * guilds_province_kill_request_percent + other_difference_requests_price = difference_requests_price * other_province_kill_request_percent + guild_return_province_kill_request_wage = return_total_pure_province_carcasses_price * guilds_province_kill_request_percent + other_return_province_kill_request_wage = return_total_pure_province_carcasses_price * other_province_kill_request_percent + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + return_union_province_kill_request_wage = return_total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + return_union_province_kill_request_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + company_province_kill_request_wage = ( + total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guilds_difference_requests_price + other_difference_requests_price) + return_company_province_kill_request_wage = ( + return_total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guild_return_province_kill_request_wage + other_return_province_kill_request_wage) + company_free_buying_live_wage = (( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * company_free_buying_live_percent) + before_total_out_live_buying_province_carcasses_price + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + return_company_province_kill_request_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_wage = ( + total_pure_province_carcasses_price * guilds_province_kill_request_percent) - guilds_difference_requests_price + return_guilds_province_kill_request_wage = 0 + guilds_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_wage = ( + total_pure_province_carcasses_price * other_province_kill_request_percent) - other_difference_requests_price + return_other_province_kill_request_wage = 0 + other_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + + shares = [ + { + "name": "اتحادیه", + "province_kill_request_wage": union_province_kill_request_wage, + "return_province_kill_request_wage": return_union_province_kill_request_wage, + "free_buying_live_wage": union_free_buying_live_wage, + "free_buying_carcasses_wage": union_free_buying_carcasses_wage, + "free_sell_carcasses_wage": union_free_sell_carcasses_wage, + "total_wage": union_total_wage, + "total_paid_wage": union_total_paid_wage, + "total_unpaid_wage": union_total_unpaid_wage, + }, + { + "name": "شرکت", + "province_kill_request_wage": company_province_kill_request_wage, + "return_province_kill_request_wage": return_company_province_kill_request_wage, + "free_buying_live_wage": company_free_buying_live_wage, + "free_buying_carcasses_wage": company_free_buying_carcasses_wage, + "free_sell_carcasses_wage": company_free_sell_carcasses_wage, + "total_wage": company_total_wage, + "total_paid_wage": company_total_paid_wage, + "total_unpaid_wage": company_total_unpaid_wage, + }, + { + "name": "صنف پروتئین", + "province_kill_request_wage": guilds_province_kill_request_wage, + "return_province_kill_request_wage": return_guilds_province_kill_request_wage, + "free_buying_live_wage": guilds_free_buying_live_wage, + "free_buying_carcasses_wage": guilds_free_buying_carcasses_wage, + "free_sell_carcasses_wage": guilds_free_sell_carcasses_wage, + "total_wage": guilds_total_wage, + "total_paid_wage": guilds_total_paid_wage, + "total_unpaid_wage": guilds_total_unpaid_wage, + }, + { + "name": "دامپزشک", + "province_kill_request_wage": other_province_kill_request_wage, + "return_province_kill_request_wage": return_other_province_kill_request_wage, + "free_buying_live_wage": other_free_buying_live_wage, + "free_buying_carcasses_wage": other_free_buying_carcasses_wage, + "free_sell_carcasses_wage": other_free_sell_carcasses_wage, + "total_wage": other_total_wage, + "total_paid_wage": other_total_paid_wage, + "total_unpaid_wage": other_total_unpaid_wage, + }] + + return { + "wage_counting_type": wage_counting_type, + "total_wage": finance_info['total_price'], + "total_paid_wage": total_paid_wage, + "off": obj.off, + "total_unpaid_wage": finance_info['total_price'] - (total_paid_wage + obj.off), + "province_kill_requests_total_wage": finance_info['total_pure_province_carcasses_price'], + "province_kill_requests_total_weight": finance_info['total_pure_province_carcasses_weight'], + "free_bars_live_total_wage": finance_info['total_out_live_buying_province_carcasses_price'], + "free_bars_live_total_weight": finance_info['total_out_live_buying_province_carcasses_weight'], + "free_bars_carcases_total_wage": finance_info['total_out_carcasses_buying_province_carcasses_price'], + "free_bars_carcases_total_weight": finance_info['total_out_carcasses_buying_province_carcasses_weight'], + "free_bars_out_province_carcases_total_wage": finance_info['total_out_selling_province_carcasses_price'], + "free_bars_out_province_carcases_total_weight": finance_info['total_out_selling_province_carcasses_weight'], + "total_province_live_weight": finance_info['total_province_live_weight'], + "total_province_carcasses_weight": finance_info['total_province_carcasses_weight'], + "province_live_wage_amount": finance_info['province_live_wage_amount'], + "free_buying_live_weight_amount": finance_info['free_buying_live_weight_amount'], + "free_buying_carcesses_weight_amount": finance_info['free_buying_carcesses_weight_amount'], + "free_sell_carcesses_weight_amount": finance_info['free_sell_carcesses_weight_amount'], + "user_token": 'k' + obj.kill_house_operator.user.user_gate_way_id, + "shares": shares, + "return_total_province_live_weight": finance_info['return_total_province_live_weight'], + "total_return_pure_province_carcasses_price": finance_info['total_return_pure_province_carcasses_price'], + + } + + +class TotalWageInformationKillHouseExclusiveKillerSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = KillHouse + fields = ['name', 'key', 'wage_info'] + + def get_wage_info(self, obj): + # kill_house_ids = KillHouseRequest.objects.filter(Q(killhouse_user=obj) | Q(killer=obj), archive_wage=False, + # trash=False + # ).values_list('killer', flat=True).distinct() + kill_house_ids = KillHousePercentage.objects.filter( + Q(kill_house=obj) | Q(kill_house_for_killer=obj, kill_house__type='exclusive'), trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids) + kill_house_srz = TotalWageInformationExclusiveKillerSerializer(kill_houses, many=True, + context={'kill_house': obj}) + return kill_house_srz.data + + +class ProvinceRequestForKillHouseLetterSerialize(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + model = ProvinceKillRequest + fields = ['id', 'wage_info'] + + def get_wage_info(self, obj): + age = (datetime.datetime.now() - obj.province_request.poultry_request.hatching.date).days + 1 + poultry = { + 'poultry': obj.province_request.poultry_request.poultry.unit_name, + 'poultry_mobile': obj.province_request.poultry_request.poultry.user.mobile, + 'poultry_city': obj.province_request.poultry_request.poultry.address.city.name, + 'quantity': obj.main_quantity, + 'Index_weight': obj.province_request.poultry_request.Index_weight, + 'chicken_age': age, + } + return poultry + + +class KillHouseLetterForProvinceSerializer(serializers.ModelSerializer): + province_kill_request = serializers.SerializerMethodField() + total_quantity = serializers.SerializerMethodField() + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['key', 'killer', 'name', 'kill_house_operator', 'province_kill_request', 'total_quantity'] + + def get_province_kill_request(self, obj): + date = self.context.get('date') + kill_requests = KillHouseRequest.objects.filter( + Q(killer=obj) | Q(killhouse_user=obj), + trash=False, + kill_request__recive_date__date=date + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__hatching', + 'province_request__poultry_request__poultry__address', + 'add_car__driver' + ) + + total_quantity = kill_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get('total_quantity', 0) + self.total_quantity = total_quantity + + poultries = [ + { + 'poultry': kill.province_request.poultry_request.poultry.unit_name, + 'poultry_mobile': kill.province_request.poultry_request.poultry.user.mobile, + 'poultry_city': kill.province_request.poultry_request.poultry.address.city.name, + 'quantity': kill.accepted_real_quantity, + 'Index_weight': kill.province_request.poultry_request.Index_weight, + 'chicken_age': (datetime.datetime.now() - kill.province_request.poultry_request.hatching.date).days + 1, + 'weight': kill.accepted_real_weight, + 'car_type': kill.add_car.driver.type_car, + 'driver_name': kill.add_car.driver.driver_name, + 'traffic_code': kill.traffic_code, + 'clearance_code': kill.clearance_code, + 'pelak': kill.add_car.driver.pelak, + } + for kill in kill_requests + ] + + return poultries + + def get_total_quantity(self, obj): + return getattr(self, 'total_quantity', 0) + + +class KillHousetestSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_province_kill_request') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'info'] + + def get_province_kill_request(self, obj): + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + total_unpaid_wage = 0 + union_total_weight = 0 + union_total_wage = 0 + union_total_paid_wage = 0 + union_total_unpaid_wage = 0 + union_province_kill_request_total_wage = 0 + freezing_union_province_kill_request_total_wage = 0 + union_kill_house_free_live_bar_total_wage = 0 + union_kill_house_free_carcases_bar_total_wage = 0 + union_chain_allocation_total_wage = 0 + union_province_kill_request_total_weight = 0 + freezing_union_province_kill_request_total_weight = 0 + union_kill_house_free_live_bar_total_weight = 0 + union_kill_house_free_carcases_bar_total_weight = 0 + union_chain_allocation_total_weight = 0 + + company_total_weight = 0 + company_total_wage = 0 + company_total_paid_wage = 0 + company_total_unpaid_wage = 0 + company_province_kill_request_total_wage = 0 + freezing_company_province_kill_request_total_wage = 0 + company_kill_house_free_live_bar_total_wage = 0 + company_kill_house_free_carcases_bar_total_wage = 0 + company_chain_allocation_total_wage = 0 + company_province_kill_request_total_weight = 0 + freezing_company_province_kill_request_total_weight = 0 + company_kill_house_free_live_bar_total_weight = 0 + company_kill_house_free_carcases_bar_total_weight = 0 + company_chain_allocation_total_weight = 0 + + guilds_total_weight = 0 + guilds_total_wage = 0 + guilds_total_paid_wage = 0 + guilds_total_unpaid_wage = 0 + guilds_province_kill_request_total_wage = 0 + freezing_guilds_province_kill_request_total_wage = 0 + guilds_kill_house_free_live_bar_total_wage = 0 + guilds_kill_house_free_carcases_bar_total_wage = 0 + guilds_chain_allocation_total_wage = 0 + guilds_province_kill_request_total_weight = 0 + freezing_guilds_province_kill_request_total_weight = 0 + guilds_kill_house_free_live_bar_total_weight = 0 + guilds_kill_house_free_carcases_bar_total_weight = 0 + guilds_chain_allocation_total_weight = 0 + province_kill_request_total_wage = 0 + province_kill_request_total_weight = 0 + freezing_province_kill_requests_total_wage = 0 + freezing_province_kill_requests_total_weight = 0 + chain_total_wage = 0 + chain_total_weight = 0 + free_bars_live_total_wage = 0 + free_bars_live_total_weight = 0 + free_bars_carcases_total_wage = 0 + free_bars_carcases_total_weight = 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ).exclude(union_share=0, company_share=0, + guilds_share=0) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=obj) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) | Q(killer=obj)), + # killhouse_user=kill_house, + archive_wage=False, + trash=False + ) + + kill_house_requests = kill_house_requests.filter(Q(killer=obj) | Q(killhouse_user=obj)).exclude( + province_kill_request__union_share=0, province_kill_request__company_share=0, + province_kill_request__guilds_share=0) + + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killhouse_user=obj) & Q(killer=obj)) | Q( + # Q(killhouse_user=obj) & Q(killer__isnull=True)) | Q( + # Q(killhouse_user=obj) | Q(killer=obj)), archive_wage=False, + # trash=False + # ).exclude(province_kill_request__union_share=0, province_kill_request__company_share=0, + # province_kill_request__guilds_share=0) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, + trash=False) + free_bars_live = free_bars.filter(buy_type='live', trash=False) + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_wage_amount'))[ + 'total'] or 0 + freezing_province_kill_request_total_wage = \ + freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + total_wage += province_kill_requests_total_wage + freezing_province_kill_request_total_wage + province_kill_requests_total_weight = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_province_kill_request_total_weight = \ + freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_weight += province_kill_requests_total_weight + freezing_province_kill_request_total_weight + kill_house_reqest_total_wage = \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + freezing_kill_house_reqest_total_wage = \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + total_wage += kill_house_reqest_total_wage + freezing_kill_house_reqest_total_wage + + kill_house_reqest_total_weight = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + freezing_kill_house_reqest_total_weight = \ + freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + total_weight += kill_house_reqest_total_weight + freezing_kill_house_reqest_total_weight + + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_live_total_wage + free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_weight += free_bars_live_total_weight + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_carcases_total_wage + free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_weight += free_bars_carcases_total_weight + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + union_province_kill_request_total_weight = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + union_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + union_province_kill_request_total_wage = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + union_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + union_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + union_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_weight = union_province_kill_request_total_weight + freezing_union_province_kill_request_total_weight + union_chain_allocation_total_weight + union_kill_house_free_live_bar_total_weight + union_kill_house_free_carcases_bar_total_weight + union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_chain_allocation_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_total_weight = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + company_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + company_province_kill_request_total_wage = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + company_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + + company_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + company_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_weight = company_province_kill_request_total_weight + freezing_company_province_kill_request_total_weight + company_chain_allocation_total_weight + company_kill_house_free_live_bar_total_weight + company_kill_house_free_carcases_bar_total_weight + company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_chain_allocation_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_total_weight = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_guilds_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + guilds_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_total_weight = guilds_province_kill_request_total_weight + freezing_guilds_province_kill_request_total_weight + guilds_chain_allocation_total_weight + guilds_kill_house_free_live_bar_total_weight + guilds_kill_house_free_carcases_bar_total_weight + guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_chain_allocation_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + return { + "total_weight": total_weight, + "total_wage": total_wage, + "total_paid_wage": total_paid_wage, + "total_unpaid_wage": total_wage - total_paid_wage, + "province_kill_requests_total_wage": province_kill_requests_total_wage, + "province_kill_requests_total_weight": province_kill_requests_total_weight, + "freezing_province_kill_requests_total_wage": freezing_province_kill_requests_total_wage, + "freezing_province_kill_requests_total_weight": freezing_province_kill_requests_total_weight, + "free_bars_live_total_wage": free_bars_live_total_wage, + "free_bars_live_total_weight": free_bars_live_total_weight, + "free_bars_carcases_total_wage": free_bars_carcases_total_wage, + "free_bars_carcases_total_weight": free_bars_carcases_total_weight, + "shares": { + "union_total_weight": union_total_weight, + "union_total_wage": union_total_wage, + "union_total_paid_wage": union_total_paid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "union_province_kill_request_total_wage": union_province_kill_request_total_wage, + "union_kill_house_free_live_bar_total_wage": union_kill_house_free_live_bar_total_wage, + "union_kill_house_free_carcases_bar_total_wage": union_kill_house_free_carcases_bar_total_wage, + "union_chain_allocation_total_wage": union_chain_allocation_total_wage, + "union_province_kill_request_total_weight": union_province_kill_request_total_weight, + "union_kill_house_free_live_bar_total_weight": union_kill_house_free_live_bar_total_weight, + "union_kill_house_free_carcases_bar_total_weight": union_kill_house_free_carcases_bar_total_weight, + "union_chain_allocation_total_weight": union_chain_allocation_total_weight, + "freezing_union_province_kill_request_total_wage": freezing_union_province_kill_request_total_wage, + "freezing_union_province_kill_request_total_weight": freezing_union_province_kill_request_total_weight, + + "company_total_weight": company_total_weight, + "company_total_wage": company_total_wage, + "company_total_paid_wage": company_total_paid_wage, + "company_total_unpaid_wage": company_total_unpaid_wage, + "company_province_kill_request_total_wage": company_province_kill_request_total_wage, + "company_kill_house_free_live_bar_total_wage": company_kill_house_free_live_bar_total_wage, + "company_kill_house_free_carcases_bar_total_wage": company_kill_house_free_carcases_bar_total_wage, + "company_chain_allocation_total_wage": company_chain_allocation_total_wage, + "company_province_kill_request_total_weight": company_province_kill_request_total_weight, + "company_kill_house_free_live_bar_total_weight": company_kill_house_free_live_bar_total_weight, + "company_kill_house_free_carcases_bar_total_weight": company_kill_house_free_carcases_bar_total_weight, + "company_chain_allocation_total_weight": company_chain_allocation_total_weight, + "freezing_company_province_kill_request_total_wage": freezing_company_province_kill_request_total_wage, + "freezing_company_province_kill_request_total_weight": freezing_company_province_kill_request_total_weight, + + "guilds_total_weight": guilds_total_weight, + "guilds_total_wage": guilds_total_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + "guilds_province_kill_request_total_wage": guilds_province_kill_request_total_wage, + "guilds_kill_house_free_live_bar_total_wage": guilds_kill_house_free_live_bar_total_wage, + "guilds_kill_house_free_carcases_bar_total_wage": guilds_kill_house_free_carcases_bar_total_wage, + "guilds_chain_allocation_total_wage": guilds_chain_allocation_total_wage, + "guilds_province_kill_request_total_weight": guilds_province_kill_request_total_weight, + "guilds_kill_house_free_live_bar_total_weight": guilds_kill_house_free_live_bar_total_weight, + "guilds_kill_house_free_carcases_bar_total_weight": guilds_kill_house_free_carcases_bar_total_weight, + "guilds_chain_allocation_total_weight": guilds_chain_allocation_total_weight, + "freezing_guilds_province_kill_request_total_wage": freezing_guilds_province_kill_request_total_wage, + "freezing_guilds_province_kill_request_total_weight": freezing_guilds_province_kill_request_total_weight, + } + } + + +class VetKillHouseSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True) + kill_houses = serializers.SerializerMethodField('get_kill_houses') + + class Meta: + model = Vet + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by', + ) + + def get_kill_houses(self, instance): + kill_houses_list = [] + kill_house_vets = KillHouseVet.objects.filter(vet=instance, trash=False).select_related( + 'kill_house__kill_house_operator__user') + if kill_house_vets.count() > 0: + for kill_house_vet in kill_house_vets: + internal_dict = { + "Kill_house_key": kill_house_vet.kill_house.key, + "Kill_house_name": kill_house_vet.kill_house.name, + "Kill_house_user_full_name": kill_house_vet.kill_house.kill_house_operator.user.fullname, + "Kill_house_user_mobile": kill_house_vet.kill_house.kill_house_operator.user.mobile, + } + kill_houses_list.append(internal_dict) + + return kill_houses_list + + +class VetFarmListSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(read_only=True) + farms = serializers.SerializerMethodField('get_farms') + + class Meta: + model = Vet + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by', + ) + + def get_farms(self, instance): + farms_list = [] + farms = VetFarm.objects.filter(vet=instance, trash=False).select_related('poultry', 'vet') + if farms.count() > 0: + for farm in farms: + internal_dict = { + "poultry_name": farm.poultry.unit_name, + "poultry_full_name": farm.poultry.user.fullname, + "poultry_mobile": farm.poultry.user.mobile, + "poultry_hall": farm.hall, + "vet_id": farm.vet.id, + "vet_farm_key": farm.key, + } + farms_list.append(internal_dict) + + return farms_list + + +class KillHouseOperatorForBarDifferenceRequestSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user'] + + +class KillHouseForBarDifferenceRequestSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForBarDifferenceRequestSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'name', 'killer', 'key'] + + +class BarDifferenceRequestSerializer(serializers.ModelSerializer): + hatching = PoultryHatchingForBarDifferenceRequestSerializer(read_only=True) + kill_house = KillHouseForBarDifferenceRequestSerializer(read_only=True) + bar_info = serializers.SerializerMethodField('get_bar_info') + + class Meta: + model = BarDifferenceRequest + fields = '__all__' + + def get_bar_info(self, obj): + total_quantity = 0 + first_total_quantity = 0 + difference_quantity = 0 + total_weight = 0 + Province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj.kill_house, trash=False, + state__in=('pending', 'accepted'), + return_to_province=False, + province_request__poultry_request__hatching=obj.hatching) + + first_total_quantity = \ + Province_kill_requests.aggregate(total=Sum('main_quantity'))[ + 'total'] or 0 + + total_quantity = \ + Province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_weight = \ + Province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + difference_quantity = first_total_quantity - total_quantity + # kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj.kill_house) | Q(killer=obj.kill_house),trash=False, + # province_request__poultry_request__hatching=obj.hatching) + # + # + # total_quantity +=\ + # kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + # 'total'] or 0 + # total_weight +=\ + # kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + # 'total'] or 0 + + result = { + "first_total_quantity": first_total_quantity, + "total_quantity": total_quantity, + "difference_quantity": difference_quantity, + "total_weight": total_weight, + } + + return result + + +class KillHouseOperatorForHatchingDetailSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryLocSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user', 'address'] + + +class KillHouseForHatchingDetailSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForHatchingDetailSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'name'] + + +class KillHouseRequestForHatchingDetailSerializer(serializers.ModelSerializer): + buyer = KillHouseForHatchingDetailSerializer(source='killhouse_user', read_only=True) + date = serializers.DateTimeField(source='kill_request.recive_date', read_only=True) + killer_info = KillHouseForHatchingDetailSerializer(source='killer', read_only=True) + product = serializers.CharField(default='مرغ گرم', read_only=True) + status = serializers.SerializerMethodField() + poultry_request = serializers.SerializerMethodField() + + class Meta: + model = KillHouseRequest + fields = [ + 'bar_code', 'date', 'buyer', 'killer_info', + 'product', 'clearance_code', 'accepted_real_quantity', 'accepted_real_weight', 'quarantine_quantity', + 'status', 'ware_house_accepted_real_quantity', 'ware_house_accepted_real_weight', 'poultry_request' + ] + read_only_fields = fields + + def get_status(self, obj): + if obj.ware_house_confirmation == True: + status = 'ورود به انبار' + elif obj.assignment_state_archive == 'True' and obj.ware_house_confirmation == False: + status = 'در انتظار ورود به انبار' + elif obj.assignment_state_archive == 'True': + status = 'تخلیه شده' + else: + status = 'درانتظار تخلیه' + return status + + def get_poultry_request(self, obj): + return PoultryRequestForBarMangementSerializer(obj.province_kill_request.province_request.poultry_request).data + + +class KillHouseForPerformanceDashboardSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForBarDifferenceRequestSerializer(read_only=True) + killing_info = serializers.SerializerMethodField('get_killing_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'kill_house_operator', 'killer', 'killing_info'] + + def get_killing_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, killhouse_user=obj, + state__in=('pending', 'accepted'), + return_to_province=False, archive_wage=False, + temporary_trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0) + kill_house_requests = KillHouseRequest.objects.filter(Q(killer=obj) | Q(killhouse_user=obj), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + calculate_status=True, temporary_trash=False, trash=False) + kill_house_free_bar = KillHouseFreeBarInformation.objects.filter(kill_house=obj, calculate_status=True, + buy_type='live', + create_date__date__gte=date1, + create_date__date__lte=date2, + temporary_trash=False, trash=False) + + province_kill_requests_aggregates = province_kill_requests.aggregate( + total_count=Count('id'), + total_weight=Sum('total_killed_weight'), + total_quantity=Sum('total_killed_quantity') + ) + + kill_house_requests_aggregates = kill_house_requests.aggregate( + total_count=Count('id'), + total_weight=Sum('accepted_real_weight'), + total_quantity=Sum('accepted_real_quantity') + ) + kill_house_requests_ware_house_true = kill_house_requests.filter(ware_house_confirmation=True).aggregate( + total_count=Count('id'), + total_weight=Sum('accepted_real_weight'), + total_quantity=Sum('accepted_real_quantity') + ) + kill_house_requests_ware_house_false = kill_house_requests.filter(ware_house_confirmation=False).aggregate( + total_count=Count('id'), + total_weight=Sum('accepted_real_weight'), + total_quantity=Sum('accepted_real_quantity') + ) + + kill_house_free_bar_aggregates = kill_house_free_bar.aggregate( + total_count=Count('id'), + total_weight=Sum('live_weight'), + total_quantity=Sum('quantity') + + ) + total_weight = (province_kill_requests_aggregates['total_weight'] or 0) + ( + kill_house_requests_aggregates['total_weight'] or 0) + \ + (kill_house_free_bar_aggregates['total_weight'] or 0) + total_quantity = (province_kill_requests_aggregates['total_quantity'] or 0) + \ + (kill_house_requests_aggregates['total_quantity'] or 0) + \ + (kill_house_free_bar_aggregates['total_quantity'] or 0) + total_avg_weight = round(total_weight / total_quantity, 1) if total_quantity > 0 else 0 + return { + "province_kill_requests_count": province_kill_requests_aggregates['total_count'] or 0, + "province_kill_requests_quantity": province_kill_requests_aggregates['total_quantity'] or 0, + "province_kill_requests_weight": province_kill_requests_aggregates['total_weight'] or 0, + "kill_house_requests_count": kill_house_requests_aggregates['total_count'] or 0, + "kill_house_requests_quantity": kill_house_requests_aggregates['total_quantity'] or 0, + "kill_house_requests_weight": kill_house_requests_aggregates['total_weight'] or 0, + "kill_house_free_bar_count": kill_house_free_bar_aggregates['total_count'] or 0, + "kill_house_free_bar_quantity": kill_house_free_bar_aggregates['total_quantity'] or 0, + "kill_house_free_bar_weight": kill_house_free_bar_aggregates['total_weight'] or 0, + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_avg_weight": total_avg_weight, + "total_count": province_kill_requests_aggregates['total_count'] or 0 + kill_house_requests_aggregates[ + 'total_count'] or 0 + + kill_house_free_bar_aggregates['total_count'] or 0, + "kill_house_requests_ware_house_true_quantity": kill_house_requests_ware_house_true['total_quantity'] or 0, + "kill_house_requests_ware_house_true_weight": kill_house_requests_ware_house_true['total_weight'] or 0, + "kill_house_requests_ware_house_false_quantity": kill_house_requests_ware_house_false[ + 'total_quantity'] or 0, + "kill_house_requests_ware_house_false_weight": kill_house_requests_ware_house_false['total_weight'] or 0, + + } + + +class DirectBuyingPaymentSerializer(serializers.ModelSerializer): + class Meta: + model = DirectBuyingPayment + fields = ['key', 'amount', 'image', 'date', 'payment_deadline_supporter_message'] + + +class KillHouseForDirectBuyingSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['name', 'kill_house_operator'] + + +class KillRequestForDirectBuyingTrueSerializer(serializers.ModelSerializer): + kill_house = KillHouseForDirectBuyingSerializer(read_only=True) + slaughter_house = KillHouseForDirectBuyingSerializer(read_only=True) + poultry = PoultryForPredictionSerializer(read_only=True) + poultry_request = PoultryRequestForMarketSerializer(read_only=True) + poultry_hatching = PoultryHatchingForLocSerializer(read_only=True) + + class Meta: + model = KillRequest + fields = ['key', 'create_date', 'recive_date', 'free_direct_buying', 'chicken_breed', 'kill_house', + 'slaughter_house', 'poultry', 'poultry_request', 'payment_deadline_date', 'payment_deadline_days', + 'kill_capacity', 'Index_weight', 'amount', 'market_final_accept', 'market_state', 'recive_time', + 'market_code_status', 'market_code', 'input_market_code', 'direct_buying_state', 'free_direct_buying', + 'poultry_hatching', 'automatic_accept', 'input_direct_buying_code'] + + +class ReturnProvinceKillRequestSerializer(serializers.ModelSerializer): + killhouse_user = KillHouseForReturnBuyingSerializer(read_only=True) + poultry_unit_name = serializers.CharField(source='province_request.poultry_request.poultry.unit_name', + read_only=True) + poultry_fullname = serializers.CharField(source='province_request.poultry_request.poultry.user.fullname', + read_only=True) + poultry_mobile = serializers.CharField(source='province_request.poultry_request.poultry.user.mobile', + read_only=True) + poultry_city = serializers.CharField(source='province_request.poultry_request.poultry.user.city.name', + read_only=True) + killing_date = serializers.CharField(source='province_request.poultry_request.send_date', read_only=True) + order_code = serializers.CharField(source='province_request.poultry_request.order_code', read_only=True) + poultry_request_quantity = serializers.CharField(source='province_request.poultry_request.quantity', read_only=True) + poultry_amount = serializers.CharField(source='province_request.poultry_request.amount', read_only=True) + + class Meta: + model = ProvinceKillRequest + fields = '__all__' diff --git a/panel/KillHouse/views.py b/panel/KillHouse/views.py new file mode 100644 index 0000000..72fd33a --- /dev/null +++ b/panel/KillHouse/views.py @@ -0,0 +1,19742 @@ +import random +import string +import threading +from datetime import datetime, timedelta + +import jdatetime +import requests +from django.contrib.auth.models import User, Group +from django.db.models import Case, When, Avg +from django.http import JsonResponse, HttpResponse +from django.http import QueryDict +from django.shortcuts import get_object_or_404 +from django.utils import timezone +from django.views.decorators.csrf import csrf_exempt +from django_filters.rest_framework import DjangoFilterBackend +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from rest_framework import status +from rest_framework import viewsets +from rest_framework.decorators import permission_classes, api_view +from rest_framework.generics import GenericAPIView +from rest_framework.pagination import PageNumberPagination +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from rest_framework.views import APIView + +from authentication.arvan_image.arvan_storage import upload_object_resize +from authentication.models import UserProfile, SystemUserProfile, City, Province, SystemAddress +from authentication.serializer.serializer import SystemUserProfileSerializer +from authentication.sms_management import kill_request_province_sms, province_kill_request_to_kill_house_sms, \ + kill_request_delete_province_sms, province_kill_request_accept_sms, document_discrepancy_sms, export_code_sms, \ + car_allocation_vet_farm_sms, delete_car_allocation_vet_farm_sms, send_sms_for_bar_difference_request, \ + confirm_price_poultry_request_direct_buying_sms, send_sms_fro_kill_request_market, send_sms_for_sale_bar +from authentication.views import ARTA_URL_CHANGE_MOBILE_NUMBER +from bot_eata import bot_eitaa_for_each_province_kill_request, bot_eitaa_for_each_delete_province_kill_request, \ + send_single_bar_to_eitaa +from deposit_id import market_code_state +from general_urls import base_url_sms, base_url_for_sms_report +from panel.KillHouse.helpers import kill_house_requests_product_warehousing, kill_house_free_buying_product_warehousing, \ + kill_house_free_sale_product_warehousing, get_finance_info, generate_unique_bar_code, \ + send_ticket_for_bar_difference_request, market_poultry_request_remain_quantity, market_kill_request_share_quantity, \ + calculate_governmental_quota, check_kill_house_remain_limitation_weight +from panel.KillHouse.serializers import ( + KillHouseSerializer, + KillHouseRequestSerializer, + KillRequestSerializer, + KillHouseAssignmentInformationSerializer, + KillHouseCheckRequestSerializer, + KillHouseADDCARSerializer, + VetSerializer, + VetCheckRequestSerializer, + ProvinceKillRequestSerializer, + KillHouseRequestExchangeSerializer, + KillHouseRequestExchangeReserveSerializer, + KillHouseRequestExchangeAddCarSerializer, + KillHouseDriverSerializer, + KillHouseOperatorSerializer, + + KillHouseRequestActionSerializer, + + KillHouseRequestActionWinnerSerializer, DriverRequestCancelSerializer, KillHouseVetSerializer, + KillHouseComplaintSerializer, CheckKillHouseComplaintSerializer, CheckUnusualCasualtiesSerializer, + KillHousePercentageSerializer, KillHouseAssignmentImagesSerializer, KillRequestFactorSerializer, + KillRequestFactorPaymentSerializer, AutomaticKillRequestSerializer, KillHouseCreditorsSerializer, + KillHouseAllowVetSerializer, KillHouseWareHouseSerializer, KillHouseFreeBarInformationSerializer, + KillHouseRequestForBarManagementSerializer, ProvinceKillRequestProvinceWageSerializer, + KillHouseForProvinceWageSerializer, KillHouseforPurchaseRequestSerializer, KillHousePurchaseRequestSerializer, + KillHouseForAutomaticStewardAllocationSerializer, KillHouseForTotalReportAutomaticStewardAllocationSerializer, + PoultryRequestLetterForProvinceVetSerializer, + ProvinceKillRequestForKillingInformationDiscrepancyReportSerializer, KillHouseRequestForDiffrentBarInfoSerializer, + PoultryRequestForTotalInformationSerializer, PoultryRequestForTotalInformationInTableSerializer, + KillHouseWareHouseForDailyBroadCastOInDetailsSerializer, KillHouseAssignmentInformationForCompletedLoadsSerializer, + KillHouseFreeSaleBarInformationSerializer, KillHouseWageForTotalDashbordSerializer, + KillHouseForProvinceWageWithDateSerializer, SlaughterHouseTransactionSerializer, KillHouseWageSerializer, + KillHouseForFreeBarWageSerializer, KillHouseForFreeBarWageWithDateSerializer, + KillHouseForTotalProvinceWageTransactionSerializer, KillHouseForTotalProvinceWageTransactionWithDAteSerializer, + KillHouseForKillHouseRequestWageWithDateSerializer, KillHouseForKillHouseRequestWageSerializer, + KillHouseFreeBarInformationForWageTotalSerializer, + TotalWageInformationKillHouseExclusiveKillerSerializer, KillHouseLetterForProvinceSerializer, + PoultryRequestoutProvinceSerializer, BarDocumentStatusSerializer, GeneralKillHouseSerializer, + VetKillHouseSerializer, VetFarmListSerializer, KillHouseForKillHouseVetKillHouseSerializer, + KillHouseForFreeSaleBarInformationViewSetSerializer, + KillHouseForFreeSaleBarInformationViewSetWithDateSerializer, KillHouseForNewWageInormationSerializer, + KillHouseRequestForInputBarsSerializer, PosKillHouseSerializer, KillHouseForProvinceWareHouseDashboardSerializer, + ParentCompanyKillHouseForNewWageInormationSerializer, KillHouseForColdHouseSerializer, + KillHouseColdHousesSerializer, BarDifferenceRequestSerializer, distributionKillHouseSerializer, + KillHouseForPerformanceDashboardSerializer, DirectBuyingPaymentSerializer, KillRequestForDirectBuyingSerializer, + ProvinceKillRequestForDirectBuyingSerializer, KillHouseForCommonlyUsedSerializer, KillHouseMarketInfoSerializer, + KillHouseForColdHouseAllocationSerializer, KillHouseForSegmentationSerializer, + KillHouseComparativeInformationSerializer, KillRequestForDirectBuyingTrueSerializer, + ReturnProvinceKillRequestSerializer, TotalKillHouseRemainWeightViewSetSerializer, + TotalKillHouseWarehouseArchiveDashboardSerializer, PspKillHouseSerializer +) +from panel.ProvinceOperator.serializers import ProvinceFactorToKillHouseSerializer, StewardAllocationSerializer +from panel.ProvinceOperator.views import ARVAN_Kill_house_Factor_URL +from panel.ReportingPanel.helper import kill_house_request_filterset_fields, \ + poultry_request_new_fields +from panel.ReportingPanel.views import get_gid_out_province +from panel.VetFarm.serializers import VetFarmSerializer +from panel.admin import PROJECT_API_KEY +from panel.filterset import KillHouseDriverFilterSet, VetFilterSet, KillHouseRequestFilterSet, \ + ProvinceKillRequestFilterSet, KillHouseFilterSet, KillRequestFilterSet, PoultryRequestFilterSet, \ + KillHouseFreeBarInformationFilterSet, DashboardEnterLoadInformationFilterSet, \ + DashboardKillHouseFreeBarInformationFilterSet, VetFarmAndKillHouseFilterSet, ProvinceKillRequestNewFilterSet, \ + DashboardKillRequestFilterSet, KillHouseFreeSaleBarInformationFilterSet, \ + BarDifferenceRequestFilterSet, DirectBuyingPaymentFilterSet, ReturnProvinceKillRequestFilterSet +from panel.helper import build_query +from panel.models import ( + KillHouse, + KillHouseRequest, + KillRequest, + ProvinceCheckOperatorRequest, + KillHouseCheckRequest, + KillHouseAssignmentInformation, + ProvinceFactorToKillHouse, + KillHouseADDCAR, + Vet, + VetCheckRequest, + ProvinceKillRequest, + KillHouseRequestExchange, + KillHouseRequestExchangeReserve, + PoultryRequestExchange, + KillHouseRequestExchangeAddCar, + PoultryRequest, + KillHouseDriver, + KillHouseOperator, + VetFarm, + KillHouseRequestAction, + KillHouseRequestActionWinner, DriverRequestCancel, KillHouseVet, PercentageOfLosses, KillHouseComplaint, + CheckKillHouseComplaint, ProvinceFactorToKillHouseForPoultry, CheckUnusualCasualties, KillHousePercentage, + TotalPoultryRequestQuantity, KillHouseAssignmentImages, VetSupervisor, KillRequestFactor, KillRequestFactorPayment, + Pricing, AutomaticKillRequest, KillHouseCreditors, ShareOfAllocation, ProvinceOperator, SmsLicense, + KillHouseAllowVet, Wallet, ProvinceAllowKillHouseRegisterCar, PoultryHatching, Poultry, + AutoAcceptProvinceKillRequest, KillHouseWareHouse, KillHouseFreeBarInformation, Guilds, + CityOperator, PoultryRequestAuction, ProvinceAllowKillHouseChooseStewardGuilds, KillHouseHourLimit, + ProvinceAllowKillHouseDirectBuying, KillHousePurchaseRequest, Steward, StewardAllocation, StewardWareHouse, + ColdHouseAllocations, KillHouseFreeSaleBarInformation, OperationLimitation, + EvacuationPermit, TimeRange, SlaughterHouseTransaction, WageType, PercentageOfWageType, + InternalTransaction, BarDocumentStatus, VetFarmAggregatePermission, OutProvinceCarcassesBuyer, RolesProducts, + AutomaticDirectBuyingPermission, FreeSaleWithinprovince, CityOperatorCheckRequest, POSMachine, ColdHouse, + BarDifferenceRequest, ChickenAgeRange, RequestLimitation, PriceConfirmation, DirectBuyingPayment, + DirectBuyingVerification, FinePermission, IndexWeightCategory, PosSegmentation, RestrictionCarcassDistribution, + AllowRegisterCodeForKillHouseFreeSaleBarInformation, ProductsTransactions, + LimitationForDirectPurchaseAndBarInformation, WarehouseArchive +) +# آدرس پایه مربوط به ذخیره عکس در گالری مربوط به کشتارگاه در استوریج آروان +from panel.poultry.helpers import poultry_prediction, create_update_chicken_commission_prices +from panel.poultry.serializers import PoultryRequestSerializer, PoultryRequestForKillingInformationSerializer +from ticket.bucket import upload_to_liara +from ticket.helper import send_image_to_server + +ARVAN_Kill_house_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +ARTA_URL_REGISTER = "https://userbackend.rasadyar.com/api/register/" + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +from django.db.models import Q + + +def get_exclusive_killer_operation(kill_houses): + for kill_house in kill_houses: + total_unpaid_wage = 0 + total_paid_wage = 0 + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) | Q(killer=kill_house)), + # killhouse_user=kill_house, + archive_wage=False, + trash=False + ) + + kill_house_requests = kill_house_requests.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)) + + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + trash=False) + + total_unpaid_wage += province_kill_requests.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_unpaid_wage += free_bars.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_unpaid_wage += \ + kill_house_requests.aggregate(total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_amount = total_unpaid_wage - total_paid_wage + kill_house_purchase = KillHousePurchaseRequest.objects.filter(limitation=True, kill_house=kill_house).first() + if kill_house_purchase: + if total_amount >= kill_house_purchase.limitation_number: + kill_house.show_exclusive = False + kill_house.save() + else: + kill_house.show_exclusive = True + kill_house.save() + else: + kill_house.show_exclusive = True + kill_house.save() + + +def update_kill_house_requests(province_kill_request, poultry_request): + # gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) + kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_request, trash=False) + + total_kill_house_requests_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity'))[ + 'total_quantity'] + total_kill_house_requests_weight = kill_house_requests.aggregate(total_weight=Sum('accepted_real_weight'))[ + 'total_weight'] + total_first_allocated_cars = kill_house_requests.aggregate(total_weight=Sum('quantity'))[ + 'total_weight'] + + province_kill_request.total_killed_quantity = total_kill_house_requests_quantity or province_kill_request.main_quantity + province_kill_request.first_car_allocated_quantity = total_first_allocated_cars or 0 + province_kill_request.total_killed_weight = total_kill_house_requests_weight or int( + province_kill_request.main_quantity * poultry_request.Index_weight) + province_kill_request.total_wage_amount = province_kill_request.total_killed_weight * province_kill_request.wage + + province_kill_request.save() + + union_percent = province_kill_request.union_share_percent / 100 if province_kill_request.union_share_percent > 0 else 0 + company_percent = province_kill_request.company_share_percent / 100 if province_kill_request.company_share_percent > 0 else 0 + guilds_percent = province_kill_request.guilds_share_percent / 100 if province_kill_request.guilds_share_percent > 0 else 0 + city_share_percent = province_kill_request.city_share_percent / 100 if province_kill_request.city_share_percent > 0 else 0 + wallet_share_percent = province_kill_request.wallet_share_percent / 100 if province_kill_request.wallet_share_percent > 0 else 0 + other_share_percent = province_kill_request.other_share_percent / 100 if province_kill_request.other_share_percent > 0 else 0 + province_kill_request.union_share = int(union_percent * province_kill_request.total_wage_amount) + province_kill_request.company_share = int(company_percent * province_kill_request.total_wage_amount) + province_kill_request.guilds_share = int(guilds_percent * province_kill_request.total_wage_amount) + province_kill_request.city_share = int(city_share_percent * province_kill_request.total_wage_amount) + province_kill_request.wallet_share = int(wallet_share_percent * province_kill_request.total_wage_amount) + province_kill_request.other_share = int(other_share_percent * province_kill_request.total_wage_amount) + province_kill_request.save() + + +def update_province_kill_requests(poultry_hatching): + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + state__in=('pending', 'accepted'), + return_to_province=False, + province_request__poultry_request__hatching=poultry_hatching + ) + + total_killed_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] + total_extra_quantity = province_kill_requests.aggregate(total=Sum('extra_killed_quantity'))['total'] + + free_filter = Q(province_request__poultry_request__free_sale_in_province=True, state__in=('pending', 'accepted'), + trash=False) + governmental_filter = ~free_filter + + total_free_quantity = \ + province_kill_requests.filter(free_filter, province_request__poultry_request__export=False).aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] + total_free_weight = \ + province_kill_requests.filter(free_filter, province_request__poultry_request__export=False).aggregate( + total=Sum('total_killed_weight'))['total'] + total_governmental_quantity = \ + province_kill_requests.filter(governmental_filter, province_request__poultry_request__export=False).aggregate( + total=Sum('total_killed_quantity'))['total'] + total_governmental_weight = \ + province_kill_requests.filter(governmental_filter, province_request__poultry_request__export=False).aggregate( + total=Sum('total_killed_weight'))['total'] + total_export_quantity = \ + province_kill_requests.filter(province_request__poultry_request__export=True).aggregate( + total=Sum('total_killed_quantity'))['total'] + total_export_weight = \ + province_kill_requests.filter(province_request__poultry_request__export=True).aggregate( + total=Sum('total_killed_weight'))['total'] + + poultry_hatching.free_killed_quantity = total_free_weight or 0 + poultry_hatching.free_quantity = total_free_quantity or 0 + poultry_hatching.governmental_killed_quantity = total_governmental_weight or 0 + poultry_hatching.governmental_quantity = total_governmental_quantity or 0 + poultry_hatching.export_killed_weight = total_export_weight or 0 + poultry_hatching.export_killed_quantity = total_export_quantity or 0 + poultry_hatching.extra_killed_quantity = total_extra_quantity or 0 + poultry_hatching.killed_quantity = total_killed_quantity or 0 + + poultry_hatching.save() + + +class BarDocumentStatusViewset(viewsets.ModelViewSet): + queryset = BarDocumentStatus.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = BarDocumentStatusSerializer + + def list(self, request, *args, **kwargs): + bar_documents_status = BarDocumentStatus.objects.filter(trash=False).order_by('priority_id') + serializer = self.serializer_class(bar_documents_status, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + + if 'priority_list' in request.data: + priority_list = request.data['priority_list'] + priorities = {item['key']: item['value'] for item in priority_list} + bar_documents_status = BarDocumentStatus.objects.filter(trash=False).order_by('priority_id') + for document in bar_documents_status: + priority_id = priorities.get(str(document.key)) + if priority_id is not None: + document.priority_id = priority_id + document.save() + + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + bar_documents_status = BarDocumentStatus.objects.get(key=request.data['bar_documents_status_key'], trash=False) + request.data.pop('bar_documents_status_key') + serializer = self.serializer_class(bar_documents_status) + serializer.update(instance=bar_documents_status, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + bar_documents_status = BarDocumentStatus.objects.get(id=pk, trash=False) + if KillHouseRequest.objects.filter(bar_document_status=bar_documents_status, + trash=False).exists(): + return Response({"result": "به علت استفاده ار این وضعیت سند بر روی بار امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + bar_documents_status.delete() + return Response({"result": "با موفقیت حذف شد."}, + status=status.HTTP_200_OK) + + +class KillHouseCreditorsViewSet(viewsets.ModelViewSet): + queryset = KillHouseCreditors.objects.all() + serializer_class = KillHouseCreditorsSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + creditors = KillHouseCreditors.objects.filter(kill_house__system_address__province=user.province).order_by('id') + serializer_request = self.serializer_class(creditors, many=True) + return Response(serializer_request.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + creditors = KillHouseCreditors.objects.get(key=request.data["key"], trash=False) + request.data.pop('key') + amount = request.data['amount'] + request.data.pop('amount') + + creditors.amount -= float(amount) + creditors.save() + + serializer = self.serializer_class(creditors) + serializer.update(instance=creditors, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به اپراتور کشتارگاه +class KillHouseOperatorViewSet(viewsets.ModelViewSet): + queryset = KillHouseOperator.objects.all() + serializer_class = KillHouseOperatorSerializer + permission_classes = [TokenHasReadWriteScope] + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house_operator_serializer = KillHouseOperatorSerializer(kill_house_operator) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + kill_house_serializer = KillHouseSerializer(kill_house, many=True) + profile_info = { + # 'profile': user_serializer.data, + 'kill_house_operator': kill_house_operator_serializer.data, + 'kill_house': kill_house_serializer.data + } + return Response(profile_info, status=status.HTTP_200_OK) + + +class KillHouseForKillHouseRequestWageViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForKillHouseRequestWageSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOPerator': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + archive_wage=False, + province_kill_request__union_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_kill_request__company_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_kill_request__guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + else: + + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOPerator': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + province_kill_request__union_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + province_kill_request__company_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + province_kill_request__guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + else: + + kill_houses = KillHouse.objects.filter(pk__in=KillHouseRequest.objects.filter( + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + if 'date1' in request.GET: + serializer = KillHouseForKillHouseRequestWageWithDateSerializer(page, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = KillHouseForProvinceWageWithDateSerializer(kill_houses, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForNewWageInormationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForNewWageInormationSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).exclude(id__in=kill_house_ids).order_by( + 'id') + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForColdHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForColdHouseSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + kill_houses = KillHouse.objects.filter(out_province=False, trash=False, + pk__in=ColdHouse.objects.filter(kill_house__isnull=False).values_list( + 'kill_house', flat=True)).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + kill_houses_list = [] + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses_list = ps.filter() + kill_houses = [] if len(kill_houses_list) == 0 else kill_houses_list + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.get_serializer(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseColdHousesViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseColdHousesSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + serializer = self.get_serializer(kill_houses) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ParentCompanyKillHouseForNewWageInormationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = ParentCompanyKillHouseForNewWageInormationSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + serializer = self.get_serializer(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForProvinceWareHouseDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + serializer_class = KillHouseForProvinceWareHouseDashboardSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + kill_house_filters = {'out_province': False, 'active': True, 'trash': False} + if role in ['CityJahad']: + kill_house_filters['kill_house_operator__user__city'] = user.city + + kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by( + 'id') + + kill_houses = kill_houses.annotate( + allocation_count=Count( + 'kill_house_steward_allocation', + filter=Q(kill_house_steward_allocation__receiver_state__in=['pending', 'accepted']) + ) + ).order_by( + '-allocation_count' + ) + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForTotalProvinceWareHouseDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + serializer_class = KillHouseForProvinceWareHouseDashboardSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + kill_house_filters = {'out_province': False, 'active': True, 'trash': False} + if role in ['CityJahad']: + kill_house_filters['kill_house_operator__user__city'] = user.city + + kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by( + 'id') + + kill_houses = kill_houses.annotate( + allocation_count=Count( + 'kill_house_steward_allocation', + filter=Q(kill_house_steward_allocation__receiver_state__in=['pending', 'accepted']) + ) + ).order_by( + '-allocation_count' + ) + products = RolesProducts.objects.filter(kill_house__in=kill_houses, trash=False, name='مرغ گرم') + + # products = RolesProducts.objects.filter(kill_house__in=kill_houses, trash=False) + # product_remain_weight = products.aggregate(total=Sum('total_remain_weight'))[ + # 'total'] or 0 + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + bars_date1 = date1 + bars_date2 = date2 + # bars_date1 = date1 - timedelta(days=1) + # bars_date2 = date2 - timedelta(days=1) + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse__in=kill_houses, + kill_request__recive_date__date__gte=bars_date1, + kill_request__recive_date__date__lte=bars_date2, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True, warehouse=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), + input_warehouse__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True).exclude( + entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, warehouse=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, trash=False, + receiver_state__in=('pending', 'accepted'), + date__date__gte=date1, + date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house__in=kill_houses, trash=False, + date__date__gte=date1, + date__date__lte=date2, warehouse=True) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product__in=products, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house__in=kill_houses, date__date__gte=date1, + date__date__lte=date2, trash=False, warehouse=True) + + + else: + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse__in=kill_houses, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True, warehouse=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter( + input_warehouse__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, warehouse=True).exclude(entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, warehouse=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, warehouse=True) + + segmentations = PosSegmentation.objects.filter(kill_house__in=kill_houses, trash=False, warehouse=True) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house__in=kill_houses, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product__in=products, transaction__paid=True, + trash=False, warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house__in=kill_houses, trash=False, warehouse=True) + + total_kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_weight = \ + kill_house_requests.filter(ware_house_confirmation=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_governmental_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_free_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + kill_house_free_bar_informations_live = kill_house_free_bar_informations.filter(buy_type='live') + kill_house_free_bar_informations_carcasses = kill_house_free_bar_informations.filter(buy_type='carcass') + total_kill_house_free_bar_quantity = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('quantity'))['total'] or 0 + total_kill_house_free_bar_weight = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('live_weight'))['total'] or 0 + total_kill_house_free_bar_carcasses = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_entered_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_weight = \ + kill_house_free_Sale_bar_informations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_sale__bar_carcasses_governmental_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_free_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_allocations_governmental_weight = \ + kill_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_allocations_free_weight = \ + kill_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + cold_house_allocations_weight = \ + cold_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cold_house_allocations_governmental_weight = \ + cold_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + cold_house_allocations_free_weight = \ + cold_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + total_archive_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_archive_free_weight=Sum('weight', filter=Q(quota='free')), + ) + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + total_archive_governmental_weight = archives_info['total_archive_governmental_weight'] or 0 + total_archive_free_weight = archives_info['total_archive_free_weight'] or 0 + + total_governmental_input_weight = total_entered_kill_house_requests_carcasses_governmental_weight + total_free_input_weight = total_entered_kill_house_requests_carcasses_free_weight + total_entered_kill_house_free_bar_carcasses_weight + total_governmental_output_weight = total_kill_house_free_sale__bar_carcasses_governmental_weight + segmentations_governmental_weight + total_kill_house_allocations_governmental_weight + cold_house_allocations_governmental_weight + int(pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_kill_house_free_sale__bar_carcasses_free_weight + total_kill_house_allocations_free_weight + segmentations_free_weight + cold_house_allocations_free_weight + int(pos_free_allocated_weight / 1000) + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight if ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight > 0 else 0 + last_total_governmental_remain_weight = ( + ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight) * -1 if ( + total_governmental_input_weight - total_governmental_output_weight) - total_archive_governmental_weight < 0 else 0 + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - total_archive_free_weight if ( + total_free_input_weight - total_free_output_weight) - total_archive_free_weight > 0 else 0 + last_total_free_remain_weight = (( + total_free_input_weight - total_free_output_weight) - total_archive_free_weight) * -1 if ( + total_free_input_weight - total_free_output_weight) - total_archive_free_weight < 0 else 0 + last_total_remain_weight = last_total_governmental_remain_weight + last_total_free_remain_weight + warehouse_total_weight = total_kill_house_requests_weight + total_kill_house_free_bar_weight + total_kill_house_free_bar_carcasses_weight + warehouse_total_entered_carcasses_weight = total_entered_kill_house_requests_carcasses_weight + total_entered_kill_house_free_bar_carcasses_weight + result = { + "product_remain_weight": int(total_governmental_remain_weight + total_free_remain_weight), + "warehouse_total_quantity": int( + total_kill_house_requests_quantity + total_kill_house_free_bar_quantity + total_kill_house_free_bar_carcasses), + "warehouse_total_weight": int(warehouse_total_weight), + "warehouse_total_entered_carcasses_weight": int(warehouse_total_entered_carcasses_weight), + "total_kill_house_allocations_weight": int(total_kill_house_allocations_weight), + "total_kill_house_free_sale_bar_carcasses_weight": int(total_kill_house_free_sale__bar_carcasses_weight), + "segmentations_weight": int(segmentations_weight), + "cold_house_allocations_weight": int(cold_house_allocations_weight), + "total_governmental_input_weight": int(total_governmental_input_weight), + "total_free_input_weight": int(total_free_input_weight), + "total_governmental_output_weight": int(total_governmental_output_weight), + "total_free_output_weight": int(total_free_output_weight), + "total_governmental_remain_weight": int(total_governmental_remain_weight), + "total_free_remain_weight": int(total_free_remain_weight), + "last_total_governmental_remain_weight": int(last_total_governmental_remain_weight), + "last_total_free_remain_weight": int(last_total_free_remain_weight), + "last_total_remain_weight": int(last_total_remain_weight), + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "total_archive_governmental_weight": total_archive_governmental_weight, + "total_archive_free_weight": total_archive_free_weight, + + } + return Response(result, status=status.HTTP_200_OK) + + +class KillHouseDistributionInormationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForNewWageInormationSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + steward_allocations = StewardAllocation.objects.filter(kill_house=kill_house, + receiver_state__in=('pending', 'accepted'), + calculate_status=True, trash=False) + free_sales = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, trash=False, + calculate_status=True) + steward_allocations_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + else: + guild = Guilds.objects.get(user=user, trash=False) + steward_allocations = StewardAllocation.objects.filter(Q(steward=guild) | Q(guilds=guild), + receiver_state__in=('pending', 'accepted'), + calculate_status=True, trash=False) + steward_allocations_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_weight = 0 + + result = { + "steward_allocations_weight": steward_allocations_weight, + "free_sales_weight": free_sales_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class KillHouseTotalDashboardForNewWageInormationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForKillHouseRequestWageSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-buy', trash=False).first() + free_sell_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-sell', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + free_buying_carcesses_weight_wage_type_amount = free_buying_carcesses_weight_wage_type.amount if free_buying_carcesses_weight_wage_type.status == True else 0 + free_sell_carcesses_weight_wage_type_amount = free_sell_carcesses_weight_wage_type.amount if free_sell_carcesses_weight_wage_type.status == True else 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__in=kill_houses, status='completed', + trash=False) + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_pure_province_carcasses_weight = total_province_carcasses_weight - total_out_selling_province_carcasses_weight + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_type_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_wage_type_amount + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_wage_type_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + + result = { + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "total_out_selling_province_carcasses_weight": total_out_selling_province_carcasses_weight, + "total_pure_province_carcasses_weight": total_pure_province_carcasses_weight, + "total_pure_province_carcasses_price": total_pure_province_carcasses_price, + "total_out_selling_province_carcasses_price": total_out_selling_province_carcasses_price, + "total_out_carcasses_buying_province_carcasses_weight": total_out_carcasses_buying_province_carcasses_weight, + "total_out_carcasses_buying_province_carcasses_price": total_out_carcasses_buying_province_carcasses_price, + "total_out_live_buying_province_carcasses_weight": total_out_live_buying_province_carcasses_weight, + "total_out_live_buying_province_carcasses_price": total_out_live_buying_province_carcasses_price, + "total_paid_wage": total_paid_wage, + "total_price": total_price, + "province_live_wage_amount": province_live_wage_type_amount, + "free_buying_live_weight_amount": free_buying_live_weight_wage_type_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_wage_type_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_wage_type_amount, + + } + return Response(result, status=status.HTTP_200_OK) + + +class KillHouseForProvinceWageViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForProvinceWageSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + + if request.GET['type'] == 'unpaid': + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOPerator': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + union_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + company_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + guilds_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + + else: + + if request.GET['role'] == 'ProvinceOPerator': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + union_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + + guilds_share__gt=0, + trash=False).values( + 'killhouse_user'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter( + + state__in=( + 'pending', + 'accepted'), + return_to_province=False, + archive_wage=False, + trash=False).values( + 'killhouse_user'), trash=False) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + if 'date1' in request.GET: + serializer = KillHouseForProvinceWageWithDateSerializer(page, many=True, context={'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = KillHouseForProvinceWageWithDateSerializer(kill_houses, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class KillHouseForProvinceWageViewSet(viewsets.ModelViewSet): +# queryset = KillHouse.objects.all() +# serializer_class = KillHouseForProvinceWageSerializer +# pagination_class = CustomPagination +# permission_classes = [TokenHasReadWriteScope] +# filter_backends = [DjangoFilterBackend] +# filterset_class = KillHouseFilterSet +# filterset_fields = [ +# 'name', +# 'kill_house_operator__user__fullname', +# 'kill_house_operator__user__mobile', +# 'system_address__city__name', +# +# ] +# +# def list(self, request, *args, **kwargs): +# +# if request.GET['type'] == 'unpaid': +# if 'date1' in request.GET: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=False, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# else: +# +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=False, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=False, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# +# +# elif request.GET['type'] == 'paid': +# if 'date1' in request.GET: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=True, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=False, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# +# else: +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=True, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=False, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# +# +# elif request.GET['type'] == 'archive': +# if 'date1' in request.GET: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=True, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# +# else: +# kill_houses = KillHouse.objects.filter(pk__in=ProvinceKillRequest.objects.filter(wage_pay=False, +# state__in=( +# 'pending', +# 'accepted'), +# archive_by_province=True, +# return_to_province=False, +# trash=False).values( +# 'killhouse_user'), trash=False) +# +# else: +# if 'date1' in request.GET: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# kill_houses = KillHouse.objects.filter( +# pk__in=ProvinceKillRequest.objects.filter( +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# state__in=('pending', 'accepted'), trash=False).values( +# 'killhouse_user'), trash=False) +# else: +# kill_houses = KillHouse.objects.filter( +# pk__in=ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), trash=False).values( +# 'killhouse_user'), trash=False) +# +# if 'search' in request.GET: +# if request.GET['search'] == 'filter': +# if request.GET['value'] != "": +# for item in self.filterset_fields: +# query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) +# if (self.filterset_class( +# data=query, +# queryset=kill_houses +# ) +# ).filter(): +# ps = self.filterset_class(data=query, queryset=kill_houses) +# kill_houses = ps.filter() +# else: +# kill_houses = kill_houses +# page_size = request.query_params.get('page_size', None) +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(kill_houses) +# if page is not None: +# if 'date1' in request.GET: +# serializer = KillHouseForProvinceWageWithDateSerializer(page, many=True, context={'request': request}) +# else: +# +# serializer = self.get_serializer(page, many=True, context={'request': request}) +# return self.get_paginated_response(serializer.data) +# +# if 'date1' in request.GET: +# serializer = KillHouseForProvinceWageWithDateSerializer(kill_houses, many=True, +# context={'request': request}) +# else: +# +# serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) +# return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForTotalProvinceWageTransactionViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForTotalProvinceWageTransactionSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + union_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + company_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + guilds_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'SuperAdmin': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + payer_type='kill_house', + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).values( + 'kill_house'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + payer_type='kill_house', + status='completed', + trash=False).values( + 'kill_house'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + union_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + company_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + guilds_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'SuperAdmin': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).values( + 'kill_house'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + trash=False).values( + 'kill_house'), trash=False) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + if 'date1' in request.GET: + serializer = KillHouseForTotalProvinceWageTransactionWithDAteSerializer(page, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = KillHouseForTotalProvinceWageTransactionWithDAteSerializer(kill_houses, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForFreeBarWageViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForFreeBarWageSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + type = request.GET['type'] + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + archive_wage=False, + union_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + else: + + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + buy_type=type, + union_share__gt=0, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + buy_type=type, + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + buy_type=type, + guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + else: + + kill_houses = KillHouse.objects.filter(pk__in=KillHouseFreeBarInformation.objects.filter( + buy_type=type, + archive_wage=False, + trash=False).values( + 'kill_house'), trash=False) + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + if 'date1' in request.GET: + serializer = KillHouseForFreeBarWageWithDateSerializer(page, many=True, context={'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = KillHouseForFreeBarWageWithDateSerializer(kill_houses, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForFreeSaleBarInformationViewSetSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2) + + + else: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(kill_house__system_address__city=user.city, + trash=False, date__date__gte=date1, + date__date__lte=date2) + + + + else: + if request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False) + + + + else: + free_sales = KillHouseFreeSaleBarInformation.objects.filter(kill_house__system_address__city=user.city, + trash=False) + + kill_houses = KillHouse.objects.filter(pk__in=free_sales.values_list('kill_house', flat=True)).order_by('id') + + if 'date1' in request.GET: + serializer = KillHouseForFreeSaleBarInformationViewSetWithDateSerializer(kill_houses, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به ثبت کشتارگاه + + +class KillHouseforPurchaseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + serializer_class = KillHouseforPurchaseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + +class KillHousePurchaseRequestPermissionViewSet(viewsets.ModelViewSet): + queryset = KillHousePurchaseRequest.objects.all() + serializer_class = KillHousePurchaseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + total_unpaid_wage = 0 + total_paid_wage = 0 + permission = True + exclusive = False + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_role = Group.objects.get(name='KillHouse') + if kill_house_role in user.role.all(): + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + exclusive = True if kill_house.type == 'exclusive' else False + purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + if purchase: + if purchase.total_limitation == True: + permission = False + else: + permission = True + else: + permission = True + + return Response({ + "permission": permission, + "exclusive": exclusive + }, status=status.HTTP_200_OK) + + +class KillHousePurchaseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHousePurchaseRequest.objects.all() + serializer_class = KillHousePurchaseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + serializer = self.serializer_class(data=request.data) + purchace = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + if purchace: + serializer.update(instance=purchace, validated_data=request.data) + else: + if serializer.is_valid(): + purchace = serializer.create(validated_data=request.data) + purchace.kill_house = kill_house + purchace.save() + + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +class TotalReportOfKillHouseWareHouseForDailyBroadCastInDetailsViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseWareHouseForDailyBroadCastOInDetailsSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + kill_houses = KillHouse.objects.filter( + pk__in=kill_house_ware_houses.values('kill_house') + ) + + serializer = self.serializer_class(kill_houses, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalReportOfKillHouseWareHouseForDailyBroadCastViewSet(viewsets.ModelViewSet): + queryset = KillHouseWareHouse.objects.all() + serializer_class = KillHouseWareHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + number_of_kill_houses = KillHouse.objects.filter( + pk__in=kill_house_ware_houses.values('kill_house') + ) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + return Response({ + "buyers": len(number_of_kill_houses), + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + "total_pre_cold_weight": total_pre_cold_weight if total_pre_cold_weight != None else 0, + "total_number_of_free_carcasses": total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + "total_free_weight_of_carcasses": total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "final_total_number_of_carcasses": final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + "final_total_weight_of_carcasses": final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + "total_allocated_quantity": total_allocated_quantity if total_allocated_quantity != None else 0, + "total_allocated_weight": total_allocated_weight if total_allocated_weight != None else 0, + "total_accepted_allocated_quantity": total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + "total_accepted_allocated_weight": total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + "total_remain_quantity": total_remain_quantity if total_remain_quantity != None else 0, + "total_remain_weight": total_remain_weight if total_remain_weight != None else 0, + "number_of_guild": number_of_guild, + "number_of_steward": number_of_steward, + + }) + + +class TotalReportForDailyBroadCastViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForTotalReportAutomaticStewardAllocationSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + date_one_day_ago = date - timedelta(days=1) + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date=date_one_day_ago).select_related( + 'killhouse_user') + kill_houses = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + ) + kill_house_ware_houses = KillHouseWareHouse.objects.filter(kill_house__in=kill_houses, date__date=date) + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, trash=False, + date__date=date).order_by('id') + + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + allocated_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_number_of_carcasses'))['total'] + allocated_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_weight_of_carcasses'))['total'] + remain_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))['total'] + remain_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))['total'] + + return Response({ + "buyers": len(kill_house_ware_houses), + "allocations": len(steward_allocations), + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "allocated_total_number_of_carcasses": allocated_total_number_of_carcasses if allocated_total_number_of_carcasses != None else 0, + "allocated_total_weight_of_carcasses": allocated_total_weight_of_carcasses if allocated_total_weight_of_carcasses != None else 0, + "remain_total_number_of_carcasses": remain_total_number_of_carcasses if remain_total_number_of_carcasses != None else 0, + "remain_total_weight_of_carcasses": remain_total_weight_of_carcasses if remain_total_weight_of_carcasses != None else 0, + }) + + +class KillHouseForTotalReportAutomaticStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForTotalReportAutomaticStewardAllocationSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + serializer = self.serializer_class(kill_house, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForAutomaticStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForAutomaticStewardAllocationSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + date = date - timedelta(days=1) + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user) + serializer = self.serializer_class(kill_house, many=True, context={'request': request}) + else: + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date=date).select_related( + 'killhouse_user') + kill_houses = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + ) + + serializer = self.serializer_class(kill_houses, context={'request': request}, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ثبت کشتارگاه + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="KillHouse") + city = City.objects.get(name=request.data['city']) + request.data.pop('city') + province = Province.objects.get(key=city.province.key) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if KillHouse.objects.filter(kill_house_operator__user=system_profile, trash=False).exists(): + return Response({"result": "این کشتارگاه قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = request.data['password'] + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + address = SystemAddress(city=city, province=province, address=request.data['address']) + address.save() + wallet = Wallet() + wallet.save() + system_profile.role.add(group) + operator = KillHouseOperator.objects.filter(user=system_profile, trash=False).last() + if operator: + pass + else: + operator = KillHouseOperator( + user=system_profile, + address=address, + wallet=wallet, + ) + operator.save() + request.data.pop('mobile') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('password') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house = serializer.create(validated_data=request.data) + kill_house.kill_house_operator = operator + kill_house.system_address = address + kill_house.save() + percentage = KillHousePercentage(kill_house=kill_house) + percentage.save() + province_allow_kill_house_choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds( + kill_house=kill_house) + province_allow_kill_house_choose_steward_guilds.save() + province_allow_direct_buying = ProvinceAllowKillHouseDirectBuying(kill_house=kill_house) + province_allow_direct_buying.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع برای نمایش مربوط به نمایش کشتارگاه + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'role' in request.GET: + # if 'kill_house' in request.GET: + # kill_house = KillHouse.objects.filter(system_address__province=user.province, killer=False, trash=False) + # + # else: + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, + trash=False) + + # if request.GET['role'] == 'ProvinceInspector' or request.GET['role'] == 'ProvinceOperator': + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + serializer = KillHouseSerializer(kill_house, many=True) + elif 'kill_house' in request.GET: + kill_house = KillHouse.objects.filter(system_address__province=user.province, + kill_house_operator__killer=False, killer=False, trash=False) + serializer = KillHouseSerializer(kill_house, many=True) + + elif 'all' in request.GET: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + serializer = KillHouseSerializer(kill_house, many=True) + + elif 'psp' in request.GET: + kill_house = KillHouse.objects.filter(out_province=False, trash=False) + serializer = PspKillHouseSerializer(kill_house, many=True) + + elif 'self_kill_houses' in request.GET: + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, + trash=False) + serializer = KillHouseSerializer(kill_house, many=True) + elif 'exclusive-killers' in request.GET: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + percentage = KillHousePercentage.objects.filter( + Q(kill_house=kill_house) | Q(kill_house_for_killer=kill_house, kill_house__type='exclusive', + kill_house__show_exclusive=True), + trash=False).values_list('kill_house__id', flat=True).distinct() + kill_houses = KillHouse.objects.filter(id__in=percentage, trash=False) + + serializer = KillHouseSerializer(kill_houses, many=True) + + elif 'total-exclude-exclusive-killers' in request.GET: + percentage = KillHousePercentage.objects.filter(kill_house_for_killer__isnull=False, + kill_house__type='exclusive', + kill_house__show_exclusive=True, trash=False).values_list( + 'kill_house__id', flat=True).distinct() + kill_houses = KillHouse.objects.filter(trash=False).exclude(id__in=percentage).order_by('id', 'killer') + + serializer = distributionKillHouseSerializer(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'exclusive-killers-free-bar' in request.GET: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + percentage = KillHousePercentage.objects.filter(kill_house_for_killer=kill_house, + kill_house__type='exclusive', + kill_house__show_exclusive=True, trash=False).values_list( + 'kill_house__id', flat=True) + + kill_houses = KillHouse.objects.filter(Q(id__in=percentage) | Q(killer=True, type='public'), trash=False) + + serializer = KillHouseSerializer(kill_houses, many=True) + + elif 'dispenser' in request.GET: + kill_house = KillHouse.objects.filter(system_address__province=user.province, + out_province=False, trash=False).order_by('id') + serializer = GeneralKillHouseSerializer(kill_house, many=True) + + elif 'gate-way-kill-houses' in request.GET: + kill_house = KillHouse.objects.filter(system_address__province=user.province, + out_province=False, trash=False) + serializer = GeneralKillHouseSerializer(kill_house, many=True) + + + else: + try: + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False).first() + serializer = KillHouseSerializer(kill_house) + except: + kill_house = KillHouse.objects.filter(out_province=False, type='public', trash=False) + serializer = KillHouseSerializer(kill_house, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع برای ویرایش درخواست کشتار ثبت شده از سمت کشتارگاه + def update(self, request, *args, pk=None, **kwargs): + # refresh(request.user.id) + + kill_house = KillHouse.objects.filter( + key=request.data['kill_house_key'], trash=False + ).select_related('kill_house_operator__user').last() + system_user_profile = SystemUserProfile.objects.get(key=kill_house.kill_house_operator.user.key) + + if 'company_gateway_percent' in request.data.keys(): + kill_house.company_gateway_percent = request.data['company_gateway_percent'] + kill_house.union_gateway_percent = request.data['union_gateway_percent'] + kill_house.guilds_gateway_percent = request.data['guilds_gateway_percent'] + kill_house.other_gateway_percent = request.data['other_gateway_percent'] + kill_house.save() + elif 'quota' in request.data.keys(): + kill_house.quota = request.data['quota'] + kill_house.governmental_quota = request.data['governmental_quota'] + kill_house.quota_max_kill_limit = request.data['quota_max_kill_limit'] + kill_house.quota_request = request.data['quota_request'] + kill_house.quota_custom = request.data['quota_custom'] + kill_house.quota_custom_quantity = request.data['quota_custom_quantity'] + kill_house.save() + elif 'maximum_load_volume_increase' in request.data.keys(): + kill_house.maximum_load_volume_increase = request.data['maximum_load_volume_increase'] + kill_house.maximum_load_volume_reduction = request.data['maximum_load_volume_reduction'] + kill_house.save() + + elif 'ware_house_remaining_weight_limitation_status' in request.data.keys(): + kill_house.ware_house_remaining_weight_limitation_status = request.data[ + 'ware_house_remaining_weight_limitation_status'] + kill_house.ware_house_remaining_weight_limitation = request.data['ware_house_remaining_weight_limitation'] + kill_house.ware_house_remaining_percent_limitation_status = request.data[ + 'ware_house_remaining_percent_limitation_status'] + kill_house.ware_house_remaining_percent_limitation = request.data['ware_house_remaining_percent_limitation'] + kill_house.save() + + + elif 'total_kill_capacity' in request.data.keys(): + kill_house.max_kill_limit = request.data['max_kill_limit'] + kill_house.total_kill_capacity = request.data['total_kill_capacity'] + kill_house.extra_bar_kill_percent = request.data['extra_bar_kill_percent'] + kill_house.save() + elif 'name' in request.data.keys(): + kill_house.name = request.data['name'] + kill_house.save() + elif 'active' in request.data.keys(): + kill_house.active = request.data['active'] + kill_house.save() + elif 'type' in request.data.keys(): + kill_house.type = request.data['type'] + kill_house.save() + + elif 'out_province_selling_limitation' in request.data.keys(): + kill_house.out_province_selling_limitation = request.data['out_province_selling_limitation'] + kill_house.out_province_selling_limitation_percent = request.data['out_province_selling_limitation_percent'] + kill_house.save() + elif 'in_province_selling_limitation' in request.data.keys(): + kill_house.in_province_selling_limitation = request.data['in_province_selling_limitation'] + kill_house.in_province_selling_limitation_percent = request.data['in_province_selling_limitation_percent'] + kill_house.save() + elif 'governmental_selling_permission' in request.data.keys(): + kill_house.governmental_selling_permission = request.data['governmental_selling_permission'] + kill_house.in_province_governmental_selling_percent = request.data[ + 'in_province_governmental_selling_percent'] + kill_house.out_province_governmental_selling_percent = request.data[ + 'out_province_governmental_selling_percent'] + kill_house.segmentation_governmental_percent = request.data['segmentation_governmental_percent'] + + kill_house.save() + + elif 'free_selling_permission' in request.data.keys(): + kill_house.free_selling_permission = request.data['free_selling_permission'] + kill_house.in_province_free_selling_percent = request.data['in_province_free_selling_percent'] + kill_house.out_province_free_selling_percent = request.data['out_province_free_selling_percent'] + kill_house.segmentation_free_selling_percent = request.data['segmentation_free_selling_percent'] + + kill_house.save() + + elif 'ware_house_remaining_weight_archive_percent': + kill_house.ware_house_remaining_weight_archive_percent = request.data[ + 'ware_house_remaining_weight_archive_percent'] + kill_house.save() + + else: + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + request.data.pop('mobile') + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + return Response({"result": "باموفقیت ویرایش شد"}, status=status.HTTP_200_OK) + + # ویوست مربوط به ثبت کشتارگاه + + +class PosKillHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = PosKillHouseSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + if pos.kill_house: + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id').exclude( + id=pos.kill_house.id) + + else: + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + kill_houses_list = [] + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_houses_list = ps.filter() + kill_houses = [] if len(kill_houses_list) == 0 else kill_houses_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseAllowVetViewSet(viewsets.ModelViewSet): + queryset = KillHouseAllowVet.objects.all() + serializer_class = KillHouseAllowVetSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ثبت کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user) + kill_houses = KillHouse.objects.filter(kill_house_operator=kill_house_operator) + kill_house_allow_vets = KillHouseAllowVet.objects.filter(kill_house__in=kill_houses) + allow = request.data['allow'] + if kill_house_allow_vets.count() > 0: + for kill_house_allow_vet in kill_house_allow_vets: + kill_house_allow_vet.allow = allow + kill_house_allow_vet.save() + else: + for kill_house in kill_houses: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allow = serializer.create(validated_data=request.data) + allow.kill_house = kill_house + allow.save() + return Response({"result": "created"}, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user) + kill_houses = KillHouse.objects.filter(kill_house_operator=kill_house_operator) + kill_house_allow_vet = KillHouseAllowVet.objects.filter(kill_house__in=kill_houses) + serializer = KillHouseAllowVetSerializer(kill_house_allow_vet, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHousePercentageViewSet(viewsets.ModelViewSet): + queryset = KillHousePercentage.objects.all() + serializer_class = KillHousePercentageSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + percents = [] + user_profile = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(system_address__province=user_profile.province, trash=False) + if kill_house: + percents = KillHousePercentage.objects.filter(kill_house__in=kill_house).order_by('-percent') + + serializer = KillHousePercentageSerializer(percents, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'percentage_list' in request.data.keys(): + kill_house_percentage_lists = request.data['percentage_list'] + request.data.pop('percentage_list') + if request.data['type'] == 'manual': + for kill_house_percentage_list in kill_house_percentage_lists: + kill_house_percentage = KillHousePercentage.objects.get(key=kill_house_percentage_list["key"], + trash=False) + kill_house_percentage.percent = kill_house_percentage_list["percent"] + if 'killer_kill_house_key' in kill_house_percentage_list.keys(): + if kill_house_percentage_list['killer_kill_house_key'] != None: + kill_house_percentage.kill_house_for_killer = KillHouse.objects.get( + key=kill_house_percentage_list['killer_kill_house_key'], trash=False) + kill_house_percentage.save() + else: + + guilds = Guilds.objects.filter(kill_house_centers_allocation__isnull=False, trash=False) + total_count = len(guilds) + total_weight = guilds.aggregate(total_quantity=Sum('allocation_limit')).get('total_quantity', 0) + + if total_count == 0: + return Response({"result": "صنفی وجود ندارد برای کشتارگاه ها و کشتارکن ها"}, + status=status.HTTP_403_FORBIDDEN) + if request.data['type'] == 'guilds_weight': + + for kill_house_percentage_list in kill_house_percentage_lists: + kill_house_percentage = KillHousePercentage.objects.get(key=kill_house_percentage_list["key"], + trash=False) + kill_house_percentage_weight = 0 + for guild in guilds: + if len(guild.kill_house_centers_allocation) == 0 or guild.kill_house_centers_allocation == None: + continue + if guild.kill_house_centers_allocation[0]['value'] == str( + kill_house_percentage.kill_house.key): + kill_house_percentage_weight += guild.allocation_limit + kill_house_percentage.percent = round((kill_house_percentage_weight / total_weight) * 100, 2) + kill_house_percentage.guilds_weight = kill_house_percentage_weight + kill_house_percentage.last_guilds_update_date = str(datetime.now()) + kill_house_percentage.save() + + + else: + + for kill_house_percentage_list in kill_house_percentage_lists: + kill_house_percentage = KillHousePercentage.objects.get(key=kill_house_percentage_list["key"], + trash=False) + kill_house_percentage_counter = 0 + for guild in guilds: + if len(guild.kill_house_centers_allocation) == 0 or guild.kill_house_centers_allocation == None: + continue + if guild.kill_house_centers_allocation[0]['value'] == str( + kill_house_percentage.kill_house.key): + kill_house_percentage_counter += 1 + kill_house_percentage.percent = round((kill_house_percentage_counter / total_count) * 100, 2) + kill_house_percentage.guilds_quantity = kill_house_percentage_counter + kill_house_percentage.last_guilds_update_date = str(datetime.now()) + kill_house_percentage.save() + + elif 'percentage_key' in request.data.keys(): + percentage = KillHousePercentage.objects.get(key=request.data['percentage_key']) + if 'identity' in request.data.keys(): + kill_house = KillHouse.objects.get(key=percentage.kill_house.key) + if kill_house.killer == False: + if request.data['identity'] == 'Killer': + previous_state = kill_house.killer + if KillHousePercentage.objects.filter( + kill_house_for_killer=kill_house).exists(): + return Response({ + "result": "این کشتارگاه توسط چندین کشتارکن رزرو شده است و امکان تغییر ماهیت وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if KillRequest.objects.filter(remain_quantity__gt=0, slaughter_house=kill_house, + trash=False).exists(): + return Response({ + "result": "این کشتارگاه توسط چندین کشتارکن در قسمت اعلام نیاز کشتارگاه رزرو شده است و امکان تغییر ماهیت وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + kill_house.killer = True + kill_house.save() + new_state = kill_house.killer + percentage.change_data = { + "previous_killer_state": previous_state, + "new_killer_state": new_state, + "type": kill_house.type, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()), + "kill_house": percentage.kill_house_for_killer.name if percentage.kill_house_for_killer != None else None, + + } + percentage.save() + + + else: + if request.data['identity'] == 'KillHouse': + previous_state = kill_house.killer + kill_house.killer = False + kill_house.save() + new_state = kill_house.killer + percentage.kill_house_for_killer = None + percentage.change_data = { + "previous_killer_state": previous_state, + "new_killer_state": new_state, + "type": kill_house.type, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()), + "kill_house": percentage.kill_house_for_killer.name if percentage.kill_house_for_killer != None else None, + + } + percentage.save() + + + else: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + percentage.kill_house_for_killer = kill_house + if percentage.change_data: + percentage.change_data["kill_house"] = kill_house.name + percentage.change_data["date"] = str(datetime.now()) + percentage.save() + return Response({"result": "با موفقیت ویرایش شد."}, status=status.HTTP_200_OK) + + +# ویوست مربوط به اضافه کردن خودرو به کشتارگاه +class KillHouseDriverViewSet(viewsets.ModelViewSet): + queryset = KillHouseDriver.objects.all() + serializer_class = KillHouseDriverSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseDriverFilterSet + filterset_fields = [ + 'health_code', + 'user__mobile', + 'user__national_id', + 'user__base_order', + ] + + # تابع مربوط به اضافه کردن خودرو به کشتارگاه + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.data['role'] + request.data.pop('role') + + # refresh(request.user.id) + kill_house = None + if 'kill_house_key' in request.data.keys(): + if request.data['kill_house_key'] != None: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + request.data.pop('kill_house_key') + if role == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + # if not ProvinceAllowKillHouseRegisterCar.objects.filter( + # kill_house__in=kill_house, allow=True).exists(): + # return Response({"result": "شما اجازه ساخت ماشین ندارید"}, status=status.HTTP_403_FORBIDDEN) + person = SystemUserProfile.objects.get(user=request.user) + group = Group.objects.get(name__exact="Driver") + city = City.objects.get(name=request.data['city_name']) + province = Province.objects.get(key=user.province.key) + request.data.pop('city_name') + # request.data.pop('province_name') + if KillHouseDriver.objects.filter(pelak=request.data['pelak'], trash=False).exists(): + return Response({"result": "این ماشین قبلا ثبت شده!"}, status=status.HTTP_403_FORBIDDEN) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['driver_mobile'], trash=False) + if system_profile.count() > 0: + system_profile = system_profile.last() + if group not in system_profile.role.all(): + system_profile.role.add(group) + + else: + + password = "00100" + data = { + "username": request.data['driver_mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + if req.status_code == 200: + user = User(username=request.data['driver_mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['driver_mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + city=city, + province=province + ) + system_profile.save() + system_profile.role.add(group) + + + else: + return Response({"result": "در ثبت کاربر مشکلی پیش آمده است!"}, status=status.HTTP_403_FORBIDDEN) + + wallet = Wallet() + wallet.save() + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + full_name = request.data['first_name'] + " " + request.data['last_name'] + request.data.pop('first_name') + request.data.pop('last_name') + kill_house_driver = serializer.create(validated_data=request.data) + kill_house_driver.user = system_profile + kill_house_driver.wallet = wallet + kill_house_driver.registrar = { + "role": role, + "full_name": person.fullname, + "mobile": person.mobile, + "date": str(kill_house_driver.create_date) + } + kill_house_driver.driver_name = full_name + kill_house_driver.save() + if kill_house != None: + if KillHouseADDCAR.objects.filter(kill_house__in=kill_house, driver=kill_house_driver, + trash=False).exists(): + return Response({"result": "این ماشین قبلا برای کشتارگاه ثبت شده!"}, + status=status.HTTP_403_FORBIDDEN) + else: + add_car = KillHouseADDCAR( + kill_house=kill_house.last(), + driver=kill_house_driver + ) + add_car.save() + else: + if kill_house_driver.type == 'rental': + # kill_houses = KillHouse.objects.filter(trash=False) + # for kill_house in kill_houses: + add_car = KillHouseADDCAR( + # kill_house=kill_house, + driver=kill_house_driver + ) + add_car.save() + + return Response({"result": "ماشین با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + if 'role' in request.GET: + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + list_car = [] + if 'health_code' in request.GET: + + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, request.GET['health_code'])) + if (self.filterset_class( + data=query, + queryset=self.queryset.filter(trash=False) + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=self.queryset) + filtered_kill_house_driver = ps.filter() + serializer = self.serializer_class(filtered_kill_house_driver, many=True) + return Response(serializer.data) + return Response(list_car) + + + # cars = KillHouseDriver.objects.filter(health_code=request.GET['health_code'], + # trash=False) + # if cars.count() > 0: + # cars = cars.last() + # dict1 = { + # "id": cars.id, + # "key": cars.key, + # "driver_name": cars.driver_name, + # "driver_mobile": cars.driver_mobile, + # "type_car": cars.type_car, + # "pelak": cars.pelak, + # "capocity": float(cars.capocity), + # "weight_without_load": cars.weight_without_load, + # "health_code": cars.health_code, + # } + # list_car.append(dict1) + # return Response(list_car, status=status.HTTP_200_OK) + else: + if request.GET['role'] == 'KillHouse': + kill_house_drivers = KillHouseDriver.objects.filter(user__province=user.province, type='rental', + archive=False) + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False).first() + add_car = KillHouseADDCAR.objects.filter(kill_house=kill_house, trash=False, + archive=False).order_by('id') + if add_car.count() > 0: + kill_house_list = [] + for add_car_obj in add_car: + allow = ProvinceAllowKillHouseRegisterCar.objects.filter( + kill_house=add_car_obj.kill_house) + if allow.count() > 0: + allow_state = allow.last().allow + else: + allow_state = None + kill_house_name = add_car_obj.kill_house.name + kill_house_key = add_car_obj.kill_house.key + kill_house_dict = {"kill_house_name": kill_house_name, "kill_house_key": kill_house_key, + "allow_state": allow_state} + if not any(d["kill_house_name"] == kill_house_name for d in kill_house_list): + kill_house_list.append(kill_house_dict) + + dict1 = { + "id": add_car_obj.driver.id, + "key": add_car_obj.driver.key, + "add_car_key": add_car_obj.key, + "driver_name": add_car_obj.driver.driver_name, + "driver_type": add_car_obj.driver.type, + "driver_active_state": add_car_obj.driver.active_state, + "add_car_active_state": add_car_obj.active_state, + "first_name": add_car_obj.driver.user.first_name, + "last_name": add_car_obj.driver.user.last_name, + "city": add_car_obj.driver.user.city.name, + "driver_mobile": add_car_obj.driver.driver_mobile, + "kill_house_list": kill_house_list, + "type_car": add_car_obj.driver.type_car, + "type": add_car_obj.driver.type, + "pelak": add_car_obj.driver.pelak, + "capocity": float(add_car_obj.driver.capocity), + "weight_without_load": add_car_obj.driver.weight_without_load, + "health_code": add_car_obj.driver.health_code, + } + list_car.append(dict1) + if kill_house_drivers: + for kill_house_driver in kill_house_drivers: + dict2 = { + "id": kill_house_driver.id, + "key": kill_house_driver.key, + "add_car_key": None, + "add_car_active_state": kill_house_driver.active_state, + "driver_name": kill_house_driver.driver_name, + "driver_type": kill_house_driver.type, + "driver_active_state": kill_house_driver.active_state, + "first_name": kill_house_driver.user.first_name, + "last_name": kill_house_driver.user.last_name, + "city": kill_house_driver.user.city.name, + "driver_mobile": kill_house_driver.driver_mobile, + "kill_house_list": [], + "type_car": kill_house_driver.type_car, + "type": kill_house_driver.type, + "pelak": kill_house_driver.pelak, + "capocity": float(kill_house_driver.capocity), + "weight_without_load": kill_house_driver.weight_without_load, + "health_code": kill_house_driver.health_code, + } + list_car.append(dict2) + + return Response(list_car, status=status.HTTP_200_OK) + else: + list_car = [] + cars = KillHouseDriver.objects.filter(user__province=user.province, trash=False, + archive=False).order_by('id') \ + .select_related('user') + + if cars.count() > 0: + for car in cars: + add_car = KillHouseADDCAR.objects.filter(driver=car, trash=False, + archive=False).select_related( + 'kill_house') + if add_car.count() > 0: + kill_house_list = [] + for add_car_obj in add_car: + if add_car_obj.kill_house != None: + allow = ProvinceAllowKillHouseRegisterCar.objects.filter( + kill_house=add_car_obj.kill_house) + if allow.count() > 0: + allow_state = allow.last().allow + else: + allow_state = None + kill_house_name = add_car_obj.kill_house.name + kill_house_key = add_car_obj.kill_house.key + kill_house_dict = {"kill_house_name": kill_house_name, + "kill_house_key": kill_house_key, "allow_state": allow_state} + if not any(d["kill_house_name"] == kill_house_name for d in kill_house_list): + kill_house_list.append(kill_house_dict) + + dict1 = { + "id": car.id, + "key": car.key, + "add_car_key": None, + "driver_name": car.driver_name, + "driver_type": car.type, + "driver_active_state": car.active_state, + "type": car.type, + "first_name": car.user.first_name, + "last_name": car.user.last_name, + "city": car.user.city.name, + "driver_mobile": car.driver_mobile, + "kill_house_list": kill_house_list, + "type_car": car.type_car, + "pelak": car.pelak, + "capocity": float(car.capocity), + "weight_without_load": car.weight_without_load, + "health_code": car.health_code, + } + list_car.append(dict1) + else: + dict1 = { + "id": car.id, + "type": car.type, + "add_car_key": None, + "key": car.key, + "driver_type": car.type, + "driver_name": car.driver_name, + "driver_active_state": car.active_state, + "first_name": car.user.first_name, + "last_name": car.user.last_name, + "city": car.user.city.name, + "driver_mobile": car.driver_mobile, + "kill_house_list": [], + "type_car": car.type_car, + "pelak": car.pelak, + "capocity": float(car.capocity), + "weight_without_load": car.weight_without_load, + "health_code": car.health_code, + } + list_car.append(dict1) + + return Response(list_car, status=status.HTTP_200_OK) + else: + return Response(list_car, status=status.HTTP_200_OK) + + else: + return Response([], status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + if 'change_activation' in request.data.keys(): + car = KillHouseDriver.objects.get(key=request.data["driver_key"]) + + add_cars = KillHouseADDCAR.objects.filter(driver=car, trash=False) + for add_car in add_cars: + add_car.active_state = request.data['change_activation'] + add_car.save() + car.active_state = request.data['change_activation'] + car.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + elif 'add_car_change_activation' in request.data.keys(): + add_car = KillHouseADDCAR.objects.get(key=request.data["add_car_key"], trash=False) + add_car.active_state = request.data['add_car_change_activation'] + add_car.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + + + else: + car = KillHouseDriver.objects.get(key=request.data["driver_key"]) + + if 'city_name' in request.data.keys() and request.data['city_name'] != None: + city = City.objects.get(name=request.data['city_name']) + else: + city = None + request.data.pop('city_name') + + user = SystemUserProfile.objects.get(key=car.user.key) + request.data.pop('driver_key') + first_name = request.data['first_name'] + last_name = request.data['last_name'] + request.data.pop('first_name') + request.data.pop('last_name') + if first_name != None: + user.first_name = first_name + if last_name != None: + user.last_name = last_name + if city != None: + user.city = city + if first_name != None and last_name != None: + car.driver_name = first_name + "" + last_name + user.fullname = first_name + "" + last_name + # serializer = self.serializer_class(car) + user.save() + car.save() + serializer = self.serializer_class(car) + serializer.update(instance=car, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + car = KillHouseDriver.objects.get(key=request.GET["key"]) + if KillHouseRequest.objects.filter(active_state='active', add_car__driver=car, trash=False).exists(): + return Response({"result": "ماشین دارای بار فعال میباشد"}, status=status.HTTP_403_FORBIDDEN) + + kill_house_cars = KillHouseADDCAR.objects.filter(driver=car, trash=False) + if kill_house_cars: + for add_car in kill_house_cars: + add_car.trash = True + add_car.save() + + car.trash = True + car.save() + return Response('ماشین با موفقیت حذف شد', status=status.HTTP_200_OK) + + +class KillHouseDriverTotalDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseDriver.objects.all() + serializer_class = KillHouseDriverSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(trash=False, user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_drivers = KillHouseDriver.objects.filter(archive=False, pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + archive=False).values_list( + 'driver__id', flat=True), trash=False) + active = kill_house_drivers.filter(pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + active_state=True, archive=False).values_list('driver__id', flat=True)) + inactive = kill_house_drivers.filter(pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + active_state=False, archive=False).values_list('driver__id', flat=True)) + suspended = 0 + + else: + kill_house_drivers = KillHouseDriver.objects.filter(trash=False, archive=False) + + active = kill_house_drivers.filter(pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house__isnull=False) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + active_state=True, archive=False).values_list('driver__id', flat=True)) + inactive = kill_house_drivers.filter(pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house__isnull=False) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + active_state=False, archive=False).values_list('driver__id', flat=True)) + suspended = kill_house_drivers.exclude(pk__in=KillHouseADDCAR.objects.filter( + Q(kill_house__isnull=False) | Q(kill_house__isnull=True, driver__type='rental'), + trash=False, archive=False).values_list('driver__id', flat=True)) + suspended = len(suspended) + + rental = kill_house_drivers.filter(type='rental') + exclusive = kill_house_drivers.filter(type='exclusive') + + result = { + "total": len(kill_house_drivers), + "exclusive": len(exclusive), + "rental": len(rental), + "active": len(active), + "inactive": len(inactive), + "suspended": suspended, + } + + return Response(result, status=status.HTTP_200_OK) + + +# ویوست مربوط به اضافه کردن خودرو به کشتارگاه +class KillHouseADDCARViewSet(viewsets.ModelViewSet): + queryset = KillHouseADDCAR.objects.all() + serializer_class = KillHouseADDCARSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به اضافه کردن خودرو به کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + driver = KillHouseDriver.objects.get(key=request.data['driver_key']) + request.data.pop('driver_key') + request.data.pop('kill_house_key') + if 'role' in request.data.keys(): + request.data.pop('role') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + if KillHouseADDCAR.objects.filter(kill_house=kill_house, driver=driver, trash=False): + return Response({"result": "already exist"}, status=status.HTTP_403_FORBIDDEN) + kill_house_car = serializer.create(validated_data=request.data) + kill_house_car.kill_house = kill_house + kill_house_car.driver = driver + kill_house_car.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش خودروهای ثبت شده کشتارگاه + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + if 'kill_request_key' in request.GET: + kill_request = KillRequest.objects.get(key=request.GET['kill_request_key']) + list_car = [] + if 'key' in request.GET: + poultry_request = PoultryRequest.objects.get(key=request.GET['key']) + else: + poultry_request = None + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + if kill_house.killer == True: + if KillHouseADDCAR.objects.filter(kill_house=kill_house, trash=False, archive=False).exists(): + cars = KillHouseADDCAR.objects.filter( + Q(kill_house=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), + trash=False, archive=False).order_by('driver__type') + else: + killer_kill_house = KillHouse.objects.get(key=kill_request.slaughter_house.key) + cars = KillHouseADDCAR.objects.filter( + Q(kill_house=killer_kill_house) | Q(kill_house__isnull=True, driver__type='rental'), + trash=False, archive=False).order_by('driver__type') + else: + cars = KillHouseADDCAR.objects.filter( + Q(kill_house=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + archive=False).order_by( + 'driver__type') + + else: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + cars = KillHouseADDCAR.objects.filter( + Q(kill_house__in=kill_house) | Q(kill_house__isnull=True, driver__type='rental'), trash=False, + archive=False).order_by( + 'driver__type') + # if poultry_request != None: + # send_date = poultry_request.send_date.date() + # list1 = [] + # kill_house_requests = KillHouseRequest.objects.filter(active_state='active') + # for kill_house_request in kill_house_requests: + # if kill_house_request.province_kill_request != None: + # date = kill_house_request.province_request.city_request_Poultry.poultry_request.send_date.date() + # if send_date.year == date.year and send_date.month == date.month and send_date.day == date.day: + # list1.append(kill_house_request) + # else: + # date2 = kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date.date() + # if send_date.year == date2.year and send_date.month == date2.month and send_date.day == date2.day: + # list1.append(kill_house_request) + # if len(list1) > 0: + # for kill_house_car in cars: + # list2 = [] + # i = 0 + # for request_car in list1: + # if i == len(list1): + # break + # if kill_house_car.driver.pelak == request_car.add_car.driver.pelak: + # dict1 = { + # "id": kill_house_car.id, + # "key": kill_house_car.key, + # "driver_name": kill_house_car.driver.driver_name, + # "driver_mobile": kill_house_car.driver.driver_mobile, + # "type_car": kill_house_car.driver.type_car, + # "pelak": kill_house_car.driver.pelak, + # "capocity": float(kill_house_car.driver.capocity), + # "weight_without_load": kill_house_car.driver.weight_without_load, + # "health_code": kill_house_car.driver.health_code, + # "busy": True + # } + # list2.append(dict1) + # i += 1 + # if len(list2) > 0: + # list_car.append(list2[0]) + # else: + # dict1 = { + # "id": kill_house_car.id, + # "key": kill_house_car.key, + # "driver_name": kill_house_car.driver.driver_name, + # "driver_mobile": kill_house_car.driver.driver_mobile, + # "type_car": kill_house_car.driver.type_car, + # "pelak": kill_house_car.driver.pelak, + # "capocity": float(kill_house_car.driver.capocity), + # "weight_without_load": kill_house_car.driver.weight_without_load, + # "health_code": kill_house_car.driver.health_code, + # "busy": False + # } + # list_car.append(dict1) + # return Response(list_car, status=status.HTTP_200_OK) + + for car in cars: + if car.active_state == True: + dict1 = { + "id": car.id, + "key": car.key, + "type": car.driver.type, + "driver_name": car.driver.driver_name, + "driver_mobile": car.driver.driver_mobile, + "type_car": car.driver.type_car, + "pelak": car.driver.pelak, + "capocity": float(car.driver.capocity), + "weight_without_load": car.driver.weight_without_load, + "health_code": car.driver.health_code, + } + list_car.append(dict1) + return Response(list_car, status=status.HTTP_200_OK) + + # تابع مربوط به حذف خودروهای ثبت شده کشتارگاه + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + car = KillHouseDriver.objects.get(key=request.GET["driver_key"]) + kill_house = KillHouse.objects.get(key=request.GET["kill_house_key"]) + if KillHouseRequest.objects.filter(active_state='active', add_car__driver=car, trash=False).exists(): + return Response({"result": "ماشین دارای بار فعال میباشد"}, status=status.HTTP_403_FORBIDDEN) + add_car = KillHouseADDCAR.objects.filter(driver=car, kill_house=kill_house, trash=False) + if add_car.count() > 0: + add_car = add_car.last() + add_car.trash = True + add_car.save() + return Response('ماشین با موفقیت حذف شد', status=status.HTTP_200_OK) + else: + return Response('مشکلی در حذف ماشین به وجود آمده است !', status=status.HTTP_403_FORBIDDEN) + + def update(self, request, pk=None, *args, **kwargs): + car = KillHouseADDCAR.objects.get(key=request.data["add_car_key"]) + request.data.pop('add_car_key') + serializer = self.serializer_class(car) + serializer.update(instance=car, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class AutomaticKillRequestViewSet(viewsets.ModelViewSet): + queryset = AutomaticKillRequest.objects.all() + serializer_class = AutomaticKillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # def create(self, request, *args, **kwargs): + # # refresh(request.user.id) + # state = request.data['active'] + # auomatic_kill_reqs = AutomaticKillRequest.objects.all() + # if auomatic_kill_reqs.count() > 0: + # auomatic_kill_reqs = auomatic_kill_reqs.last() + # auomatic_kill_reqs.active = state + # auomatic_kill_reqs.save() + # serializer_request = self.serializer_class(auomatic_kill_reqs) + # return Response(serializer_request.data, status=status.HTTP_200_OK) + # else: + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # auomatic_kill_reqs = serializer.create(validated_data=request.data) + # + # serializer_request = self.serializer_class(auomatic_kill_reqs) + # return Response(serializer_request.data, status=status.HTTP_201_CREATED) + + def create(self, request, *args, **kwargs): + try: + automatic_kill_req = AutomaticKillRequest.objects.latest('id') + except AutomaticKillRequest.DoesNotExist: + automatic_kill_req = None + + serializer = self.serializer_class(automatic_kill_req, data=request.data) + if serializer.is_valid(): + if automatic_kill_req: + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + else: + serializer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + else: + return Response(serializer.errors) + + +class KillRequestForPoultryViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + serializer_class = KillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + kill_req = KillRequest.objects.get(key=request.data['kill_req_key'], trash=False) + kill_req.remain_quantity_for_poultry += int(request.data['quantity_sum']) + kill_req.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class DeleteDebtorsKillRequestsViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + serializer_class = KillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def destroy(self, request, pk=None, *args, **kwargs): + today = datetime.now().date() + kill_requests = KillRequest.objects.filter(trash=False, recive_date__date=today, market=False) + for kill_request in kill_requests: + kill_house = kill_request.kill_house + kill_house_purchase = KillHousePurchaseRequest.objects.filter(limitation=True, + kill_house=kill_house).first() + if kill_house_purchase: + total_unpaid_wage = 0 + total_paid_wage = 0 + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_amount = total_unpaid_wage - total_paid_wage + if total_amount >= kill_house_purchase.limitation_number: + if not ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + kill_request__recive_date__date=today, + killhouse_user=kill_house).exists(): + kill_request.message = 'به علت بدهی اعلام نیاز حذف گردید' + kill_request.trash = True + kill_request.save() + + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_200_OK) + + +# ویوست مربوط به ثبت درخواست کشتار از سمت کشتارگاه +class KillRequestViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + serializer_class = KillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'slaughter_house__name', + 'export_country', + 'export_code', + 'direct_buying_code', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + ] + + # تابع مربوط به ثبت درخواست کشتار از سمت کشتارگاه + def create(self, request, *args, **kwargs): + total_unpaid_wage = 0 + total_paid_wage = 0 + + limitation_direct_purchase = LimitationForDirectPurchaseAndBarInformation.objects.filter( + trash=False, active=True).first() + is_in_limitation_range = False + + if limitation_direct_purchase and limitation_direct_purchase.start_time and limitation_direct_purchase.end_time: + current_time = datetime.now().time() + if limitation_direct_purchase.start_time <= current_time <= limitation_direct_purchase.end_time: + is_in_limitation_range = True + + if not is_in_limitation_range: + time_range = TimeRange.objects.filter(trash=False).first() + if time_range: + time = next( + (t for t in time_range.time_range if t.get("name") == "kill_request" and t.get("active", False)), + None) + if time: + start_hour = datetime.strptime(time.get("start", 0), "%H:%M:%S").time() + end_hour = datetime.strptime(time.get("end", 0), "%H:%M:%S").time() + current_hour = datetime.now().time().replace(second=0, microsecond=0) + if not (start_hour < current_hour < end_hour): + return Response( + {"result": "لطفا در ساعات مجاز برای ثبت درخواست اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + if 'role' in request.data.keys() and request.data['role'] != None: + role = request.data['role'] + request.data.pop('role') + else: + role = None + if role != None and role == 'KillHouse': + now_request_date = datetime.now().date() + now = datetime.now().time() + now_hour = KillHouseHourLimit.objects.filter(trash=False).last() + if now_hour and 'poultry_key' not in request.data.keys(): + if now_hour.active == True: + request_date = datetime.strptime(request.data['recive_date'], '%Y-%m-%d %H:%M:%S').date() + if request_date.year >= now_request_date.year and request_date.month >= now_request_date.month and request_date.day > now_request_date.day: + pass + + else: + if now.hour >= now_hour.hour: + text = 'زمان ثبت درخواست کشتار درامروز تا ساعت {0} بوده است. شما میتوانید برای تاریخ های آینده درخواست ثبت نمایید ! '.format( + now_hour.hour) + if 'role' not in request.data.keys(): + return Response({'result': text}, status=status.HTTP_403_FORBIDDEN) + + killer_kill_house = None + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + if kill_house.out_province == True: + return Response({ + "result": "امکان ثبت اعلام نیاز برای کشتارگاه خارج از استان وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + kill_house_purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + if kill_house_purchase: + if kill_house_purchase.allow == False: + return Response({ + "result": "شما مجاز به ثبت درخواست خرید نمیباشید جهت اطلاع با اتحادیه مرغ گوشتی استان خود تماس حاصل فرمایید"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house_purchase.limitation == True: + try: + recive_date = datetime.strptime(str(request.data['recive_date']), + '%Y-%m-%dT%H:%M:%S.%fZ').date() + except: + recive_date = datetime.strptime(str(request.data['recive_date']), '%Y-%m-%d %H:%M:%S').date() + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + if kill_house_purchase.limitation_number <= total_unpaid_wage - total_paid_wage: + if not ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + kill_request__recive_date__date=recive_date, + trash=False, + state__in=('pending', 'accepted')).exists(): + return Response({ + "result": "به علت بدهی امکان ثبت درخواست وحود ندارد لطفا بدهی خود را در پنل کارمزد ها تسویه کنید"}, + status=status.HTTP_403_FORBIDDEN) + if kill_house.poultry_payment_limitation: + today_check_date = datetime.now().date() + if ProvinceKillRequest.objects.filter(Q(payment_deadline_date__date__lt=today_check_date, + extension_payment_deadline_date__isnull=True) | Q( + payment_deadline_date__date__lt=today_check_date, + extension_payment_deadline_date__date__lt=today_check_date), trash=False, temporary_trash=False, + return_to_province=False, + state__in=('pending', 'accepted'), payment_deadline_archive=False, + payment_deadline_state__in=('pending', 'rejected')).exists(): + return Response({ + "result": "به دلیل عدم تسویه با مرغدار شما مجاز به خرید نمی باشید لطفا اطلاعات پرداخت را در بخش تسویه حساب بارگزاری کنید!"}, + status=status.HTTP_403_FORBIDDEN) + if 'killer_kill_house_key' in request.data.keys(): + if request.data['killer_kill_house_key'] != None: + killer_kill_house = KillHouse.objects.get(key=request.data['killer_kill_house_key'], trash=False) + request.data.pop('killer_kill_house_key') + else: + request.data.pop('killer_kill_house_key') + cash = request.data['cash'] + credit = request.data['credit'] + low_weight = request.data['low_weight'] + high_weight = request.data['high_weight'] + credit = request.data['credit'] + request.data.pop('cash') + request.data.pop('credit') + request.data.pop('low_weight') + request.data.pop('high_weight') + poultry = None + hatching = None + if 'poultry_key' in request.data.keys(): + poultry = Poultry.objects.get(key=request.data['poultry_key']) + hatching = PoultryHatching.objects.get(key=request.data['hatching_key']) + request.data.pop('poultry_key') + request.data.pop('hatching_key') + if poultry.order_limit: + return Response({ + "result": "امکان ثبت کشتار برای مرغدار وجود ندارد جهت اطلاعات بیشتر بااتحادیه استان خود هماهنگ کنید!"}, + status=status.HTTP_403_FORBIDDEN) + if 'confirm_poultry_mobile' in request.data.keys() and len(request.data['confirm_poultry_mobile']) == 11: + + first_mobile_number = poultry.user.mobile + second_mobile_number = request.data['confirm_poultry_mobile'] + request.data.pop('confirm_poultry_mobile') + if first_mobile_number != second_mobile_number: + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + system_person = SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False) + if system_person: + return Response({"result": f'این شماره در سامانه به نام {system_person.first().fullname} است'}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + system_user_profile.user.username = second_mobile_number + system_user_profile.user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + try: + recive_date = datetime.strptime(str(request.data['recive_date']), '%Y-%m-%dT%H:%M:%S.%fZ').date() + except: + recive_date = datetime.strptime(str(request.data['recive_date']), '%Y-%m-%d %H:%M:%S').date() + + if request.data['free_direct_buying'] == True: + + if kill_house.quota: + kill_house_info = calculate_governmental_quota(kill_house) + if kill_house_info == 'not_allowed': + return Response({"result": " امکان خرید آزاد تا تکمیل تعهد دولتی وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + age_range = ChickenAgeRange.objects.filter(trash=False).first() + if role and role not in ('AdminX', 'SuperAdmin'): + + if age_range.active == True: + chicken_age = (datetime.now().date() - hatching.date.date()).days + 1 + if chicken_age < age_range.minimum or chicken_age > age_range.maximum: + return Response( + {"result": "به علت استاندارد نبودن سن مرغ برای کشتار امکان ثبت درخواست وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if kill_house.max_kill_limit and kill_house.total_kill_capacity > 0: + recive_date = datetime.strptime(str(request.data['recive_date']), '%Y-%m-%dT%H:%M:%S.%fZ').date() + + if kill_house.max_kill_limit and kill_house.total_kill_capacity > 0: + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + killhouse_user=kill_house, + kill_request__recive_date__date=recive_date) + total_province_kill_requests_quantity = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + if kill_house.total_kill_capacity < total_province_kill_requests_quantity + int( + request.data['kill_capacity']): + return Response({"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + dict1 = {} + dict2 = {} + if kill_house.ware_house_remaining_weight_limitation_status: + if kill_house.total_remain_warehouse_governmental_weight > kill_house.ware_house_remaining_weight_limitation: + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_house.ware_house_remaining_percent_limitation_status: + if not check_kill_house_remain_limitation_weight(kill_house): + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده روزانه انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_request = serializer.create(validated_data=request.data) + buying_verification = DirectBuyingVerification.objects.filter(trash=False).first() + price_confirmation = PriceConfirmation.objects.filter(trash=False).first() + price_confirmation = price_confirmation.poultry_status if price_confirmation else False + kill_request.kill_house = kill_house + free_sale_in_province = False if kill_request.free_direct_buying == False else True + kill_request.previous_kill_capacity = kill_request.kill_capacity + if poultry != None: + # hatching = PoultryHatching.objects.filter(trash=False, poultry=poultry).only('chicken_breed').first() + if 'payment_deadline_days' in request.data.keys(): + kill_request.payment_deadline_date = datetime.now() + timedelta( + days=request.data['payment_deadline_days']) + kill_request.payment_deadline = True + + kill_request.chicken_breed = hatching.chicken_breed + province_operator = SystemUserProfile.objects.filter(trash=False, role__name='ProvinceOperator').first() + kill_request.poultry = poultry + kill_request.poultry_hatching = hatching + mobile = poultry.user.mobile + poultry_name = poultry.user.fullname + code = str(random.randint(10000, 99000)) + kill_request.direct_buying_code = code + buyer = kill_request.kill_house.kill_house_operator.user.fullname + buyer_mobile = kill_request.kill_house.kill_house_operator.user.mobile + quantity = kill_request.kill_capacity + kill_place = kill_request.slaughter_house.name if kill_request.slaughter_house != None else kill_request.kill_house.name + date_str = str(kill_request.recive_date) + # if kill_request.recive_date.date().day == datetime.now().date().day: + try: + date = datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S.%f%z').date() + except: + date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + date = jdatetime.datetime.fromgregorian(year=date.year, month=date.month, + day=date.day).strftime( + '%Y-%m-%d') + date_list = reversed(date.split('-')) + separate = "-" + date = separate.join(date_list) + if kill_request.export_status == False: + pass + + # sms_direct_buying_sms = threading.Thread( + # target=direct_buying_code_sms, + # args=( + # mobile, buyer, buyer_mobile, quantity, kill_place, date, code)) + # sms_direct_buying_sms.start() + else: + export_country = kill_request.export_country + sms_export_sms = threading.Thread( + target=export_code_sms, + args=( + mobile, buyer, buyer_mobile, quantity, kill_place, date, export_country, + code, poultry_name, province_operator.mobile)) + sms_export_sms.start() + + # kill_request.remain_quantity_for_poultry = kill_request.kill_capacity + if killer_kill_house != None: + kill_request.slaughter_house = killer_kill_house + kill_request.remain_quantity = kill_request.kill_capacity + dict1.update({ + 'cash': cash, + 'credit': credit + }) + kill_request.buy_type = dict1 + dict2.update({ + 'low_weight': low_weight, + 'high_weight': high_weight + + }) + kill_request.weight_type = dict2 + if role != None: + kill_request.registrar = { + "role": role, + "full_name": user.fullname, + "date": str(kill_request.create_date) + } + kill_request.save() + permission_duirect_buying = AutomaticDirectBuyingPermission.objects.first() + if role == 'KillHouse': + if kill_request.poultry is None: + if SmsLicense.objects.filter(kill_request=True).exists(): + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + date_str = kill_request.recive_date + try: + send_date = datetime.strptime(date_str, '%Y-%m-%dT%H:%M:%S.%f%z').date() + except: + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + # send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + province = kill_request.kill_house.system_address.province.name + city = kill_request.kill_house.system_address.city.name + kill_house_name = kill_request.kill_house.name + province_operator_mobile = province_operator.user.mobile + province_operator_name = province_operator.user.fullname + sms_kill_request_province_sms = threading.Thread(target=kill_request_province_sms, + args=( + province_operator_mobile, kill_house_name, + quantity, + chicken_breed, + send_date, province, city)) + sms_kill_request_province_sms.start() + serializer_request = self.serializer_class(kill_request) + if price_confirmation: + kill_request.price_confirmation = True + kill_request.save() + return Response({"result": "درخواست شما با موفقیت برای استان ارسال شد."}, + status=status.HTTP_201_CREATED) + + else: + kill_request.remain_quantity = kill_request.kill_capacity + kill_request.province_state = 'accepted' + kill_request.final_accept = True + kill_request.save() + price = Pricing.objects.all() + if price.count() > 0: + price = price.last() + factor = KillRequestFactor( + kill_request=kill_request, + amount=round( + (kill_request.kill_capacity * kill_request.Index_weight) * price.live_chicken_price, + 0), + minimum_amount=round( + ((kill_request.kill_capacity * kill_request.Index_weight) * price.live_chicken_price) * ( + 70 / 100), + 0) + + ) + factor.save() + kill_request.factor_amount = factor.amount + kill_request.save() + if kill_request.poultry is None: + if SmsLicense.objects.filter(kill_request=True).exists(): + mobile = kill_request.kill_house.kill_house_operator.user.mobile + kill_house_name = kill_request.kill_house.name + sms_province_kill_request_accept_sms = threading.Thread( + target=province_kill_request_accept_sms, + args=( + kill_house_name,)) + sms_province_kill_request_accept_sms.start() + now = datetime.now().time().replace(second=0, microsecond=0) + if price_confirmation: + poultry_fullname = poultry.unit_name + # poultry_mobile = poultry.user.mobile + poultry_mobile = second_mobile_number if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + kill_request.price_confirmation = True + kill_request.save() + return Response({"result": "درخواست شما با موفقیت ارسال شد."}, + status=status.HTTP_201_CREATED) + else: + if permission_duirect_buying.allow == True and not buying_verification.poultry_code_mandatory and permission_duirect_buying.start_time < \ + now < permission_duirect_buying.end_time: + poultry_requests = PoultryRequest.objects.filter(poultry=kill_request.poultry, + trash=False).order_by( + 'create_date') + if not hatching: + hatching = PoultryHatching.objects.filter(poultry=kill_request.poultry, state='pending', + archive=False, + allow_hatching='pending', trash=False).order_by( + 'id').last() + + poultry = Poultry.objects.get(key=kill_request.poultry.key, trash=False) + vet_farm = VetFarm.objects.filter(trash=False, poultry=poultry).first() + last_poultry_request = PoultryRequest.objects.all() + if last_poultry_request.count() > 0: + general_order_code = last_poultry_request.last().general_order_code + 1 + else: + general_order_code = 1 + + if poultry_requests.count() > 0: + order_code = poultry_requests.last().order_code + 1 + else: + order_code = int(str(poultry.user.base_order) + '0001') + city_operator = CityOperator.objects.filter(unit_name=poultry.city_operator, trash=False).last() + if not city_operator: + city_operator = CityOperator.objects.filter(unit_name='اتحادیه استان (فاقد تعاونی)', + trash=False).last() + if hatching.left_over < kill_request.kill_capacity: + return Response({"result": "تعداد جوجه در سالن کمتر از تعداد درخواستی است"}, + status=status.HTTP_403_FORBIDDEN) + + poultry_request = PoultryRequest( + hatching=hatching, + order_code=order_code, + general_order_code=general_order_code, + city_operator=city_operator, + poultry=poultry, + previous_quantity=kill_request.kill_capacity, + remain_quantity=kill_request.kill_capacity, + quantity=kill_request.kill_capacity, + first_quantity=kill_request.kill_capacity, + chicken_breed=hatching.chicken_breed, + Index_weight=kill_request.Index_weight, + state_process='accepted', + province_state='accepted', + direct_buying=True, + free_sale_in_province=free_sale_in_province, + send_date=kill_request.recive_date, + amount=kill_request.amount, + ) + poultry_request.save() + kill_request.poultry_request = poultry_request + if kill_request.export_status == True: + poultry_request.export = True + send_date_str = poultry_request.send_date + send_date_datetime = datetime.strptime(str(send_date_str), '%Y-%m-%dT%H:%M:%S.%fZ') + poultry_request.killing_age = (send_date_datetime.date() - hatching.date.date()).days + 1 + + poultry_request.state = { + "city_operator": city_operator.user.fullname, + "city_state": poultry_request.state_process, + "city_operator_mobile": city_operator.user.mobile, + "province_operator": "", + "province_state": "" + } + poultry_request.registrar = { + "role": role, + "fullname": user.fullname, + "date": str(poultry_request.create_date) + } + poultry_request.save() + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=True, + province_state='accept', + allow_hatching=True + + ) + city_operator_check_request.save() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + wage = wage_type.amount if wage_type.status == True else 0 + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + province_killrequest = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + kill_request=kill_request, + province_request=check, + quantity=kill_request.kill_capacity, + total_killed_quantity=kill_request.kill_capacity, + total_killed_weight=int(kill_request.kill_capacity * poultry_request.Index_weight), + main_quantity=kill_request.kill_capacity, + wage=wage, + direct_buying=True, + total_wage_amount=wage * int(kill_request.kill_capacity * poultry_request.Index_weight), + ) + province_killrequest.save() + # fine = FinePermission.objects.filter(trash=False).first() + # time_for_fine = datetime.now() + # time_for_fine = time_for_fine.replace(second=0, microsecond=0).time() + # if fine.direct_buying: + # if fine.direct_buying_start_time < time_for_fine < fine.direct_buying_end_time: + # province_killrequest.direct_buying_fine = True + # province_killrequest.direct_buying_fine_amount = fine.direct_buying_fine_coefficient * province_killrequest.total_wage_amount + # province_killrequest.direct_buying_fine_coefficient = fine.direct_buying_fine_coefficient + create_update_chicken_commission_prices() + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_killrequest.union_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.union_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'company': + province_killrequest.company_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_killrequest.guilds_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.guilds_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'city': + province_killrequest.city_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_killrequest.wallet_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.wallet_share_percent = percentage_wage_type.percent + + else: + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + province_killrequest.save() + + tomorrow = datetime.now().date() + timedelta(days=1) + if not KillHouseWareHouse.objects.filter(kill_house=kill_request.kill_house, + date__date=tomorrow).exists(): + ware_house_date = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, + hour=1, + minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_request.kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_killrequest, + state='accepted' + ) + + kill_house_check.save() + province_killrequest.state = 'accepted' + if buying_verification.payment_deadline: + province_killrequest.payment_deadline = True + province_killrequest.payment_deadline_date = datetime.now() + timedelta( + days=request.data['payment_deadline_days']) + province_killrequest.save() + check.quantity = 0 + check.save() + + if poultry_request.export == True: + hatching.export_killed_weight += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.export_killed_quantity += kill_request.kill_capacity + + + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.free_quantity += kill_request.kill_capacity + + else: + hatching.governmental_killed_quantity += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.governmental_quantity += kill_request.kill_capacity + hatching.killed_quantity += kill_request.kill_capacity + hatching.save() + poultry_request.remain_quantity = 0 + poultry_request.direct_buying_kill_place = kill_request.kill_house.name + poultry_request.direct_buying_buyer_info = { + "buyer_fullname": kill_request.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": kill_request.kill_house.kill_house_operator.user.mobile, + } + poultry_request.save() + if kill_request.export_status == True: + kill_request.export_state = 'accepted' + kill_request.direct_buying_message = request.data['direct_buying_message'] + + else: + kill_request.direct_buying_state = 'accepted' + + kill_request.accept_reject_date = datetime.now() + + kill_request.save() + poultry_fullname = poultry.unit_name + # poultry_mobile = poultry.user.mobile + poultry_mobile = second_mobile_number if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + if isinstance(date_str, str): + clean_date_str = date_str.split('.')[0] + clean_date_str = clean_date_str.replace('T', ' ') + clean_date_str = clean_date_str.replace('Z', '') + + send_date = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + elif isinstance(date_str, datetime): + send_date = date_str.date() + # clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + # send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + code = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + bot_eitaa_for_each_province_kill_request(province_killrequest, vet_farm) + return Response({"result": "درخواست شما با موفقیت ارسال شد."}, + status=status.HTTP_201_CREATED) + else: + poultry_fullname = poultry.unit_name + # poultry_mobile = poultry.user.mobile + poultry_mobile = second_mobile_number if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + if isinstance(date_str, str): + clean_date_str = date_str.split('.')[0] + clean_date_str = clean_date_str.replace('T', ' ') + clean_date_str = clean_date_str.replace('Z', '') + + send_date = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + elif isinstance(date_str, datetime): + send_date = date_str.date() + # clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + # send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + code = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + return Response({"result": "درخواست شما با موفقیت به پنل تخصیص اضافه شد."}, + status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + if 'direct_buying' in request.GET: + from django.db.models import Value + kill_req_list = [] + # if request.GET['type'] == 'pending': + # querysets = KillRequest.objects.filter(kill_house__in=kill_house, recive_date__date__gte=date1, + # recive_date__date__lte=date2, poultry__isnull=False, + # direct_buying_state='pending', + # export_status=False,trash=False + # ).order_by( + # 'recive_date') + # else: + querysets = KillRequest.objects.filter(kill_house__in=kill_house, recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + direct_buying_state__in=( + 'accepted', 'rejected', 'deleted', 'pending'), + export_status=False, trash=False, market=False, + ).order_by( + Case( + When(direct_buying_state='pending', then=Value(0)), + default=Value(1) + ), + '-recive_date' # مرتب‌سازی بر اساس تاریخ بعد از مرتب‌سازی بر اساس حالت + ) + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=querysets + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=querysets) + kill_req_list = ps.filter() + querysets = [] if len(kill_req_list) == 0 else kill_req_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(querysets) + if page is not None: + serializer = KillRequestSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillRequestSerializer(querysets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + if 'export' in request.GET: + kill_req_list = [] + if request.GET['type'] == 'pending': + querysets = KillRequest.objects.filter(kill_house__in=kill_house, recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, market=False, + export_state='pending' + ).order_by( + 'recive_date') + else: + querysets = KillRequest.objects.filter(kill_house__in=kill_house, recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, market=False, + export_state__in=( + 'accepted', 'rejected', 'deleted'), + ).order_by( + 'recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=querysets + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=querysets) + kill_req_list = ps.filter() + querysets = [] if len(kill_req_list) == 0 else kill_req_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(querysets) + if page is not None: + serializer = KillRequestSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillRequestSerializer(querysets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + queryset_list = KillRequest.objects.filter(kill_house__in=kill_house, trash=False, market=False, + poultry__isnull=True).order_by( + 'recive_date') + querysets = [ + kill_request for kill_request in queryset_list + if date1 <= kill_request.recive_date.date() <= date2 + ] + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + if 'direct_buying' in request.GET: + from django.db.models import Value + kill_req_list = [] + # if request.GET['type'] == 'pending': + # querysets = KillRequest.objects.filter( + # recive_date__date__gte=date1, + # recive_date__date__lte=date2, poultry__isnull=False, + # direct_buying_state='pending', + # export_status=False,trash=False + # ).order_by( + # 'recive_date') + # else: + querysets = KillRequest.objects.filter( + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, market=False, + final_accept=True, + direct_buying_state__in=( + 'accepted', 'rejected', 'deleted', 'pending'), + export_status=False, trash=False + ).select_related( + 'poultry', 'kill_house', 'slaughter_house', 'poultry_hatching' + + ).order_by( + Case( + When(direct_buying_state='pending', then=Value(0)), + default=Value(1) + ), + '-recive_date' # مرتب‌سازی بر اساس تاریخ بعد از مرتب‌سازی بر اساس حالت + ) + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=querysets + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=querysets) + kill_req_list = ps.filter() + querysets = [] if len(kill_req_list) == 0 else kill_req_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(querysets) + if page is not None: + serializer = KillRequestForDirectBuyingTrueSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillRequestSerializer(querysets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + if 'export' in request.GET: + kill_req_list = [] + if request.GET['type'] == 'pending': + querysets = KillRequest.objects.filter( + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, market=False, + export_state='pending' + ).order_by( + 'recive_date') + else: + querysets = KillRequest.objects.filter( + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + export_status=True, market=False, + export_state__in=( + 'accepted', 'rejected', 'deleted'), + ).order_by( + 'recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=querysets + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=querysets) + kill_req_list = ps.filter() + querysets = [] if len(kill_req_list) == 0 else kill_req_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(querysets) + if page is not None: + serializer = KillRequestSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillRequestSerializer(querysets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + querysets_list = KillRequest.objects.filter( + trash=False, poultry__isnull=True).order_by('-recive_date') + # for queryset in querysets_list: + # if (now - queryset.recive_date.date()).days > 2: + # queryset.remain_quantity = 0 + # queryset.save() + + querysets = [ + queryset_list for queryset_list in querysets_list + if date1 <= queryset_list.recive_date.date() <= date2 + ] + elif 'poultry_key' in request.GET: + kill_requests = [] + today = datetime.now().date() + poultry = Poultry.objects.get(key=request.GET['poultry_key'], trash=False) + kill_requests = KillRequest.objects.filter(direct_buying_state__in=('pending', 'accepted'), market=False, + poultry=poultry, recive_date__date=today, trash=False) + serializer = KillRequestSerializer(kill_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + else: + if '0' in request.GET: + poultry_request = PoultryRequest.objects.get(key=request.GET['0']) + + queryset = KillRequest.objects.filter( + recive_date__year=poultry_request.send_date.year, + recive_date__month=poultry_request.send_date.month, + recive_date__day=poultry_request.send_date.day, + province_state='accepted', market=False, + # automatic=False, + trash=False, poultry__isnull=True).order_by('id') + result_list = [] + if len(poultry_request.kill_house_list) != 0: + querysets = [] + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + result_list.append(name) + for kill_house in result_list: + priority_requests = [] + remaining_requests = [] + for kill_request in queryset: + if kill_request.kill_house.name == kill_house: + priority_requests.append(kill_request) + kill_request.priority = True + kill_request.save() + else: + kill_request.priority = False + kill_request.save() + remaining_requests.append(kill_request) + for x in priority_requests: + if x in querysets: + pass + else: + querysets.append(x) + for y in remaining_requests: + if y in querysets: + pass + else: + querysets.append(y) + + + else: + + for kill_request in queryset: + kill_request.priority = False + kill_request.save() + querysets = queryset + + else: + querysets = [] + serializer = KillRequestSerializer(querysets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به حذف درخواست کشتارهای ثبت شده از سمت کشتارگاه + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'role' in request.GET: + kill_request = KillRequest.objects.get(key=request.GET['kill_request_key']) + + limitation_direct_purchase = LimitationForDirectPurchaseAndBarInformation.objects.filter( + trash=False, active=True).first() + + if limitation_direct_purchase and limitation_direct_purchase.start_time and limitation_direct_purchase.end_time: + current_time = datetime.now().time() + if limitation_direct_purchase.start_time <= current_time <= limitation_direct_purchase.end_time: + record_create_time = kill_request.create_date.time() + if not ( + limitation_direct_purchase.start_time <= record_create_time <= limitation_direct_purchase.end_time): + return Response( + {"result": "شما فقط می‌توانید بارهایی که در بازه زمانی مجاز ثبت شده‌اند را حذف کنید!"}, + status=status.HTTP_403_FORBIDDEN) + if request.GET['role'] == 'KillHouse': + if kill_request.direct_buying_state != 'pending' and kill_request.export_status == False: + return Response({"result": "به علت تایید یا رد استان شما نمیتوانیددرخواست رو حذف کنید"}) + if kill_request.export_state != 'pending' and kill_request.export_status == True: + return Response({"result": "به علت تایید یا رد استان شما نمیتوانیددرخواست رو حذف کنید"}) + if kill_request.export_status == False: + kill_request.direct_buying_state = 'deleted' + else: + kill_request.export_state = 'deleted' + + kill_request.trash = True + kill_request.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + user = SystemUserProfile.objects.get(user=request.user) + kill_request = KillRequest.objects.get(id=pk) + if ProvinceKillRequest.objects.filter(kill_request=kill_request, trash=False).exists(): + return Response({"result": "error"}, status=status.HTTP_403_FORBIDDEN) + if SmsLicense.objects.filter(kill_request=True).exists(): + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + date_str = str(kill_request.recive_date) + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + province = kill_request.kill_house.system_address.province.name + city = kill_request.kill_house.system_address.city.name + kill_house_name = kill_request.kill_house.name + province_operator_mobile = province_operator.user.mobile + province_operator_name = province_operator.user.fullname + # kill_request_province_sms(province_operator_mobile, kill_house_name, quantity, chicken_breed, + # send_date, province, city) + + sms_kill_request_delete_province_sms = threading.Thread(target=kill_request_delete_province_sms, + args=( + province_operator_mobile, kill_house_name, + quantity, + chicken_breed, + send_date, province, city)) + sms_kill_request_delete_province_sms.start() + kill_request.trash = True + kill_request.save() + + return Response('request deleted', status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + if 'kill_request_key' in request.data.keys(): + kill_request_instance = KillRequest.objects.filter(key=request.data['kill_request_key'], + trash=False).first() + if kill_request_instance: + limitation_direct_purchase = LimitationForDirectPurchaseAndBarInformation.objects.filter( + trash=False, active=True).first() + + if limitation_direct_purchase and limitation_direct_purchase.start_time and limitation_direct_purchase.end_time: + current_time = datetime.now().time() + if limitation_direct_purchase.start_time <= current_time <= limitation_direct_purchase.end_time: + record_create_time = kill_request_instance.create_date.time() + if not ( + limitation_direct_purchase.start_time <= record_create_time <= limitation_direct_purchase.end_time): + return Response( + { + "result": "شما فقط می‌توانید بارهایی که در بازه زمانی مجاز ثبت شده‌اند را ویرایش کنید!"}, + status=status.HTTP_403_FORBIDDEN) + + if 'role' in request.data.keys(): + kill_request = KillRequest.objects.get(key=request.data['kill_request_key']) + if kill_request.trash: + return Response({"result": "به علت بدهی درخواست شما حذف گردید!"}, status=status.HTTP_403_FORBIDDEN) + if request.data['role'] == 'KillHouse': + if kill_request.direct_buying_state != 'pending': + return Response({"result": "به علت تایید یا رد استان شما نمیتوانیددرخواست رو ویرایش کنید"}) + request.data.pop('role') + request.data.pop('kill_request_key') + if 'input_direct_buying_code' in request.data.keys(): + if request.data['input_direct_buying_code'] != None or request.data['input_direct_buying_code'] != "": + if request.data['input_direct_buying_code'] != kill_request.direct_buying_code: + return Response({"result": "کد وارد شده صحیح نمی باشد"}, status=status.HTTP_403_FORBIDDEN) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().time().replace(second=0, microsecond=0) + + free_sale_in_province = False if kill_request.free_direct_buying == False else True + + permission_duirect_buying = AutomaticDirectBuyingPermission.objects.first() + + if permission_duirect_buying.allow == True and permission_duirect_buying.start_time < \ + now < permission_duirect_buying.end_time: + # kill_request.kill_capacity = int(request.data['quantity']) + # kill_request.remain_quantity = int(request.data['quantity']) + # kill_request.save() + # request.data.pop('quantity') + poultry_requests = PoultryRequest.objects.filter(poultry__user=kill_request.poultry.user, + trash=False).order_by( + 'create_date') + + if kill_request.poultry_hatching: + hatching = kill_request.poultry_hatching + else: + + hatching = PoultryHatching.objects.filter(poultry=kill_request.poultry, state='pending', + archive=False, + allow_hatching='pending', trash=False).order_by( + 'id').last() + + poultry = Poultry.objects.get(key=kill_request.poultry.key, trash=False) + vet_farm = VetFarm.objects.filter(trash=False, poultry=poultry).first() + last_poultry_request = PoultryRequest.objects.all() + if last_poultry_request.count() > 0: + general_order_code = last_poultry_request.last().general_order_code + 1 + else: + general_order_code = 1 + + if poultry_requests.count() > 0: + order_code = poultry_requests.last().order_code + 1 + else: + order_code = int(str(poultry.user.base_order) + '0001') + city_operator = CityOperator.objects.filter(unit_name=poultry.city_operator, trash=False).last() + if not city_operator: + city_operator = CityOperator.objects.filter(unit_name='اتحادیه استان (فاقد تعاونی)', + trash=False).last() + if hatching.left_over < kill_request.kill_capacity: + return Response({"result": "تعداد جوجه در سالن کمتر از تعداد درخواستی است"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_request.kill_house.max_kill_limit and kill_request.kill_house.total_kill_capacity > 0: + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + archive_wage=False, + state__in=( + 'pending', 'accepted'), + killhouse_user=kill_request.kill_house, + kill_request__recive_date__date=kill_request.recive_date.date()) + total_province_kill_requests_quantity = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + if kill_request.kill_house.total_kill_capacity < total_province_kill_requests_quantity + kill_request.kill_capacity: + return Response( + {"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + poultry_request = PoultryRequest( + hatching=hatching, + order_code=order_code, + general_order_code=general_order_code, + city_operator=city_operator, + poultry=poultry, + previous_quantity=kill_request.kill_capacity, + remain_quantity=kill_request.kill_capacity, + quantity=kill_request.kill_capacity, + first_quantity=kill_request.kill_capacity, + chicken_breed=hatching.chicken_breed, + Index_weight=kill_request.Index_weight, + state_process='accepted', + province_state='accepted', + direct_buying=True, + amount=kill_request.amount, + free_sale_in_province=free_sale_in_province, + send_date=kill_request.recive_date + ) + + poultry_request.save() + kill_request.poultry_request = poultry_request + poultry_prediction(poultry_request.poultry) + + if kill_request.export_status == True: + poultry_request.export = True + + send_date_str = poultry_request.send_date + + if isinstance(send_date_str, str): + # حذف میلی‌ثانیه و کاراکترهای اضافی + clean_date_str = send_date_str.split('.')[0] # حذف بخش .759000 + clean_date_str = clean_date_str.replace('T', ' ') # جایگزینی T با فاصله + clean_date_str = clean_date_str.replace('Z', '') # حذف Z اگر وجود دارد + + # تبدیل به تاریخ میلادی + send_date_datetime = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + # اگر از قبل شی datetime است + elif isinstance(send_date_str, datetime): + send_date_datetime = send_date_str.date() + + # send_date_datetime = datetime.strptime(str(send_date_str), '%Y-%m-%dT%H:%M:%S.%fZ') + poultry_request.killing_age = (send_date_datetime - hatching.date.date()).days + 1 + + poultry_request.state = { + "city_operator": city_operator.user.fullname, + "city_state": poultry_request.state_process, + "city_operator_mobile": city_operator.user.mobile, + "province_operator": "", + "province_state": "" + } + poultry_request.registrar = { + "role": 'KillHouse', + "fullname": user.fullname, + "date": str(poultry_request.create_date) + } + poultry_request.save() + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=True, + province_state='accept', + allow_hatching=True + + ) + city_operator_check_request.save() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + wage = wage_type.amount if wage_type.status == True else 0 + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + province_killrequest = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + kill_request=kill_request, + province_request=check, + quantity=kill_request.kill_capacity, + total_killed_quantity=kill_request.kill_capacity, + total_killed_weight=int(kill_request.kill_capacity * poultry_request.Index_weight), + main_quantity=kill_request.kill_capacity, + wage=wage, + direct_buying=True, + total_wage_amount=wage * int(kill_request.kill_capacity * poultry_request.Index_weight), + ) + province_killrequest.save() + # fine = FinePermission.objects.filter(trash=False).first() + # time_for_fine = datetime.now() + # time_for_fine = time_for_fine.replace(second=0, microsecond=0).time() + # if fine.direct_buying: + # if fine.direct_buying_start_time < time_for_fine < fine.direct_buying_end_time: + # province_killrequest.direct_buying_fine = True + # province_killrequest.direct_buying_fine_amount = ( + # fine.direct_buying_fine_coefficient - 1) * province_killrequest.total_wage_amount if fine.direct_buying_fine_coefficient > 1 else province_killrequest.total_wage_amount + # province_killrequest.direct_buying_fine_coefficient = fine.direct_buying_fine_coefficient + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_killrequest.union_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.union_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'company': + province_killrequest.company_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_killrequest.guilds_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.guilds_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'city': + province_killrequest.city_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_killrequest.wallet_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.wallet_share_percent = percentage_wage_type.percent + + else: + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + province_killrequest.save() + + tomorrow = datetime.now().date() + timedelta(days=1) + if not KillHouseWareHouse.objects.filter(kill_house=kill_request.kill_house, + date__date=tomorrow).exists(): + ware_house_date = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=1, + minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_request.kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_killrequest, + state='accepted' + ) + + kill_house_check.save() + province_killrequest.state = 'accepted' + + if kill_request.payment_deadline: + province_killrequest.payment_deadline = True + province_killrequest.payment_deadline_date = kill_request.payment_deadline_date + province_killrequest.save() + check.quantity = 0 + check.save() + + if poultry_request.export == True: + hatching.export_killed_weight += int(kill_request.kill_capacity * poultry_request.Index_weight) + hatching.export_killed_quantity += kill_request.kill_capacity + + + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int(kill_request.kill_capacity * poultry_request.Index_weight) + hatching.free_quantity += kill_request.kill_capacity + + else: + hatching.governmental_killed_quantity += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.governmental_quantity += kill_request.kill_capacity + hatching.killed_quantity += kill_request.kill_capacity + hatching.save() + poultry_request.remain_quantity = 0 + poultry_request.direct_buying_kill_place = kill_request.kill_house.name + poultry_request.direct_buying_buyer_info = { + "buyer_fullname": kill_request.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": kill_request.kill_house.kill_house_operator.user.mobile, + } + poultry_request.save() + if kill_request.export_status == True: + kill_request.export_state = 'accepted' + kill_request.direct_buying_message = request.data['direct_buying_message'] + + else: + kill_request.direct_buying_state = 'accepted' + + kill_request.accept_reject_date = datetime.now() + kill_request.automatic_accept = True + kill_request.input_direct_buying_code = request.data['input_direct_buying_code'] + kill_request.save() + bot_eitaa_for_each_province_kill_request(province_killrequest, vet_farm) + return Response({"result": "درخواست شما با موفقیت تایید و ارسال شد."}, + status=status.HTTP_201_CREATED) + if 'input_export_code' in request.data.keys(): + if request.data['input_export_code'] != None or request.data['input_export_code'] != "": + if request.data['input_export_code'] != kill_request.export_code: + return Response({"result": "کد وارد شده صحیح نمی باشد"}, status=status.HTTP_403_FORBIDDEN) + + if 'final_accept' in request.data.keys(): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_request.final_accept = True + now = datetime.now().time().replace(second=0, microsecond=0) + price_confirmation = PriceConfirmation.objects.filter(trash=False).first() + price_confirmation = price_confirmation.poultry_status if price_confirmation else False + buying_verification = DirectBuyingVerification.objects.filter(trash=False).first() + + if buying_verification.poultry_code_mandatory: + poultry_fullname = kill_request.poultry.unit_name + poultry_mobile = kill_request.poultry.user.mobile if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + # clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + + # send_date = datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + # send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + # day=send_date.day).strftime('%Y-%m-%d') + # + # date_list = reversed(send_date.split('-')) + # separate = "-" + # send_date = separate.join(date_list) + + if isinstance(date_str, str): + clean_date_str = date_str.split('.')[0] + clean_date_str = clean_date_str.replace('T', ' ') + clean_date_str = clean_date_str.replace('Z', '') + + send_date = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + elif isinstance(date_str, datetime): + send_date = date_str.date() + + jalali_date = jdatetime.date.fromgregorian( + year=send_date.year, + month=send_date.month, + day=send_date.day + ) + + formatted_jalali = jalali_date.strftime('%Y-%m-%d') + + date_parts = formatted_jalali.split('-') + send_date = '-'.join(reversed(date_parts)) + + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + kill_request.direct_buying_code)) + confirm_price_poultry_request.start() + kill_request.price_confirmation = price_confirmation + kill_request.save() + return Response({"result": "درخواست شما با موفقیت تایید و ارسال شد."}, + status=status.HTTP_201_CREATED) + else: + free_sale_in_province = False if kill_request.free_direct_buying == False else True + + permission_duirect_buying = AutomaticDirectBuyingPermission.objects.first() + + if permission_duirect_buying.allow == True and permission_duirect_buying.start_time < \ + now < permission_duirect_buying.end_time: + # kill_request.kill_capacity = int(request.data['quantity']) + # kill_request.remain_quantity = int(request.data['quantity']) + # kill_request.save() + # request.data.pop('quantity') + poultry_requests = PoultryRequest.objects.filter(poultry__user=kill_request.poultry.user, + trash=False).order_by( + 'create_date') + + if kill_request.poultry_hatching: + hatching = kill_request.poultry_hatching + else: + + hatching = PoultryHatching.objects.filter(poultry=kill_request.poultry, state='pending', + archive=False, + allow_hatching='pending', trash=False).order_by( + 'id').last() + # hatching = PoultryHatching.objects.filter(poultry=kill_request.poultry, state='pending', + # archive=False, + # allow_hatching='pending', trash=False).order_by( + # 'left_over').last() + + poultry = Poultry.objects.get(key=kill_request.poultry.key, trash=False) + vet_farm = VetFarm.objects.filter(trash=False, poultry=poultry).first() + last_poultry_request = PoultryRequest.objects.all() + if last_poultry_request.count() > 0: + general_order_code = last_poultry_request.last().general_order_code + 1 + else: + general_order_code = 1 + + if poultry_requests.count() > 0: + order_code = poultry_requests.last().order_code + 1 + else: + order_code = int(str(poultry.user.base_order) + '0001') + city_operator = CityOperator.objects.filter(unit_name=poultry.city_operator, trash=False).last() + if not city_operator: + city_operator = CityOperator.objects.filter(unit_name='اتحادیه استان (فاقد تعاونی)', + trash=False).last() + if hatching.left_over < kill_request.kill_capacity: + return Response({"result": "تعداد جوجه در سالن کمتر از تعداد درخواستی است"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_request.kill_house.max_kill_limit and kill_request.kill_house.total_kill_capacity > 0: + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + archive_wage=False, + state__in=( + 'pending', + 'accepted'), + killhouse_user=kill_request.kill_house, + kill_request__recive_date__date=kill_request.recive_date.date()) + total_province_kill_requests_quantity = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + if kill_request.kill_house.total_kill_capacity < total_province_kill_requests_quantity + kill_request.kill_capacity: + return Response( + {"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + poultry_request = PoultryRequest( + hatching=hatching, + order_code=order_code, + general_order_code=general_order_code, + city_operator=city_operator, + poultry=poultry, + previous_quantity=kill_request.kill_capacity, + remain_quantity=kill_request.kill_capacity, + quantity=kill_request.kill_capacity, + first_quantity=kill_request.kill_capacity, + chicken_breed=hatching.chicken_breed, + Index_weight=kill_request.Index_weight, + state_process='accepted', + province_state='accepted', + direct_buying=True, + amount=kill_request.amount, + free_sale_in_province=free_sale_in_province, + send_date=kill_request.recive_date + ) + + poultry_request.save() + kill_request.poultry_request = poultry_request + poultry_prediction(poultry_request.poultry) + + if kill_request.export_status == True: + poultry_request.export = True + date_str = poultry_request.send_date + if isinstance(date_str, str): + # حذف میلی‌ثانیه و کاراکترهای اضافی + clean_date_str = date_str.split('.')[0] # حذف بخش .759000 + clean_date_str = clean_date_str.replace('T', ' ') # جایگزینی T با فاصله + clean_date_str = clean_date_str.replace('Z', '') # حذف Z اگر وجود دارد + + # تبدیل به تاریخ میلادی + send_date_datetime = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + # اگر از قبل شی datetime است + elif isinstance(date_str, datetime): + send_date_datetime = date_str.date() + # send_date_datetime = datetime.strptime(str(send_date_str), '%Y-%m-%dT%H:%M:%S') + poultry_request.killing_age = (send_date_datetime - hatching.date.date()).days + 1 + + poultry_request.state = { + "city_operator": city_operator.user.fullname, + "city_state": poultry_request.state_process, + "city_operator_mobile": city_operator.user.mobile, + "province_operator": "", + "province_state": "" + } + poultry_request.registrar = { + "role": "KillHouse", + "fullname": user.fullname, + "date": str(poultry_request.create_date) + } + poultry_request.save() + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=True, + province_state='accept', + allow_hatching=True + + ) + city_operator_check_request.save() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + wage = wage_type.amount if wage_type.status == True else 0 + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + province_killrequest = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + kill_request=kill_request, + province_request=check, + quantity=kill_request.kill_capacity, + total_killed_quantity=kill_request.kill_capacity, + total_killed_weight=int(kill_request.kill_capacity * poultry_request.Index_weight), + main_quantity=kill_request.kill_capacity, + wage=wage, + direct_buying=True, + total_wage_amount=wage * int(kill_request.kill_capacity * poultry_request.Index_weight), + ) + province_killrequest.save() + # fine = FinePermission.objects.filter(trash=False).first() + # time_for_fine = datetime.now() + # time_for_fine = time_for_fine.replace(second=0, microsecond=0).time() + # if fine.direct_buying: + # if fine.direct_buying_start_time < time_for_fine < fine.direct_buying_end_time: + # province_killrequest.direct_buying_fine = True + # province_killrequest.direct_buying_fine_amount = ( + # fine.direct_buying_fine_coefficient - 1) * province_killrequest.total_wage_amount if fine.direct_buying_fine_coefficient > 1 else province_killrequest.total_wage_amount + # province_killrequest.direct_buying_fine_coefficient = fine.direct_buying_fine_coefficient + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_killrequest.union_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.union_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'company': + province_killrequest.company_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_killrequest.guilds_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.guilds_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'city': + province_killrequest.city_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_killrequest.wallet_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.wallet_share_percent = percentage_wage_type.percent + + else: + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + province_killrequest.save() + + tomorrow = datetime.now().date() + timedelta(days=1) + if not KillHouseWareHouse.objects.filter(kill_house=kill_request.kill_house, + date__date=tomorrow).exists(): + ware_house_date = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, + hour=1, + minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_request.kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_killrequest, + state='accepted' + ) + + kill_house_check.save() + province_killrequest.state = 'accepted' + if kill_request.payment_deadline: + province_killrequest.payment_deadline = True + province_killrequest.payment_deadline_date = kill_request.payment_deadline_date + province_killrequest.save() + check.quantity = 0 + check.save() + + if poultry_request.export == True: + hatching.export_killed_weight += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.export_killed_quantity += kill_request.kill_capacity + + + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.free_quantity += kill_request.kill_capacity + + else: + hatching.governmental_killed_quantity += int( + kill_request.kill_capacity * poultry_request.Index_weight) + hatching.governmental_quantity += kill_request.kill_capacity + hatching.killed_quantity += kill_request.kill_capacity + hatching.save() + poultry_request.remain_quantity = 0 + poultry_request.direct_buying_kill_place = kill_request.kill_house.name + poultry_request.direct_buying_buyer_info = { + "buyer_fullname": kill_request.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": kill_request.kill_house.kill_house_operator.user.mobile, + } + poultry_request.save() + if kill_request.export_status == True: + kill_request.export_state = 'accepted' + kill_request.direct_buying_message = request.data['direct_buying_message'] + + else: + kill_request.direct_buying_state = 'accepted' + + kill_request.accept_reject_date = datetime.now() + kill_request.automatic_accept = True + + kill_request.save() + poultry_fullname = poultry.unit_name + poultry_mobile = poultry.user.mobile if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + if isinstance(date_str, str): + clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + else: + clean_date_str = date_str.strftime('%Y-%m-%d %H:%M:%S') + send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + code = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + + bot_eitaa_for_each_province_kill_request(province_killrequest, vet_farm) + return Response({"result": "درخواست شما با موفقیت تایید و ارسال شد."}, + status=status.HTTP_201_CREATED) + + + + else: + poultry = Poultry.objects.get(key=kill_request.poultry.key, trash=False) + poultry_fullname = poultry.unit_name + poultry_mobile = poultry.user.mobile if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + if isinstance(date_str, str): + clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + else: + clean_date_str = date_str.strftime('%Y-%m-%d %H:%M:%S') + send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + code = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + kill_request.save() + return Response({"result": "درخواست شما با موفقیت تایید و ارسال شد."}, + status=status.HTTP_201_CREATED) + kill_request.save() + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + serializer.update(instance=kill_request, validated_data=request.data) + return Response({"result": "با موفقیت ویرایش شد"}, status=status.HTTP_200_OK) + else: + return Response({"result": "در ثبت مقادیر مشکلی به وجود آمده است !"}, status=status.HTTP_403_FORBIDDEN) + + if 'previous_requests' in request.data.keys(): + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user) + querysets_list = KillRequest.objects.filter( + kill_house__system_address__province=user.province, + trash=False, remain_quantity__gt=0).order_by('-recive_date') + for queryset in querysets_list: + if (now - queryset.recive_date.date()).days > 2: + queryset.remain_quantity = 0 + queryset.save() + return Response({"result": "با موفقیت ثبت شد"}, + status=status.HTTP_200_OK) + + province_kill_request_quantity = 0 + kill_request = KillRequest.objects.get(key=request.data["kill_request_key"], trash=False) + request.data.pop('kill_request_key') + quantity = int(request.data['quantity']) + request.data.pop('quantity') + province_kill_requests = ProvinceKillRequest.objects.filter(kill_request=kill_request, trash=False) + if province_kill_requests.count() > 0: + + for province_kill_request in province_kill_requests: + province_kill_request_quantity += province_kill_request.main_quantity + if quantity < province_kill_request_quantity: + return Response({"result": "تعداد وارد شده از تعداد تخصیص داده شده کمتر است "}, + status=status.HTTP_403_FORBIDDEN) + if int(quantity) < kill_request.kill_capacity: + kill_request.remain_quantity -= kill_request.kill_capacity - int(quantity) + else: + kill_request.remain_quantity += int(quantity) - kill_request.kill_capacity + else: + kill_request.remain_quantity = int(quantity) + + kill_request.kill_capacity = int(quantity) + kill_request.save() + serializer = self.serializer_class(kill_request) + serializer.update(instance=kill_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillRequestFactorViewSet(viewsets.ModelViewSet): + queryset = KillRequestFactor.objects.all() + serializer_class = KillRequestFactorSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + user_profile = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_user = get_object_or_404(KillHouseOperator, user=user_profile) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_user) + + factor_list = KillRequestFactor.objects.filter(kill_request__kill_house__in=kill_house, trash=False).order_by( + 'id') + factors = [ + kill_request_factor for kill_request_factor in factor_list + if date1 <= kill_request_factor.kill_request.recive_date.date() <= date2 + ] + serializer = KillRequestFactorSerializer(factors, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'state' in request.data: + if request.data['state'] == 'cancel': + factor = KillRequestFactor.objects.get(key=request.data['factor_key'], trash=False) + kill_request = KillRequest.objects.get(key=factor.kill_request.key) + kill_request.trash = True + kill_request.save() + factor.trash = True + factor.save() + return Response({"result": "done!"}, status=status.HTTP_200_OK) + + +class KillRequestFactorPaymentViewSet(viewsets.ModelViewSet): + queryset = KillRequestFactorPayment.objects.all() + serializer_class = KillRequestFactorPaymentSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + factor = KillRequestFactor.objects.get(key=request.data['factor_key'], trash=False) + kill_request = KillRequest.objects.get(key=factor.kill_request.key) + kill_house = KillHouse.objects.get(key=kill_request.kill_house.key) + request.data.pop('factor_key') + image = request.data['image'] + request.data.pop('image') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + factor_payment = serializer.create(validated_data=request.data) + factor_payment.kill_request_factor = factor + factor_payment.image = send_image_to_server(image) + factor_payment.remain_amount = float(request.data['amount']) + factor_payment.state = 'paid' + factor_payment.save() + factor.state = 'paid' + factor.save() + kill_request.payment_info = { + "amount": factor_payment.amount, + "total_amount": factor.amount, + "image": factor_payment.image, + "date": str(factor_payment.create_date) + } + kill_request.factor_deposit = factor_payment.amount + kill_request.save() + kill_house.wallet_amount += factor_payment.amount + kill_house.save() + + serializer_request = self.serializer_class(factor_payment) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +def update_province_kill_request(): + wage = ShareOfAllocation.objects.all().last() + wage = wage.province_union if wage else 0 + for province_kill_request in ProvinceKillRequest.objects.all(): + province_request = ProvinceCheckOperatorRequest.objects.filter( + key=province_kill_request.province_request.key).last() + province_kill_request.total_amount = wage * ( + province_kill_request.main_quantity * province_request.poultry_request.Index_weight) + province_kill_request.save() + + +from django.db import models, transaction +from django.db.models import Sum, Count, F + + +# ... (previous code) + +class ReportingProvinceKillRequestsWageViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, return_to_province=False, state__in=('accepted', 'pending') + ).annotate( + total_quantity=Sum('total_killed_quantity'), + total_weight=Sum('total_killed_weight'), + total_amount_wage=Sum( + F('wage') * F('total_killed_weight')), + total_paid=Count('id', filter=models.Q(wage_pay=True, archive_by_province=False)), + total_unpaid=Count('id', filter=models.Q(wage_pay=False, archive_by_province=False)), + total_archive=Count('id', filter=models.Q(wage_pay=False, archive_by_province=True)), + # total_kill_houses=Count('kill_request__kill_house', distinct=True) + ) + + total_requests_buyers = province_kill_requests.values('kill_request__kill_house').distinct().count() + total_requests = province_kill_requests.count() + total_requests_quantity = province_kill_requests.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = province_kill_requests.aggregate(total=Sum('total_weight'))['total'] + total_requests_amount = province_kill_requests.aggregate(total=Sum('total_amount_wage'))['total'] + total_paid_requests = province_kill_requests.aggregate(total=Sum('total_paid'))['total'] + total_paid_requests_quantity = \ + province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_quantity'))['total'] + total_paid_requests_weight = province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_weight'))[ + 'total'] + total_paid_requests_amount = \ + province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_amount_wage'))['total'] + total_unpaid_requests = province_kill_requests.aggregate(total=Sum('total_unpaid'))['total'] + total_unpaid_requests_quantity = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_quantity'))['total'] + total_unpaid_requests_weight = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_weight'))['total'] + total_unpaid_requests_amount = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_amount_wage'))['total'] + + total_archive_requests = province_kill_requests.aggregate(total=Sum('total_archive'))['total'] + total_archive_requests_quantity = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_quantity'))['total'] + total_archive_requests_weight = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_weight'))['total'] + total_archive_requests_amount = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_amount_wage'))['total'] + total_free_request = province_kill_requests.filter( + province_request__poultry_request__free_sale_in_province=True) + total_free_request_quantity = total_free_request.aggregate(total=Sum('total_quantity'))['total'] + total_free_request_weight = total_free_request.aggregate(total=Sum('total_weight'))['total'] + + total_government_request = province_kill_requests.filter( + province_request__poultry_request__free_sale_in_province=False) + total_government_request_quantity = total_government_request.aggregate(total=Sum('total_quantity'))['total'] + total_government_request_weight = total_government_request.aggregate(total=Sum('total_weight'))['total'] + + return Response({ + "total_requests_buyers": total_requests_buyers, + "total_requests": total_requests, + "total_requests_quantity": total_requests_quantity, + "total_requests_weight": total_requests_weight, + "total_requests_amount": total_requests_amount, + "total_paid_requests": total_paid_requests, + "total_paid_requests_quantity": total_paid_requests_quantity if total_paid_requests_quantity != None else 0, + "total_paid_requests_weight": total_paid_requests_weight if total_paid_requests_weight != None else 0, + "total_paid_requests_amount": total_paid_requests_amount if total_paid_requests_amount != None else 0, + "total_unpaid_requests": total_unpaid_requests, + "total_unpaid_requests_quantity": total_unpaid_requests_quantity, + "total_unpaid_requests_weight": total_unpaid_requests_weight, + "total_unpaid_requests_amount": total_unpaid_requests_amount, + "total_archive_requests": total_archive_requests, + "total_archive_requests_quantity": total_archive_requests_quantity, + "total_archive_requests_weight": total_archive_requests_weight, + "total_archive_requests_amount": total_archive_requests_amount, + "total_free_request": len(total_free_request), + "total_free_request_quantity": total_free_request_quantity, + "total_free_request_weight": total_free_request_weight, + "total_government_request": len(total_government_request), + "total_government_request_quantity": total_government_request_quantity, + "total_government_request_weight": total_government_request_weight, + + }, status=status.HTTP_200_OK) + + +def provincearchiveprovincekillrequestforwage(province_kill_request_list, message, role, user_fullname, date): + province_kill_requests = ProvinceKillRequest.objects.filter(key__in=province_kill_request_list, + trash=False) + for province_kill_request in province_kill_requests: + province_kill_request.archive_by_province = True + province_kill_request.archive_message = message + province_kill_request.archiver = { + "role": role, + "fullname": user_fullname, + "date": date, + } + province_kill_request.save() + + +# class ReportingProvinceKillRequestsWageViewSet(viewsets.ModelViewSet): +# queryset = ProvinceKillRequest.objects.all() +# serializer_class = ProvinceKillRequestSerializer +# permission_classes = [TokenHasReadWriteScope] +# +# def list(self, request, *args, **kwargs): +# total_requests_buyers = 0 +# total_requests = 0 +# total_requests_quantity = 0 +# total_requests_weight = 0 +# total_requests_amount = 0 +# total_paid_requests = 0 +# total_paid_requests_quantity = 0 +# total_paid_requests_weight = 0 +# total_paid_requests_amount = 0 +# total_unpaid_requests = 0 +# total_unpaid_requests_quantity = 0 +# total_unpaid_requests_weight = 0 +# total_unpaid_requests_amount = 0 +# province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('accepted', 'pending')) +# for province_kill_request in province_kill_requests: +# if province_kill_request.wage_pay == True: +# total_paid_requests +=1 +# total_paid_requests_quantity += province_kill_request.main_quantity +# total_paid_requests_weight += int(province_kill_request.main_quantity * province_kill_request.province_request.poultry_request.Index_weight) +# total_paid_requests_amount += int(province_kill_request.wage * (province_kill_request.main_quantity * province_kill_request.province_request.poultry_request.Index_weight)) +# else: +# +# total_unpaid_requests +=1 +# total_unpaid_requests_quantity += province_kill_request.main_quantity +# total_unpaid_requests_weight += int(province_kill_request.main_quantity * province_kill_request.province_request.poultry_request.Index_weight) +# total_unpaid_requests_amount += int(province_kill_request.wage * (province_kill_request.main_quantity * province_kill_request.province_request.poultry_request.Index_weight)) +# +# total_requests_buyers = len(province_kill_requests) +# total_requests = total_paid_requests + total_unpaid_requests +# total_requests_quantity = total_paid_requests_quantity + total_unpaid_requests_quantity +# total_requests_weight = total_paid_requests_weight + total_unpaid_requests_weight +# total_requests_amount = total_paid_requests_amount + total_unpaid_requests_amount +# +# +# return Response({ +# +# "total_requests_buyers":total_requests_buyers, +# "total_requests":total_requests, +# "total_requests_quantity" :total_requests_quantity, +# "total_requests_weight":total_requests_weight, +# "total_requests_amount":total_requests_amount, +# "total_paid_requests":total_paid_requests, +# "total_paid_requests_quantity":total_paid_requests_quantity, +# "total_paid_requests_weight":total_paid_requests_weight, +# "total_paid_requests_amount":total_paid_requests_amount, +# "total_unpaid_requests":total_unpaid_requests, +# "total_unpaid_requests_quantity":total_unpaid_requests_quantity, +# "total_unpaid_requests_weight":total_unpaid_requests_weight, +# "total_unpaid_requests_amount":total_unpaid_requests_amount, +# },status=status.HTTP_200_OK +# ) + + +# def auto_steward_allocation(kill_house_key, quantity, weight, date): +# kill_house = KillHouse.objects.get(key=kill_house_key, trash=False) +# stewards = Steward.objects.filter(guilds__steward=True, trash=False).order_by('id') +# stewards_list = [] +# allocatated_quantity = 0 +# kill_house_total_quantity = 0 +# for steward in stewards: +# if steward.centers_allocation != None: +# for center_allocation in steward.centers_allocation: +# if str(kill_house.key) == center_allocation['value']: +# kill_house_total_quantity += steward.allocation_limit +# stewards_list.append(steward) +# if len(stewards_list) > 0: +# for steward_list in stewards_list: +# allocatated_quantity = (steward_list.allocation_limit / kill_house_total_quantity) * quantity +# auto_allocation = StewardAllocation( +# kill_house=kill_house, +# steward=steward_list, +# number_of_carcasses=allocatated_quantity, +# real_number_of_carcasses=allocatated_quantity, +# weight_of_carcasses=int(allocatated_quantity * weight), +# real_weight_of_carcasses=int(allocatated_quantity * weight), +# type='auto', +# date=date +# ) +# auto_allocation.save() +class WalletWagePaymentViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # def update(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # province_kill_request_keys = [] + # for province_kill_request_key in request.data['province_kill_requests']: + # province_kill_request_keys.append(province_kill_request_key) + # province_kill_requests = ProvinceKillRequest.objects.filter( + # key__in=province_kill_request_keys).order_by('id') + # kill_house = KillHouse.objects.get(key=province_kill_requests.last().killhouse_user.key, trash=False) + # now = datetime.now() + # total_amount = 0 + # + # for province_kill_request in province_kill_requests: + # province_kill_request.wage_pay = True + # province_kill_request.wallet_pay = True + # province_kill_request.depositor = { + # "role": request.data['role'], + # "payer": user.fullname, + # "date": str(now), + # "payment_type": 'wallet', + # "tracking_code": '-', + # "refId": '-', + # "orderId": '-', + # "total_amount": province_kill_request.total_killed_weight * province_kill_request.wage + # } + # province_kill_request.save() + # total_amount += province_kill_request.total_killed_weight * province_kill_request.wage + # transaction = ExternalTransaction( + # amount=total_amount, + # type="withdraw", + # transaction_type="wallet", + # status='completed', + # kill_house_user=kill_house.kill_house_operator.user, + # creator=user, + # receiver=user, + # creator_role='KillHouse', + # receiver_role='ProvinceOperator', + # payer=kill_house.kill_house_operator.user.fullname, + # + # ) + # transaction.save() + # + # return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_200_OK) + + +# ویوست مربوط به تخصیص به کشتارگاه توسط استان +class ProvinceKillRequestViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + filterset_class = ProvinceKillRequestNewFilterSet + + # تابع مربوط به تخصیص به کشتارگاه توسط استان + def create(self, request, *args, **kwargs): + wage = 0 + province_check = ProvinceCheckOperatorRequest.objects.get(key=request.data['province_check_request_key'], + trash=False) + if province_check.poultry_request.price_confirmation and not province_check.poultry_request.input_price_confirmation_code: + return Response({"result": "به علت عدم ورود کد احراز مرغدار امکان تخصیص وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if province_check.poultry_request.freezing == True: + wage_type = WageType.objects.filter(en_name='province-kill-request-freezing', trash=False).first() + else: + + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + time_range = TimeRange.objects.filter(trash=False).first() + if time_range: + time = next( + (t for t in time_range.time_range if + t.get("name") == "province_kill_request" and t.get("active", False)), None) + if time: + start_hour = datetime.strptime(time.get("start", 0), "%H:%M:%S").time() + end_hour = datetime.strptime(time.get("end", 0), "%H:%M:%S").time() + current_hour = datetime.now().time().replace(second=0, microsecond=0) + if not (start_hour < current_hour < end_hour): + return Response( + {"result": "لطفا در ساعات مجاز برای ثبت درخواست اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + now = datetime.now().date() + kill_request = KillRequest.objects.get(key=request.data['kill_request_key'], trash=False) + if OperationLimitation.objects.all().first().province_allocation_limitation == True: + + if now != kill_request.recive_date.date(): + return Response({"result": "مغایرت در تاریخ اعلام نیاز کشتار گاه و تاریخ تخصیص به کشتارگاه !"}, + status=status.HTTP_403_FORBIDDEN) + kill_house = KillHouse.objects.get(id=kill_request.kill_house.id, trash=False) + poultry_request = PoultryRequest.objects.get(key=province_check.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + if hatching.left_over < int(request.data['quantity']): + return Response({"result": "تعداد تخصیص داده شده کمتر از تعداد موجود در سالن مرغدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + request.data.pop('kill_request_key') + request.data.pop('province_check_request_key') + if poultry_request.send_date.year != kill_request.recive_date.year or poultry_request.send_date.month != kill_request.recive_date.month or poultry_request.send_date.day != kill_request.recive_date.day: + return Response({"result": "تاریخ درخواست کشتارها یکی نیست!"}, status=status.HTTP_403_FORBIDDEN) + if province_check.quantity == 0: + return Response("forbidden", status=status.HTTP_403_FORBIDDEN) + if int(request.data['quantity']) > kill_request.remain_quantity: + return Response({"result": "تعداد وارد شده از مانده سهمیه بیشتر است !"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.max_kill_limit and kill_house.total_kill_capacity > 0: + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + killhouse_user=kill_house, + kill_request__recive_date__date=kill_request.recive_date.date()) + total_province_kill_requests_quantity = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + + if kill_house.total_kill_capacity < total_province_kill_requests_quantity + int(request.data['quantity']): + return Response({"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + if poultry_request.free_sale_in_province == True: + + if kill_house.quota: + kill_house_info = calculate_governmental_quota(kill_house) + if kill_house_info == 'not_allowed': + return Response({"result": " امکان خرید آزاد تا تکمیل تعهد دولتی وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_house.ware_house_remaining_weight_limitation_status: + if kill_house.total_remain_warehouse_governmental_weight > kill_house.ware_house_remaining_weight_limitation: + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_house.ware_house_remaining_percent_limitation_status: + if not check_kill_house_remain_limitation_weight(kill_house): + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده روزانه انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + province_kills = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + province_request__city_request_Poultry__poultry_request_id=province_check.city_request_Poultry.poultry_request.id, + state__in=('pending', 'accepted'), trash=False) + if province_kills.count() > 0: + province = province_kills.last() + + if province.main_quantity == province.quantity: + province.total_killed_quantity += int(request.data['quantity']) + province.total_killed_weight += int(int(request.data['quantity']) * poultry_request.Index_weight) + province.quantity += int(request.data['quantity']) + province.main_quantity += int(request.data['quantity']) + kill_request.remain_quantity = kill_request.remain_quantity - int(request.data['quantity']) + kill_request.save() + province.save() + province_check.quantity -= int(request.data['quantity']) + province_check.save() + poultry_request.remain_quantity -= int(request.data['quantity']) + poultry_request.save() + if poultry_request.export == True: + hatching.export_killed_weight += int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity += int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.free_quantity += int(request.data['quantity']) + else: + hatching.governmental_killed_quantity += int( + int(request.data['quantity']) * poultry_request.Index_weight) + + hatching.governmental_quantity += int(request.data['quantity']) + hatching.save() + tomorrow = now + timedelta(days=1) + if not KillHouseWareHouse.objects.filter(kill_house=kill_house, date__date=tomorrow).exists(): + ware_house_date = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=1, + minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + province.total_wage_amount = province.total_killed_weight * province.wage + province.save() + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province.union_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.union_share_percent = percentage_wage_type.percent + province.save() + elif percentage_wage_type.share_type.en_name == 'company': + province.company_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.company_share_percent = percentage_wage_type.percent + province.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + province.guilds_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.guilds_share_percent = percentage_wage_type.percent + province.save() + elif percentage_wage_type.share_type.en_name == 'city': + province.city_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.city_share_percent = percentage_wage_type.percent + province.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + province.wallet_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.wallet_share_percent = percentage_wage_type.percent + province.save() + + elif percentage_wage_type.share_type.en_name == 'other': + province.other_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.other_share_percent = percentage_wage_type.percent + province.save() + + else: + province.other_share = int((percentage_wage_type.percent / 100) * province.total_wage_amount) + province.other_share_percent = percentage_wage_type.percent + province.save() + + return Response({"result": "object create"}, status=status.HTTP_201_CREATED) + + serializer = self.serializer_class(data=request.data) + + if serializer.is_valid(): + province_kill_request_list = [] + if hatching.left_over < int(request.data['quantity']): + return Response({"result": "تعداد تخصیص داده شده بیشتر از تعداد موجود در سالن مرغدار است!"}, + status=status.HTTP_403_FORBIDDEN) + province_kill_request = serializer.create(validated_data=request.data) + province_kill_request.kill_request = kill_request + province_kill_request.province_request = province_check + province_kill_request.wage = wage + province_kill_request.state = "pending" + if province_check.quantity < int(request.data['quantity']): + province_kill_request.quantity = province_check.quantity + province_kill_request.killhouse_user = kill_house + province_kill_request.main_quantity = int(request.data['quantity']) + province_kill_request.total_killed_quantity = province_kill_request.main_quantity + province_kill_request.total_killed_weight = int( + province_kill_request.main_quantity * poultry_request.Index_weight) + province_kill_request.total_wage_amount = province_kill_request.total_killed_weight * province_kill_request.wage + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_kill_request.union_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.union_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'company': + province_kill_request.company_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_kill_request.guilds_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.guilds_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'city': + province_kill_request.city_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_kill_request.other_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_kill_request.wallet_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.wallet_share_percent = percentage_wage_type.percent + + else: + province_kill_request.other_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.other_share_percent = percentage_wage_type.percent + province_kill_request.save() + + province_kill_request.save() + poultry_request.remain_quantity -= province_kill_request.main_quantity + poultry_request.save() + + province_check.quantity = province_check.quantity - int(int(request.data['quantity'])) + if province_check.quantity < 0 or province_check.quantity == 0: + province_check.quantity = 0 + province_check.province_show_kill_house = 'accepted' + province_check.save() + kill_request.remain_quantity -= province_kill_request.main_quantity + kill_request.save() + kill_house_request_serializer = self.serializer_class(province_kill_request) + dict1 = { + "kill_house_req_key": str(province_kill_request.key), + "kill_req_key": province_kill_request.kill_request.key, + "province_kill_request_state": province_kill_request.state, + "kill_house_name": province_kill_request.kill_request.kill_house.name, + "kill_house_user_name": province_kill_request.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": province_kill_request.kill_request.kill_house.kill_house_operator.address.city.name, + "kill_house_mobile": province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": province_kill_request.quantity, + "fee": province_kill_request.fee, + "time": province_kill_request.kill_request.recive_time, + "date": province_kill_request.kill_request.recive_date, + } + + factor = KillRequestFactor.objects.filter(kill_request=kill_request) + if factor.count() > 0: + factor = factor.last() + if KillRequestFactorPayment.objects.filter(kill_request_factor=factor).exists(): + factor.state = 'paid' + else: + factor.state = 'unpaid' + factor.save() + province_kill_request_list.append(province_kill_request.key) + + if AutoAcceptProvinceKillRequest.objects.filter(allow=True).exists(): + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_kill_request, + role="ProvinceOperator", + state="accepted" + + ) + province_kill_request.state = 'accepted' + kill_house_check.save() + province_kill_request.save() + if poultry_request.export == True: + hatching.export_killed_weight += int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity += int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.free_quantity += int(request.data['quantity']) + else: + hatching.governmental_killed_quantity += int( + int(request.data['quantity']) * poultry_request.Index_weight) + + hatching.governmental_quantity += int(request.data['quantity']) + hatching.save() + vet_farm = VetFarm.objects.filter(trash=False, poultry=hatching.poultry).first() + if SmsLicense.objects.filter(province_kill_request=True).exists(): + kill_house_name = kill_house.name + kill_house_mobile = kill_house.kill_house_operator.user.mobile + kill_house_second_mobile = kill_house.alternate_number + quantity = province_kill_request.quantity + sale_in_province = province_check.poultry_request.free_sale_in_province + amount = province_check.poultry_request.amount + chicken_breed = province_check.poultry_request.chicken_breed + poultry_name = province_check.poultry_request.poultry.unit_name + poultry_mobile = province_check.poultry_request.poultry.user.mobile + date_str = str(province_check.poultry_request.send_date) + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + province = province_check.poultry_request.poultry.address.province.name + city = province_check.poultry_request.poultry.address.city.name + province_kill_request_to_kill_house_sms(kill_house_mobile, quantity, chicken_breed, send_date, + poultry_name, + poultry_mobile, province, city, sale_in_province, amount, + kill_house_name + ) + if kill_house_second_mobile != None: + province_kill_request_to_kill_house_sms_threading = threading.Thread( + target=province_kill_request_to_kill_house_sms, + args=( + kill_house_second_mobile, quantity, chicken_breed, send_date, + poultry_name, + poultry_mobile, province, city, sale_in_province, amount, + kill_house_name + )) + province_kill_request_to_kill_house_sms_threading.start() + if not KillHouseWareHouse.objects.filter(kill_house=kill_house, date__date=now).exists(): + ware_house_date = datetime(year=now.year, month=now.month, day=now.day, hour=1, minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + if base_url_sms == 'ha': + poultry_name = province_kill_request.province_request.poultry_request.poultry.unit_name + poultry_mobile = province_kill_request.province_request.poultry_request.poultry.user.mobile + quantity = province_kill_request.main_quantity + Index_weight = province_kill_request.province_request.poultry_request.Index_weight + kill_house_name = province_kill_request.killhouse_user.name + kill_house_mobile = province_kill_request.killhouse_user.kill_house_operator.user.mobile + date_str = str( + province_kill_request.province_request.poultry_request.send_date) + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + # city = province_kill_request.province_request.poultry_request.poultry.address.city.name + # vet_farm = VetFarm.objects.filter( + # poultry=province_kill_request.province_request.poultry_request.poultry).first() + # sms_allocation_for_vet_farm(poultry_name, poultry_mobile, + # quantity, Index_weight, kill_house_name, kill_house_mobile, city, send_date, + # vet_farm.vet.user.mobile) + create_update_chicken_commission_prices() + bot_eitaa_for_each_province_kill_request(province_kill_request, vet_farm) + return Response(dict1, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + # تابع مربوط به نمایش تخصیصات به کشتارگاها توسط استان + def list(self, request, *args, **kwargs): + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + # refresh(request.user.id) + info_dict_list = [] + exclusive_killer = False + info_list = [] + province_kill_reqs = [] + + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, + trash=False) + + if 'car' in request.GET: + if KillHousePercentage.objects.filter(kill_house_for_killer__in=kill_house, + kill_house__type='exclusive').exists(): + exclusive_killer = True + province_kill_reqs = ProvinceKillRequest.objects.filter( + Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house), + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, + state='accepted', + return_to_province=False, + province_request__city_request_Poultry__poultry_request__final_state='pending', + trash=False, quantity__gt=0).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + # province_kill_reqs = [ + # province_request for province_request in province_kill_req_lists + # if date1 <= province_request.province_request.poultry_request.send_date.date() <= date2 + # ] + elif 'id' in request.GET: + poultry_request = PoultryRequest.objects.get(id=int(request.GET['id'])) + province_kill_reqs = ProvinceKillRequest.objects.filter(state='accepted', + killhouse_user__in=kill_house, + province_request__city_request_Poultry__poultry_request=poultry_request, + province_request__city_request_Poultry__poultry_request__final_state='pending', + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + elif 'allocations' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter( + Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house), + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__city_request_Poultry__poultry_request__poultry__user', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city', + 'kill_request__kill_house', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city' + ).values( + "province_request__poultry_request__order_code", + "province_request__poultry_request__amount", + "province_request__poultry_request__financial_operation", + "province_request__poultry_request__Index_weight", + "province_request__poultry_request__send_date", + "province_request__poultry_request__freezing", + "province_request__poultry_request__export", + "province_request__poultry_request__poultry__unit_name", + "province_request__poultry_request__poultry__user__fullname", + "province_request__city_request_Poultry__poultry_request__poultry__user__mobile", + "province_request__city_request_Poultry__poultry_request__poultry__user__city__name", + "province_request__poultry_request__quantity", + "kill_request__market", + "kill_request__kill_house__name", + "kill_request__kill_house__kill_house_operator__user__mobile", + "kill_request__kill_house__system_address__city__name", + "create_date", + "main_quantity", + "quantity", + "return_to_province", + "returner", + "key", + "state", + "kill_house_price", + "province_request__poultry_request__union", + "province_request__poultry_request__direct_buying", + "province_request__poultry_request__free_sale_in_province", + # "allocated_car_state" + ).order_by('province_request__poultry_request__send_date') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + province_kill_requests = province_kill_requests.filter( + build_query(self.filterset_class, value) + ) + province_kill_reqs_list_final_state = [] + for request_data in province_kill_requests: + allocated_car_state = True if request_data.get('main_quantity') != request_data.get( + 'quantity') else False + + internal_dict = { + "order_code": request_data.get('province_request__poultry_request__order_code'), + "freezing": request_data.get('province_request__poultry_request__freezing'), + "export": request_data.get('province_request__poultry_request__export'), + "amount": request_data.get('province_request__poultry_request__amount'), + "financial_operation": request_data.get( + 'province_request__poultry_request__financial_operation'), + "index_weight": request_data.get('province_request__poultry_request__Index_weight'), + "total_weight": request_data.get('main_quantity') * request_data.get( + 'province_request__poultry_request__Index_weight'), + "send_date": request_data.get('province_request__poultry_request__send_date'), + "poultry_unit_name": request_data.get( + 'province_request__poultry_request__poultry__unit_name'), + "poultry_full_name": request_data.get( + 'province_request__poultry_request__poultry__user__fullname'), + "poultry_mobile": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__mobile'), + "poultry_city": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__city__name'), + "poultry_quantity": request_data.get('province_request__poultry_request__quantity'), + "kill_house_name": request_data.get('kill_request__kill_house__name'), + "market": request_data.get('kill_request__market'), + "kill_house_mobile": request_data.get( + 'kill_request__kill_house__kill_house_operator__user__mobile'), + "kill_house_city": request_data.get( + 'kill_request__kill_house__system_address__city__name'), + "date_of_allocate": request_data.get('create_date'), + "allocated_quantity": request_data.get('main_quantity'), + "return_to_province": request_data.get('return_to_province'), + "returner": request_data.get('returner'), + "allocated_remain_quantity": request_data.get('quantity') if request_data.get( + 'return_to_province') == False else 0, + "province_kill_request_key": request_data.get('key'), + "allocated_state": request_data.get('state'), + "union": request_data.get('province_request__poultry_request__union'), + "direct_buying": request_data.get( + 'province_request__poultry_request__direct_buying'), + "allocated_car_state": allocated_car_state, + "free_sale_in_province": request_data.get( + 'province_request__poultry_request__free_sale_in_province'), + "kill_house_price": request_data.get('kill_house_price') + } + + province_kill_reqs_list_final_state.append(internal_dict) + return Response(province_kill_reqs_list_final_state, status=status.HTTP_200_OK) + elif 'allocated_car_state' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter( + Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house), + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False, first_car_allocated_quantity=0 + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__city_request_Poultry__poultry_request__poultry__user', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city', + 'kill_request__kill_house', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city' + ).values( + "province_request__poultry_request__order_code", + "province_request__poultry_request__amount", + "province_request__poultry_request__financial_operation", + "province_request__poultry_request__Index_weight", + "province_request__poultry_request__send_date", + "province_request__poultry_request__freezing", + "province_request__poultry_request__export", + "province_request__poultry_request__poultry__unit_name", + "province_request__poultry_request__poultry__user__fullname", + "province_request__city_request_Poultry__poultry_request__poultry__user__mobile", + "province_request__city_request_Poultry__poultry_request__poultry__user__city__name", + "province_request__poultry_request__quantity", + "kill_request__kill_house__name", + "kill_request__market", + "kill_request__kill_house__kill_house_operator__user__mobile", + "kill_request__kill_house__system_address__city__name", + "create_date", + "main_quantity", + "quantity", + "return_to_province", + "returner", + "key", + "state", + "kill_house_price", + "province_request__poultry_request__union", + "province_request__poultry_request__direct_buying", + "province_request__poultry_request__free_sale_in_province", + # "allocated_car_state" + ).order_by('province_request__poultry_request__send_date') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + province_kill_requests = province_kill_requests.filter( + build_query(self.filterset_class, value) + ) + province_kill_reqs_list_final_state = [] + for request_data in province_kill_requests: + allocated_car_state = True if request_data.get('main_quantity') != request_data.get( + 'quantity') else False + + internal_dict = { + "order_code": request_data.get('province_request__poultry_request__order_code'), + "freezing": request_data.get('province_request__poultry_request__freezing'), + "export": request_data.get('province_request__poultry_request__export'), + "amount": request_data.get('province_request__poultry_request__amount'), + "financial_operation": request_data.get( + 'province_request__poultry_request__financial_operation'), + "index_weight": request_data.get('province_request__poultry_request__Index_weight'), + "total_weight": request_data.get('main_quantity') * request_data.get( + 'province_request__poultry_request__Index_weight'), + "send_date": request_data.get('province_request__poultry_request__send_date'), + "poultry_unit_name": request_data.get( + 'province_request__poultry_request__poultry__unit_name'), + "poultry_full_name": request_data.get( + 'province_request__poultry_request__poultry__user__fullname'), + "poultry_mobile": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__mobile'), + "poultry_city": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__city__name'), + "poultry_quantity": request_data.get('province_request__poultry_request__quantity'), + "kill_house_name": request_data.get('kill_request__kill_house__name'), + "market": request_data.get('kill_request__market'), + "kill_house_mobile": request_data.get( + 'kill_request__kill_house__kill_house_operator__user__mobile'), + "kill_house_city": request_data.get( + 'kill_request__kill_house__system_address__city__name'), + "date_of_allocate": request_data.get('create_date'), + "allocated_quantity": request_data.get('main_quantity'), + "return_to_province": request_data.get('return_to_province'), + "returner": request_data.get('returner'), + "allocated_remain_quantity": request_data.get('quantity') if request_data.get( + 'return_to_province') == False else 0, + "province_kill_request_key": request_data.get('key'), + "allocated_state": request_data.get('state'), + "union": request_data.get('province_request__poultry_request__union'), + "direct_buying": request_data.get( + 'province_request__poultry_request__direct_buying'), + "allocated_car_state": allocated_car_state, + "free_sale_in_province": request_data.get( + 'province_request__poultry_request__free_sale_in_province'), + "kill_house_price": request_data.get('kill_house_price') + } + + province_kill_reqs_list_final_state.append(internal_dict) + return Response(province_kill_reqs_list_final_state, status=status.HTTP_200_OK) + else: + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, killhouse_user__in=kill_house, + province_request__city_request_Poultry__poultry_request__final_state='pending', + trash=False, + state='pending', + dont_show_kill_house=False).select_related('province_request__poultry_request').order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + + # province_kill_reqs = [ + # province_request for province_request in province_kill_req_list + # if date1 <= province_request.province_request.poultry_request.send_date.date() <= date2 + # ] + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + + if 'id' in request.GET: + poultry_request = PoultryRequest.objects.get(id=int(request.GET['id'])) + province_kill_reqs = ProvinceKillRequest.objects.filter(state='accepted', + province_request__city_request_Poultry__poultry_request=poultry_request, + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + elif 'allocations' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request__poultry__user__province=user.province, + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__city_request_Poultry__poultry_request__poultry__user', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city', + 'kill_request__kill_house', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city' + ).values( + "province_request__poultry_request__order_code", + "province_request__poultry_request__amount", + "province_request__poultry_request__financial_operation", + "province_request__poultry_request__Index_weight", + "province_request__poultry_request__send_date", + "province_request__poultry_request__freezing", + "province_request__poultry_request__export", + "province_request__poultry_request__poultry__unit_name", + "province_request__poultry_request__poultry__user__fullname", + "province_request__city_request_Poultry__poultry_request__poultry__user__mobile", + "province_request__city_request_Poultry__poultry_request__poultry__user__city__name", + "province_request__poultry_request__quantity", + "kill_request__kill_house__name", + "kill_request__market", + "kill_request__kill_house__kill_house_operator__user__mobile", + "kill_request__kill_house__system_address__city__name", + "create_date", + "main_quantity", + "quantity", + "return_to_province", + "returner", + "key", + "state", + "kill_house_price", + "province_request__poultry_request__union", + "province_request__poultry_request__direct_buying", + "province_request__poultry_request__free_sale_in_province", + # "allocated_car_state" + ).order_by('province_request__poultry_request__send_date') + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + province_kill_requests = province_kill_requests.filter( + build_query(self.filterset_class, value) + ) + province_kill_reqs_list_final_state = [] + for request_data in province_kill_requests: + allocated_car_state = True if request_data.get('main_quantity') != request_data.get( + 'quantity') else False + + internal_dict = { + "order_code": request_data.get('province_request__poultry_request__order_code'), + "freezing": request_data.get('province_request__poultry_request__freezing'), + "export": request_data.get('province_request__poultry_request__export'), + "amount": request_data.get('province_request__poultry_request__amount'), + "financial_operation": request_data.get( + 'province_request__poultry_request__financial_operation'), + "index_weight": request_data.get('province_request__poultry_request__Index_weight'), + "total_weight": request_data.get('main_quantity') * request_data.get( + 'province_request__poultry_request__Index_weight'), + "send_date": request_data.get('province_request__poultry_request__send_date'), + "poultry_unit_name": request_data.get( + 'province_request__poultry_request__poultry__unit_name'), + "poultry_full_name": request_data.get( + 'province_request__poultry_request__poultry__user__fullname'), + "poultry_mobile": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__mobile'), + "poultry_city": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__city__name'), + "poultry_quantity": request_data.get('province_request__poultry_request__quantity'), + "kill_house_name": request_data.get('kill_request__kill_house__name'), + "market": request_data.get('kill_request__market'), + "kill_house_mobile": request_data.get( + 'kill_request__kill_house__kill_house_operator__user__mobile'), + "kill_house_city": request_data.get( + 'kill_request__kill_house__system_address__city__name'), + "date_of_allocate": request_data.get('create_date'), + "allocated_quantity": request_data.get('main_quantity'), + "return_to_province": request_data.get('return_to_province'), + "returner": request_data.get('returner'), + "allocated_remain_quantity": request_data.get('quantity') if request_data.get( + 'return_to_province') == False else 0, + "province_kill_request_key": request_data.get('key'), + "allocated_state": request_data.get('state'), + "union": request_data.get('province_request__poultry_request__union'), + "direct_buying": request_data.get( + 'province_request__poultry_request__direct_buying'), + "allocated_car_state": allocated_car_state, + "free_sale_in_province": request_data.get( + 'province_request__poultry_request__free_sale_in_province'), + "kill_house_price": request_data.get('kill_house_price') + } + + province_kill_reqs_list_final_state.append(internal_dict) + return Response(province_kill_reqs_list_final_state, status=status.HTTP_200_OK) + elif 'allocated_car_state' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request__poultry__user__province=user.province, + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False, first_car_allocated_quantity=0 + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__city_request_Poultry__poultry_request__poultry__user', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city', + 'kill_request__kill_house', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city' + ).values( + "province_request__poultry_request__order_code", + "province_request__poultry_request__amount", + "province_request__poultry_request__financial_operation", + "province_request__poultry_request__Index_weight", + "province_request__poultry_request__send_date", + "province_request__poultry_request__freezing", + "province_request__poultry_request__export", + "province_request__poultry_request__poultry__unit_name", + "province_request__poultry_request__poultry__user__fullname", + "province_request__city_request_Poultry__poultry_request__poultry__user__mobile", + "province_request__city_request_Poultry__poultry_request__poultry__user__city__name", + "province_request__poultry_request__quantity", + "kill_request__kill_house__name", + "kill_request__market", + "kill_request__kill_house__kill_house_operator__user__mobile", + "kill_request__kill_house__system_address__city__name", + "create_date", + "main_quantity", + "quantity", + "return_to_province", + "returner", + "key", + "state", + "kill_house_price", + "province_request__poultry_request__union", + "province_request__poultry_request__direct_buying", + "province_request__poultry_request__free_sale_in_province", + # "allocated_car_state" + ).order_by('province_request__poultry_request__send_date') + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + province_kill_requests = province_kill_requests.filter( + build_query(self.filterset_class, value) + ) + province_kill_reqs_list_final_state = [] + for request_data in province_kill_requests: + allocated_car_state = True if request_data.get('main_quantity') != request_data.get( + 'quantity') else False + + internal_dict = { + "order_code": request_data.get('province_request__poultry_request__order_code'), + "freezing": request_data.get('province_request__poultry_request__freezing'), + "export": request_data.get('province_request__poultry_request__export'), + "amount": request_data.get('province_request__poultry_request__amount'), + "financial_operation": request_data.get( + 'province_request__poultry_request__financial_operation'), + "index_weight": request_data.get('province_request__poultry_request__Index_weight'), + "total_weight": request_data.get('main_quantity') * request_data.get( + 'province_request__poultry_request__Index_weight'), + "send_date": request_data.get('province_request__poultry_request__send_date'), + "poultry_unit_name": request_data.get( + 'province_request__poultry_request__poultry__unit_name'), + "poultry_full_name": request_data.get( + 'province_request__poultry_request__poultry__user__fullname'), + "poultry_mobile": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__mobile'), + "poultry_city": request_data.get( + 'province_request__city_request_Poultry__poultry_request__poultry__user__city__name'), + "poultry_quantity": request_data.get('province_request__poultry_request__quantity'), + "kill_house_name": request_data.get('kill_request__kill_house__name'), + "market": request_data.get('kill_request__market'), + "kill_house_mobile": request_data.get( + 'kill_request__kill_house__kill_house_operator__user__mobile'), + "kill_house_city": request_data.get( + 'kill_request__kill_house__system_address__city__name'), + "date_of_allocate": request_data.get('create_date'), + "allocated_quantity": request_data.get('main_quantity'), + "return_to_province": request_data.get('return_to_province'), + "returner": request_data.get('returner'), + "allocated_remain_quantity": request_data.get('quantity') if request_data.get( + 'return_to_province') == False else 0, + "province_kill_request_key": request_data.get('key'), + "allocated_state": request_data.get('state'), + "union": request_data.get('province_request__poultry_request__union'), + "direct_buying": request_data.get( + 'province_request__poultry_request__direct_buying'), + "allocated_car_state": allocated_car_state, + "free_sale_in_province": request_data.get( + 'province_request__poultry_request__free_sale_in_province'), + "kill_house_price": request_data.get('kill_house_price') + } + + province_kill_reqs_list_final_state.append(internal_dict) + return Response(province_kill_reqs_list_final_state, status=status.HTTP_200_OK) + elif request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.filter(user=user, trash=False) + if vet.count() > 0: + vet = vet.last() + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + kill_house_vet = kill_house_vet.last() + + if 'id' in request.GET: + poultry_request = PoultryRequest.objects.get(id=int(request.GET['id'])) + province_kill_reqs = ProvinceKillRequest.objects.filter(state='accepted', + killhouse_user=kill_house_vet.kill_house, + province_request__city_request_Poultry__poultry_request=poultry_request, + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + else: + province_kill_reqs = ProvinceKillRequest.objects.filter(killhouse_user=kill_house_vet.kill_house, + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet) + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + if len(poultries) == 0: + return Response([], status=status.HTTP_200_OK) + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request__poultry__in=poultries, + province_request__poultry_request__poultry__address__province=vet.user.province, + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + elif request.GET['role'] == 'VetSupervisor': + vet = VetSupervisor.objects.get(user=user, trash=False) + + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request__poultry__address__province=vet.user.province, + trash=False).order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + + + else: + if 'state' in request.GET: + if request.GET['state'] == 'accepted': + province_kill_reqs = ProvinceKillRequest.objects.filter(state='accepted', trash=False) + else: + province_kill_reqs = ProvinceKillRequest.objects.filter(vet_state='accepted', trash=False) + if len(province_kill_reqs) == 0: + return Response(province_kill_reqs, status=status.HTTP_200_OK) + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + province_kill_reqs = province_kill_reqs.filter( + build_query(self.filterset_class, value) + ) + for province_kill_req in province_kill_reqs: + check_key = KillHouseCheckRequest.objects.filter(province_kill_request=province_kill_req) + if check_key.count() > 0: + check_key = check_key.last().key + else: + check_key = None + internal_dict_infos = { + "poultry_req_id": province_kill_req.province_request.city_request_Poultry.poultry_request.id, + "freezing": province_kill_req.province_request.city_request_Poultry.poultry_request.freezing, + "direct_buying": province_kill_req.province_request.city_request_Poultry.poultry_request.direct_buying, + "export": province_kill_req.province_request.city_request_Poultry.poultry_request.export, + "amount": province_kill_req.province_request.city_request_Poultry.poultry_request.amount, + "financial_operation": province_kill_req.province_request.city_request_Poultry.poultry_request.financial_operation, + "poultry_req_key": province_kill_req.province_request.city_request_Poultry.poultry_request.key, + "province_kill_req_key": province_kill_req.key, + "poultry_name": province_kill_req.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "order_code": province_kill_req.province_request.city_request_Poultry.poultry_request.order_code, + "send_date": province_kill_req.province_request.city_request_Poultry.poultry_request.send_date, + "city": province_kill_req.province_request.city_request_Poultry.poultry_request.poultry.address.city.name, + "province": province_kill_req.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "poultry_mobile": province_kill_req.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "kill_house_key": province_kill_req.kill_request.kill_house.key, + "kill_house_check_key": check_key, + "kill_house_name": province_kill_req.kill_request.kill_house.name, + "kill_house_mobile": province_kill_req.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": province_kill_req.quantity if province_kill_req.return_to_province == False else 0, + "main_quantity": province_kill_req.main_quantity, + "time": province_kill_req.kill_request.recive_time, + "date": province_kill_req.kill_request.recive_date, + "age": ( + datetime.now() - province_kill_req.province_request.city_request_Poultry.poultry_request.hatching.date).days + 1, + "province_kill_req": province_kill_req.key, + "return_to_province": province_kill_req.return_to_province, + "returner": province_kill_req.returner, + "kill_request_key": province_kill_req.kill_request.key, + "market": province_kill_req.kill_request.market, + "province_kill_state": province_kill_req.state, + "allocated_quantity": province_kill_req.main_quantity - province_kill_req.quantity, + "remain_quantity": province_kill_req.quantity, + "chicken_breed": province_kill_req.kill_request.chicken_breed, + "index_weight": province_kill_req.province_request.poultry_request.Index_weight, + "total_weight": province_kill_req.main_quantity * province_kill_req.province_request.poultry_request.Index_weight, + "province_kill_reviewer": province_kill_req.reviewer, + "province_kill_clearance_code": province_kill_req.clearance_code, + "exclusive_killer": exclusive_killer, + "kill_house_price": province_kill_req.kill_house_price, + "province_kill_request_key": province_kill_req.key, + "kill_house_assignments": "", + "free_sale_in_province": province_kill_req.province_request.poultry_request.free_sale_in_province, + + } + kill_house_check = KillHouseCheckRequest.objects.filter(province_kill_request=province_kill_req, + trash=False) + if kill_house_check: + kill_house_check = kill_house_check.last() + internal_dict_infos.update({ + "kill_house_check_key": kill_house_check.key, + }) + for kill_house_req_obj in KillHouseRequest.objects.filter( + province_kill_request=province_kill_req, trash=False): + internal_kill_house_request_dict_infos = { + "kill_house_req_key": kill_house_req_obj.key, + "kill_req_key": kill_house_req_obj.kill_request.key, + "barcod": kill_house_req_obj.bar_code, + "kill_house_state": kill_house_req_obj.state, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_user_name": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": kill_house_req_obj.kill_request.kill_house.kill_house_operator.address.city.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "show_kill_house": kill_house_req_obj.show_kill_house, + "kill_house_message": kill_house_req_obj.kill_house_message, + } + + info_list.append(internal_kill_house_request_dict_infos) + + internal_dict_infos["kill_house_assignments"] = info_list + + info_dict_list.append(internal_dict_infos) + return Response(info_dict_list, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.data['role'] + request.data.pop('role') + if 'type' in request.data.keys(): + if request.data['type'] == 'archive': + user_fullname = user.fullname + date = str(datetime.now()) + archive_province_kill_request_wage_threading = threading.Thread( + target=provincearchiveprovincekillrequestforwage, + args=( + request.data['province_kill_request_list'], request.data['message'], role, user_fullname, date + )) + archive_province_kill_request_wage_threading.start() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + + elif request.data['type'] == 'return_archive': + user_fullname = user.fullname + date = str(datetime.now().date()) + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key']) + province_kill_request.archive_by_province = False + if 'return_archive_message' in request.data.keys(): + province_kill_request.return_archive_message = request.data['return_archive_message'] + province_kill_request.returner = { + "fullname": user_fullname, + "date": date, + "role": role + } + province_kill_request.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + elif 'edit_allocation_quantity' in request.data.keys(): + wage = 0 + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key'], + trash=False) + if province_kill_request.market: + return Response({"result": "امکان ویرایش برای تخصیصات پنل معاملات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, + trash=False) + if poultry_request.freezing == True: + wage_type = WageType.objects.filter(en_name='province-kill-request-freezing', trash=False).first() + else: + + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if KillHouseRequest.objects.filter(trash=False, province_kill_request=province_kill_request).exists(): + return Response({"result": "برای این تخصیص بارایجاد شده است امکان ویرایش وجود ندارد"}, + status=status.HTTP_403_FORBIDDEN) + amount = province_kill_request.main_quantity + if request.data['quantity'] > amount: + different_amount = request.data['quantity'] - amount + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + province_request__poultry_request=poultry_request) + total_quantity = \ + province_kill_requests.aggregate(total=Sum('main_quantity'))['total'] or 0 + if different_amount + total_quantity > poultry_request.quantity: + return Response({"result": "تعداد وارد شده بیشتر از اعلام نیاز مرغدار است!"}, + status=status.HTTP_403_FORBIDDEN) + total_quantity_for_hatching = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + if different_amount + total_quantity_for_hatching > hatching.left_over: + return Response({"result": "تعداد وارد شده بیشتر از باقی مانده جوجه ریزی مرغدار است!"}, + status=status.HTTP_403_FORBIDDEN) + province_kill_requests_for_kill_request = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + kill_request=province_kill_request.kill_request) + total_quantity_for_kill_request = \ + province_kill_requests_for_kill_request.aggregate(total=Sum('main_quantity'))['total'] or 0 + if province_kill_request.kill_request.kill_capacity < total_quantity_for_kill_request + different_amount: + return Response({"result": "تعداد وارد شده بیشتر از اعلام نیاز کشتارگاه است!"}, + status=status.HTTP_403_FORBIDDEN) + province_kill_request.province_request.quantity -= different_amount + if province_kill_request.province_request.quantity < 0: + province_kill_request.province_request.quantity = 0 + province_kill_request.province_request.save() + province_kill_request.kill_request.remain_quantity = province_kill_request.kill_request.kill_capacity - total_quantity_for_kill_request + province_kill_request.kill_request.remain_quantity -= different_amount + province_kill_request.kill_request.save() + poultry_request.remain_quantity -= different_amount + poultry_request.save() + else: + province_kill_requests_for_kill_request = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + kill_request=province_kill_request.kill_request) + total_quantity_for_kill_request = \ + province_kill_requests_for_kill_request.aggregate(total=Sum('main_quantity'))['total'] or 0 + different_amount = amount - request.data['quantity'] + province_kill_request.province_request.quantity += different_amount + province_kill_request.province_request.save() + province_kill_request.kill_request.remain_quantity = province_kill_request.kill_request.kill_capacity - total_quantity_for_kill_request + province_kill_request.kill_request.remain_quantity += different_amount + province_kill_request.kill_request.save() + poultry_request.remain_quantity += different_amount + poultry_request.save() + + province_kill_request.main_quantity = int(request.data['quantity']) + province_kill_request.total_killed_quantity = province_kill_request.main_quantity + province_kill_request.total_killed_weight = int( + province_kill_request.main_quantity * poultry_request.Index_weight) + province_kill_request.total_wage_amount = province_kill_request.total_killed_weight * province_kill_request.wage + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_kill_request.union_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.union_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'company': + province_kill_request.company_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_kill_request.guilds_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.guilds_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'city': + province_kill_request.city_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_kill_request.other_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_kill_request.wallet_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.wallet_share_percent = percentage_wage_type.percent + + else: + province_kill_request.other_share = int( + (percentage_wage_type.percent / 100) * province_kill_request.total_wage_amount) + province_kill_request.other_share_percent = percentage_wage_type.percent + province_kill_request.save() + + province_kill_request.save() + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key']) + request.data.pop('province_kill_request_key') + if 'kill_house_price' not in request.data.keys(): + if province_kill_request.prev_total_amount == None: + province_kill_request.prev_total_amount = province_kill_request.total_amount + province_kill_request.total_amount_editor = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + province_kill_request.save() + serializer = self.serializer_class(province_kill_request) + serializer.update(instance=province_kill_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + if 'delete_allocation' in request.GET: + + province_kill_request = ProvinceKillRequest.objects.get(key=request.GET['province_kill_request_key'], + trash=False) + if request.GET['role'] == 'KillHouse': + if province_kill_request.market: + return Response({ + "result": "امکان حذف برای تخصیص پنل معاملاتی وجود ندارد. در صورت نیاز به کاربر اتحادیه اطلاع دهید."}, + status=status.HTTP_403_FORBIDDEN) + + now = datetime.now() + now_time = now.time() + if now.date() != province_kill_request.kill_request.recive_date.date(): + return Response({"result": "با توجه به مغایرت تاریخ امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if now_time.hour >= 16: + return Response({"result": "با توجه به اتمام زمان حذف مجاز امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if province_kill_request.quantity != province_kill_request.main_quantity: + return Response({"result": "برای تخصیص ماشین ثبت شده امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, + trash=False) + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= province_kill_request.total_killed_weight + # hatching.free_killed_quantity -= int(province_kill_request.main_quantity * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= province_kill_request.main_quantity + else: + hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight + # hatching.governmental_killed_quantity -= int( + # province_kill_request.main_quantity * poultry_request.Index_weight) + + hatching.governmental_quantity -= province_kill_request.total_killed_quantity + # hatching.governmental_quantity -= province_kill_request.main_quantity + # hatching.killed_quantity -= province_kill_request.main_quantity + hatching.save() + + if poultry_request.remain_quantity > 0: + # province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + else: + + # province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + # poultry_request.quantity -= province_kill_request.quantity + # poultry_request.first_quantity -= province_kill_request.quantity + # poultry_request.previous_quantity -= province_kill_request.quantity + # poultry_request.save() + # if poultry_request.quantity == 0: + # poultry_request.trash = True + # poultry_request.save() + # hatching.left_over += province_kill_request.quantity + # hatching.state = 'pending' + # hatching.allow_hatching = 'pending' + # hatching.save() + kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + kill_request.remain_quantity += province_kill_request.main_quantity + if kill_request.market: + user = SystemUserProfile.objects.get(trash=False, user=request.user) + kill_request.market_state_message = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + kill_request.market_state = 'deleted' + else: + if kill_request.poultry_request: + kill_request.trash = True + kill_request.save() + province_kill_request.delete_message = request.GET['message'] + province_kill_request.trash = True + user = SystemUserProfile.objects.get(user=request.user, trash=False) + province_kill_request.returner = {"fullname": user.fullname, "mobile": user.mobile, + "date": str(datetime.now())} + province_kill_request.save() + bot_eitaa_for_each_delete_province_kill_request(province_kill_request) + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + elif 'return_allocation_quantity' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + province_kill_request = ProvinceKillRequest.objects.get(key=request.GET['province_kill_request_key'], + trash=False) + if province_kill_request.quantity == 0: + return Response({"result": "باقی مانده تخصیص صفر است امکان بازگشت تعداد وجود ندارد"}, + status=status.HTTP_403_FORBIDDEN) + amount = province_kill_request.quantity + + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, + trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + + if province_kill_request.main_quantity - province_kill_request.quantity == 0: + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + kill_request.remain_quantity += province_kill_request.main_quantity + if kill_request.market: + kill_request.market_state = 'deleted' + user = SystemUserProfile.objects.get(trash=False, user=request.user) + kill_request.market_state_message = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + + else: + if kill_request.poultry_request: + kill_request.trash = True + kill_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= province_kill_request.total_killed_weight + # hatching.free_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= amount + else: + hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight + # hatching.governmental_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.governmental_quantity -= province_kill_request.total_killed_quantity + # hatching.governmental_quantity -= amount + # hatching.killed_quantity -= amount + hatching.save() + # province_kill_request.trash = True + province_kill_request.quantity = 0 + province_kill_request.total_killed_quantity = 0 + province_kill_request.total_killed_weight = 0 + province_kill_request.return_to_province = True + province_kill_request.returner = {"fullname": user.fullname, "mobile": user.mobile, + "date": str(datetime.now())} + province_kill_request.save() + bot_eitaa_for_each_delete_province_kill_request(province_kill_request) + else: + + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity - province_kill_request.quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity - province_kill_request.quantity + poultry_request.save() + kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + kill_request.remain_quantity += province_kill_request.main_quantity - province_kill_request.quantity + kill_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= int(( + province_kill_request.main_quantity - province_kill_request.quantity) * poultry_request.Index_weight) + # hatching.free_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= amount + else: + hatching.governmental_killed_quantity -= int(( + province_kill_request.main_quantity - province_kill_request.quantity) * poultry_request.Index_weight) + # hatching.governmental_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.governmental_quantity -= province_kill_request.main_quantity - province_kill_request.quantity + # hatching.governmental_quantity -= amount + # hatching.killed_quantity -= amount + hatching.save() + province_kill_request.main_quantity = province_kill_request.main_quantity - province_kill_request.quantity + province_kill_request.quantity = 0 + province_kill_request.save() + + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + queryset = ProvinceKillRequest.objects.get(key=request.GET['key']) + poultry_request = PoultryRequest.objects.get(key=queryset.province_request.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + check = KillHouseCheckRequest.objects.filter(province_kill_request=queryset, state='accepted') + if check.count() > 0: + return Response({"result": "can not delete"}, status=status.HTTP_403_FORBIDDEN) + province = ProvinceCheckOperatorRequest.objects.get(key=queryset.province_request.key) + province.quantity += queryset.quantity + province.save() + kill_request = KillRequest.objects.get(key=queryset.kill_request.key) + kill_request.remain_quantity += queryset.quantity + kill_request.save() + # queryset.delete() + poultry_request.remain_quantity += queryset.quantity + poultry_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= queryset.total_killed_weight + # hatching.free_killed_quantity -= int(queryset.quantity * poultry_request.Index_weight) + hatching.free_quantity -= queryset.total_killed_quantity + else: + hatching.governmental_killed_quantity -= queryset.total_killed_weight + # hatching.governmental_killed_quantity -= int( + # queryset.quantity * poultry_request.Index_weight) + hatching.governmental_quantity -= queryset.total_killed_quantity + # hatching.killed_quantity -= queryset.total_killed_quantity + hatching.save() + bot_eitaa_for_each_delete_province_kill_request(queryset) + queryset.delete() + return Response(status=status.HTTP_200_OK) + + +class KillHouseWageForTotalDashbordViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseWageForTotalDashbordSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + serializer = self.get_serializer(kill_house) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceKillRequestProvinceWageViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestProvinceWageSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = ProvinceKillRequestFilterSet + filterset_fields = [ + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__poultry__address__city__name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'type' in request.GET: + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Company', 'Guilds', 'Supporter']: + if request.GET['type'] == 'unpaid': + if 'date1' in request.GET: + + if request.GET['role'] == 'ProvinceOperator': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + union_share__gt=0, + trash=False).order_by('kill_request__recive_date') + elif request.GET['role'] == 'Company': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + company_share__gt=0, + trash=False).order_by('kill_request__recive_date') + + elif request.GET['role'] == 'Guilds': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + guilds_share__gt=0, + trash=False).order_by('kill_request__recive_date') + + elif request.GET['role'] in ['SuperAdmin', 'AdminX', 'Supporter']: + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by('kill_request__recive_date') + else: + if request.GET['role'] == 'ProvinceOperator': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + union_share__gt=0, + trash=False).order_by('kill_request__recive_date') + elif request.GET['role'] == 'Company': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + company_share__gt=0, + trash=False).order_by('kill_request__recive_date') + + elif request.GET['role'] == 'Guilds': + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + guilds_share__gt=0, + trash=False).order_by('kill_request__recive_date') + + elif request.GET['role'] in ['SuperAdmin', 'AdminX', 'Supporter']: + province_kill_request = self.queryset.filter( + killhouse_user__key=request.GET['kill_house_key'], + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + trash=False).order_by('kill_request__recive_date') + + + else: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + if request.GET['type'] == 'unpaid': + if 'date1' in request.GET: + + province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by('kill_request__recive_date') + else: + province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, + state__in=('pending', 'accepted'), wage_pay=False, + archive_wage=False, + return_to_province=False, + trash=False).order_by('kill_request__recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=province_kill_request + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=province_kill_request) + province_kill_request = ps.filter() + else: + province_kill_request = province_kill_request + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(province_kill_request) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(province_kill_request, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class ProvinceKillRequestProvinceWageViewSet(viewsets.ModelViewSet): +# queryset = ProvinceKillRequest.objects.all() +# serializer_class = ProvinceKillRequestProvinceWageSerializer +# pagination_class = CustomPagination +# permission_classes = [TokenHasReadWriteScope] +# filter_backends = [DjangoFilterBackend] +# filterset_class = ProvinceKillRequestFilterSet +# filterset_fields = [ +# 'province_request__poultry_request__chicken_breed', +# 'province_request__poultry_request__order_code', +# 'province_request__poultry_request__poultry__address__city__name', +# 'province_request__poultry_request__poultry__user__mobile', +# 'province_request__poultry_request__poultry__user__fullname', +# +# ] +# +# def list(self, request, *args, **kwargs): +# if 'type' in request.GET: +# if 'date1' in request.GET: +# date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() +# +# date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() +# +# if request.GET['role'] in ['ProvinceOperator', 'SuperAdmin']: +# if request.GET['type'] == 'unpaid': +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=False, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=False, +# return_to_province=False, +# trash=False).order_by('kill_request__recive_date') +# +# elif request.GET['type'] == 'archive': +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=True, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=True, +# return_to_province=False, +# +# trash=False).order_by('kill_request__recive_date') +# +# +# else: +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=True, +# archive_by_province=False, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# province_kill_request = self.queryset.filter(killhouse_user__key=request.GET['kill_house_key'], +# state__in=('pending', 'accepted'), wage_pay=True, +# archive_by_province=False, +# return_to_province=False, +# trash=False).order_by('kill_request__recive_date') +# +# else: +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) +# +# if request.GET['type'] == 'unpaid': +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=False, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=False, +# return_to_province=False, +# trash=False).order_by('kill_request__recive_date') +# elif request.GET['type'] == 'archive': +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=True, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=False, +# archive_by_province=True, +# return_to_province=False, +# trash=False).order_by('kill_request__recive_date') +# +# else: +# +# if 'date1' in request.GET: +# +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=True, +# archive_by_province=False, +# return_to_province=False, +# kill_request__recive_date__date__gte=date1, +# kill_request__recive_date__date__lte=date2, +# trash=False).order_by('kill_request__recive_date') +# else: +# province_kill_request = self.queryset.filter(killhouse_user__in=kill_house, +# state__in=('pending', 'accepted'), wage_pay=True, +# archive_by_province=False, +# return_to_province=False, +# trash=False).order_by('kill_request__recive_date') +# if 'search' in request.GET: +# if request.GET['search'] == 'filter': +# if request.GET['value'] != "": +# for item in self.filterset_fields: +# query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) +# if (self.filterset_class( +# data=query, +# queryset=province_kill_request +# ) +# ).filter(): +# ps = self.filterset_class(data=query, queryset=province_kill_request) +# province_kill_request = ps.filter() +# else: +# province_kill_request = province_kill_request +# +# page_size = request.query_params.get('page_size', None) +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(province_kill_request) +# if page is not None: +# serializer = self.get_serializer(page, many=True) +# return self.get_paginated_response(serializer.data) +# +# serializer = self.get_serializer(province_kill_request, many=True) +# return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به تایید یا رد تخصیص از سمت استان توسط کشتارگاه +class KillHouseCheckRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseCheckRequest.objects.all() + serializer_class = KillHouseCheckRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به تایید یا رد تخصیص از سمت استان توسط کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + # role = request.data['role'] + province_kill_house_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key'], + trash=False) + kill_request = KillRequest.objects.get(id=province_kill_house_request.kill_request.id, trash=False) + request.data.pop('province_kill_request_key') + # request.data.pop('role') + province_check = ProvinceCheckOperatorRequest.objects.get(id=province_kill_house_request.province_request.id, + trash=False) + poultry_request = PoultryRequest.objects.get(key=province_check.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + if KillHouseCheckRequest.objects.filter(province_kill_request=province_kill_house_request, + trash=False).exists(): + return Response({'result': 'already exist'}, status=status.HTTP_403_FORBIDDEN) + kill_house_check_request = serializer.create(validated_data=request.data) + kill_house_check_request.province_kill_request = province_kill_house_request + + if kill_house_check_request.state == 'accepted': + province_kill_house_request.state = 'accepted' + province_kill_house_request.save() + # barcode = kill_house_request.bar_code + # driver_mobile = kill_house_request.car['driver_mobile'] + # driver_name = kill_house_request.car['driver_name'] + # quantity = kill_house_request.quantity + # kill_house = kill_house_request.kill_request.kill_house.name + # poultry = kill_house_request.province_request.city_request_Poultry.poultry_request.user.fullname + # province = kill_house_request.province_request.city_request_Poultry.poultry_request.user.address.province + # city = kill_house_request.province_request.city_request_Poultry.poultry_request.user.address.city + # address = kill_house_request.province_request.city_request_Poultry.poultry_request.user.address.address + # date = kill_house_request.province_request.city_request_Poultry.poultry_request.send_date.date() + # date = (str(jdatetime.datetime.fromgregorian(year=date.year, month=date.month, day=date.day).date())) + # time1 = kill_request.recive_time + # list1 = reversed(date.split('-')) + # s = "-" + # date1 = s.join(list1) + # time = reversed(kill_request.recive_time.split('-')) + # o = "-" + # time1 = o.join(time) + # driver_sms(driver_mobile, driver_name, quantity, poultry, barcode, province, city, address, date, + # time1, + # kill_house) + elif kill_house_check_request.state == 'rejected': + if poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= int( + province_kill_house_request.main_quantity * poultry_request.Index_weight) + hatching.free_killed_quantity -= province_kill_house_request.main_quantity + else: + hatching.governmental_killed_quantity -= int( + province_kill_house_request.main_quantity * poultry_request.Index_weight) + hatching.governmental_quantity -= province_kill_house_request.main_quantity + # hatching.killed_quantity -= province_kill_house_request.main_quantity + hatching.save() + province_kill_house_request.state = 'rejected' + province_kill_house_request.message = kill_house_check_request.message + province_kill_house_request.save() + province_check.quantity += province_kill_house_request.quantity + province_check.save() + # kill_request.cars.append(kill_house_request.car) + kill_request.remain_quantity += province_kill_house_request.quantity + kill_request.save() + poultry_request.remain_quantity += province_kill_house_request.quantity + poultry_request.save() + # kill_house_check_request.role = { + # "role": role, + # "name": user.fullname, + # "mobile": user.mobile + # } + kill_house_check_request.save() + if kill_house_check_request.state == 'accepted': + # if SmsLicense.objects.filter().exists(): + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + province_operator_mobile = province_operator.user.mobile + province_operator_name = province_operator.user.fullname + kill_house_name = kill_house_check_request.province_kill_request.kill_request.kill_house.name + kill_house_mobile = kill_house_check_request.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile + quantity = kill_house_check_request.province_kill_request.quantity + chicken_breed = kill_house_check_request.province_kill_request.province_request.poultry_request.chicken_breed + poultry_name = kill_house_check_request.province_kill_request.province_request.poultry_request.poultry.unit_name + poultry_mobile = kill_house_check_request.province_kill_request.province_request.poultry_request.poultry.user.mobile + Index_weight = kill_house_check_request.province_kill_request.province_request.poultry_request.Index_weight + date_str = str( + kill_house_check_request.province_kill_request.province_request.poultry_request.send_date) + send_date = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + province = kill_house_check_request.province_kill_request.province_request.poultry_request.poultry.address.province.name + city = kill_house_check_request.province_kill_request.province_request.poultry_request.poultry.address.city.name + # kill_house_province_kill_request_accept_to_province_sms(province_operator_mobile, + # province_operator_name, quantity, + # chicken_breed, send_date, poultry_name, + # poultry_mobile, province, city, kill_house_name, + # + # ) + + kill_house_check_request_serializer = self.serializer_class(kill_house_check_request) + return Response(kill_house_check_request_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +class KillHouseWareHouseAcceptedKillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + request.data.pop('kill_house_request_key') + kill_house = kill_house_request.killhouse_user + bar_date = kill_house_request.kill_request.recive_date.date() + timedelta(days=1) + now = datetime.now().date() + product = RolesProducts.objects.filter(parent_product__product_id=2, kill_house=kill_house).first() + if not product: + return Response( + {"result": "جهت افزایش موجودی محصول ابتدا محصول را برای کشتارگاه ثبت کنید! "}, + status=status.HTTP_403_FORBIDDEN) + if kill_house_request.date_of_ware_house: + if now != datetime.strptime(kill_house_request.date_of_ware_house, '%Y-%m-%d %H:%M:%S.%f').date(): + return Response( + {"result": "بازه زمانی ویرایش این بار به اتمام رسیده ! "}, + status=status.HTTP_403_FORBIDDEN) + input_weight = request.data['ware_house_accepted_real_weight'] if request.data[ + 'input_type'] == 'input_weight' else int( + kill_house_request.accepted_real_weight - ( + (kill_house_request.accepted_real_weight * request.data['loss_percent']) / 100)) + if kill_house_request.ware_house_accepted_real_weight > input_weight: + diffrence = kill_house_request.ware_house_accepted_real_weight - input_weight + if product.total_remain_weight - diffrence < 0: + return Response( + {"result": "به علت منفی شدن موجودی انبار امکان ویرایش وجود ندارد! "}, + status=status.HTTP_403_FORBIDDEN) + + if request.data['input_type'] == 'input_weight': + kill_house_request.ware_house_accepted_real_quantity = request.data['ware_house_accepted_real_quantity'] + kill_house_request.ware_house_accepted_real_weight = request.data['ware_house_accepted_real_weight'] + kill_house_request.weight_loss = request.data['loss_percent'] + else: + # kill_house_request.ware_house_accepted_real_quantity = int(kill_house_request.accepted_real_quantity - ( + # (kill_house_request.accepted_real_quantity * request.data['loss_percent']) / 100)) + kill_house_request.ware_house_accepted_real_quantity = kill_house_request.accepted_real_quantity + kill_house_request.ware_house_accepted_real_weight = int(kill_house_request.accepted_real_weight - ( + (kill_house_request.accepted_real_weight * request.data['loss_percent']) / 100)) + kill_house_request.weight_loss = request.data['loss_percent'] + poultry_prediction(kill_house_request.province_request.poultry_request.poultry) + + kill_house_request.ware_house_input_type = request.data['input_type'] + kill_house_request.ware_house_confirmation = True + kill_house_request.date_of_ware_house = str(datetime.now()) + govermental_commitment_percent = kill_house.in_province_governmental_selling_percent + free_commitment_percent = kill_house.in_province_free_selling_percent + if kill_house_request.province_request.poultry_request.free_sale_in_province: + kill_house_request.warehouse_commitment_weight = int( + (free_commitment_percent / 100) * kill_house_request.ware_house_accepted_real_weight) + else: + kill_house_request.warehouse_commitment_weight = int( + (govermental_commitment_percent / 100) * kill_house_request.ware_house_accepted_real_weight) + if 'input_warehouse' in request.data.keys(): + if request.data['input_warehouse'] == 'self': + kill_house_request.input_warehouse = kill_house_request.killhouse_user + else: + kill_house_request.input_warehouse = kill_house_request.killer + product = RolesProducts.objects.filter(parent_product__product_id=2, + kill_house=kill_house_request.killer).first() + + else: + kill_house_request.input_warehouse = kill_house_request.killhouse_user + + kill_house_request.save() + kill_house_requests_product_warehousing(product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +# ویوست مربوط به ایجاد درخواست کشتار توسط کشتارگاه بعد از تخصیص +class KillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ایجاد درخواست کشتار توسط کشتارگاه بعد از تخصیص + def create(self, request, *args, **kwargs): + + limitation_direct_purchase = LimitationForDirectPurchaseAndBarInformation.objects.filter( + trash=False, active=True).first() + is_in_limitation_range = False + + if limitation_direct_purchase and limitation_direct_purchase.start_time and limitation_direct_purchase.end_time: + current_time = datetime.now().time() + if limitation_direct_purchase.start_time <= current_time <= limitation_direct_purchase.end_time: + is_in_limitation_range = True + + if not is_in_limitation_range: + time_range = TimeRange.objects.filter(trash=False).first() + if time_range: + time = next( + (t for t in time_range.time_range if + t.get("name") == "kill_house_request" and t.get("active", False)), + None) + if time: + start_hour = datetime.strptime(time.get("start", 0), "%H:%M:%S").time() + end_hour = datetime.strptime(time.get("end", 0), "%H:%M:%S").time() + current_hour = datetime.now().time().replace(second=0, microsecond=0) + if not (start_hour < current_hour < end_hour): + return Response( + {"result": "لطفا در ساعات مجاز برای ثبت درخواست اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + real_car = None + killer_for_kill_house = None + if 'real_car_key' in request.data.keys(): + real_car = KillHouseADDCAR.objects.get(key=request.data['real_car_key'], trash=False) + request.data.pop('real_car_key') + date_time_of_now = datetime.now().date() + tomorrow = datetime.now().date() + timedelta(days=1) + role = request.data['role'] + request.data.pop('role') + dict1 = {} + try: + kill_house_auction_winner_key = request.data['winner_key'] + + kill_house_auction_winner = KillHouseRequestActionWinner.objects.get(key=kill_house_auction_winner_key, + trash=False) + kill_house = kill_house_auction_winner.kill_house_request_auction.kill_house + request.data.pop('winner_key') + + except: + kill_house_auction_winner = None + + try: + kill_house_check_key = request.data['kill_house_check_key'] + + kill_house_check = KillHouseCheckRequest.objects.get(key=kill_house_check_key, trash=False) + kill_house = kill_house_check.province_kill_request.kill_request.kill_house + request.data.pop('kill_house_check_key') + + except: + kill_house_check = None + if kill_house_check != None: + kill_house = KillHouse.objects.get(id=kill_house_check.province_kill_request.kill_request.kill_house.id, + trash=False) + kill_req = KillRequest.objects.get(id=kill_house_check.province_kill_request.kill_request.id, trash=False) + if OperationLimitation.objects.all().first().kill_house_allocation_limitation == True: + + if date_time_of_now != kill_req.recive_date.date(): + # if date_time_of_now > kill_req.recive_date.date() + timedelta(days=1): + return Response({"result": "مغایرت در تاریخ اعلام نیاز کشتار گاه و تاریخ تخصیص به خودرو !"}, + status=status.HTTP_403_FORBIDDEN) + province_request = ProvinceCheckOperatorRequest.objects.get( + id=kill_house_check.province_kill_request.province_request.id, trash=False) + province_kill_request = ProvinceKillRequest.objects.get(id=kill_house_check.province_kill_request.id, + trash=False) + if province_kill_request.market: + if province_kill_request.first_car_allocated_quantity > 0: + if province_kill_request.total_killed_quantity + request.data[ + 'quantity'] > province_kill_request.main_quantity: + return Response( + {"result": "مجموع حجم ماشین های ایجاد شده بیشتر از تخصیص داده شده از پنل معاملات میباشد"}, + status=status.HTTP_403_FORBIDDEN) + else: + if request.data['quantity'] > province_kill_request.main_quantity: + return Response( + {"result": "مجموع حجم ماشین های ایجاد شده بیشتر از تخصیص داده شده از پنل معاملات میباشد"}, + status=status.HTTP_403_FORBIDDEN) + poultry_request = PoultryRequest.objects.get(key=province_request.poultry_request.key) + poultry_hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + + user = province_request.city_request_Poultry.poultry_request.poultry.user + if province_kill_request.quantity == 0: + return Response({"result": "quantity is 0"}, status=status.HTTP_403_FORBIDDEN) + elif kill_house_auction_winner != None: + user = kill_house_auction_winner.kill_house_request_auction.poultry_request.poultry.user + kill_house = KillHouse.objects.get(id=kill_house_auction_winner.kill_house_request_auction.kill_house.id, + trash=False) + if 'killer_key' in request.data.keys(): + if request.data['killer_key'] != None: + killer_for_kill_house = KillHouse.objects.get(key=request.data['killer_key'], trash=False) + if kill_house.id != killer_for_kill_house.id: + kill_house_purchase = KillHousePurchaseRequest.objects.filter(limitation=True, + kill_house=killer_for_kill_house).first() + if kill_house_purchase: + total_unpaid_wage = 0 + total_paid_wage = 0 + + total_unpaid_wage = get_finance_info(killer_for_kill_house)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=killer_for_kill_house, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_amount = total_unpaid_wage - total_paid_wage + if total_amount >= kill_house_purchase.limitation_number: + return Response( + { + "result": "به علت بدهی کشتارکن اختصاصی امکان ایجاد بار برای کشتار کن امکان پذیر نیست!"}, + status=status.HTTP_403_FORBIDDEN) + request.data.pop('killer_key') + + car = request.data['car'] + add_car = KillHouseADDCAR.objects.get(key=car['key'], trash=False) + request.data.pop('car') + if request.data['quantity'] > (poultry_hatching.left_over + province_kill_request.main_quantity + ( + (poultry_hatching.quantity * 5) / 100)): + return Response({"result": "تعداد قطعه وارد شده بیشتراز مانده در سالن مرغدار است!"}, + status=status.HTTP_403_FORBIDDEN) + if kill_house.max_kill_limit and kill_house.total_kill_capacity > 0: + extra_bar_kill_percent = (kill_house.extra_bar_kill_percent / 100) * kill_house.total_kill_capacity + + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + killhouse_user=kill_house, + first_car_allocated_quantity=0, + kill_request__recive_date__date=kill_req.recive_date.date()).exclude( + id=kill_house_check.province_kill_request.id) + + total_province_kill_requests_quantity_with_out_bar = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + + total_kill_house_requests = KillHouseRequest.objects.filter(trash=False, + archive_wage=False, + killhouse_user=kill_house, + kill_request__recive_date__date=kill_req.recive_date.date()) + total_kill_house_requests_quantity = \ + total_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + if ( + kill_house.total_kill_capacity + extra_bar_kill_percent) < total_kill_house_requests_quantity + \ + request.data['quantity'] + total_province_kill_requests_quantity_with_out_bar: + return Response({"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_request = serializer.create(validated_data=request.data) + kill_house_request.accepted_real_quantity = int(kill_house_request.quantity) + kill_house_request.accepted_real_weight = float( + kill_house_request.quantity) * kill_house_check.province_kill_request.province_request.poultry_request.Index_weight + if kill_house_check != None: + bar_code = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request__poultry__user=user, trash=False) + + else: + bar_code = KillHouseRequest.objects.filter( + kill_house_request_auction_winner__kill_house_request_auction__poultry_request__poultry__user=user, + trash=False) + if bar_code.count() > 0: + bar_code = bar_code.order_by( + 'create_date') + if bar_code.last().bar_code != None: + kill_house_request.bar_code = bar_code.last().bar_code + 1 + + else: + if kill_house_check != None: + kill_house_request.bar_code = int( + str(province_request.city_request_Poultry.poultry_request.order_code) + '0001') + else: + kill_house_request.bar_code = int( + str(kill_house_auction_winner.kill_house_request_auction.poultry_request.order_code) + '0001') + + if kill_house_check != None: + kill_house_request.kill_request = kill_req + kill_house_request.province_request = province_request + kill_house_request.fee = kill_house_check.province_kill_request.fee + kill_house_request.province_kill_request = province_kill_request + kill_house_request.amount = province_kill_request.kill_house_price + if kill_house_check.state == 'accepted': + kill_house_request.state = "accepted" + kill_house_request.save() + + else: + + kill_house_request.kill_house_request_auction_winner = kill_house_auction_winner + kill_house_request.state = "accepted" + kill_house_request.fee = kill_house_auction_winner.fee + kill_house_request.auction = True + kill_house_auction_winner.quantity -= int(kill_house_request.quantity) + kill_house_auction_winner.save() + kill_house_request.role = { + 'role': role, + 'name': user.fullname, + 'mobile': user.mobile + } + kill_house_request.save() + + kill_house_request.car = car + kill_house_request.add_car = add_car + if real_car != None: + kill_house_request.real_add_car = real_car + if killer_for_kill_house != None: + kill_house_request.killer = killer_for_kill_house + kill_house_request.killhouse_user = kill_house + kill_house_request.show_kill_house = "accepted" + kill_house_request.save() + province_kill_request.first_car_allocated_quantity += kill_house_request.quantity + province_kill_request.save() + + kill_house_request_serializer = self.serializer_class(kill_house_request) + + ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, date__date=tomorrow).first() + if not ware_house: + ware_house = KillHouseWareHouse( + kill_house=kill_house, + date=tomorrow + ) + ware_house.save() + + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(poultry_hatching) + poultry_prediction(poultry_hatching.poultry) + vet_farm = VetFarm.objects.filter(trash=False, + poultry=kill_house_request.province_request.poultry_request.poultry).first() + if vet_farm: + car_allocation_vet_farm_sms(kill_house_request.kill_request.recive_date.date(), + kill_house_request.province_request.poultry_request.poultry.user.fullname, + kill_house_request.province_request.poultry_request.hatching.chicken_age, + kill_house_request.quantity, kill_house_request.add_car.driver.type_car, + kill_house_request.traffic_code, + kill_house_request.add_car.driver.pelak, + kill_house_request.kill_request.kill_house.name, + vet_farm.vet.user.mobile, + kill_house_request.province_request.poultry_request.amount, + kill_house_request.province_request.poultry_request.free_sale_in_province) + + if kill_house_check != None: + + dict1 = { + "kill_house_req_key": str(kill_house_request.key), + "kill_req_key": kill_house_request.kill_request.key, + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_request.kill_house.name, + "kill_house_user_name": kill_house_request.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": kill_house_request.kill_request.kill_house.system_address.city.name, + "kill_house_mobile": kill_house_request.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_request.quantity, + "time": kill_house_request.kill_request.recive_time, + "date": kill_house_request.kill_request.recive_date, + "car": kill_house_request.car, + } + elif kill_house_auction_winner != None: + + dict1 = { + "kill_house_req_key": str(kill_house_request.key), + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_user_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.system_address.city.name, + "kill_house_mobile": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_request.quantity, + "date": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date, + "car": kill_house_request.car, + } + + # ارسال بار به ایتای دامپزشک (فقط برای همدان و در ساعات 16 تا 23:59) + if base_url_for_sms_report == 'ha': + current_hour = datetime.now().hour + if 16 <= current_hour <= 23: + try: + send_single_bar_to_eitaa(kill_house_request) + except Exception as e: + pass + + return Response(dict1, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + # تابع مربوط به نمایش درخواست کشتار های ایجاد شده توسط کشتارگاه بعد از تخصیص + def list(self, request, *args, **kwargs): + from django.db.models import Q + info_dict = [] + info_list = [] + # refresh(request.user.id) + + if request.GET['operator'] == 'ProvinceOperator': + queryset = KillHouseRequest.objects.filter(trash=False).order_by('create_date') + serializer = KillHouseRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif request.GET['operator'] == 'VetSupervisor': + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + querysets_list = KillHouseRequest.objects.filter( + vet_state__in=('pending', 'accepted'), + active_state__in=('active', 'inactive'), trash=False).order_by( + 'create_date') + queryset = [ + queryset_list for queryset_list in querysets_list + if date1 <= queryset_list.province_request.poultry_request.send_date.date() <= date2 + ] + if len(queryset) > 0: + info_list = [] + + for kill_house_req_obj in queryset: + kill_place = kill_house_req_obj.kill_request.kill_house.name if not kill_house_req_obj.kill_request.slaughter_house else kill_house_req_obj.kill_request.slaughter_house.name + real_car = None + if kill_house_req_obj.real_add_car != None: + real_car = { + "real_driver_name": kill_house_req_obj.real_add_car.driver.driver_name, + "real_driver_mobile": kill_house_req_obj.real_add_car.driver.driver_mobile, + "real_pelak": kill_house_req_obj.real_add_car.driver.pelak, + "real_type_car": kill_house_req_obj.real_add_car.driver.type_car + } + exclusive_killer = None + if kill_house_req_obj.killer != None: + exclusive_killer = { + "killer_name": kill_house_req_obj.killer.name, + "killer_mobile": kill_house_req_obj.killer.kill_house_operator.user.mobile, + "killer_fullname": kill_house_req_obj.killer.kill_house_operator.user.fullname, + } + vet_check_date = None + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_req_obj).first() + if vet_check: + vet_check_date = vet_check.create_date + if kill_house_req_obj.province_kill_request != None: + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.id, + "poultry_request_key": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.key, + "chicken_breed": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.chicken_breed, + "index_weight": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.Index_weight, + "amount": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.amount, + "bar_amount": kill_house_req_obj.amount, + "poultry_name": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "send_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.send_date, + "create_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.create_date, + "poultry_request_quantity": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.quantity, + "poultry_city": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + "poultry_province": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "barcod": kill_house_req_obj.bar_code, + "order_code": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.order_code, + "freezing": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.freezing, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "accepted_real_quantity": kill_house_req_obj.accepted_real_quantity, + "accepted_real_weight": kill_house_req_obj.accepted_real_weight, + "kill_house_request_key": kill_house_req_obj.key, + "clearance_code": kill_house_req_obj.clearance_code, + "vet_state": kill_house_req_obj.vet_state, + "traffic_code": kill_house_req_obj.traffic_code, + "driver_name": kill_house_req_obj.add_car.driver.driver_name, + "driver_mobile": kill_house_req_obj.add_car.driver.driver_mobile, + "pelak": kill_house_req_obj.add_car.driver.pelak, + "car_key": kill_house_req_obj.add_car.key, + "type_car": kill_house_req_obj.add_car.driver.type_car, + "real_car": real_car, + "killer": exclusive_killer, + "age": ( + datetime.now() - kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.hatching.date).days + 1, + + "vet_check_date": vet_check_date, + "first_weight": kill_house_req_obj.quantity * kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight, + "kill_place": kill_place, + "auction": "False" + } + elif kill_house_req_obj.kill_house_request_auction_winner != None: + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.id, + "poultry_request_key": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.key, + "poultry_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.fullname, + "mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.mobile, + "city": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.city.name, + "province": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.province.name, + "send_date": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date, + "freezing": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.freezing, + "create_date": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.create_date, + "poultry_quantity": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.quantity, + "barcod": kill_house_req_obj.bar_code, + "kill_house_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "kill_house_request_key": kill_house_req_obj.key, + "auction": "True" + + } + + info_list.append(internal_dict_infos) + # info_dict.append(info_list) + return Response(info_list, status=status.HTTP_200_OK) + + elif request.GET['operator'] == 'KillHouseVet': + user = SystemUserProfile.objects.get(user=request.user, trash=False) + # vet = Vet.objects.get(user=user, trash=False) + kill_house_vet = KillHouseVet.objects.filter(vet__user=user, trash=False) + kill_house_list = kill_house_vet.values_list('kill_house', flat=True).distinct() + # for kill_house in kill_house_vet: + # kill_house_list.append(kill_house.kill_house) + + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + queryset = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_house_list) | Q( + kill_request__slaughter_house__in=kill_house_list), + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, + vet_state__in=('pending', 'accepted'), + active_state__in=('active', 'inactive'), trash=False).order_by( + 'create_date') + # queryset = [ + # queryset_list for queryset_list in querysets_list + # if date1 <= queryset_list.province_request.poultry_request.send_date.date() <= date2 + # ] + if len(queryset) > 0: + info_dict = [] + info_list = [] + + for kill_house_req_obj in queryset: + kill_place = kill_house_req_obj.kill_request.kill_house.name if not kill_house_req_obj.kill_request.slaughter_house else kill_house_req_obj.kill_request.slaughter_house.name + vet_check_date = None + real_car = None + if kill_house_req_obj.real_add_car != None: + real_car = { + "real_driver_name": kill_house_req_obj.real_add_car.driver.driver_name, + "real_driver_mobile": kill_house_req_obj.real_add_car.driver.driver_mobile, + "real_pelak": kill_house_req_obj.real_add_car.driver.pelak, + "real_type_car": kill_house_req_obj.real_add_car.driver.type_car + } + exclusive_killer = None + if kill_house_req_obj.killer != None: + exclusive_killer = { + "killer_name": kill_house_req_obj.killer.name, + "killer_mobile": kill_house_req_obj.killer.kill_house_operator.user.mobile, + "killer_fullname": kill_house_req_obj.killer.kill_house_operator.user.fullname, + } + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_req_obj).first() + if vet_check: + vet_check_date = vet_check.create_date + if kill_house_req_obj.province_kill_request != None: + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.id, + "poultry_request_key": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.key, + "chicken_breed": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.chicken_breed, + "index_weight": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.Index_weight, + "amount": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.amount, + "bar_amount": kill_house_req_obj.amount, + "poultry_name": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "send_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.send_date, + "freezing": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.freezing, + "create_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.create_date, + "poultry_request_quantity": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.quantity, + "poultry_city": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + "poultry_province": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "barcod": kill_house_req_obj.bar_code, + "order_code": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.order_code, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "accepted_real_quantity": kill_house_req_obj.accepted_real_quantity, + "accepted_real_weight": kill_house_req_obj.accepted_real_weight, + "kill_house_request_key": kill_house_req_obj.key, + "clearance_code": kill_house_req_obj.clearance_code, + "vet_state": kill_house_req_obj.vet_state, + "traffic_code": kill_house_req_obj.traffic_code, + "driver_name": kill_house_req_obj.add_car.driver.driver_name, + "driver_mobile": kill_house_req_obj.add_car.driver.driver_mobile, + "pelak": kill_house_req_obj.add_car.driver.pelak, + "car_key": kill_house_req_obj.add_car.key, + "type_car": kill_house_req_obj.add_car.driver.type_car, + "real_car": real_car, + "killer": exclusive_killer, + "first_weight": kill_house_req_obj.quantity * kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight, + "age": ( + datetime.now() - kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.hatching.date).days + 1, + + "vet_check_date": vet_check_date, + "kill_place": kill_place, + "auction": "False" + } + elif kill_house_req_obj.kill_house_request_auction_winner != None: + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.id, + "poultry_request_key": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.key, + "poultry_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.fullname, + "mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.mobile, + "city": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.city.name, + "province": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.province.name, + "send_date": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date, + "freezing": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.freezing, + "create_date": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.create_date, + "poultry_quantity": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.quantity, + "barcod": kill_house_req_obj.bar_code, + "kill_house_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "kill_house_request_key": kill_house_req_obj.key, + "auction": "True" + + } + + info_list.append(internal_dict_infos) + # info_dict.append(info_list) + return Response(info_list, status=status.HTTP_200_OK) + + elif request.GET['operator'] == 'KillHouse': + # info_dict = [] + info_list = [] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + if 'role' in request.GET: + if request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.filter(user=user, trash=False) + if vet.count() > 0: + kill_house_list = [] + vet = vet.last() + kill_house_vet = KillHouseVet.objects.filter(vet=vet, trash=False) + for k_vet in kill_house_vet: + kill_house_list.append(k_vet.kill_house) + # kill_house = KillHouse.objects.filter(key=kill_house_vet.kill_house.key, trash=False) + kill_house_allow_vet = KillHouseAllowVet.objects.filter(kill_house__in=kill_house_list) + + if kill_house_allow_vet.count() > 0: + + kill_house_allow_vet = kill_house_allow_vet.last() + if vet != None and kill_house_allow_vet.allow == False: + return Response(info_list) + + kill_requests_list = KillHouseRequest.objects.filter((Q(killhouse_user__in=kill_house_list) | Q( + kill_request__slaughter_house__in=kill_house_list)), + active_state__in=('active', 'inactive'), + trash=False) + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + kill_requests = [ + kill_request_list for kill_request_list in kill_requests_list + if date1 <= kill_request_list.kill_request.recive_date.date() <= date2 + ] + for kill_house_req_obj in kill_requests: + vet_check_date = None + real_car = None + if kill_house_req_obj.real_add_car != None: + real_car = { + "real_driver_name": kill_house_req_obj.real_add_car.driver.driver_name, + "real_driver_mobile": kill_house_req_obj.real_add_car.driver.driver_mobile, + "real_pelak": kill_house_req_obj.real_add_car.driver.pelak, + "real_type_car": kill_house_req_obj.real_add_car.driver.type_car + } + exclusive_killer = None + if kill_house_req_obj.killer != None: + exclusive_killer = { + "killer_name": kill_house_req_obj.killer.name, + "killer_mobile": kill_house_req_obj.killer.kill_house_operator.user.mobile, + "killer_fullname": kill_house_req_obj.killer.kill_house_operator.user.fullname, + } + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_req_obj).first() + if vet_check: + vet_check_date = vet_check.create_date + if kill_house_req_obj.province_kill_request != None: + check = KillHouseCheckRequest.objects.get( + province_kill_request=kill_house_req_obj.province_kill_request) + bar_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_req_obj) + if bar_info.count() > 0: + bar_info = bar_info.last() + assignment_info = { + "kill_house_assignment_key": bar_info.key, + "kill_house_weight_without_load": bar_info.car_weight_without_load, + "kill_house_weight_with_load": bar_info.car_weight_with_load, + "kill_house_image_without_load": bar_info.car_weight_without_load_image, + "kill_house_image_with_load": bar_info.car_weight_with_load_image, + "kill_house_net_weight": bar_info.net_weight, + "driver_name": bar_info.kill_house_request.add_car.driver.driver_name, + "pelak": bar_info.kill_house_request.add_car.driver.pelak, + "type_car": bar_info.kill_house_request.add_car.driver.type_car, + "kill_house_assignment_state": bar_info.state, + "real_quantity": bar_info.real_quantity, + + } + else: + assignment_info = None + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.id, + "poultry_request_key": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.key, + "amount": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.amount, + "bar_amount": kill_house_req_obj.amount, + "poultry_name": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "send_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.send_date, + "freezing": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.freezing, + "create_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.create_date, + "poultry_request_quantity": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.quantity, + "poultry_city": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + "poultry_province": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "barcod": kill_house_req_obj.bar_code, + "order_code": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.order_code, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "kill_house_request_key": kill_house_req_obj.key, + "vet_state": kill_house_req_obj.vet_state, + "traffic_code": kill_house_req_obj.traffic_code, + "driver_name": kill_house_req_obj.add_car.driver.driver_name, + "driver_mobile": kill_house_req_obj.add_car.driver.driver_mobile, + "pelak": kill_house_req_obj.add_car.driver.pelak, + "car_key": kill_house_req_obj.add_car.key, + "type_car": kill_house_req_obj.add_car.driver.type_car, + "real_car": real_car, + "killer": exclusive_killer, + "kill_house_check_key": check.key, + "bar_info": assignment_info, + "auction": "False", + "kill_house_create_date": kill_house_req_obj.create_date, + "accepted_real_quantity": kill_house_req_obj.accepted_real_quantity, + "accepted_real_weight": kill_house_req_obj.accepted_real_weight, + "vet_check_date": vet_check_date, + "first_weight": kill_house_req_obj.quantity * kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight, + + "age": ( + datetime.now() - kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.hatching.date).days + 1, + + } + + elif kill_house_req_obj.kill_house_request_auction_winner != None: + + internal_dict_infos = { + "poultry_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.mobile, + "barcod": kill_house_req_obj.bar_code, + "kill_house_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "kill_house_request_key": kill_house_req_obj.key + } + + info_list.append(internal_dict_infos) + # info_dict.append(info_list) + return Response(info_list, status=status.HTTP_200_OK) + + else: + # kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + kill_request_car = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + active_state__in=('active', 'inactive'), + assignment_state_archive='pending', + trash=False).select_related('province_request__city_request_Poultry__poultry_request', + 'real_add_car__driver', 'killer', + 'kill_request__kill_house__kill_house_operator') + + # kill_request_car = [ + # kill_request for kill_request in kill_requests + # if date1 <= kill_request.kill_request.recive_date.date() <= date2 + # ] + for kill_house_req_obj in kill_request_car: + vet_check_date = None + real_car = None + if kill_house_req_obj.real_add_car != None: + real_car = { + "real_driver_name": kill_house_req_obj.real_add_car.driver.driver_name, + "real_driver_mobile": kill_house_req_obj.real_add_car.driver.driver_mobile, + "real_pelak": kill_house_req_obj.real_add_car.driver.pelak, + "real_type_car": kill_house_req_obj.real_add_car.driver.type_car + } + exclusive_killer = None + if kill_house_req_obj.killer != None: + exclusive_killer = { + "killer_name": kill_house_req_obj.killer.name, + "killer_mobile": kill_house_req_obj.killer.kill_house_operator.user.mobile, + "killer_fullname": kill_house_req_obj.killer.kill_house_operator.user.fullname, + } + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_req_obj).first() + if vet_check: + vet_check_date = vet_check.create_date + if kill_house_req_obj.province_kill_request != None: + check = KillHouseCheckRequest.objects.get( + province_kill_request=kill_house_req_obj.province_kill_request) + bar_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_req_obj) + if bar_info.count() > 0: + bar_info = bar_info.last() + assignment_info = { + "kill_house_assignment_key": bar_info.key, + "kill_house_weight_without_load": bar_info.car_weight_without_load, + "kill_house_weight_with_load": bar_info.car_weight_with_load, + "kill_house_image_without_load": bar_info.car_weight_without_load_image, + "kill_house_image_with_load": bar_info.car_weight_with_load_image, + "kill_house_net_weight": bar_info.net_weight, + "driver_name": bar_info.kill_house_request.add_car.driver.driver_name, + "pelak": bar_info.kill_house_request.add_car.driver.pelak, + "type_car": bar_info.kill_house_request.add_car.driver.type_car, + "kill_house_assignment_state": bar_info.state, + "real_quantity": bar_info.real_quantity, + + } + else: + assignment_info = None + + internal_dict_infos = { + "poultry_request_id": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.id, + "poultry_request_key": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.key, + "amount": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.amount, + "bar_amount": kill_house_req_obj.amount, + "poultry_name": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "send_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.send_date, + "freezing": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.freezing, + "create_date": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.create_date, + "poultry_request_quantity": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.quantity, + "poultry_city": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + "poultry_province": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "barcod": kill_house_req_obj.bar_code, + "order_code": kill_house_req_obj.province_request.city_request_Poultry.poultry_request.order_code, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "kill_house_request_key": kill_house_req_obj.key, + "vet_state": kill_house_req_obj.vet_state, + "traffic_code": kill_house_req_obj.traffic_code, + "driver_name": kill_house_req_obj.add_car.driver.driver_name, + "driver_mobile": kill_house_req_obj.add_car.driver.driver_mobile, + "pelak": kill_house_req_obj.add_car.driver.pelak, + "car_key": kill_house_req_obj.add_car.key, + "type_car": kill_house_req_obj.add_car.driver.type_car, + "real_car": real_car, + "killer": exclusive_killer, + "kill_house_check_key": check.key, + "free_sale_in_province": kill_house_req_obj.province_request.poultry_request.free_sale_in_province, + "bar_info": assignment_info, + "age": ( + datetime.now() - kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.hatching.date).days + 1, + + "auction": "False", + "kill_house_create_date": kill_house_req_obj.create_date, + "accepted_real_quantity": kill_house_req_obj.accepted_real_quantity, + "accepted_real_weight": kill_house_req_obj.accepted_real_weight, + "vet_check_date": vet_check_date, + "first_weight": kill_house_req_obj.quantity * kill_house_req_obj.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight, + + } + + elif kill_house_req_obj.kill_house_request_auction_winner != None: + + internal_dict_infos = { + "poultry_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.fullname, + "poultry_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.poultry.user.mobile, + "barcod": kill_house_req_obj.bar_code, + "kill_house_name": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": kill_house_req_obj.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "kill_house_request_key": kill_house_req_obj.key + } + + info_list.append(internal_dict_infos) + # info_dict.append(info_list) + return Response(info_list, status=status.HTTP_200_OK) + + # تابع مربوط به ویرایش درخواست کشتار های ایجاد شده توسط کشتارگاه بعد از تخصیص + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_request = KillHouseRequest.objects.get(key=request.data['key'], trash=False) + + if 'traffic_code' in request.data.keys(): + if kill_house_request.clearance_code: + return Response( + {"result": "به علت وارد شدن کد قرنطینه، امکان ویرایش وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN + ) + + bar_date = kill_house_request.kill_request.recive_date.date() + if now != bar_date: + return Response( + {"result": "فقط بار همان روز قابل ویرایش است!"}, + status=status.HTTP_403_FORBIDDEN + ) + + if 'non_receipt' not in request.data.keys(): + if 'bar_document_status_key' in request.data.keys() and request.data['bar_document_status_key'] != None: + document_status = BarDocumentStatus.objects.get(key=request.data['bar_document_status_key']) + kill_house_request.bar_document_status = document_status + kill_house_request.save() + request.data.pop('bar_document_status_key') + + if 'quarantine_quantity' not in request.data.keys(): + role = request.data['role'] + if role == 'KillHouse' and now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1) \ + and 'traffic_code' in request.data.keys(): + return Response( + {"result": "تنها یک روز بعد از ثبت اطلاعات امکان تغییر وجود دارد!"}, + status=status.HTTP_403_FORBIDDEN) + request.data.pop('role') + kill_house_request.editor_traffic_code = { + "role": role, + "full_name": user.first_name, + "mobile": user.mobile + } + kill_house_request.save() + + # kill_house_request.assignment_state_archive = 'accepted' + # kill_house_request.save() + serializer = self.serializer_class(kill_house_request) + serializer.update(instance=kill_house_request, validated_data=request.data) + if kill_house_request.bar_document_status is not None and kill_house_request.bar_document_status.sms == True: + document_discrepancy_sms(kill_house_request.killhouse_user.killer, kill_house_request.killhouse_user.name, + kill_house_request.bar_code, kill_house_request.bar_document_status.title, + kill_house_request.killhouse_user.kill_house_operator.user.mobile, + kill_house_request.kill_request.recive_date.date()) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به حذف درخواست کشتار های ایجاد شده توسط کشتارگاه بعد از تخصیص + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + tomorrow = datetime.now().date() + timedelta(days=1) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'delete_bar' in request.GET: + + kill_house_req = KillHouseRequest.objects.get(key=request.GET['kill_house_request_key'], trash=False) + + if KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_req, trash=False).exists(): + return Response({"result": "به علت ورود اطلاعات بار امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + # if kill_house_req.vet_state == 'accepted' or kill_house_req.assignment_state_archive == 'True': + # return Response({"result": "به علت تایید تخلیه توسط دامپزشک امکان حذف وجود ندارد!"}, + # status=status.HTTP_403_FORBIDDEN) + province_kill_req = ProvinceKillRequest.objects.get(key=kill_house_req.province_kill_request.key, + trash=False) + kill_house_req.trash = True + kill_house_req.save() + province_kill_req.first_car_allocated_quantity -= kill_house_req.quantity + if province_kill_req.first_car_allocated_quantity < 0: + province_kill_req.first_car_allocated_quantity = 0 + province_kill_req.save() + # kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_req, + # trash=False) + + poultry_request = PoultryRequest.objects.get(key=province_kill_req.province_request.poultry_request.key, + trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + update_kill_house_requests(province_kill_req, poultry_request) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + + + else: + kill_house_req = KillHouseRequest.objects.get(key=request.GET['kill_house_request_key'], trash=False) + if KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_req, trash=False).exists(): + return Response({"result": "به علت ورود اطلاعات بار امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if kill_house_req.vet_state == 'accepted' or kill_house_req.clearance_code != None: + return Response({"result": "به علت وارد شدن کد قرنطینه امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + kill_house_req.trash = True + kill_house_req.save() + + if kill_house_req.kill_house_request_auction_winner != None: + kill_house_request_auction_winner = KillHouseRequestActionWinner.objects.get( + key=kill_house_req.kill_house_request_auction_winner.key) + kill_house_request_auction_winner.quantity += kill_house_req.quantity + kill_house_request_auction_winner.save() + else: + province_kill_request = ProvinceKillRequest.objects.get(key=kill_house_req.province_kill_request.key, + trash=False) + province_kill_request.first_car_allocated_quantity -= kill_house_req.quantity + if province_kill_request.first_car_allocated_quantity < 0: + province_kill_request.first_car_allocated_quantity = 0 + province_kill_request.save() + # kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_request, + # trash=False) + poultry_request = PoultryRequest.objects.get( + key=province_kill_request.province_request.poultry_request.key, + trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + vet_farm = VetFarm.objects.filter(trash=False, + poultry=kill_house_req.province_request.poultry_request.poultry).first() + delete_car_allocation_vet_farm_sms(kill_house_req.kill_request.recive_date.date(), + kill_house_req.province_request.poultry_request.poultry.user.fullname, + kill_house_req.province_request.poultry_request.hatching.chicken_age, + kill_house_req.quantity, kill_house_req.add_car.driver.type_car, + kill_house_req.traffic_code, + kill_house_req.add_car.driver.pelak, + kill_house_req.kill_request.kill_house.name, + vet_farm.vet.user.mobile, + kill_house_req.province_request.poultry_request.amount, + kill_house_req.province_request.poultry_request.free_sale_in_province + ) + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + + kill_house_req.trash = True + if 'message' in request.GET: + message = request.GET['message'] + else: + message = 'حذف توسط کشتارگاه' + + kill_house_req.message = message + role = request.GET['role'] if 'role' in request.GET else 'KillHouse' + now = datetime.now() + kill_house_req.bar_remover = { + "full_name": user.fullname, + "role": role, + "mobile": user.mobile, + "date": str(now) + } + kill_house_req.save() + + ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house_req.killhouse_user, + date__date=tomorrow).first() + if ware_house: + ware_house.final_total_number_of_carcasses -= kill_house_req.accepted_real_quantity + ware_house.final_total_weight_of_carcasses -= kill_house_req.accepted_real_weight + ware_house.total_number_of_carcasses -= kill_house_req.accepted_real_quantity + ware_house.total_weight_of_carcasses -= kill_house_req.accepted_real_weight + ware_house.remain_total_number_of_carcasses -= kill_house_req.accepted_real_quantity + ware_house.remain_total_weight_of_carcasses -= kill_house_req.accepted_real_weight + ware_house.bar_quantity -= 1 + # ware_house.allocated_quantity -= kill_house_req.accepted_real_quantity + ware_house.bar_live_weight -= kill_house_req.accepted_real_weight + ware_house.number_of_carcasses -= kill_house_req.accepted_real_quantity + ware_house.save() + return Response("object deleted", status=status.HTTP_200_OK) + + +class UpdateKillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + kill_house_request = KillHouseRequest.objects.get(key=request.data['key'], trash=False) + if 'traffic_code' in request.data.keys() or 'car_key' in request.data.keys(): + if kill_house_request.clearance_code: + return Response( + {"result": "به علت وارد شدن کد قرنطینه، امکان ویرایش وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN + ) + + bar_date = kill_house_request.kill_request.recive_date.date() + if now != bar_date: + return Response( + {"result": "فقط بار همان روز قابل ویرایش است!"}, + status=status.HTTP_403_FORBIDDEN + ) + if 'car_key' in request.data.keys(): + add_car = KillHouseADDCAR.objects.get(key=request.data['car_key'], trash=False) + kill_house_request.add_car = add_car + kill_house_request.car = { + "id": add_car.id, + "key": str(add_car.key), + "pelak": add_car.driver.pelak, + "capocity": add_car.driver.capocity, + "type_car": add_car.driver.type_car, + "driver_name": add_car.driver.driver_name, + "driver_mobile": add_car.driver.driver_mobile, + "weight_without_load": add_car.driver.weight_without_load, + } + kill_house_request.save() + request.data.pop('car_key') + + serializer = self.serializer_class(kill_house_request) + serializer.update(instance=kill_house_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseRequestPricingViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + now = datetime.now() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_request = KillHouseRequest.objects.get(key=request.data['key'], trash=False) + role = request.data.get('role') + image = request.FILES.get('file') + if image: + file_url = upload_to_liara(image, image.name) + kill_house_request.image = file_url + if kill_house_request.price_registerar: + kill_house_request.price_editor = user.fullname + kill_house_request.price_editor_role = role + kill_house_request.price_editor_date = now + else: + kill_house_request.price_registerar = user.fullname + kill_house_request.price_registerar_role = role + kill_house_request.price_register_date = now + kill_house_request.save() + serializer = self.serializer_class(kill_house_request) + serializer.update(instance=kill_house_request, validated_data=request.data) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class KillHouseRequestForCompleteInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + # تابع مربوط به نمایش درخواست کشتار های ایجاد شده توسط کشتارگاه بعد از تخصیص + def list(self, request, *args, **kwargs): + kill_house_request_list = [] + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + if request.GET['role'] == 'KillHouseVet': + kill_house_vet = KillHouseVet.objects.filter(vet__user=user, trash=False) + kill_house_list = kill_house_vet.values_list('kill_house', flat=True).distinct() + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_house_list) | Q( + kill_request__slaughter_house__in=kill_house_list), kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False).order_by( + 'create_date') + + else: + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_request_list = ps.filter() + kill_house_requests = [] if len(kill_house_request_list) == 0 else kill_house_request_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseRequestStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = KillHouseRequestSerializer + + def list(self, request, *args, **kwargs): + + now = timezone.now().date() + ten_days_ago = now - timedelta(days=int(request.GET['day'])) + + kill_house_requests_list = [] + + for day in range(int(request.GET['day']) + 1): + date = ten_days_ago + timedelta(days=day) + + total_quantites = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date, + trash=False + ).aggregate(total_quantity=Sum('quantity'))['total_quantity'] or 0 + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + total_quantity = total_quantites.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + total_quantity = total_quantites.filter( + province_request__poultry_request__poultry__address__city=user.city) + else: + total_quantity = total_quantites + else: + total_quantity = total_quantites + + kill_house_requests_list.append({"date": str(date), "quantity": total_quantity}) + + return Response(kill_house_requests_list) + + +class KillHouseRequestWeightStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = KillHouseRequestSerializer + + def list(self, request, *args, **kwargs): + + now = timezone.now().date() + ten_days_ago = now - timedelta(days=int(request.GET['day'])) + + kill_house_requests_list = [] + + for day in range(int(request.GET['day']) + 1): + date = ten_days_ago + timedelta(days=day) + total_weight = 0 + kill_house_requestes = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date, + trash=False + ) + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + kill_house_requests = kill_house_requestes.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + kill_house_requests = kill_house_requestes.filter( + province_request__poultry_request__poultry__address__city=user.city) + else: + kill_house_requests = kill_house_requestes + else: + kill_house_requests = kill_house_requestes + if kill_house_requests: + for kill_house_request in kill_house_requests: + kill_house_request_information = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request).last() + if kill_house_request_information: + total_weight += kill_house_request_information.net_weight + else: + total_weight += kill_house_request.province_request.poultry_request.Index_weight * kill_house_request.quantity + + kill_house_requests_list.append({"date": str(date), "weight": total_weight}) + + return Response(kill_house_requests_list) + + +class KillHouseRequestChangeStateViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + keys = request.data['keys'] + request.data.pop('keys') + for key in keys: + kill_house_request = KillHouseRequest.objects.get(key=key, trash=False) + kill_house_request.show_kill_house = 'accepted' + kill_house_request.save() + return Response("objects updated", status=status.HTTP_200_OK) + + +class KillHouseAssignmentImagesViewSet(viewsets.ModelViewSet): + queryset = KillHouseAssignmentImages.objects.all() + serializer_class = KillHouseAssignmentImagesSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به وارد کردن اطلاعات بار توسط کشتارگاه + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + role = request.data['role'] + request.data.pop('role') + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + + try: + health_certificate_image = request.data['health_certificate_img'] + request.data.pop('health_certificate_img') + + except: + health_certificate_image = None + try: + national_card_image = request.data['national_card_image'] + except: + national_card_image = None + try: + birth_certificate_image = request.data['birth_certificate_image'] + except: + birth_certificate_image = None + try: + police_clearance_image = request.data['police_clearance_image'] + except: + police_clearance_image = None + try: + no_addiction_image = request.data['no_addiction_image'] + except: + no_addiction_image = None + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_images = KillHouseAssignmentImages.objects.filter(kill_house=kill_house) + if kill_house_images.count() > 0: + kill_house_images = kill_house_images.last() + else: + kill_house_images = serializer.create(validated_data=request.data) + if health_certificate_image != None: + kill_house_images.health_certificate_image = send_image_to_server(health_certificate_image) + if national_card_image != None: + kill_house_images.national_card_image = send_image_to_server(national_card_image) + if birth_certificate_image != None: + kill_house_images.birth_certificate_image = send_image_to_server(birth_certificate_image) + if police_clearance_image != None: + kill_house_images.police_clearance_image = send_image_to_server(police_clearance_image) + if no_addiction_image != None: + kill_house_images.no_addiction_image = send_image_to_server(no_addiction_image) + kill_house_images.save() + + kill_house_images_serializer = self.serializer_class(kill_house_images) + return Response(kill_house_images_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +class KillHouseAssignmentInformationForAggregateLoadViewSet(viewsets.ModelViewSet): + queryset = KillHouseAssignmentInformation.objects.all() + serializer_class = KillHouseAssignmentInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user) + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + province_kill_request = ProvinceKillRequest.objects.get(key=kill_house_request.province_kill_request.key) + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + kill_house_check = KillHouseCheckRequest.objects.get( + province_kill_request__key=kill_house_request.province_kill_request.key) + if OperationLimitation.objects.all().first().vet_check_kill_house_assignment_limitation == True: + if kill_house_request.vet_state == 'pending': + return Response({"result": "به علت عدم تایید تخلیه دامپزشک کشتارگاه امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + date_time_of_now = datetime.now().date() + if OperationLimitation.objects.all().first().kill_house_assignment_limitation == True: + + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response({"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + role = request.data['role'] + request.data.pop('kill_house_request_key') + request.data.pop('role') + assignment_info = KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).first() + if not assignment_info: + assignment_info = KillHouseAssignmentInformation() + assignment_info.save() + + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # assignment_info = serializer.create(validated_data=request.data) + assignment_info.kill_house_check = kill_house_check + assignment_info.kill_house_request = kill_house_request + assignment_info.car_weight_with_load = int(request.data['net_weight']) + assignment_info.net_weight = int(request.data['net_weight']) + assignment_info.real_quantity = int(request.data['real_quantity']) + assignment_info.importer = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(now), + "role": role + } + assignment_info.save() + kill_house_request.accepted_real_weight = int(request.data['net_weight']) + kill_house_request.accepted_real_quantity = int(request.data['real_quantity']) + kill_house_request.accepted_assignment_real_quantity = int(request.data['net_weight']) + kill_house_request.accepted_assignment_real_weight = int(request.data['real_quantity']) + kill_house_request.save() + # kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_request, + # trash=False) + + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + + kill_house_request.accepted_real_weight = int(request.data['net_weight']) + kill_house_request.accepted_real_quantity = int(request.data['real_quantity']) + assignment_info.save() + if assignment_info.net_weight != 0 and assignment_info.real_quantity != 0 and assignment_info.car_weight_with_load_image != None: + kill_house_request.assignment_state_archive = 'True' + kill_house_request.save() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + image = request.data['image'] + role = request.data['role'] + now = datetime.now() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + image_url = send_image_to_server(image) + # upload_object_resize(image_data=image, bucket_name="profileimagedefault", + # object_name="{0}.jpg".format(str(ran))) + if 'bar_key' in request.data.keys(): + bar_key = request.data['bar_key'] + request.data.pop('bar_key') + kill_house_request = KillHouseRequest.objects.get(key=bar_key, trash=False) + kill_house_check = KillHouseCheckRequest.objects.get( + province_kill_request__key=kill_house_request.province_kill_request.key) + assignment_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=bar_key).first() + if OperationLimitation.objects.all().first().vet_check_kill_house_assignment_limitation == True: + if kill_house_request.vet_state == 'pending': + return Response({"result": "به علت عدم تایید تخلیه دامپزشک کشتارگاه امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + date_time_of_now = datetime.now().date() + if OperationLimitation.objects.all().first().kill_house_assignment_limitation == True: + + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response( + {"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if not assignment_info: + assignment_info = KillHouseAssignmentInformation(kill_house_check=kill_house_check, + kill_house_request=kill_house_request) + assignment_info.save() + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # assignment_info = serializer.create(validated_data=request.data) + # assignment_info.car_weight_with_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + assignment_info.car_weight_with_load_image = image_url + assignment_info.importer = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(now), + "role": role + } + assignment_info.save() + kill_house_request = KillHouseRequest.objects.get(key=bar_key, trash=False) + if assignment_info.net_weight != 0 and assignment_info.real_quantity != 0 and assignment_info.car_weight_with_load_image != None: + kill_house_request.assignment_state_archive = 'True' + kill_house_request.save() + + else: + assingment_info_keys = request.data['bar_keys'] + request.data.pop('bar_keys') + for assingment_info_key in assingment_info_keys: + kill_house_request = KillHouseRequest.objects.get(key=assingment_info_key, trash=False) + kill_house_check = KillHouseCheckRequest.objects.get( + province_kill_request__key=kill_house_request.province_kill_request.key) + if OperationLimitation.objects.all().first().vet_check_kill_house_assignment_limitation == True: + if kill_house_request.vet_state == 'pending': + return Response( + {"result": "به علت عدم تایید تخلیه دامپزشک کشتارگاه امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + date_time_of_now = datetime.now().date() + if OperationLimitation.objects.all().first().kill_house_assignment_limitation == True: + + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response( + {"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + assignment_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=assingment_info_key).first() + + if not assignment_info: + assignment_info = KillHouseAssignmentInformation(kill_house_check=kill_house_check, + kill_house_request=kill_house_request) + assignment_info.save() + + if assignment_info.car_weight_with_load_image == None: + # assignment_info.car_weight_with_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + assignment_info.car_weight_with_load_image = image_url + assignment_info.importer = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(now), + "role": role + } + assignment_info.save() + kill_house_request = KillHouseRequest.objects.get(key=assignment_info.kill_house_request.key, + trash=False) + if assignment_info.net_weight != 0 and assignment_info.real_quantity != 0 and assignment_info.car_weight_with_load_image != None: + kill_house_request.assignment_state_archive = 'True' + kill_house_request.save() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_200_OK) + + +# class KillHouseAssignmentInformationForcompletedloadsViewSet(viewsets.ModelViewSet): +# queryset = KillHouseAssignmentInformation.objects.all() +# serializer_class = KillHouseAssignmentInformationSerializer +# permission_classes = [TokenHasReadWriteScope] +# +# def list(self, request, *args, **kwargs): +# # refresh(request.user.id) +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# now = datetime.now().date() +# date1 = datetime.strptime(str(request.GET['date1']), +# '%Y-%m-%d').date() if 'date1' in request.GET else now +# date2 = datetime.strptime(str(request.GET['date2']), +# '%Y-%m-%d').date() if 'date2' in request.GET else now +# province = user.province.name +# if request.GET['role'] in ('ProvinceFinancial', 'ProvinceOperator'): +# kill_house_assignments = KillHouseAssignmentInformation.objects.filter( +# Q(car_weight_with_load_image__isnull=False) | Q(car_weight_without_load_image__isnull=False), +# kill_house_request__killhouse_user__kill_house_operator__address__province__name=province, +# net_weight__gt=0, +# real_quantity__gt=0, +# kill_house_request__kill_request__recive_date__date__gte=date1, +# kill_house_request__kill_request__recive_date__date__lte=date2, +# trash=False).select_related( +# 'kill_house_request__province_request__poultry_request__hatching', +# 'kill_house_request__province_request__poultry_request__poultry', +# 'kill_house_request__province_request__poultry_request__poultry__user__city', +# 'kill_house_request__province_request__poultry_request__poultry__user__province', +# 'kill_house_request__province_request__poultry_request__poultry__user', +# +# 'kill_house_request__kill_request__kill_house', +# 'kill_house_request__kill_request__slaughter_house', +# 'kill_house_request__killhouse_user', +# 'kill_house_request__killhouse_user__kill_house_operator__user', +# 'kill_house_request__add_car__driver', +# 'kill_house_request__real_add_car__driver', +# ).values( +# "kill_house_request__province_request__poultry_request__poultry__user__province__name", +# "kill_house_request__province_request__poultry_request__poultry__user__city__name", +# "kill_house_request__province_request__poultry_request__poultry__user__fullname", +# "kill_house_request__province_request__poultry_request__poultry__user__mobile", +# "kill_house_request__province_request__poultry_request__poultry__unit_name", +# "kill_house_request__province_request__poultry_request__poultry__key", +# "kill_house_request__province_request__poultry_request__order_code", +# "kill_house_request__province_request__poultry_request__quantity", +# "kill_house_request__province_request__poultry_request__id", +# "kill_house_request__province_request__poultry_request__Index_weight", +# "kill_house_request__province_request__poultry_request__chicken_breed", +# "kill_house_request__province_request__poultry_request__create_date", +# "kill_house_request__province_request__poultry_request__send_date", +# "kill_house_request__province_request__poultry_request__cell_type", +# "kill_house_request__province_request__poultry_request__hatching__losses", +# "kill_house_request__province_request__poultry_request__hatching__date", +# "kill_house_request__killhouse_user", +# 'kill_house_request__kill_request__kill_house__name', +# 'kill_house_request__kill_request__slaughter_house__name', +# "kill_house_request__add_car__driver__driver_name", +# "kill_house_request__add_car__driver__driver_mobile", +# "kill_house_request__add_car__driver__type_car", +# "kill_house_request__add_car__driver__pelak", +# "kill_house_request__add_car__driver__health_code", +# "kill_house_request__real_add_car__driver__driver_name", +# "kill_house_request__real_add_car__driver__driver_mobile", +# "kill_house_request__real_add_car__driver__type_car", +# "kill_house_request__real_add_car__driver__pelak", +# "kill_house_request__real_add_car__driver__health_code", +# "kill_house_request__quantity", +# "kill_house_request__bar_code", +# "kill_house_request__quarantine_quantity", +# "kill_house_request__vet_state", +# "kill_house_request__assignment_state_archive", +# "kill_house_request__clearance_code", +# "kill_house_request__traffic_code", +# "kill_house_request__accepted_real_quantity", +# "kill_house_request__accepted_real_weight", +# "kill_house_request", +# "car_weight_without_load", +# "car_weight_without_load_image", +# "car_weight_with_load", +# "car_weight_with_load_image", +# "net_weight", +# "state", +# "real_quantity", +# "protest_time", +# +# # "allocated_car_state" +# ) +# else: +# if request.GET['role'] == 'KillHouse': +# operator = KillHouseOperator.objects.get(user=user, trash=False) +# kill_house = KillHouse.objects.filter(kill_house_operator=operator, trash=False) +# else: +# vet = Vet.objects.get(user=user) +# kill_house_vet = KillHouseVet.objects.filter(vet=vet, trash=False) +# kill_house_list = [kill_house.kill_house.key for kill_house in kill_house_vet] +# kill_house = KillHouse.objects.filter(key__in=kill_house_list) +# +# kill_house_assignments = KillHouseAssignmentInformation.objects.filter( +# # state='pending', +# Q(car_weight_with_load_image__isnull=False) | Q(car_weight_without_load_image__isnull=False), +# +# kill_house_request__killhouse_user__in=kill_house, +# # car_weight_with_load_image__isnull=False, +# net_weight__gt=0, +# real_quantity__gt=0, +# trash=False, +# kill_house_request__kill_request__recive_date__date__gte=date1, +# kill_house_request__kill_request__recive_date__date__lte=date2, +# unusual_casualties=False).select_related( +# 'kill_house_request__province_request__poultry_request__hatching', +# 'kill_house_request__province_request__poultry_request__poultry', +# 'kill_house_request__province_request__poultry_request__poultry__user__city', +# 'kill_house_request__province_request__poultry_request__poultry__user__province', +# 'kill_house_request__province_request__poultry_request__poultry__user', +# +# 'kill_house_request__kill_request__kill_house', +# 'kill_house_request__kill_request__slaughter_house', +# 'kill_house_request__killhouse_user', +# 'kill_house_request__killhouse_user__kill_house_operator__user', +# 'kill_house_request__add_car__driver', +# 'kill_house_request__real_add_car__driver', +# ).values( +# "kill_house_request__province_request__poultry_request__poultry__user__province__name", +# "kill_house_request__province_request__poultry_request__poultry__user__city__name", +# "kill_house_request__province_request__poultry_request__poultry__user__fullname", +# "kill_house_request__province_request__poultry_request__poultry__user__mobile", +# "kill_house_request__province_request__poultry_request__poultry__unit_name", +# "kill_house_request__province_request__poultry_request__poultry__key", +# "kill_house_request__province_request__poultry_request__order_code", +# "kill_house_request__province_request__poultry_request__quantity", +# "kill_house_request__province_request__poultry_request__id", +# "kill_house_request__province_request__poultry_request__Index_weight", +# "kill_house_request__province_request__poultry_request__chicken_breed", +# "kill_house_request__province_request__poultry_request__create_date", +# "kill_house_request__province_request__poultry_request__send_date", +# "kill_house_request__province_request__poultry_request__cell_type", +# "kill_house_request__province_request__poultry_request__hatching__losses", +# "kill_house_request__province_request__poultry_request__hatching__date", +# "kill_house_request__killhouse_user", +# 'kill_house_request__kill_request__kill_house__name', +# 'kill_house_request__kill_request__slaughter_house__name', +# "kill_house_request__add_car__driver__driver_name", +# "kill_house_request__add_car__driver__driver_mobile", +# "kill_house_request__add_car__driver__type_car", +# "kill_house_request__add_car__driver__pelak", +# "kill_house_request__add_car__driver__health_code", +# "kill_house_request__real_add_car__driver__driver_name", +# "kill_house_request__real_add_car__driver__driver_mobile", +# "kill_house_request__real_add_car__driver__type_car", +# "kill_house_request__real_add_car__driver__pelak", +# "kill_house_request__real_add_car__driver__health_code", +# "kill_house_request__quantity", +# "kill_house_request__bar_code", +# "kill_house_request__quarantine_quantity", +# "kill_house_request__vet_state", +# "kill_house_request__assignment_state_archive", +# "kill_house_request__clearance_code", +# "kill_house_request__traffic_code", +# "kill_house_request__accepted_real_quantity", +# "kill_house_request__accepted_real_weight", +# "kill_house_request", +# "car_weight_without_load", +# "car_weight_without_load_image", +# "car_weight_with_load", +# "car_weight_with_load_image", +# "net_weight", +# "state", +# "real_quantity", +# "protest_time", +# +# # "allocated_car_state" +# ) +# +# assignments_list_final_state = [] +# allocation = ShareOfAllocation.objects.all() +# if allocation.count() > 0: +# allocation = allocation.last().total +# else: +# allocation = 0 +# for request_data in kill_house_assignments: +# poultry_name_of_bank_user = None +# poultry_bank_name = None +# poultry_card = None +# poultry_account = None +# poultry_shaba = None +# province_name_of_bank_user = None +# province_bank_name = None +# province_card = None +# province_account = None +# province_shaba = None +# kill_house_vet = KillHouseVet.objects.filter( +# kill_house=request_data.get('kill_house_request__killhouse_user'), trash=False).select_related('vet__user').values( +# 'vet__user__fullname', +# 'vet__user__mobile', +# ) +# if kill_house_vet.count() > 0: +# kill_house_vet = kill_house_vet.last() +# kill_house_vet_name = kill_house_vet.get('vet__user__fullname') +# kill_house_vet_mobile = kill_house_vet.get('vet__user__mobile') +# if request_data.get('kill_house_request__kill_request__slaughter_house') != None: +# kill_place = request_data.get('kill_house_request__kill_request__slaughter_house__name') +# else: +# kill_place = request_data.get('kill_house_request__kill_request__kill_house__name') +# +# vet_check = VetCheckRequest.objects.filter( +# kill_house_request=request_data.get('kill_house_request'), trash=False).select_related('kill_house_request').values('kill_house_request','create_date').first() +# +# vet_check_date = vet_check.get('create_date') if vet_check else None +# poultry = Poultry.objects.filter( +# key=request_data.get('kill_house_request__province_request__poultry_request__poultry__key'), +# trash=False).select_related('user_bank_info').values( +# 'user_bank_info', +# 'user_bank_info__name_of_bank_user', +# 'user_bank_info__bank_name', +# 'user_bank_info__card', +# 'user_bank_info__account', +# 'user_bank_info__shaba', +# ).first() +# if poultry.get('user_bank_info') != None: +# poultry_name_of_bank_user = poultry.get('user_bank_info__name_of_bank_user') +# poultry_bank_name = poultry.get('user_bank_info__bank_name') +# poultry_card = poultry.get('user_bank_info__card') +# poultry_account = poultry.get('user_bank_info__account') +# poultry_shaba = poultry.get('user_bank_info__shaba') +# operator = ProvinceOperator.objects.filter(trash=False).select_related('user_bank_info').values( +# 'user_bank_info', +# 'user_bank_info__name_of_bank_user', +# 'user_bank_info__bank_name', +# 'user_bank_info__card', +# 'user_bank_info__account', +# 'user_bank_info__shaba', +# ) +# if operator.last().get('user_bank_info') != None: +# operator = operator.last() +# province_name_of_bank_user = operator.get('user_bank_info__name_of_bank_user') +# province_bank_name = operator.get('user_bank_info__bank_name') +# province_card = operator.get('user_bank_info__card') +# province_account = operator.get('user_bank_info__account') +# province_shaba = operator.get('user_bank_info__shaba') +# +# internal_dict = { +# "order_code": request_data.get('kill_house_request__province_request__poultry_request__order_code'), +# "poultry_province": request_data.get( +# 'kill_house_request__province_request__poultry_request__poultry__user__province__name'), +# "poultry_city": request_data.get( +# 'kill_house_request__province_request__poultry_request__poultry__user__city__name'), +# "poultry_fullname": request_data.get( +# 'kill_house_request__province_request__poultry_request__poultry__user__fullname'), +# "poultry_mobile": request_data.get( +# 'kill_house_request__province_request__poultry_request__poultry__user__mobile'), +# "poultry_name": request_data.get( +# 'kill_house_request__province_request__poultry_request__poultry__unit_name'), +# "poultry_key": request_data.get('kill_house_request__province_request__poultry_request__poultry__key'), +# "poultry_request_quantity": request_data.get( +# 'kill_house_request__province_request__poultry_request__quantity'), +# "poultry_request_id": request_data.get('kill_house_request__province_request__poultry_request__id'), +# "Index_weight": request_data.get('kill_house_request__province_request__poultry_request__Index_weight'), +# "chicken_breed": request_data.get( +# 'kill_house_request__province_request__poultry_request__chicken_breed'), +# "create_date": request_data.get('kill_house_request__province_request__poultry_request__create_date'), +# "send_date": request_data.get('kill_house_request__province_request__poultry_request__send_date'), +# "cell_type": request_data.get('kill_house_request__province_request__poultry_request__cell_type'), +# "losses": request_data.get('kill_house_request__province_request__poultry_request__hatching__losses'), +# "hatching__date": request_data.get( +# 'kill_house_request__province_request__poultry_request__hatching__date'), +# "driver_name": request_data.get('kill_house_request__add_car__driver__driver_name'), +# "driver_mobile": request_data.get('kill_house_request__add_car__driver__driver_mobile'), +# "type_car": request_data.get('kill_house_request__add_car__driver__type_car'), +# "pelak": request_data.get('kill_house_request__add_car__driver__pelak'), +# "health_code": request_data.get('kill_house_request__add_car__driver__health_code'), +# "real_driver_name": request_data.get('kill_house_request__real_add_car__driver__driver_name'), +# "real_driver_mobile": request_data.get('kill_house_request__real_add_car__driver__driver_mobile'), +# "real_type_car": request_data.get('kill_house_request__real_add_car__driver__type_car'), +# "real_pelak": request_data.get('kill_house_request__real_add_car__driver__pelak'), +# "real_health_code": request_data.get('kill_house_request__real_add_car__driver__health_code'), +# "quantity": request_data.get('kill_house_request__quantity'), +# "bar_code": request_data.get('kill_house_request__bar_code'), +# "quarantine_quantity": request_data.get('kill_house_request__quarantine_quantity'), +# "vet_state": request_data.get('kill_house_request__vet_state'), +# "assignment_state_archive": request_data.get('kill_house_request__assignment_state_archive'), +# "clearance_code": request_data.get('kill_house_request__clearance_code'), +# "traffic_code": request_data.get('kill_house_request__traffic_code'), +# "accepted_real_quantity": request_data.get('kill_house_request__accepted_real_quantity'), +# "accepted_real_weight": request_data.get('kill_house_request__accepted_real_weight'), +# "car_weight_without_load": request_data.get('car_weight_without_load'), +# "car_weight_without_load_image": request_data.get('car_weight_without_load_image'), +# "car_weight_with_load": request_data.get('car_weight_with_load'), +# "car_weight_with_load_image": request_data.get('car_weight_with_load_image'), +# "net_weight": request_data.get('net_weight'), +# "state": request_data.get('state'), +# "real_quantity": request_data.get('real_quantity'), +# "protest_time": request_data.get('protest_time'), +# "average_weight": request_data.get('net_weight') / request_data.get('real_quantity') , +# "first_weight": request_data.get('kill_house_request__quantity') * request_data.get('kill_house_request__province_request__poultry_request__Index_weight') , +# "poultry_name_of_bank_user": poultry_name_of_bank_user, +# "poultry_bank_name": poultry_bank_name, +# "poultry_card": poultry_card, +# "poultry_account": poultry_account, +# "poultry_shaba": poultry_shaba, +# "province_name_of_bank_user": province_name_of_bank_user, +# "province_bank_name": province_bank_name, +# "province_card": province_card, +# "province_account": province_account, +# "province_shaba": province_shaba, +# "kill_house_vet_name": kill_house_vet_name, +# "kill_house_vet_mobile": kill_house_vet_mobile, +# "kill_place": kill_place, +# "vet_check_date": vet_check_date, +# "allocation": allocation, +# +# } +# +# assignments_list_final_state.append(internal_dict) +# return Response(len(assignments_list_final_state), status=status.HTTP_200_OK) +class KillHouseAssignmentInformationForcompletedloadsViewSet(viewsets.ModelViewSet): + queryset = KillHouseAssignmentInformation.objects.all() + serializer_class = KillHouseAssignmentInformationForCompletedLoadsSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + province = user.province.name + if request.GET['role'] in ('ProvinceFinancial', 'ProvinceOperator'): + kill_house_assignments = KillHouseAssignmentInformation.objects.filter( + Q(car_weight_with_load_image__isnull=False) | Q(car_weight_without_load_image__isnull=False), + kill_house_request__killhouse_user__kill_house_operator__address__province__name=province, + net_weight__gt=0, + real_quantity__gt=0, + kill_house_request__kill_request__recive_date__date__gte=date1, + kill_house_request__kill_request__recive_date__date__lte=date2, + trash=False) + else: + if request.GET['role'] == 'KillHouse': + operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=operator, trash=False) + else: + vet = Vet.objects.get(user=user) + kill_house_vet = KillHouseVet.objects.filter(vet=vet, trash=False) + kill_house_list = [kill_house.kill_house.key for kill_house in kill_house_vet] + kill_house = KillHouse.objects.filter(key__in=kill_house_list) + + kill_house_assignments = KillHouseAssignmentInformation.objects.filter( + # state='pending', + Q(car_weight_with_load_image__isnull=False) | Q(car_weight_without_load_image__isnull=False), + + kill_house_request__killhouse_user__in=kill_house, + # car_weight_with_load_image__isnull=False, + net_weight__gt=0, + real_quantity__gt=0, + trash=False, + kill_house_request__kill_request__recive_date__date__gte=date1, + kill_house_request__kill_request__recive_date__date__lte=date2, + unusual_casualties=False) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_assignments) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(kill_house_assignments, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به وارد کردن اطلاعات بار توسط کشتارگاه +class KillHouseAssignmentInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseAssignmentInformation.objects.all() + serializer_class = KillHouseAssignmentInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'bar_code', + 'bar_document_status__title', + ] + + # تابع مربوط به وارد کردن اطلاعات بار توسط کشتارگاه + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + pic = [] + dict1 = {} + role = request.data['role'] + request.data.pop('role') + date_time_of_now = datetime.now().date() + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + province_kill_request = ProvinceKillRequest.objects.get(key=kill_house_request.province_kill_request.key) + if OperationLimitation.objects.all().first().vet_check_kill_house_assignment_limitation == True: + if kill_house_request.vet_state == 'pending': + return Response({"result": "به علت عدم تایید تخلیه دامپزشک کشتارگاه امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if OperationLimitation.objects.all().first().kill_house_assignment_limitation == True: + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response({"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + # if kill_house_request.vet_state == 'pending': + # return Response({"result": "بار توسط دامپزشک تخلیه نشده است !"}, status=status.HTTP_403_FORBIDDEN) + if kill_house_request.province_kill_request != None: + kill_house_check = KillHouseCheckRequest.objects.get( + province_kill_request__key=kill_house_request.province_kill_request.key) + else: + kill_house_check = None + # if 'car_without_load_image' in request.data.keys() and 'car_with_load_image' in request.data.keys(): + # if request.data['car_without_load_image'] != None and request.data['car_with_load_image'] != None: + # car_without_load_image = request.data['car_without_load_image'] + # car_with_load_image = request.data['car_with_load_image'] + # pic.append(car_without_load_image) + # pic.append(car_with_load_image) + # request.data.pop('car_without_load_image') + # request.data.pop('car_with_load_image') + + if 'car_with_load_image' in request.data.keys(): + if request.data['car_with_load_image'] != None: + car_with_load_image = request.data['car_with_load_image'] + pic.append(car_with_load_image) + request.data.pop('car_with_load_image') + + request.data.pop('kill_house_request_key') + + if KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).exists(): + return Response({'result': 'already exist'}, status=status.HTTP_403_FORBIDDEN) + if 'killer_key' in request.data.keys(): + if request.data['killer_key'] != None: + killer = KillHouse.objects.get(key=request.data['killer_key']) + kill_house_request.killer = killer + request.data.pop('killer_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + assignment_info = serializer.create(validated_data=request.data) + if kill_house_check != None: + assignment_info.kill_house_check = kill_house_check + assignment_info.kill_house_request = kill_house_request + if len(pic) > 0: + for p in pic: + ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + # upload_object_resize(image_data=p, bucket_name="profileimagedefault", + # object_name="{0}.jpg".format(str(ran))) + # if p == car_without_load_image: + # assignment_info.car_weight_without_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format( + # str(ran)) + # # os.remove("{0}.jpg".format(str(ran))) + # else: + # assignment_info.car_weight_with_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + assignment_info.car_weight_with_load_image = send_image_to_server(p) + # os.remove("{0}.jpg".format(str(ran))) + kill_house_request.assignment_state_archive = 'True' + kill_house_request.save() + if role == 'Poultry': + dict1.update({ + "Poultry": True, + "CityOperator": False, + "ProvinceOperator": False, + "ProvinceFinancial": False, + "KillHouse": False, + }) + elif role == 'CityOperator': + dict1.update({ + "Poultry": False, + "CityOperator": True, + "ProvinceOperator": False, + "ProvinceFinancial": False, + "KillHouse": False, + }) + elif role == 'ProvinceFinancial': + dict1.update({ + "Poultry": False, + "CityOperator": False, + "ProvinceOperator": False, + "ProvinceFinancial": True, + "KillHouse": False, + }) + elif role == 'ProvinceOperator': + dict1.update({ + "Poultry": False, + "CityOperator": False, + "ProvinceOperator": True, + "ProvinceFinancial": False, + "KillHouse": False, + }) + else: + dict1.update({ + "Poultry": False, + "CityOperator": False, + "ProvinceOperator": False, + "ProvinceFinancial": False, + "KillHouse": True, + }) + assignment_info.importer = dict1 + now = datetime.now() + houre = PercentageOfLosses.objects.all() + if houre.count() > 0: + houre = houre.last().houre + assignment_info.protest_time = now + timedelta(hours=int(houre)) + assignment_info.net_weight = float(assignment_info.car_weight_with_load) - float( + assignment_info.car_weight_without_load) + assignment_info.save() + kill_house_request.active_state = 'inactive' + poultry = PoultryRequest.objects.get( + key=kill_house_request.province_request.city_request_Poultry.poultry_request.key) + poultry.assignment = True + poultry.save() + kill_house_request.accepted_real_quantity = assignment_info.real_quantity + kill_house_request.accepted_real_weight = assignment_info.net_weight + kill_house_request.accepted_assignment_real_quantity = assignment_info.real_quantity + kill_house_request.accepted_assignment_real_weight = assignment_info.net_weight + kill_house_request.save() + hatching = PoultryHatching.objects.get(key=poultry.hatching.key) + update_kill_house_requests(province_kill_request, poultry) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + kill_house_request.accepted_real_quantity = assignment_info.real_quantity + kill_house_request.accepted_real_weight = assignment_info.net_weight + kill_house_request.save() + assignment_info_serializer = self.serializer_class(assignment_info) + return Response(assignment_info_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + # تابع مربوط به نمایش اطلاعات بار وارد شده توسط کشتارگاه + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + # user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house = [] + kill_house_requests_list = [] + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + for kill_house_vet in kill_house_vets: + kill_house.append(kill_house_vet.kill_house) + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if request.GET['role'] in ['CityOperator', 'CityJahad', 'CityPoultry']: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + if 'without_bar_document' in request.GET and request.GET['without_bar_document'] == "true": + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + bar_document_status__isnull=True, + non_receipt=False, + trash=False, province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + if 'without_bar_document' in request.GET and request.GET['without_bar_document'] == "true": + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + bar_document_status__isnull=True, + non_receipt=False, + trash=False, province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + + else: + + if 'without_bar_document' in request.GET and request.GET['without_bar_document'] == "true": + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + bar_document_status__isnull=True, + non_receipt=False, + trash=False, + + ).order_by('-kill_request__recive_date') + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='True', + non_receipt=False, + trash=False, + + ).order_by('-kill_request__recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_requests_list = ps.filter() + kill_house_requests = [] if len(kill_house_requests_list) == 0 else kill_house_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش اطلاعات بار وارد شده توسط کشتارگاه + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + role = request.data['role'] + request.data.pop('role') + kill_house_assignment = KillHouseAssignmentInformation.objects.get(key=request.data['key'], trash=False) + if kill_house_assignment.state == 'accepted': + return Response({"result": "به علت تایید اطلاعات از سمت استان امکان ویرایش وجود ندارد!"}) + kill_house_request = KillHouseRequest.objects.get(key=kill_house_assignment.kill_house_request.key) + province_kill_request = ProvinceKillRequest.objects.get(key=kill_house_request.province_kill_request.key) + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key) + date_time_of_now = datetime.now().date() + if OperationLimitation.objects.all().first().kill_house_assignment_limitation == True: + + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response({"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + car_with_load_image = request.data['car_with_load_image'] + request.data.pop('key') + + request.data.pop('car_with_load_image') + if 'killer_key' in request.data.keys(): + if request.data['killer_key'] != None: + killer = KillHouse.objects.get(key=request.data['killer_key']) + kill_house_request.killer = killer + request.data.pop('killer_key') + + pic = [] + # if 'car_without_load_image' in request.data.keys(): + # car_without_load_image = request.data['car_without_load_image'] + # request.data.pop('car_without_load_image') + # pic.append(car_without_load_image) + pic.append(car_with_load_image) + + for p in pic: + ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + # upload_object_resize(image_data=p, bucket_name="profileimagedefault", + # object_name="{0}.jpg".format(str(ran))) + # if p == car_without_load_image: + # kill_house_assignment.car_weight_without_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + # # os.remove("{0}.jpg".format(str(ran))) + # + # else: + # kill_house_assignment.car_weight_with_load_image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + kill_house_assignment.car_weight_with_load_image = send_image_to_server(p) + # os.remove("{0}.jpg".format(str(ran))) + kill_house_assignment.state = 'pending' + if role == 'Poultry': + kill_house_assignment.poultry_update = True + elif role == 'CityOperator': + kill_house_assignment.city_update = True + elif role == 'ProvinceFinancial': + kill_house_assignment.province_update = True + + kill_house_assignment.state = 'pending' + kill_house_assignment.net_weight = request.data['car_weight_with_load'] - request.data[ + 'car_weight_without_load'] + kill_house_assignment.save() + kill_house_request.accepted_real_quantity = request.data['real_quantity'] + kill_house_request.accepted_real_weight = request.data['car_weight_with_load'] - request.data[ + 'car_weight_without_load'] + kill_house_request.accepted_assignment_real_quantity = int(request.data['real_quantity']) + kill_house_request.accepted_assignment_real_weight = request.data['car_weight_with_load'] - request.data[ + 'car_weight_without_load'] + kill_house_request.assignment_state_archive = 'True' + kill_house_request.save() + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + serializer = self.serializer_class(kill_house_assignment) + serializer.update(instance=kill_house_assignment, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به ایجاد و ویرایش و جذف و نمایش فاکتور از سمت استان برای کشتارگاه +class ProvinceFactorToKillHouseViewSet(viewsets.ModelViewSet): + queryset = ProvinceFactorToKillHouse.objects.all() + serializer_class = ProvinceFactorToKillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + +# ویوست مربوط به ایجاد و ویرایش و جذف و نمایش نماینده دامپزشکی برای کشتارگاه +class VetViewSet(viewsets.ModelViewSet): + queryset = Vet.objects.all() + serializer_class = VetSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = VetFilterSet + pagination_class = CustomPagination + filterset_fields = [ + 'user__national_id', + 'user__base_order', + 'user__mobile', + + ] + + # تابع مربوط به ایجاد نماینده دامپزشکی برای کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = UserProfile.objects.get(key=request.data['user_key'], trash=False) + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('user_key') + request.data.pop('kill_house_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + vet = serializer.create(validated_data=request.data) + vet.kill_house = kill_house + vet.user = user + vet.save() + vet_serializer = self.serializer_class(vet) + return Response(vet_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + def retrieve(self, request, pk=None, *args, **kwargs): + + # refresh(request.user.id) + + if 'kill_house_info' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + vet = Vet.objects.get(user=user, trash=False) + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + if kill_house_vet.count() > 0: + kill_house_vet = kill_house_vet.last() + profile_info = { + 'kill_house_name': kill_house_vet.kill_house.name, + 'kill_house_user': kill_house_vet.kill_house.kill_house_operator.user.fullname, + 'kill_house_mobile': kill_house_vet.kill_house.kill_house_operator.user.mobile, + 'kill_house_city': kill_house_vet.kill_house.kill_house_operator.user.city.name, + 'kill_house_province': kill_house_vet.kill_house.kill_house_operator.user.province.name, + } + return Response(profile_info, status=status.HTTP_200_OK) + + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + user_serializer = SystemUserProfileSerializer(user) + vet = Vet.objects.get(user=user, trash=False) + vet_serializer = VetSerializer(vet) + vet_farm = VetFarm.objects.filter(vet=vet, trash=False) + serializer = VetFarmSerializer(vet_farm, many=True) + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + if kill_house_vet.count() > 0: + kill_house_vet_serializer = KillHouseVetSerializer(kill_house_vet.last()) + profile_info = { + # 'profile': user_serializer.data, + 'vet': vet_serializer.data, + 'kill_house_vet': kill_house_vet_serializer.data + } + else: + + profile_info = { + # 'profile': user_serializer.data, + 'vet': vet_serializer.data + # 'vet_farms':serializer.data + } + return Response(profile_info, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + vet_farm_flag = request.GET.get('vet_farm') + + excluded_ids = set() + if vet_farm_flag: + if vet_farm_flag == 'true': + excluded_ids = set(VetFarm.objects.filter(trash=False).values_list('vet__id', flat=True).distinct()) + elif vet_farm_flag == 'false': + excluded_ids = set( + KillHouseVet.objects.filter(trash=False).values_list('vet__id', flat=True).distinct()) + else: + vet_farm_ids = set(VetFarm.objects.filter(trash=False).values_list('vet__id', flat=True).distinct()) + kill_house_ids = set(KillHouseVet.objects.filter(trash=False).values_list('vet__id', flat=True).distinct()) + excluded_ids = vet_farm_ids.union(kill_house_ids) + + vets = Vet.objects.filter(trash=False) + if vet_farm_flag: + vets = vets.filter(id__in=excluded_ids) + else: + vets = vets.exclude(id__in=excluded_ids) + + if value and search == 'filter' and value.strip() and value != 'undefined': + vets = vets.filter(build_query(VetFarmAndKillHouseFilterSet, value)) + + page_size = request.query_params.get('page_size') + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(vets) + if page is not None: + serializer_class = ( + VetFarmListSerializer if vet_farm_flag == 'true' else VetKillHouseSerializer + if vet_farm_flag == 'false' else VetSerializer + ) + serializer = serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = VetKillHouseSerializer(vets, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseVetViewSet(viewsets.ModelViewSet): + queryset = KillHouseVet.objects.all() + serializer_class = KillHouseVetSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + if 'role' in request.data.keys(): + if request.data['role'] == 'ProvinceInspector' or request.data['role'] == 'ProvinceOperator': + user = SystemUserProfile.objects.get(key=request.data['user_key']) + vet = Vet.objects.get(user=user, trash=False) + request.data.pop('user_key') + request.data.pop('role') + + + else: + request.data.pop('role') + user = SystemUserProfile.objects.get(user=request.user) + vet = Vet.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.get(key=request.data['key']) + request.data.pop('key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_vet = serializer.create(validated_data=request.data) + kill_house_vet.vet = vet + kill_house_vet.kill_house = kill_house + kill_house_vet.save() + kill_house_vet_serializer = self.serializer_class(kill_house_vet) + return Response(kill_house_vet_serializer.data, status=status.HTTP_201_CREATED) + return Response({"result": "مشکلی پیش آمذه است !"}, status=status.HTTP_403_FORBIDDEN) + + def destroy(self, request, pk=None, *args, **kwargs): + try: + user = SystemUserProfile.objects.get(key=request.GET['user_key']) + vet = Vet.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.get(key=request.GET['key']) + kill_house_vet = KillHouseVet.objects.get(kill_house=kill_house, vet=vet, trash=False) + kill_house_vet.trash = True + kill_house_vet.save() + + return Response(status=status.HTTP_200_OK) + except: + return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_403_FORBIDDEN) + + +# ویوست مربوط به تایید یا رد بار رسیده به کشتارگاه توسط نماینده دامپزشکی +class VetCheckRequestViewSet(viewsets.ModelViewSet): + queryset = VetCheckRequest.objects.all() + serializer_class = VetCheckRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به تایید یا رد بار رسیده به کشتارگاه توسط نماینده دامپزشکی + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + vet = Vet.objects.get(user=user, trash=False) + kill_house_vet = KillHouseVet.objects.filter(vet=vet, trash=False).last() + kill_house_req = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + evacuation_permit = EvacuationPermit.objects.all().first() + if evacuation_permit: + if evacuation_permit.type == 'force': + if kill_house_req.clearance_code == None: + return Response( + {"result": "قبل از ورود کد قرنطینه توسط دامپزشک فارم امکان تایید تخلیه وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if OperationLimitation.objects.all().first().kill_house_vet_limitation == True: + + if kill_house_req.assignment_state_archive == 'True': + return Response({"result": "به علت ورود اطلاعات بار امکان تایید تخلیه وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + province_kill_request = ProvinceKillRequest.objects.get(key=kill_house_req.province_kill_request.key, + trash=False) + if int(request.data['accepted_real_quantity']) > 0 and request.data['accepted_real_weight'] > 0: + kill_house_req.accepted_real_quantity = int(request.data['accepted_real_quantity']) + kill_house_req.accepted_real_weight = request.data['accepted_real_weight'] + kill_house_req.vet_accepted_real_quantity = int(request.data['accepted_real_quantity']) + kill_house_req.vet_accepted_real_weight = request.data['accepted_real_weight'] + kill_house_req.save() + + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + request.data.pop('kill_house_request_key') + if 'accepted_real_quantity' in request.data.keys() and 'accepted_real_weight' in request.data.keys(): + if request.data['accepted_real_quantity'] != None and request.data['accepted_real_weight'] != None: + if int(request.data['accepted_real_quantity']) > 0 and request.data['accepted_real_weight'] > 0: + if kill_house_req.assignment_state_archive == 'pending' and kill_house_req.accepted_assignment_real_quantity == 0: + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(hatching) + poultry_prediction(hatching.poultry) + + # kill_house_req.accepted_real_quantity = int(request.data['accepted_real_quantity']) + kill_house_req.vet_accepted_real_quantity = int(request.data['accepted_real_quantity']) + + request.data.pop('accepted_real_quantity') + if 'accepted_real_weight' in request.data.keys(): + if request.data['accepted_real_weight'] != None: + # kill_house_req.accepted_real_weight = request.data['accepted_real_weight'] + kill_house_req.vet_accepted_real_weight = request.data['accepted_real_weight'] + request.data.pop('accepted_real_weight') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + vet_check = serializer.create(validated_data=request.data) + vet_check.kill_house_request = kill_house_req + if vet_check.state == 'accepted': + kill_house_req.vet_state = 'accepted' + kill_house_req.active_state = 'inactive' + kill_house_req.save() + else: + kill_house_req.vet_state = 'rejected' + kill_house_req.active_state = 'inactive' + kill_house_req.save() + + vet_check.kill_house_vet = kill_house_vet + vet_check.save() + vet_check_serializer = self.serializer_class(vet_check) + return Response(vet_check_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +# ویوست مربوط به ایجاد نمایش و ویرایش و حذف درخواست بورسی کشتارگاه +class KillHouseRequestExchangeViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequestExchange.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestExchangeSerializer + + # تابع مربوط به ایجاد درخواست بورسی کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = UserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.get(user=user, trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_request_exchange = serializer.create(validated_data=request.data) + kill_house_request_exchange.user = user + kill_house_request_exchange.kill_house = kill_house + kill_house_request_exchange.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به ایجاد نمایش و ویرایش و حذف درخواست بورسی رزرو شده کشتارگاه +class KillHouseRequestExchangeReserveViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequestExchangeReserve.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestExchangeReserveSerializer + + # تابع مربوط به ایجاد درخواست بورسی رزرو شده کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = UserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.get(user=user, trash=False) + poultry_exchange = PoultryRequestExchange.objects.get(key=request.data['key'], trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_request_exchange_reserve = serializer.create(validated_data=request.data) + kill_house_request_exchange_reserve.poultry_exchange = poultry_exchange + kill_house_request_exchange_reserve.kill_house = kill_house + kill_house_request_exchange_reserve.save() + poultry_exchange.state = 'reserved' + poultry_exchange.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به ایجاد نمایش و ویرایش و حذف درخواست بورسی رزرو شده کشتارگاه +class KillHouseRequestActionViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequestAction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestActionSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.get(kill_house_operator__user=user, trash=False) + poultry_request = PoultryRequest.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_auction = serializer.create(validated_data=request.data) + kill_house_auction.kill_house = kill_house + kill_house_auction.poultry_request = poultry_request + kill_house_auction.date = datetime.now() + timedelta(minutes=10) + kill_house_auction.save() + kill_house_auction_serializer = self.serializer_class(kill_house_auction) + return Response(kill_house_auction_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.get(kill_house_operator=kill_house_operator, trash=False) + queryset = KillHouseRequestAction.objects.filter(kill_house=kill_house, trash=False) + # queryset = WareHouseFactor.objects.all().order_by('-create_date') + serializer = KillHouseRequestActionSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + queryset = KillHouseRequestAction.objects.get(key__exact=request.GET["key"], trash=False) + now = datetime.now() + if now.hour <= queryset.date.hour and now.minute <= queryset.date.minute: + queryset.delete() + return Response({"result": "object deleted"}, status=status.HTTP_200_OK) + else: + return Response({"result": "object can not deleted"}, status=status.HTTP_403_FORBIDDEN) + + +# ویوست مربوط به ایجاد نمایش و ویرایش و حذف درخواست بورسی رزرو شده کشتارگاه +class KillHouseRequestActionWinnerViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequestActionWinner.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestActionWinnerSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.get(kill_house_operator=kill_house_operator, trash=False) + queryset = KillHouseRequestActionWinner.objects.filter(kill_house_request_auction__kill_house=kill_house, + trash=False) + # queryset = WareHouseFactor.objects.all().order_by('-create_date') + serializer = KillHouseRequestActionWinnerSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به ایجاد نمایش و ویرایش و ... اضافه کردن ماشین به درخواست بورسی رزرو شده تایید شده کشتارگاه +class KillHouseRequestExchangeAddCarViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequestExchangeAddCar.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestExchangeAddCarSerializer + + # تابع مربوط به اضافه کردن ماشین به درخواست بورسی رزرو شده تایید شده کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + kill_house_reserve = KillHouseRequestExchangeReserve.objects.get(key=request.data['key'], trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_request_exchange_add_car = serializer.create(validated_data=request.data) + kill_house_request_exchange_add_car.kill_house_reserve = kill_house_reserve + kill_house_request_exchange_add_car.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +class DriverViewSet(viewsets.ModelViewSet): + queryset = KillHouseDriver.objects.all() + serializer_class = KillHouseDriverSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + """ + Show Driver Cars Information + """ + if 'my_car' in request.GET: + # get user object + userprofile = SystemUserProfile.objects.get( + user=request.user, trash=False + ) + # get driver object & cars information + # driver = self.queryset.get(user=userprofile, trash=False) + # cars_objects = driver.Kill_house_add_car + # serializer = KillHouseADDCARSerializer(cars_objects) + # return Response(serializer.data, status=status.HTTP_200_OK) + cars = KillHouseDriver.objects.filter(user=userprofile, trash=False) + # cars_objects = KillHouseADDCAR.objects.filter(driver=driver, trash=False) + # serializer = KillHouseADDCARSerializer(cars_objects, many=True) + serializer = KillHouseDriverSerializer(cars, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # Show Driver Kill Requests Allocation + if 'my_allocations' in request.GET: + driver_allocations = [] + # get user object + userprofile = SystemUserProfile.objects.get( + user=request.user, trash=False + ) + # get driver object & cars information + # driver = self.queryset.get(user=userprofile, trash=False) + # cars_object = driver.Kill_house_add_car + kill_reqs = KillHouseRequest.objects.filter(add_car__driver__user=userprofile, trash=False) + # for item in kill_req: + # if str(cars_object.key) == item.car['key']: + # driver_allocations.append(item) + serializer = KillHouseRequestSerializer(kill_reqs, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + return Response("Enter The Parameter", status=status.HTTP_400_BAD_REQUEST) + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_driver = KillHouseDriver.objects.get(user=user, trash=False) + kill_house_driver_serializer = KillHouseDriverSerializer(kill_house_driver) + profile_info = { + 'profile': kill_house_driver_serializer.data, + } + return Response(profile_info, status=status.HTTP_200_OK) + + +class DriverRequestCancelViewSet(viewsets.ModelViewSet): + queryset = DriverRequestCancel.objects.all() + serializer_class = DriverRequestCancelSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + request.data.pop('kill_house_request_key') + add_car = KillHouseADDCAR.objects.get(key=request.data['Kill_house_add_car_key'], trash=False) + request.data.pop('Kill_house_add_car_key') + if KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).exists(): + return Response({"result": "can not cancel"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + driver_cancel = serializer.create(validated_data=request.data) + if kill_house_request.province_kill_request != None: + province_kill_request = ProvinceKillRequest.objects.get( + key=kill_house_request.province_kill_request.key, trash=False) + province_kill_request.quantity += kill_house_request.quantity + province_kill_request.save() + else: + kill_house_request_auction = KillHouseRequestActionWinner.objects.get( + key=kill_house_request.kill_house_request_auction_winner.key, trash=False) + kill_house_request_auction.quantity += kill_house_request.quantity + kill_house_request_auction.save() + driver_cancel.kill_house_request = kill_house_request + driver_cancel.Kill_house_add_car = add_car + driver_cancel.save() + kill_house_request.trash = True + kill_house_request.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +class KillHouseComplaintViewSet(viewsets.ModelViewSet): + queryset = KillHouseComplaint.objects.all() + serializer_class = KillHouseComplaintSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + role = request.data['role'] + request.data.pop('role') + image_list = [] + bar = KillHouseAssignmentInformation.objects.get(key=request.data['bar_key'], trash=False) + request.data.pop('bar_key') + percent = request.data['percent'] + request.data.pop('percent') + try: + images = request.data['image'] + request.data.pop('image') + except: + images = None + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + complaint = serializer.create(validated_data=request.data) + complaint.bar = bar + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + complaint.image = image_list + if percent != None: + complaint.percent = percent + complaint.save() + bar.unusual_casualties = True + bar.save() + if role == 'KillHouse': + kill_house = KillHouse.objects.get(kill_house_operator__user=user) + kill_house_name = kill_house.kill_house_operator.user.fullname + information = { + "role": role, + "kill_house_name": kill_house.name, + "kill_house_operator_name": kill_house_name, + "date": str(complaint.create_date) + } + + elif role == "KillHouseVet": + vet = Vet.objects.get(user=user) + kill_house_vet = KillHouseVet.objects.get(vet=vet) + kill_house_vet_name = kill_house_vet.vet.user.fullname + + information = { + "role": role, + "kill_house_vet": kill_house_vet_name, + "date": str(complaint.create_date) + } + + complaint.registrar = information + complaint.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + if 'role' in request.GET: + killhousecomplaints = [] + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user) + kill_house = KillHouse.objects.get(kill_house_operator=kill_house_operator) + killhousecomplaints = KillHouseComplaint.objects.filter( + bar__kill_house_request__killhouse_user=kill_house) + if killhousecomplaints.count() > 0: + serializer = KillHouseComplaintSerializer(killhousecomplaints, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.get(user=user) + kill_house_vet = KillHouseVet.objects.get(vet=vet) + kill_house = KillHouse.objects.get(key=kill_house_vet.kill_house.key) + killhousecomplaints = KillHouseComplaint.objects.filter( + bar__kill_house_request__killhouse_user=kill_house) + if killhousecomplaints.count() > 0: + serializer = KillHouseComplaintSerializer(killhousecomplaints, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + killhousecomplaints = KillHouseComplaint.objects.filter( + bar__kill_house_request__killhouse_user__system_address__province__id=user.province.id) + if killhousecomplaints.count() > 0: + serializer = KillHouseComplaintSerializer(killhousecomplaints, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(killhousecomplaints, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + # refresh(request.user.id) + Killhousecomplaint = KillHouseComplaint.objects.get(key=request.data['key']) + new_bar = KillHouseAssignmentInformation.objects.get(key=request.data['bar_key'], trash=False) + request.data.pop('key') + request.data.pop('bar_key') + percent = request.data['percent'] + new_title = request.data['title'] + new_image = request.data['image'] + new_percent = request.data['percent'] + new_message = request.data['message'] + + Killhousecomplaint.bar = new_bar + Killhousecomplaint.title = new_title + Killhousecomplaint.image = new_image + Killhousecomplaint.percent = new_percent + Killhousecomplaint.message = new_message + Killhousecomplaint.save() + + return Response(status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + # refresh(request.user.id) + Killhousecomplaint = KillHouseComplaint.objects.get(key=request.data['key']) + Killhousecomplaint.trash = True + Killhousecomplaint.save() + + return Response(status=status.HTTP_200_OK) + + +class CheckKillHouseComplaintViewSet(viewsets.ModelViewSet): + queryset = CheckKillHouseComplaint.objects.all() + serializer_class = CheckKillHouseComplaintSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + complaint = KillHouseComplaint.objects.get(key=request.data['complaint_key'], trash=False) + request.data.pop('complaint_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + percent = PercentageOfLosses.objects.all() + if percent.count() > 0: + percent = percent.last() + else: + return Response('dont have PercentageOfLosses ', status=status.HTTP_403_FORBIDDEN) + + check = serializer.create(validated_data=request.data) + check.camplaint = complaint + if check.state == 'accepted': + bar = KillHouseAssignmentInformation.objects.get(key=complaint.bar.key) + complaint_percent = complaint.percent + if float(complaint_percent) > float(percent.percent): + main_percent = float(complaint_percent) - float(percent.percent) + bar.car_weight_with_load = float(bar.car_weight_with_load) - ( + (main_percent / 100) * (float(bar.car_weight_with_load))) + bar.net_weight = float(bar.net_weight) - ( + (main_percent / 100) * (float(bar.net_weight))) + bar.save() + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__key=complaint.bar.key) + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__key=complaint.bar.key) + + complaint.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors) + + +class KillHouseBarReportingViewSet(viewsets.ModelViewSet): + queryset = KillHouseAssignmentInformation.objects.all() + serializer_class = KillHouseAssignmentInformationSerializer + permission_classes = [AllowAny] + + def create(self, request, *args, **kwargs): + return Response(status=status.HTTP_401_UNAUTHORIZED) + + def update(self, request, *args, **kwargs): + return Response(status=status.HTTP_401_UNAUTHORIZED) + + def destroy(self, request, *args, **kwargs): + return Response(status=status.HTTP_401_UNAUTHORIZED) + + def partial_update(self, request, *args, **kwargs): + return Response(status=status.HTTP_401_UNAUTHORIZED) + + def list(self, request, *args, **kwargs): + total_list = [] + net_weight = 0 + api_key = request.GET['api_key'] + if api_key == PROJECT_API_KEY: + for kill_house in KillHouse.objects.filter(system_address__province__id=1): + internal_list = [] + + date_time = datetime.strptime(request.GET['date'], '%Y-%m-%d') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__killhouse_user=kill_house, create_date__year=date_time.year, + create_date__month=date_time.month, create_date__day=date_time.day) + if assignments.count() > 0: + + for assignment in assignments: + net_weight += assignment.net_weight + + internal_dict = { + + "date": date_time, + "weight": net_weight, + } + internal_list.append(internal_dict) + + kill_house_dict = { + "kill_house_name": kill_house.name, + "fullname": kill_house.kill_house_operator.user.fullname, + "mobile": kill_house.kill_house_operator.user.mobile, + "city": kill_house.system_address.city.name, + "province": kill_house.system_address.province.name, + "bar_info": internal_list, + } + total_list.append(kill_house_dict) + + return Response(total_list, status=status.HTTP_200_OK) + + +class CheckUnusualCasualtiesViewSet(viewsets.ModelViewSet): + queryset = CheckUnusualCasualties.objects.all() + serializer_class = CheckUnusualCasualtiesSerializer + permission_classes = [AllowAny] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + # return Response(user.fullname) + kill_house_complaint = KillHouseComplaint.objects.get(key=request.data['key']) + request.data.pop('key') + bar_info = KillHouseAssignmentInformation.objects.get(key=kill_house_complaint.bar.key) + state = request.data['state'] + if state == "accepted": + percentage_losses = PercentageOfLosses.objects.all() + if percentage_losses.count() > 0: + percentage_losses = percentage_losses.last().percent + else: + return Response({"result": "enter percentage of losses"}, status=status.HTTP_403_FORBIDDEN) + weight = kill_house_complaint.bar.net_weight - (kill_house_complaint.bar.net_weight * ( + (kill_house_complaint.percent / 100) - (percentage_losses / 100))) + bar_info.weight_withs_losses = weight + bar_info.save() + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + unusualcasualties = serializer.create(validated_data=request.data) + unusualcasualties.complaint = kill_house_complaint + if unusualcasualties.state == 'accepted': + kill_house_complaint.state = 'accepted' + kill_house_complaint.save() + if unusualcasualties.state == 'rejected': + unusualcasualties.message = request.data['message'] + kill_house_complaint.state = 'rejected' + kill_house_complaint.message = request.data['message'] + kill_house_complaint.save() + unusualcasualties.save() + inter_dict = { + "operatorname": user.fullname, + "create_date": str(unusualcasualties.create_date), + "role": request.data['role'], + "state": unusualcasualties.state, + } + unusualcasualties.role = inter_dict + unusualcasualties.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + + +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def make_kill_request(request): + user = SystemUserProfile.objects.get(user=request.user) + now = datetime.now().date() + for kill_house in KillHouse.objects.filter(system_address__province=user.province): + debt_amount = 0 + percentage = KillHousePercentage.objects.get(kill_house=kill_house) + total_poultry_request = TotalPoultryRequestQuantity.objects.filter(create_date__year=now.year, + create_date__month=now.month, + create_date__day=now.day).order_by('id') + first_average_weight = 0 + first_assignment_average_weight = 0 + seconde_average_weight = 0 + seconde_assignment_average_weight = 0 + all_assigntments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__killhouse_user=kill_house).order_by('id') + if all_assigntments.count() > 0: + for all_assigntment in all_assigntments: + first_assignment_average_weight += all_assigntment.net_weight / all_assigntment.real_quantity + first_average_weight += round(first_assignment_average_weight / all_assigntments.count(), 2) + four_all_assigntments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__killhouse_user=kill_house).order_by('id')[:4] + + for four_last_assingment in four_all_assigntments: + seconde_assignment_average_weight += four_last_assingment.net_weight / four_last_assingment.real_quantity + seconde_average_weight += round(seconde_assignment_average_weight / four_all_assigntments.count(), 2) + + if total_poultry_request.count() > 0: + total_poultry_request = total_poultry_request.last() + if total_poultry_request.input_quantity != 0: + percentage.quantity = int(((percentage.percent / 100) / 100) * total_poultry_request.input_quantity) + else: + percentage.quantity = int(((percentage.percent / 10000) * total_poultry_request.quantity)) + percentage.save() + poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user=kill_house, + paid_state='pending') + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user=kill_house, + paid_state='pending') + if poultry_factors.count() > 0: + for poultry_factor in poultry_factors: + debt_amount += poultry_factor.total_price + if province_factors.count() > 0: + + for province_factor in province_factors: + debt_amount += province_factor.total_price + + kill_req = KillRequest( + kill_capacity=percentage.quantity, + remain_quantity=percentage.quantity, + recive_time='06 - 14', + recive_date=datetime.now(), + first_average_weight=seconde_average_weight, + second_average_weight=first_average_weight, + kill_house=kill_house + + ) + kill_req.save() + if debt_amount > 0: + kill_req.debt_amount = debt_amount + kill_req.debt = True + kill_req.save() + + return JsonResponse({"msg": "Done"}) + + +class KillHouseNewViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.select_related('kill_house_operator__user').filter(trash=False) + # queryset = KillHouse.objects.filter(trash=False) + serializer_class = KillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + kill_houses = self.queryset.all() + + FullName = [kill_house.kill_house_operator.user.fullname for kill_house in kill_houses] + + return Response(FullName, status=status.HTTP_200_OK) + + +class KillHouseWareHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouseWareHouse.objects.all() + serializer_class = KillHouseWareHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + date = datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else now + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + else: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, + date__date=date, + trash=False).last() + + if kill_house_ware_house is None: + ware_house_date = datetime(year=date.year, month=date.month, day=date.day, hour=1, minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + + bar_quantity = 0 + allocated_quantity = 0 + bar_live_weight = 0 + number_of_carcasses = 0 + update_number_of_carcasses = 0 + weight_of_carcasses = 0 + update_weight_of_carcasses = 0 + ave_weight_of_carcasses = 0 + free_number_of_carcasses = 0 + free_weight_of_carcasses = 0 + free_sale_number_of_carcasses = 0 + free_sale_weight_of_carcasses = 0 + free_bar_quantity = 0 + free_sale_bar_quantity = 0 + total_bar_quantity = 0 + total_number_of_carcasses = 0 + total_weight_of_carcasses = 0 + + # assingments = KillHouseAssignmentInformation.objects.filter(kill_house_request__killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # kill_house_request__kill_request__recive_date__year=date.year, + # kill_house_request__kill_request__recive_date__month=date.month, + # kill_house_request__kill_request__recive_date__day=date.day, + # trash=False).select_related('kill_house_request') + one_day_ago = date - timedelta(days=1) + + kill_house_requests = KillHouseRequest.objects.filter(killhouse_user=kill_house, + kill_request__recive_date__date=one_day_ago, + ware_house_confirmation=True, trash=False) + if kill_house_requests.count() > 0: + for kill_house_request in kill_house_requests: + bar_quantity += 1 + allocated_quantity += kill_house_request.accepted_real_quantity + bar_live_weight += kill_house_request.accepted_real_weight + number_of_carcasses += kill_house_request.ware_house_accepted_real_quantity + weight_of_carcasses += kill_house_request.ware_house_accepted_real_weight + # kill_house_loss_percentage = KillHousePercentageOfLosses.objects.all().last() + # if kill_house_loss_percentage: + # weight_of_carcasses += kill_house_request.accepted_real_weight - ( + # (kill_house_loss_percentage.percent / 100) * kill_house_request.accepted_real_weight) + # else: + # weight_of_carcasses += kill_house_request.accepted_real_weight - ( + # (25 / 100) * kill_house_request.accepted_real_weight) + + ave_weight_of_carcasses += weight_of_carcasses / number_of_carcasses + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, date__date=date, ware_house=True, + trash=False) + freezing_quantity = 0 + freezing_weight = 0 + freezing_bars = ColdHouseAllocations.objects.filter(kill_house_ware_house=kill_house_ware_house, + state__in=('pending', 'accepted'), date__date=date, + trash=False) + if len(freezing_bars) > 0: + for freezing_bar in freezing_bars: + freezing_quantity += freezing_bar.accepted_quantity if freezing_bar.accepted_quantity > 0 else freezing_bar.quantity + freezing_weight += freezing_bar.accepted_weight if freezing_bar.accepted_weight > 0 else freezing_bar.weight + if free_bars.count() > 0: + for free_bar in free_bars: + free_bar_quantity += 1 + free_number_of_carcasses += free_bar.number_of_carcasses + free_weight_of_carcasses += free_bar.weight_of_carcasses + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + date__date=date, + trash=False) + if kill_house_free_sale_bar_info.count() > 0: + for kill_house_free_sale in kill_house_free_sale_bar_info: + free_sale_bar_quantity += 1 + free_sale_number_of_carcasses += kill_house_free_sale.number_of_carcasses + free_sale_weight_of_carcasses += kill_house_free_sale.weight_of_carcasses + + update_number_of_carcasses = kill_house_ware_house.updated_number_of_carcasses + update_weight_of_carcasses = kill_house_ware_house.updated_weight_of_carcasses + total_bar_quantity = bar_quantity + free_bar_quantity + free_sale_bar_quantity + total_number_of_carcasses = number_of_carcasses + free_number_of_carcasses + kill_house_ware_house.pre_cold_number_of_carcasses_to_ware_house + update_total_number_of_carcasses = update_number_of_carcasses + free_number_of_carcasses + kill_house_ware_house.pre_cold_number_of_carcasses_to_ware_house if update_number_of_carcasses > 0 else 0 + total_weight_of_carcasses = weight_of_carcasses + free_weight_of_carcasses + kill_house_ware_house.pre_cold_weight_of_carcasses_to_ware_house + update_total_weight_of_carcasses = update_weight_of_carcasses + free_weight_of_carcasses + kill_house_ware_house.pre_cold_weight_of_carcasses_to_ware_house if update_weight_of_carcasses > 0 else 0 + + kill_house_ware_house.bar_quantity = bar_quantity + kill_house_ware_house.allocated_quantity = allocated_quantity + kill_house_ware_house.bar_live_weight = bar_live_weight + kill_house_ware_house.number_of_carcasses = number_of_carcasses + kill_house_ware_house.update_number_of_carcasses = update_number_of_carcasses + kill_house_ware_house.weight_of_carcasses = weight_of_carcasses + kill_house_ware_house.update_weight_of_carcasses = update_weight_of_carcasses + kill_house_ware_house.ave_weight_of_carcasses = weight_of_carcasses / number_of_carcasses if number_of_carcasses > 0 else 0 + kill_house_ware_house.update_ave_weight_of_carcasses = update_weight_of_carcasses / update_number_of_carcasses if update_number_of_carcasses > 0 else 0 + kill_house_ware_house.free_bar_quantity = free_bar_quantity + kill_house_ware_house.number_of_free_carcasses = free_number_of_carcasses + kill_house_ware_house.free_weight_of_carcasses = free_weight_of_carcasses + kill_house_ware_house.free_sale_quantity = free_sale_number_of_carcasses + kill_house_ware_house.free_sale_weight = free_sale_weight_of_carcasses + kill_house_ware_house.total_bar_quantity = total_bar_quantity + kill_house_ware_house.freezing_quantity = freezing_quantity + kill_house_ware_house.freezing_weight = freezing_weight + kill_house_ware_house.total_number_of_carcasses = total_number_of_carcasses + kill_house_ware_house.update_total_number_of_carcasses = update_total_number_of_carcasses + kill_house_ware_house.total_weight_of_carcasses = total_weight_of_carcasses + kill_house_ware_house.update_total_weight_of_carcasses = update_total_weight_of_carcasses + if update_total_weight_of_carcasses == 0: + kill_house_ware_house.remain_total_weight_of_carcasses = total_weight_of_carcasses - kill_house_ware_house.allocated_total_weight_of_carcasses if kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house == 0 else 0 + else: + kill_house_ware_house.remain_total_weight_of_carcasses = update_total_weight_of_carcasses - kill_house_ware_house.allocated_total_weight_of_carcasses if kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house == 0 else 0 + if update_total_number_of_carcasses == 0: + kill_house_ware_house.remain_total_number_of_carcasses = total_number_of_carcasses - kill_house_ware_house.allocated_total_number_of_carcasses if kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house == 0 else 0 + else: + kill_house_ware_house.remain_total_number_of_carcasses = update_total_number_of_carcasses - kill_house_ware_house.allocated_total_number_of_carcasses if kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house == 0 else 0 + kill_house_ware_house.final_total_number_of_carcasses = kill_house_ware_house.update_total_number_of_carcasses if kill_house_ware_house.update_total_number_of_carcasses > 0 else kill_house_ware_house.total_number_of_carcasses + kill_house_ware_house.final_total_weight_of_carcasses = kill_house_ware_house.update_total_weight_of_carcasses if kill_house_ware_house.update_total_weight_of_carcasses > 0 else kill_house_ware_house.total_weight_of_carcasses + kill_house_ware_house.save() + + if 'state' in request.GET: + total_number_of_carcasses_temp = kill_house_ware_house.update_total_number_of_carcasses if kill_house_ware_house.update_total_number_of_carcasses > 0 else kill_house_ware_house.total_number_of_carcasses + total_weight_of_carcasses_temp = kill_house_ware_house.update_total_weight_of_carcasses if kill_house_ware_house.update_total_weight_of_carcasses > 0 else kill_house_ware_house.total_weight_of_carcasses + update_fields = { + "ware_house_key": kill_house_ware_house.key, + "total_number_of_carcasses": kill_house_ware_house.final_total_number_of_carcasses, + "pre_cold_number_of_carcasses_self_ware_house": kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house, + "pre_cold_weight_of_carcasses_self_ware_house": kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house, + "total_weight_of_carcasses": kill_house_ware_house.final_total_weight_of_carcasses, + "allocated_total_number_of_carcasses": kill_house_ware_house.allocated_total_number_of_carcasses, + "allocated_total_weight_of_carcasses": kill_house_ware_house.allocated_total_weight_of_carcasses, + "remain_total_number_of_carcasses": kill_house_ware_house.remain_total_number_of_carcasses, + "remain_total_weight_of_carcasses": kill_house_ware_house.remain_total_weight_of_carcasses, + "freezing_quantity": kill_house_ware_house.freezing_quantity, + "freezing_weight": kill_house_ware_house.freezing_weight, + "free_sale_quantity": kill_house_ware_house.free_sale_quantity, + "free_sale_weight": kill_house_ware_house.free_sale_weight, + "total_average_weight_of_carcasses": round( + kill_house_ware_house.final_total_weight_of_carcasses / kill_house_ware_house.final_total_number_of_carcasses, + 2) if kill_house_ware_house.final_total_number_of_carcasses > 0 else 0, + + } + return Response(update_fields, status=status.HTTP_200_OK) + + serializer = KillHouseWareHouseSerializer(kill_house_ware_house) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + ware_house = KillHouseWareHouse.objects.get(key=request.data['key']) + ware_house.updated_number_of_carcasses = int(request.data['updated_number_of_carcasses']) + ware_house.updated_weight_of_carcasses = request.data['updated_weight_of_carcasses'] + ware_house.total_weight_of_carcasses = request.data[ + 'updated_weight_of_carcasses'] + ware_house.free_weight_of_carcasses + ware_house.total_number_of_carcasses = int(request.data[ + 'updated_number_of_carcasses']) + ware_house.number_of_free_carcasses + ware_house.save() + serializer = self.serializer_class(ware_house) + serializer.update(instance=ware_house, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseWareHouseForDispensersViewSet(viewsets.ModelViewSet): + queryset = KillHouseWareHouse.objects.all() + serializer_class = KillHouseWareHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] in ('CityCommerce', 'CityJahad', 'CityPoultry', 'CityOperator'): + kill_house_ware_houses = KillHouseWareHouse.objects.filter(kill_house__system_address__city=user.city, + date__date__gte=date1, date__date__lte=date2, + trash=False) + else: + kill_house_ware_houses = KillHouseWareHouse.objects.filter(date__date__gte=date1, date__date__lte=date2, + trash=False) + result = { + "kill_houses": len(kill_house_ware_houses.values_list('kill_house', flat=True).distinct()), + + "total_number_of_carcasses": kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] or 0, + "total_weight_of_carcasses": kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] or 0, + "pre_cold_number_of_carcasses_self_ware_house": + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_self_ware_house'))[ + 'total'] or 0, + "pre_cold_weight_of_carcasses_self_ware_house": + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_self_ware_house'))[ + 'total'] or 0, + "allocated_total_number_of_carcasses": + kill_house_ware_houses.aggregate(total=Sum('allocated_total_number_of_carcasses'))['total'] or 0, + "allocated_total_weight_of_carcasses": + kill_house_ware_houses.aggregate(total=Sum('allocated_total_weight_of_carcasses'))['total'] or 0, + "remain_total_number_of_carcasses": + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))['total'] or 0, + "remain_total_weight_of_carcasses": + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))['total'] or 0, + "freezing_quantity": kill_house_ware_houses.aggregate(total=Sum('freezing_quantity'))['total'] or 0, + "freezing_weight": kill_house_ware_houses.aggregate(total=Sum('freezing_weight'))['total'] or 0, + "free_sale_quantity": kill_house_ware_houses.aggregate(total=Sum('free_sale_quantity'))['total'] or 0, + "free_sale_weight": kill_house_ware_houses.aggregate(total=Sum('free_sale_weight'))['total'] or 0 + } + + return Response(result, status=status.HTTP_200_OK) + + +class PreColdKillHouseWareHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouseWareHouse.objects.all() + serializer_class = KillHouseWareHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + now = datetime.now().date() + kill_house_ware_house = KillHouseWareHouse.objects.get(key=request.data['ware_house_key']) + if kill_house_ware_house.date.date() != now: + return Response({"result": "به علت مغایرت تاریخ امکان پیش سرد وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + tomorrow = kill_house_ware_house.date + timedelta(days=1) + kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house = kill_house_ware_house.remain_total_number_of_carcasses + kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house = kill_house_ware_house.remain_total_weight_of_carcasses + kill_house_ware_house.remain_total_number_of_carcasses = 0 + kill_house_ware_house.remain_total_weight_of_carcasses = 0 + kill_house_ware_house.save() + tomorrow_kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house_ware_house.kill_house, + date__date=tomorrow.date()).first() + if not tomorrow_kill_house_ware_house: + tomorrow_kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_house_ware_house.kill_house, + date=kill_house_ware_house.date + timedelta(days=1) + ) + tomorrow_kill_house_ware_house.save() + tomorrow_kill_house_ware_house.final_total_number_of_carcasses += kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.total_number_of_carcasses += kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.final_total_weight_of_carcasses += kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.total_weight_of_carcasses += kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.remain_total_number_of_carcasses += kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.remain_total_weight_of_carcasses += kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.pre_cold_number_of_carcasses_to_ware_house = kill_house_ware_house.pre_cold_number_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.pre_cold_weight_of_carcasses_to_ware_house = kill_house_ware_house.pre_cold_weight_of_carcasses_self_ware_house + tomorrow_kill_house_ware_house.save() + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_201_CREATED) + + +class KillHouseFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeSaleBarInformation.objects.all() + serializer_class = KillHouseFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeSaleBarInformationFilterSet + filterset_fields = [ + 'type_car', + 'pelak', + 'clearance_code', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'buyer__fullname', + 'buyer__first_name', + 'buyer__last_name', + 'buyer__mobile', + 'buyer__unit_name', + 'buyer_name', + 'buyer_mobile', + 'province', + 'city', + + ] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + now_time = datetime.now().time() + quota = request.data['quota'] + buyer = None + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + if 'kill_house_key' in request.data.keys(): + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + request.data.pop('kill_house_key') + elif 'buyer_key' in request.data.keys(): + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + buyer = OutProvinceCarcassesBuyer.objects.get(key=request.data['buyer_key']) + request.data.pop('buyer_key') + product = RolesProducts.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + date = datetime(year=date.year, month=date.month, day=date.day, hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('date') + request.data.pop('production_date') + if OperationLimitation.objects.all().first().kill_house_free_sale_limitation == True: + + if now != date.date(): + return Response({"result": "به علت مغایرت تاریخ امکان فروش بار وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + carcass_distribution = RestrictionCarcassDistribution.objects.filter(trash=False, + distribution_type='KillHouse', + allow=True, + out=True).first() + if carcass_distribution and datetime.now().time() > carcass_distribution.time: + return Response({"result": "لطفا در ساعات مجاز اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + # ware_house = KillHouseWareHouse.objects.get(kill_house=kill_house, date__date=date) + # if request.data['weight_of_carcasses'] > ware_house.remain_total_weight_of_carcasses: + # return Response({"result": "تعداد یا مقدار وارد شده از موجودی انبار بیشتر است !"}, + # status=status.HTTP_403_FORBIDDEN) + kill_house_total_input_warehouse_governmental_weight = kill_house.total_input_warehouse_governmental_weight + kill_house_total_input_warehouse_free_weight = kill_house.total_input_warehouse_free_weight + + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + free_sale_type = request.data['sale_type'] + if kill_house.governmental_selling_permission: + if free_sale_type == 'free': + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_selling_out_province_governmental_weight > 0: + if kill_house.total_selling_out_province_governmental_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_selling_out_province_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_selling_out_province_free_weight > 0: + if kill_house.total_selling_out_province_free_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_selling_out_province_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + ware_house_remain_weight = product.total_remain_weight + allocations_weight = StewardAllocation.objects.filter(trash=False, receiver_state__in=('pending', 'accepted'), + kill_house=kill_house, date__date=now).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + free_sales_weight = \ + KillHouseFreeSaleBarInformation.objects.filter(trash=False, kill_house=kill_house, + date__date=now).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_weight = ware_house_remain_weight + allocations_weight + free_sales_weight + free_sales_weight += request.data['weight_of_carcasses'] + + # if kill_house.in_province_selling_limitation and kill_house.in_province_selling_limitation_percent > 0: + # in_province_limitation_weight = int( + # total_weight * (kill_house.in_province_selling_limitation_percent / 100)) + # if allocations_weight < in_province_limitation_weight: + # return Response( + # {"result": "به دلیل عدم رعایت حداقل فروش/توزیع داخل استان امکان فروش به خارج استان وجود ندارد!"}, + # status=status.HTTP_403_FORBIDDEN) + # + # if kill_house.out_province_selling_limitation and kill_house.out_province_selling_limitation_percent > 0: + # max_out_province_limitation_weight = int( + # total_weight * (kill_house.out_province_selling_limitation_percent / 100)) + # if free_sales_weight > max_out_province_limitation_weight: + # return Response({"result": "سقف فروش به خارج استان امروز شما پر شده است!"}, + # status=status.HTTP_403_FORBIDDEN) + if KillHouseFreeSaleBarInformation.objects.filter(trash=False, clearance_code=request.data['clearance_code'], + quarantine_weight_of_carcasses__gt=0).exists(): + return Response({"result": "کد قرنطینه در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_free_sale_bar_info = serializer.create(validated_data=request.data) + kill_house_free_sale_bar_info.kill_house = kill_house + if buyer is not None: + kill_house_free_sale_bar_info.buyer = buyer + kill_house_free_sale_bar_info.buyer_name = buyer.fullname + kill_house_free_sale_bar_info.buyer_mobile = buyer.mobile + kill_house_free_sale_bar_info.city = buyer.city + kill_house_free_sale_bar_info.province = buyer.province + + kill_house_free_sale_bar_info.date = date + kill_house_free_sale_bar_info.production_date = production_date + kill_house_free_sale_bar_info.product = product + kill_house_free_sale_bar_info.dispenser = dispenser if dispenser else None + kill_house_free_sale_bar_info.representative = representative if representative else None + kill_house_free_sale_bar_info.real_number_of_carcasses = kill_house_free_sale_bar_info.number_of_carcasses + kill_house_free_sale_bar_info.real_weight_of_carcasses = kill_house_free_sale_bar_info.weight_of_carcasses + # ware_house.allocated_total_number_of_carcasses += kill_house_free_sale_bar_info.number_of_carcasses + # ware_house.allocated_total_weight_of_carcasses += kill_house_free_sale_bar_info.weight_of_carcasses + # ware_house.save() + + wage = 0 + wage_type = WageType.objects.filter(en_name='carcasse-sell', trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + kill_house_free_sale_bar_info.wage = wage + kill_house_free_sale_bar_info.total_wage_amount = wage * kill_house_free_sale_bar_info.real_weight_of_carcasses + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + kill_house_free_sale_bar_info.union_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.union_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'company': + kill_house_free_sale_bar_info.company_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + kill_house_free_sale_bar_info.guilds_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.guilds_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'city': + kill_house_free_sale_bar_info.city_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + kill_house_free_sale_bar_info.wallet_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.wallet_share_percent = percentage_wage_type.percent + + else: + kill_house_free_sale_bar_info.other_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.other_share_percent = percentage_wage_type.percent + kill_house_free_sale_bar_info.save() + allow_register_code = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + number = random.randint(10000, 99000) + kill_house_free_sale_bar_info.registration_code = number + kill_house_free_sale_bar_info.system_registration_code = True + if int(allow_register_code.time) > 0: + kill_house_free_sale_bar_info.active_expire_date_time = True + kill_house_free_sale_bar_info.expire_date_time_registration_code = datetime.now() + timedelta( + minutes=int(allow_register_code.time)) + kill_house_free_sale_bar_info.save() + send_sms_for_sale_bar(kill_house_free_sale_bar_info) + get_gid_out_province(kill_house_free_sale_bar_info.id) + kill_house_free_sale_product_warehousing(product) + return Response(serializer.data, status=status.HTTP_201_CREATED) + # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + kill_house_key = request.GET.get('kill_house_key') + if 'type' in request.GET: + role = request.GET['role'] + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + + if role in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + if kill_house_key and kill_house_key != 'all': + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house__key=kill_house_key, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + + elif role in ['CityJahad', 'CityPoultry', 'CityOperator']: + + if kill_house_key and kill_house_key != 'all': + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + kill_house__key=kill_house_key, + trash=False) + + else: + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + + + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + else: + if role in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + + if kill_house_key and kill_house_key != 'all': + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, kill_house__key=kill_house_key) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + trash=False) + + + elif role in ['CityJahad', 'CityPoultry', 'CityOperator']: + if kill_house_key and kill_house_key != 'all': + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + trash=False, kill_house__key=kill_house_key) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + trash=False) + + + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False) + + if 'search' in request.GET: + kill_house_free_sale_bar_info_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_sale_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_sale_bar_info) + kill_house_free_sale_bar_info_list = ps.filter() + kill_house_free_sale_bar_info = [] if len( + kill_house_free_sale_bar_info_list) == 0 else kill_house_free_sale_bar_info_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_free_sale_bar_info) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + else: + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + date__year=date.year, + date__month=date.month, + date__day=date.day, + trash=False) + + serializer = self.serializer_class(kill_house_free_sale_bar_info, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + free_sale_bar = KillHouseFreeSaleBarInformation.objects.get(key=request.data['key']) + product = free_sale_bar.product + kill_house = free_sale_bar.kill_house + if KillHouseFreeSaleBarInformation.objects.filter(trash=False, + clearance_code=request.data.get('clearance_code'), + quarantine_weight_of_carcasses__gt=0).exists() and 'register_code' not in request.data.keys(): + return Response({"result": "کد قرنطینه در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + now = datetime.now().date() + if free_sale_bar.quota == 'governmental': + if free_sale_bar.kill_house.total_input_warehouse_governmental_weight < ( + ( + free_sale_bar.kill_house.total_selling_warehouse_governmental_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if free_sale_bar.kill_house.total_input_warehouse_free_weight < ( + (free_sale_bar.kill_house.total_selling_warehouse_free_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + allow_register_code = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + if 'register_code' in request.data.keys(): + code = request.data['register_code'] + if code != free_sale_bar.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + free_sale_bar.logged_registration_code = code + request.data.pop('register_code') + free_sale_bar.save() + serializer = self.serializer_class(free_sale_bar) + + serializer.update(instance=free_sale_bar, validated_data=request.data) + kill_house_free_sale_product_warehousing(product) + free_sale_bar.real_number_of_carcasses = free_sale_bar.number_of_carcasses + free_sale_bar.real_weight_of_carcasses = free_sale_bar.weight_of_carcasses + free_sale_bar.total_wage_amount = free_sale_bar.wage * free_sale_bar.real_weight_of_carcasses + free_sale_bar.save() + kill_house_free_sale_product_warehousing(product) + + union_percent = free_sale_bar.union_share_percent / 100 if free_sale_bar.union_share_percent > 0 else 0 + company_percent = free_sale_bar.company_share_percent / 100 if free_sale_bar.company_share_percent > 0 else 0 + guilds_percent = free_sale_bar.guilds_share_percent / 100 if free_sale_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_sale_bar.city_share_percent / 100 if free_sale_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_sale_bar.wallet_share_percent / 100 if free_sale_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_sale_bar.other_share_percent / 100 if free_sale_bar.other_share_percent > 0 else 0 + free_sale_bar.union_share = int(union_percent * free_sale_bar.total_wage_amount) + free_sale_bar.company_share = int(company_percent * free_sale_bar.total_wage_amount) + free_sale_bar.guilds_share = int(guilds_percent * free_sale_bar.total_wage_amount) + free_sale_bar.city_share = int(city_share_percent * free_sale_bar.total_wage_amount) + free_sale_bar.wallet_share = int(wallet_share_percent * free_sale_bar.total_wage_amount) + free_sale_bar.other_share = int(other_share_percent * free_sale_bar.total_wage_amount) + + get_gid_out_province(free_sale_bar.id) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_sale_bar = KillHouseFreeSaleBarInformation.objects.get(key=request.GET['key']) + product = free_sale_bar.product + + # ware_house = KillHouseWareHouse.objects.get(kill_house=free_sale_bar.kill_house, + # date__date=free_sale_bar.date.date(), trash=False) + # + # if ware_house.allocated_total_number_of_carcasses != free_sale_bar.real_number_of_carcasses or ware_house.allocated_total_weight_of_carcasses != free_sale_bar.real_weight_of_carcasses: + # if ware_house.remain_total_number_of_carcasses < free_sale_bar.real_number_of_carcasses or ware_house.remain_total_weight_of_carcasses < free_sale_bar.real_weight_of_carcasses: + # return Response({"result": "به علت تخصیص بار به مباشرین و صنف ها امکان حذف بار وجود ندارد!"}, + # status=status.HTTP_403_FORBIDDEN) + free_sale_bar.trash = True + free_sale_bar.save() + kill_house_free_sale_product_warehousing(product) + + # + # ware_house.allocated_total_number_of_carcasses -= free_sale_bar.real_number_of_carcasses + # ware_house.allocated_total_weight_of_carcasses -= free_sale_bar.real_weight_of_carcasses + # ware_house.save() + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class PosKillHouseFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeSaleBarInformation.objects.all() + serializer_class = KillHouseFreeSaleBarInformationSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeSaleBarInformationFilterSet + filterset_fields = [ + 'type_car', + 'pelak', + 'clearance_code', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'buyer__fullname', + 'buyer__first_name', + 'buyer__last_name', + 'buyer__mobile', + 'buyer__unit_name', + 'buyer_name', + 'buyer_mobile', + 'province', + 'city', + + ] + + def create(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + now_time = datetime.now().time() + quota = request.data['quota'] + pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False) + kill_house = pos.kill_house + buyer = OutProvinceCarcassesBuyer.objects.get(key=request.data['buyer_key']) + request.data.pop('buyer_key') + product = RolesProducts.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + request.data.pop('pos-id') + date = datetime.now() + # date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + # date = datetime(year=date.year, month=date.month, day=date.day, hour=now_time.hour, + # minute=now_time.minute, + # second=now_time.second) + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + # request.data.pop('date') + request.data.pop('production_date') + if OperationLimitation.objects.all().first().kill_house_free_sale_limitation == True: + + if now != date.date(): + return Response({"result": "به علت مغایرت تاریخ امکان فروش بار وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + carcass_distribution = RestrictionCarcassDistribution.objects.filter(trash=False, + distribution_type='KillHouse', + allow=True, + out=True).first() + if carcass_distribution and datetime.now().time() > carcass_distribution.time: + return Response({"result": "لطفا در ساعات مجاز اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + free_sale_type = request.data['sale_type'] + if kill_house.governmental_selling_permission: + if free_sale_type == 'free': + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_selling_out_province_governmental_weight > 0: + if kill_house.total_selling_out_province_governmental_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_selling_out_province_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_selling_out_province_free_weight > 0: + if kill_house.total_selling_out_province_free_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_selling_out_province_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + ware_house_remain_weight = product.total_remain_weight + allocations_weight = StewardAllocation.objects.filter(trash=False, receiver_state__in=('pending', 'accepted'), + kill_house=kill_house, date__date=now).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + free_sales_weight = \ + KillHouseFreeSaleBarInformation.objects.filter(trash=False, kill_house=kill_house, + date__date=now).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_weight = ware_house_remain_weight + allocations_weight + free_sales_weight + free_sales_weight += request.data['weight_of_carcasses'] + + if KillHouseFreeSaleBarInformation.objects.filter(trash=False, clearance_code=request.data['clearance_code'], + quarantine_weight_of_carcasses__gt=0).exists(): + return Response({"result": "کد قرنطینه در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_free_sale_bar_info = serializer.create(validated_data=request.data) + kill_house_free_sale_bar_info.kill_house = kill_house + if buyer is not None: + kill_house_free_sale_bar_info.buyer = buyer + kill_house_free_sale_bar_info.buyer_name = buyer.fullname + kill_house_free_sale_bar_info.buyer_mobile = buyer.mobile + kill_house_free_sale_bar_info.city = buyer.city + kill_house_free_sale_bar_info.province = buyer.province + + kill_house_free_sale_bar_info.date = date + kill_house_free_sale_bar_info.production_date = production_date + kill_house_free_sale_bar_info.product = product + kill_house_free_sale_bar_info.real_number_of_carcasses = kill_house_free_sale_bar_info.number_of_carcasses + kill_house_free_sale_bar_info.real_weight_of_carcasses = kill_house_free_sale_bar_info.weight_of_carcasses + + wage = 0 + wage_type = WageType.objects.filter(en_name='carcasse-sell', trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + kill_house_free_sale_bar_info.wage = wage + kill_house_free_sale_bar_info.total_wage_amount = wage * kill_house_free_sale_bar_info.real_weight_of_carcasses + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + kill_house_free_sale_bar_info.union_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.union_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'company': + kill_house_free_sale_bar_info.company_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + kill_house_free_sale_bar_info.guilds_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.guilds_share_percent = percentage_wage_type.percent + elif percentage_wage_type.share_type.en_name == 'city': + kill_house_free_sale_bar_info.city_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + kill_house_free_sale_bar_info.wallet_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.wallet_share_percent = percentage_wage_type.percent + + else: + kill_house_free_sale_bar_info.other_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_sale_bar_info.total_wage_amount) + kill_house_free_sale_bar_info.other_share_percent = percentage_wage_type.percent + kill_house_free_sale_bar_info.save() + allow_register_code = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + number = random.randint(10000, 99000) + kill_house_free_sale_bar_info.registration_code = number + kill_house_free_sale_bar_info.system_registration_code = True + if int(allow_register_code.time) > 0: + kill_house_free_sale_bar_info.active_expire_date_time = True + kill_house_free_sale_bar_info.expire_date_time_registration_code = datetime.now() + timedelta( + minutes=int(allow_register_code.time)) + kill_house_free_sale_bar_info.save() + send_sms_for_sale_bar(kill_house_free_sale_bar_info) + get_gid_out_province(kill_house_free_sale_bar_info.id) + kill_house_free_sale_product_warehousing(product) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET['role'] + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=pos.kill_house, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=pos.kill_house, + trash=False) + + if 'search' in request.GET: + kill_house_free_sale_bar_info_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_sale_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_sale_bar_info) + kill_house_free_sale_bar_info_list = ps.filter() + kill_house_free_sale_bar_info = [] if len( + kill_house_free_sale_bar_info_list) == 0 else kill_house_free_sale_bar_info_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_free_sale_bar_info) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(kill_house_free_sale_bar_info, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + free_sale_bar = KillHouseFreeSaleBarInformation.objects.get(key=request.data['key']) + product = free_sale_bar.product + kill_house = free_sale_bar.kill_house + if KillHouseFreeSaleBarInformation.objects.filter(trash=False, + clearance_code=request.data.get('clearance_code'), + quarantine_weight_of_carcasses__gt=0).exists(): + return Response({"result": "کد قرنطینه در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + now = datetime.now().date() + + if free_sale_bar.quota == 'governmental': + if free_sale_bar.kill_house.total_input_warehouse_governmental_weight < ( + ( + free_sale_bar.kill_house.total_selling_warehouse_governmental_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if free_sale_bar.kill_house.total_input_warehouse_free_weight < ( + (free_sale_bar.kill_house.total_selling_warehouse_free_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + allow_register_code = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + if 'register_code' in request.data.keys(): + code = request.data['register_code'] + if code != free_sale_bar.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + free_sale_bar.logged_registration_code = code + request.data.pop('register_code') + free_sale_bar.save() + serializer = self.serializer_class(free_sale_bar) + + serializer.update(instance=free_sale_bar, validated_data=request.data) + kill_house_free_sale_product_warehousing(product) + free_sale_bar.real_number_of_carcasses = free_sale_bar.number_of_carcasses + free_sale_bar.real_weight_of_carcasses = free_sale_bar.weight_of_carcasses + free_sale_bar.total_wage_amount = free_sale_bar.wage * free_sale_bar.real_weight_of_carcasses + free_sale_bar.save() + kill_house_free_sale_product_warehousing(product) + + union_percent = free_sale_bar.union_share_percent / 100 if free_sale_bar.union_share_percent > 0 else 0 + company_percent = free_sale_bar.company_share_percent / 100 if free_sale_bar.company_share_percent > 0 else 0 + guilds_percent = free_sale_bar.guilds_share_percent / 100 if free_sale_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_sale_bar.city_share_percent / 100 if free_sale_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_sale_bar.wallet_share_percent / 100 if free_sale_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_sale_bar.other_share_percent / 100 if free_sale_bar.other_share_percent > 0 else 0 + free_sale_bar.union_share = int(union_percent * free_sale_bar.total_wage_amount) + free_sale_bar.company_share = int(company_percent * free_sale_bar.total_wage_amount) + free_sale_bar.guilds_share = int(guilds_percent * free_sale_bar.total_wage_amount) + free_sale_bar.city_share = int(city_share_percent * free_sale_bar.total_wage_amount) + free_sale_bar.wallet_share = int(wallet_share_percent * free_sale_bar.total_wage_amount) + free_sale_bar.other_share = int(other_share_percent * free_sale_bar.total_wage_amount) + + get_gid_out_province(free_sale_bar.id) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_sale_bar = KillHouseFreeSaleBarInformation.objects.get(key=request.GET['key']) + product = free_sale_bar.product + free_sale_bar.trash = True + free_sale_bar.save() + kill_house_free_sale_product_warehousing(product) + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class KillHouseFreeSaleBarInformationDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeSaleBarInformation.objects.all() + serializer_class = KillHouseFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeSaleBarInformationFilterSet + filterset_fields = [ + 'type_car', + 'pelak', + 'clearance_code', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'buyer__fullname', + 'buyer__first_name', + 'buyer__last_name', + 'buyer__mobile', + 'buyer__unit_name', + 'buyer_name', + 'buyer_mobile', + 'province', + 'city', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET['role'] + kill_house_key = request.GET.get('kill_house_key') + date1 = request.GET['date1'] + date2 = request.GET['date2'] + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + if role in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + if date1: + ware_houses = KillHouseWareHouse.objects.filter(date__date__gte=date1, + date__date__lte=date2) + if kill_house_key and kill_house_key != 'all': + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + kill_house__key=kill_house_key, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + else: + ware_houses = KillHouseWareHouse.objects.filter(trash=False) + + if kill_house_key and kill_house_key != 'all': + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + kill_house__key=kill_house_key, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + kill_houses = KillHouse.objects.filter(trash=False, + pk__in=kill_house_free_sale_bar_info.values_list('kill_house', + flat=True)) + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + + + + elif role in ['CityJahad', 'CityPoultry', 'CityOperator']: + if date1: + + ware_houses = KillHouseWareHouse.objects.filter(kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2) + + if kill_house_key and kill_house_key != 'all': + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + kill_house__key=kill_house_key, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + else: + ware_houses = KillHouseWareHouse.objects.filter(kill_house__system_address__city=user.city, trash=False) + if kill_house_key and kill_house_key != 'all': + + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + kill_house__key=kill_house_key, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + kill_houses = KillHouse.objects.filter(trash=False, + pk__in=kill_house_free_sale_bar_info.values_list('kill_house', + flat=True)) + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + + + + else: + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if date1: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + else: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_houses, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False) + + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + if 'search' in request.GET: + kill_house_free_sale_bar_info_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_sale_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_sale_bar_info) + kill_house_free_sale_bar_info_list = ps.filter() + kill_house_free_sale_bar_info = [] if len( + kill_house_free_sale_bar_info_list) == 0 else kill_house_free_sale_bar_info_list + + if role == 'KillHouse': + result = { + "number_of_allocations": len(kill_house_free_sale_bar_info), + "number_of_buyers": buyers, + "total_number_of_allocation_carcasses": + kill_house_free_sale_bar_info.aggregate(total=Sum('number_of_carcasses'))['total'] or 0, + "total_weight_of_allocation_carcasses": + kill_house_free_sale_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0, + + } + + else: + result = { + "number_of_kill_houses": len(kill_houses), + "number_of_allocations": len(kill_house_free_sale_bar_info), + "number_of_buyers": buyers, + "total_number_of_allocation_carcasses": + kill_house_free_sale_bar_info.aggregate(total=Sum('number_of_carcasses'))['total'] or 0, + "total_weight_of_allocation_carcasses": int( + kill_house_free_sale_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0), + "remain_total_number_of_carcasses": + ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0, + "remain_total_weight_of_carcasses": + ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0, + + } + + return Response(result, status=status.HTTP_200_OK) + + +class KillHousebuyersDashboarForFreeSaleBarInformationdViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForKillHouseVetKillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + role = request.GET['role'] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + else: + kill_house = KillHouse.objects.filter(key=request.GET['kill_house_key'], kill_house_operator__user=user, + trash=False).first() + + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=kill_house, trash=False) + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, kill_house=kill_house) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + result = { + "buyers": len(buyers), + "number_of_requests": len(free_sales), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + return Response({"result": result}, status=status.HTTP_200_OK) + + +class KillHouseFreeBarInformationforWageTotalViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeBarInformation.objects.all() + serializer_class = KillHouseFreeBarInformationForWageTotalSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type = request.GET['type'] + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + else: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['role'] == 'ProvinceOperator': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif request.GET['role'] == 'Guilds': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + else: + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + trash=False).order_by('id') + + else: + if request.GET['role'] == 'ProvinceOperator': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + union_share__gt=0, + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + company_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif request.GET['role'] == 'Guilds': + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + guilds_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + else: + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + buy_type=type, + archive_wage=False, + trash=False).order_by('id') + + if 'search' in request.GET: + kill_house_free_bar_info_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_free_bar_info) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(kill_house_free_bar_info, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeBarInformation.objects.all() + serializer_class = KillHouseFreeBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'bar_code', + 'city', + 'driver_name', + 'driver_mobile', + 'bar_clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + def create(self, request, *args, **kwargs): + killer = None + now_time = datetime.now().time() + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + free_commitment_percent = kill_house.out_province_free_buying_commitment_percent + if 'bar_clearance_code' in request.data.keys(): + if KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=request.data[ + 'bar_clearance_code']).exists(): + return Response({'result': 'کد قرنطینه قبلا در سامانه ثبت شده است!'}, status=status.HTTP_403_FORBIDDEN) + if 'product_key' not in request.data.keys(): + return Response({'result': 'لطفا محصول را انتخاب کنید!'}, status=status.HTTP_403_FORBIDDEN) + product = RolesProducts.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + if 'killer_key' in request.data.keys() and request.data['killer_key'] != None: + killer = KillHouse.objects.get(key=request.data['killer_key']) + request.data.pop('killer_key') + + try: + image = request.data['bar_image'] + request.data.pop('bar_image') + except: + image = None + date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + date = datetime(year=date.year, month=date.month, day=date.day, hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('date') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + kill_house_free_bar_info = serializer.create(validated_data=request.data) + if image != None: + kill_house_free_bar_info.bar_image = send_image_to_server(image) + kill_house_free_bar_info.kill_house = kill_house + kill_house_free_bar_info.date = date + if kill_house_free_bar_info.buy_type == 'carcass': + kill_house_free_bar_info.warehouse_commitment_weight = int( + (free_commitment_percent / 100) * int(kill_house_free_bar_info.weight_of_carcasses)) + + kill_house_free_bar_info.ware_house = True + if killer: + if killer.killer and killer.type == 'public': + kill_house_free_bar_info.kill_house = killer + kill_house_free_bar_info.public_killer = kill_house + kill_house_free_bar_info.input_warehouse = killer + product = RolesProducts.objects.get(kill_house=killer, trash=False) + else: + kill_house_free_bar_info.exclusive_killer = killer + kill_house_free_bar_info.input_warehouse = killer + product = RolesProducts.objects.get(kill_house=killer, trash=False) + + else: + kill_house_free_bar_info.input_warehouse = kill_house + kill_house_free_bar_info.product = product + kill_house_free_bar_info.dispenser = dispenser if dispenser else None + kill_house_free_bar_info.representative = representative if representative else None + kill_house_free_bar_info.bar_code = generate_unique_bar_code() + kill_house_free_bar_info.save() + wage = 0 + type = 'live-buy' if kill_house_free_bar_info.buy_type == 'live' else 'carcasse-buy' + wage_type = WageType.objects.filter(en_name=type, trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + kill_house_free_bar_info.wage = wage + kill_house_free_bar_info.total_wage_amount = wage * int( + kill_house_free_bar_info.live_weight) if kill_house_free_bar_info.buy_type == 'live' else wage * int( + kill_house_free_bar_info.weight_of_carcasses) + kill_house_free_bar_info.register_date = datetime.now() + kill_house_free_bar_info.save() + kill_house_free_buying_product_warehousing(product) + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + kill_house_free_bar_info.union_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.union_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'company': + kill_house_free_bar_info.company_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.company_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + kill_house_free_bar_info.guilds_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.guilds_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + elif percentage_wage_type.share_type.en_name == 'city': + kill_house_free_bar_info.city_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.city_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + kill_house_free_bar_info.wallet_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.wallet_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + + else: + kill_house_free_bar_info.other_share = int( + (percentage_wage_type.percent / 100) * kill_house_free_bar_info.total_wage_amount) + kill_house_free_bar_info.other_share_percent = percentage_wage_type.percent + kill_house_free_bar_info.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type = request.GET.get('type') + date_type = request.GET.get('date_type') + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if date_type: + if date_type == 'buy': + + filters = { + 'register_date__date__gte': date1, + 'register_date__date__lte': date2, + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + else: + order_by_type = '-date' + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + else: + filters = { + 'register_date__date__gte': date1, + 'register_date__date__lte': date2, + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + else: + filters = { + 'trash': False, + 'temporary_trash': False, + 'temporary_deleted': False, + 'calculate_status': True + } + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + if kill_houses is not None: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house__in=kill_houses) | Q(exclusive_killer__in=kill_houses) | Q(public_killer__in=kill_houses), + **filters).order_by(order_by_type) + else: + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_free_bar_info) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_free_bar_info, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + free_bar = KillHouseFreeBarInformation.objects.get(key=request.data['key']) + # product = free_bar.product + + if 'live_weight' in request.data.keys(): + if int(request.data['live_weight']) < free_bar.weight_of_carcasses: + return Response( + {"result": "مقدار وارد شده کمتر از وزن لاشه است! "}, + status=status.HTTP_403_FORBIDDEN) + + if 'bar_clearance_code' in request.data.keys(): + existing_bar = KillHouseFreeBarInformation.objects.filter(trash=False, bar_clearance_code=request.data[ + 'bar_clearance_code']).exclude(id=free_bar.id).first() + if existing_bar: + if existing_bar.register_type == 'automatic': + existing_bar.trash = True + existing_bar.save() + else: + return Response({'result': 'کد قرنطینه قبلا در سامانه ثبت شده است!'}, + status=status.HTTP_403_FORBIDDEN) + if 'number_of_carcasses' in request.data.keys(): + now = datetime.now().date() + if OperationLimitation.objects.all().first().kill_house_input_bar_limitation == True: + + if now != free_bar.date.date(): + return Response({"result": "به علت وجود مفایرت در تاریخ ثبت امکان ویرایش وجود ندارد! "}, + status=status.HTTP_403_FORBIDDEN) + + # ware_house = KillHouseWareHouse.objects.filter(kill_house=free_bar.kill_house, + # date__date=free_bar.date.date(), trash=False).first() + # allocation = StewardAllocation.objects.filter(ware_house=ware_house, trash=False) + # + # if len(allocation) > 0: + # if OperationLimitation.objects.all().first().kill_house_input_bar_limitation == True: + # return Response( + # {"result": "به علت وجود تخصیص به مباشر یا صنف برای امروز امکان ویرایش وجود ندارد! "}, + # status=status.HTTP_403_FORBIDDEN) + if 'return_entered_bar' in request.data.keys(): + free_bar.weight_of_carcasses = 0 + free_bar.number_of_carcasses = 0 + free_bar.entered_message = None + free_bar.ware_house = False + if 'bar_image' in request.data.keys(): + if request.data['bar_image'] != " ": + free_bar.bar_image = send_image_to_server(request.data['bar_image']) + free_bar.save() + request.data.pop('bar_image') + if 'kill_house_vet_state' in request.data.keys(): + free_bar.date_of_accept_reject = datetime.now() + free_bar.acceptor_rejector = user.fullname + if 'killer_key' in request.data.keys() and request.data['killer_key'] != None and request.data[ + 'killer_key'] != '': + exclusive_killer = KillHouse.objects.filter(trash=False, key=request.data['killer_key']).first() + if exclusive_killer.killer and exclusive_killer.type == 'public': + if not free_bar.public_killer: + free_bar.public_killer = free_bar.kill_house + free_bar.kill_house = exclusive_killer + free_bar.input_warehouse = exclusive_killer + if free_bar.exclusive_killer: + free_bar.exclusive_killer = None + else: + free_bar.exclusive_killer = exclusive_killer + free_bar.input_warehouse = exclusive_killer + if free_bar.public_killer: + free_bar.kill_house = free_bar.public_killer + free_bar.public_killer = None + request.data.pop('killer_key') + serializer = self.serializer_class(free_bar) + serializer.update(instance=free_bar, validated_data=request.data) + free_commitment_percent = free_bar.kill_house.out_province_free_buying_commitment_percent + free_bar.total_wage_amount = free_bar.wage * int( + free_bar.live_weight) if free_bar.buy_type == 'live' else free_bar.wage * int(free_bar.weight_of_carcasses) + free_bar.warehouse_commitment_weight = int((free_commitment_percent / 100) * int(free_bar.weight_of_carcasses)) + if free_bar.exclusive_killer: + product = RolesProducts.objects.get(kill_house=free_bar.exclusive_killer, trash=False) + free_bar.product = product + free_bar.save() + kill_house_free_buying_product_warehousing(free_bar.product) + union_percent = free_bar.union_share_percent / 100 if free_bar.union_share_percent > 0 else 0 + company_percent = free_bar.company_share_percent / 100 if free_bar.company_share_percent > 0 else 0 + guilds_percent = free_bar.guilds_share_percent / 100 if free_bar.guilds_share_percent > 0 else 0 + city_share_percent = free_bar.city_share_percent / 100 if free_bar.city_share_percent > 0 else 0 + wallet_share_percent = free_bar.wallet_share_percent / 100 if free_bar.wallet_share_percent > 0 else 0 + other_share_percent = free_bar.other_share_percent / 100 if free_bar.other_share_percent > 0 else 0 + free_bar.union_share = int(union_percent * free_bar.total_wage_amount) + free_bar.company_share = int(company_percent * free_bar.total_wage_amount) + free_bar.guilds_share = int(guilds_percent * free_bar.total_wage_amount) + free_bar.city_share = int(city_share_percent * free_bar.total_wage_amount) + free_bar.wallet_share = int(wallet_share_percent * free_bar.total_wage_amount) + free_bar.other_share = int(other_share_percent * free_bar.total_wage_amount) + free_bar.save() + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_bar = KillHouseFreeBarInformation.objects.get(trash=False, key=request.GET['key']) + free_bar.trash = True + free_bar.save() + product = free_bar.product + kill_house_free_buying_product_warehousing(product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class ParentCompanyKillHouseFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeBarInformation.objects.all() + serializer_class = KillHouseFreeBarInformationSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'bar_clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + def list(self, request, *args, **kwargs): + type = request.GET.get('type') + date_type = request.GET.get('date_type') + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = '-create_date' + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if date_type: + if date_type == 'buy': + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + order_by_type = '-date' + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_free_bar_info + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_free_bar_info) + kill_house_free_bar_info_list = ps.filter() + kill_house_free_bar_info = [] if len( + kill_house_free_bar_info_list) == 0 else kill_house_free_bar_info_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_free_bar_info) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_free_bar_info, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseRequestForBarManagementViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'bar_code', + 'traffic_code', + 'clearance_code' + ] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + breed_list = [] + city_list = [] + quantity_list = [] + total_list = [] + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'role' in request.GET: + if request.GET['role'] == 'Poultry': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__user=user, awaiting_payment=True, + trash=False, out=False).order_by('-send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__user=user, inspector='pending', + trash=False, out=False).order_by('-send_date') + else: + now = datetime.now().date() + + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + queryset_lists = PoultryRequest.objects.filter(poultry__user=user, + final_state__in=('pending', 'archive'), + trash=False, out=False).order_by('-send_date') + queryset = [ + queryset_list for queryset_list in queryset_lists + if date1 <= queryset_list.send_date.date() <= date2 + ] + elif request.GET['role'] == 'VetSupervisor': + + if 'check' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'search' in request.GET: + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, temporary_trash=False, temporary_deleted=False, + message__isnull=False + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + non_receipt=False, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + non_receipt=False, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + if 'check' in request.GET: + kill_house_requests = [] + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + if 'deleted_requests' in request.GET: + aggregate_permission = VetFarmAggregatePermission.objects.filter( + trash=False).first() + if aggregate_permission and aggregate_permission.allow == True: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + aggregate_permission = VetFarmAggregatePermission.objects.filter( + trash=False).first() + if aggregate_permission and aggregate_permission.allow == True: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + non_receipt=False, + trash=False + ).select_related('kill_request').order_by( + 'province_request__poultry_request__poultry', 'killhouse_user') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + non_receipt=False, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + non_receipt=False, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + elif 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + else: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + final_state__in=('pending', 'archive'), + trash=False, out=False).order_by('send_date') + else: + queryset = [] + + elif request.GET['role'] == 'ProvinceInspector': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + # elif 'out' in request.GET: + + else: + + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + + if 'check' in request.GET: + kill_house_requests = [] + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'search' in request.GET: + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + non_receipt=False, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + non_receipt=False, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + # list1 = [] + # for c in CityUnit.objects.filter(city__name=user.city.name, trash=False): + # list1.append(c.name) + elif 'waiting' in request.GET: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # awaiting_payment=True, + # trash=False).order_by('send_date') + + queryset = PoultryRequest.objects.filter(city_operator=city_operator, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # inspector='pending', + # trash=False).order_by('send_date') + queryset = PoultryRequest.objects.filter(city_operator=city_operator, + inspector='pending', + trash=False, out=False).order_by('send_date') + else: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # trash=False).order_by( + # 'send_date') + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + queryset_list = PoultryRequest.objects.filter(poultry__city_operator=city_operator.unit_name, + trash=False, out=False, final_state='pending', + ).order_by('send_date') + queryset = [ + poultry_req for poultry_req in queryset_list + if date1 <= poultry_req.send_date.date() <= date2 + ] + + elif request.GET['role'] in ['CityCommerce', 'CityVet', 'CityJahad', 'CityPoultry']: + if 'check' in request.GET: + kill_house_requests = [] + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__city=user.city, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__city=user.city, + non_receipt=False, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__city=user.city, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__city=user.city, + non_receipt=False, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif request.GET['role'] == 'LiveStockSupport': + if 'check' in request.GET: + kill_house_requests = [] + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__freezing=True, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__freezing=True, + non_receipt=False, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__freezing=True, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__freezing=True, + non_receipt=False, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + elif request.GET['role'] == 'ProvinceFinancial': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + elif 'all' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + assignment=True, + final_state='pending', + trash=False, out=False).order_by('send_date') + else: + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor', 'SuperAdmin', 'AdminX', + 'ImprovingLivestock', 'Supporter']: + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + elif 'out' in request.GET: + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now() + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day, + trash=False, out=True).order_by('-send_date') + elif 'check' in request.GET: + kill_house_requests = [] + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, temporary_trash=False, temporary_deleted=False + # message__isnull=False + ).select_related('kill_request') + else: + if 'without_quarantine_code_state' in request.GET and request.GET[ + 'without_quarantine_code_state'] == 'true': + kill_house_requests = KillHouseRequest.objects.filter( + clearance_code__isnull=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + # (Q(trash=False) | Q(trash=True, clearance_code__isnull=False, + # temporary_trash=False, temporary_deleted=False)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + + trash=False + ).select_related('kill_request') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + kill_house_requests = kill_house_requests.filter( + build_query(DashboardEnterLoadInformationFilterSet, value) + ) + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, + # message__isnull=False + ).select_related('kill_request') + else: + if 'without_quarantine_code_state' in request.GET and request.GET[ + 'without_quarantine_code_state'] == 'true': + kill_house_requests = KillHouseRequest.objects.filter( + clearance_code__isnull=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + # (Q(trash=False) | Q(trash=True, clearance_code__isnull=False)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'date1' in request.GET and 'date2' in request.GET: + + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + queryset_lists = PoultryRequest.objects.filter(poultry__address__province=user.province, + trash=False, out=False, + ).order_by('-send_date') + + queryset = [ + queryset_list for queryset_list in queryset_lists + if date1 <= queryset_list.send_date.date() <= date2 + ] + + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # queryset_list = PoultryRequest.objects.filter(poultry__address__province=user.province, + # trash=False, out=False, + # ).order_by('-send_date') + # + # queryset = [] + # queryset = [ + # poultry_req for poultry_req in queryset_list + # if date1 <= poultry_req.send_date.date() <= date2 + # ] + else: + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now() - timedelta(days=2) + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year__gte=date.year, + send_date__month__gte=date.month, + send_date__day__gte=date.day + ).order_by('-send_date') + + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + if 'check' in request.GET: + kill_house_requests = [] + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house) | Q(killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, temporary_trash=False, temporary_deleted=False + # message__isnull=False + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house) | Q(killer__in=kill_house)), + # (Q(trash=False) | Q(trash=True, clearance_code__isnull=False, temporary_trash=False, + # temporary_deleted=False)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house) | Q(killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, temporary_trash=False, temporary_deleted=False + # message__isnull=False + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house) | Q(killer__in=kill_house)), + # (Q(trash=False) | Q(trash=True, clearance_code__isnull=False, temporary_trash=False, + # temporary_deleted=False)), + + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + non_receipt=False, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + if 'date' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + + else: + + if 'type' in request.GET: + if request.GET['type'] == 'auction': + queryset = [] + poultry_req_auctions = PoultryRequestAuction.objects.filter(state='active', + trash=False).order_by( + 'fee').order_by( + 'create_date') + for poultry_req_auction in poultry_req_auctions: + queryset.append( + PoultryRequest.objects.get(id=poultry_req_auction.poultry_request.id, auction=True)) + + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ParentCompanyKillHouseRequestForBarManagementViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'bar_code', + 'traffic_code', + 'clearance_code' + ] + + def list(self, request, *args, **kwargs): + + kill_house_requests = [] + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'search' in request.GET: + + if 'deleted_requests' in request.GET: + + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=True, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + else: + if 'without_quarantine_code_state' in request.GET and request.GET[ + 'without_quarantine_code_state'] == 'true': + kill_house_requests_list = KillHouseRequest.objects.filter( + clearance_code__isnull=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + + ).select_related('kill_request') + else: + kill_house_requests_list = KillHouseRequest.objects.filter( + (Q(trash=False) | Q(trash=True, clearance_code__isnull=False, temporary_trash=False, + temporary_deleted=False)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).select_related('kill_request') + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests_list + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests_list) + kill_house_requests = ps.filter() + else: + kill_house_requests = kill_house_requests_list + else: + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=True, + ).select_related('kill_request') + else: + if 'without_quarantine_code_state' in request.GET and request.GET[ + 'without_quarantine_code_state'] == 'true': + kill_house_requests = KillHouseRequest.objects.filter( + clearance_code__isnull=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + ).select_related('kill_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(trash=False) | Q(trash=True, clearance_code__isnull=False)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).select_related('kill_request') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseRequestForBarManagementWageViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + def list(self, request, *args, **kwargs): + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False) + + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False) + + else: + + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_kill_request__union_share__gt=0, + trash=False) + elif request.GET['role'] == 'Company': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_kill_request__company_share__gt=0, + trash=False) + + elif request.GET['role'] == 'Guilds': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_kill_request__guilds_share__gt=0, + trash=False) + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False) + + else: + if request.GET['role'] == 'ProvinceOperator': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + province_kill_request__union_share__gt=0, + trash=False) + elif request.GET['role'] == 'Company': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + province_kill_request__company_share__gt=0, + trash=False) + + elif request.GET['role'] == 'Guilds': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + province_kill_request__guilds_share__gt=0, + trash=False) + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False) + + if 'search' in request.GET: + kill_house_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_request_list = ps.filter() + kill_house_requests = [] if len(kill_house_request_list) == 0 else kill_house_request_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseRequestForAggregateLoadsViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + # user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house = [] + kill_house_requests_list = [] + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + for kill_house_vet in kill_house_vets: + kill_house.append(kill_house_vet.kill_house) + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if request.GET['role'] in ['CityOperator', 'CityJahad', 'CityPoultry']: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, + + ).order_by('-kill_request__recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_requests_list = ps.filter() + kill_house_requests = [] if len(kill_house_requests_list) == 0 else kill_house_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillingInformationDiscrepancyReportViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestLetterForProvinceVetSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province), + trash=False).select_related( + 'user').first() + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=user.province, + poultry__city_operator=city_operator.unit_name, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, + out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date').annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')), + total_remain_quantity=Sum('remain_quantity'), + total_remain_weight=Sum(F('remain_quantity') * F('Index_weight')), + + ) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=user.province, + poultry__address__city=user.city, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, + out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date').annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')), + total_remain_quantity=Sum('remain_quantity'), + total_remain_weight=Sum(F('remain_quantity') * F('Index_weight')), + + ) + else: + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, + out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date').annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')), + total_remain_quantity=Sum('remain_quantity'), + total_remain_weight=Sum(F('remain_quantity') * F('Index_weight')), + + ) + poultry_request_total_quantity = poultry_requests.aggregate(total=Sum('total_quantity'))['total'] + poultry_request_total_weight = poultry_requests.aggregate(total=Sum('total_weight'))['total'] + poultry_request_total_remain_quantity = poultry_requests.aggregate(total=Sum('total_remain_quantity'))['total'] + poultry_request_remain_weight = poultry_requests.aggregate(total=Sum('total_remain_weight'))['total'] + + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request__in=poultry_requests, trash=False, + state__in=('pending', 'accepted')).annotate( + total_quantity=Sum('main_quantity'), + total_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight')), + ) + + province_kill_requests_total_quantity = province_kill_requests.aggregate(total=Sum('total_quantity'))['total'] + province_kill_requests_total_weight = province_kill_requests.aggregate(total=Sum('total_weight'))['total'] + + province_kill_requests_with_left_over = ProvinceKillRequest.objects.filter( + province_request__poultry_request__in=poultry_requests, trash=False, + state__in=('pending', 'accepted'), quantity__gt=0) + province_kill_requests_serializer = ProvinceKillRequestForKillingInformationDiscrepancyReportSerializer( + province_kill_requests_with_left_over, many=True) + # if 'role' in request.GET: + # if request.GET['role'] == 'ProvinceSupervisor': + # last_date = datetime(2024, 4, 14, 7, 33).date() + # if date2 > last_date and date1 <= last_date: + # kill_house_request_without_clearance_code = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=last_date, clearance_code__isnull=True, trash=False) + # + # kill_house_request_diffrent_quarantine_quantity = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), + # province_kill_request__in=province_kill_requests, clearance_code__isnull=False, + # quarantine_quantity__isnull=False, trash=False) + # kill_house_request_without_vet_check = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=last_date, vet_state='pending', trash=False) + # kill_house_request_without_bar_info = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=last_date, vet_state='accepted', + # assignment_state_archive='pending', + # trash=False) + # kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('vet_accepted_real_quantity')) | Q( + # quantity__lt=F('vet_accepted_real_quantity')) | Q( + # quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__gt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__lt=F('accepted_real_quantity')), + # # kill_request__recive_date__date__gte=date1, + # # kill_request__recive_date__date__lte=last_date, + # province_kill_request__in=province_kill_requests, vet_state='accepted', + # assignment_state_archive='True', + # trash=False) + # elif date2 > last_date and date1 > last_date: + # kill_house_request_without_clearance_code = [] + # kill_house_request_without_vet_check = [] + # kill_house_request_without_bar_info = [] + # kill_house_request_diffrent_quarantine_quantity = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), + # province_kill_request__in=province_kill_requests, clearance_code__isnull=False, + # quarantine_quantity__isnull=False, trash=False) + # kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('vet_accepted_real_quantity')) | Q( + # quantity__lt=F('vet_accepted_real_quantity')) | Q( + # quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__gt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__lt=F('accepted_real_quantity')), + # province_kill_request__in=province_kill_requests, vet_state='accepted', + # assignment_state_archive='True', + # trash=False) + # else: + # + # kill_house_request_without_clearance_code = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, clearance_code__isnull=True, trash=False) + # + # kill_house_request_diffrent_quarantine_quantity = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), + # province_kill_request__in=province_kill_requests, clearance_code__isnull=False, + # quarantine_quantity__isnull=False, trash=False) + # kill_house_request_without_vet_check = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, vet_state='pending', trash=False) + # kill_house_request_without_bar_info = KillHouseRequest.objects.filter( + # province_kill_request__in=province_kill_requests, vet_state='accepted', + # assignment_state_archive='pending', + # trash=False) + # kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('vet_accepted_real_quantity')) | Q( + # quantity__lt=F('vet_accepted_real_quantity')) | Q( + # quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__gt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__lt=F('accepted_real_quantity')), + # province_kill_request__in=province_kill_requests, vet_state='accepted', + # assignment_state_archive='True', + # trash=False) + # else: + kill_house_request_without_clearance_code = KillHouseRequest.objects.filter( + province_kill_request__in=province_kill_requests, clearance_code__isnull=True, trash=False) + + kill_house_request_diffrent_quarantine_quantity = KillHouseRequest.objects.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), + province_kill_request__in=province_kill_requests, clearance_code__isnull=False, + quarantine_quantity__isnull=False, trash=False) + kill_house_request_without_vet_check = KillHouseRequest.objects.filter( + province_kill_request__in=province_kill_requests, vet_state='pending', trash=False) + kill_house_request_without_bar_info = KillHouseRequest.objects.filter( + province_kill_request__in=province_kill_requests, + assignment_state_archive='pending', + trash=False) + + kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + Q(quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')), + province_kill_request__in=province_kill_requests, + assignment_state_archive='True', + trash=False) + + # kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('vet_accepted_real_quantity')) | Q(quantity__lt=F('vet_accepted_real_quantity')) | Q( + # quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__gt=F('accepted_real_quantity') | Q(vet_accepted_real_quantity__lt=F('accepted_real_quantity'))), + # province_kill_request__in=province_kill_requests, vet_state='accepted', assignment_state_archive='True', + # trash=False) + + # kill_house_request_diffrent_bar_info = KillHouseRequest.objects.filter( + # Q(quantity__gt=F('vet_accepted_real_quantity')) | Q(quantity__lt=F('vet_accepted_real_quantity')) | Q( + # quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__gt=F('accepted_real_quantity')) | Q( + # vet_accepted_real_quantity__lt=F('accepted_real_quantity')), + # province_kill_request__in=province_kill_requests, vet_state='accepted', assignment_state_archive='True', + # trash=False) + + kill_house_request_without_clearance_code_serializer = KillHouseRequestForBarManagementSerializer( + kill_house_request_without_clearance_code, many=True) + kill_house_request_diffrent_quarantine_quantitye_serializer = KillHouseRequestForBarManagementSerializer( + kill_house_request_diffrent_quarantine_quantity, many=True) + kill_house_request_without_vet_check_serializer = KillHouseRequestForBarManagementSerializer( + kill_house_request_without_vet_check, many=True) + kill_house_request_without_bar_info_serializer = KillHouseRequestForBarManagementSerializer( + kill_house_request_without_bar_info, many=True) + kill_house_request_diffrent_bar_info_serializer = KillHouseRequestForDiffrentBarInfoSerializer( + kill_house_request_diffrent_bar_info, many=True) + + return Response({ + "part_one": { + "total_requests": poultry_requests.count(), + "poultry_request_total_quantity": poultry_request_total_quantity if poultry_request_total_quantity != None else 0, + "poultry_request_total_weight": poultry_request_total_weight if poultry_request_total_weight != None else 0, + "province_kill_requests_total_quantity": province_kill_requests_total_quantity if province_kill_requests_total_quantity != None else 0, + "province_kill_requests_total_weight": province_kill_requests_total_weight if province_kill_requests_total_weight != None else 0, + "poultry_request_total_remain_quantity": poultry_request_total_remain_quantity if poultry_request_total_remain_quantity != None else 0, + "poultry_request_remain_weight": poultry_request_remain_weight if poultry_request_remain_weight != None else 0, + "operator_fullname": province_operator.user.fullname, + "operator_mobile": province_operator.user.mobile, + "role": "ProvinceOperator", + }, + "part_two": province_kill_requests_serializer.data, + "part_three": kill_house_request_without_clearance_code_serializer.data, + "part_seven": kill_house_request_diffrent_quarantine_quantitye_serializer.data, + "part_four": kill_house_request_without_vet_check_serializer.data, + "part_five": kill_house_request_without_bar_info_serializer.data, + "part_six": kill_house_request_diffrent_bar_info_serializer.data, + }) + + +class PoultryRequestForTotalInformationInTableViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + kill_house_requests_queryset = KillHouseRequest.objects.all() + serializer_class = PoultryRequestForTotalInformationInTableSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = poultry_request_new_fields + kill_house_requests_filter_class = KillHouseRequestFilterSet + kill_house_requests_filterset_fields = kill_house_request_filterset_fields + + def list(self, request, *args, **kwargs): + poultry_requests_for_search = [] + kill_house_request_for_search = [] + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'clearance_code' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + clearance_code__isnull=request.GET[ + 'clearance_code']).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + elif 'assignment' in request.GET: + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive=request.GET[ + 'assignment']).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + + + elif 'discharge' in request.GET: + if request.GET['discharge'] == 'pending': + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + vet_state='pending', + assignment_state_archive='pending').select_related( + 'province_request__poultry_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(vet_state='pending') | Q(vet_state='pending', assignment_state_archive='True')), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, ).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + + else: + poultry_requests = PoultryRequest.objects.filter( + poultry__address__province=user.province, + # state_process__in=('pending', 'accepted'), + # province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__in=poultry_requests) + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_requests + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_requests) + poultry_requests_for_search = ps.filter() + + poultry_requests = [] if len(poultry_requests_for_search) == 0 else poultry_requests_for_search + + for item in self.kill_house_requests_filterset_fields: + kill_house_request_query = QueryDict('{0}={1}'.format(item, request.GET['value'])) + if (self.kill_house_requests_filter_class( + data=kill_house_request_query, + queryset=kill_house_requests + + ) + ).filter(): + ks = self.kill_house_requests_filter_class(data=kill_house_request_query, + queryset=kill_house_requests) + kill_house_request_for_search = ks.filter() + kill_house_requests = [] if len(kill_house_request_for_search) == 0 else kill_house_request_for_search + if len(kill_house_requests) > 0: + for kill_house_request in kill_house_requests: + if kill_house_request.province_request.poultry_request not in poultry_requests: + poultry_requests.append(kill_house_request.province_request.poultry_request) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_requests) + if page is not None: + serializer = PoultryRequestForTotalInformationInTableSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForTotalInformationInTableSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryRequestForTotalInformationViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + kill_house_requests_queryset = KillHouseRequest.objects.all() + serializer_class = PoultryRequestForTotalInformationSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = poultry_request_new_fields + kill_house_requests_filter_class = KillHouseRequestFilterSet + kill_house_requests_filterset_fields = kill_house_request_filterset_fields + + def list(self, request, *args, **kwargs): + poultry_requests_for_search = [] + kill_house_request_for_search = [] + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'clearance_code' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + clearance_code__isnull=request.GET[ + 'clearance_code']).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + elif 'assignment' in request.GET: + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive=request.GET[ + 'assignment']).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + + + elif 'discharge' in request.GET: + if request.GET['discharge'] == 'pending': + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + vet_state='pending', + assignment_state_archive='pending').select_related( + 'province_request__poultry_request') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(vet_state='pending') | Q(vet_state='pending', assignment_state_archive='True')), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, ).select_related( + 'province_request__poultry_request') + + poultry_requests = PoultryRequest.objects.filter( + pk__in=kill_house_requests.values('province_request__poultry_request'), + poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + + else: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_requests = PoultryRequest.objects.filter( + poultry__address__province=user.province, + poultry__city_operator=city_operator.unit_name, + # final_state='pending', + trash=False, + # out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = PoultryRequest.objects.filter( + poultry__address__city=user.city, + # final_state='pending', + trash=False, + # out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + elif request.GET['role'] == 'LiveStockSupport': + poultry_requests = PoultryRequest.objects.filter( + poultry__address__province=user.province, + freezing=True, + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + poultry__address__province=user.province, + # final_state='pending', + trash=False, + # out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date') + kill_house_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__in=poultry_requests) + + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_requests + + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_requests) + poultry_requests_for_search = ps.filter() + + poultry_requests = [] if len(poultry_requests_for_search) == 0 else poultry_requests_for_search + + for item in self.kill_house_requests_filterset_fields: + kill_house_request_query = QueryDict('{0}={1}'.format(item, request.GET['value'])) + if (self.kill_house_requests_filter_class( + data=kill_house_request_query, + queryset=kill_house_requests + + ) + ).filter(): + ks = self.kill_house_requests_filter_class(data=kill_house_request_query, + queryset=kill_house_requests) + kill_house_request_for_search = ks.filter() + kill_house_requests = [] if len(kill_house_request_for_search) == 0 else kill_house_request_for_search + if len(kill_house_requests) > 0: + for kill_house_request in kill_house_requests: + if kill_house_request.province_request.poultry_request not in poultry_requests: + poultry_requests.append(kill_house_request.province_request.poultry_request) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_requests) + if page is not None: + serializer = PoultryRequestForTotalInformationSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForTotalInformationSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class GeneralPoultryRequestLetterReportViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestLetterForProvinceVetSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + if request.GET['type'] == 'broadcast': + date_one_day_ago = date - timedelta(days=1) + else: + date_one_day_ago = date + + poultry_requests_first_letter = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date=date_one_day_ago + ).order_by('-send_date') + serializer_poultry_requests_first_letter = PoultryRequestForKillingInformationSerializer( + poultry_requests_first_letter, many=True) + poultry_requests_seconde_letter = PoultryRequest.objects.filter(send_date__date=date_one_day_ago, + quantity__gt=F('remain_quantity'), + trash=False) + serializer_poultry_requests_seconde_letter = PoultryRequestLetterForProvinceVetSerializer( + poultry_requests_seconde_letter, many=True) + + kill_house_requests_third_letter_part_two = KillHouseRequest.objects.filter( + Q(vet_state='accepted') | Q(assignment_state_archive='True'), + kill_request__recive_date__date=date_one_day_ago, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).only('accepted_real_quantity', 'accepted_real_weight') + kill_house_requests_third_letter_part_two_quantity = \ + kill_house_requests_third_letter_part_two.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] + kill_house_requests_third_letter_part_two_weight = \ + kill_house_requests_third_letter_part_two.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] + kill_house_requests_third_letter_part_three = KillHouseRequest.objects.filter( + clearance_code__isnull=False, + kill_request__recive_date__date=date_one_day_ago, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).only('accepted_real_quantity', 'accepted_real_weight') + + # total_weight = kill_house_requests_third_letter.aggregate(total=Sum('accepted_real_weight'))[ + # 'total'] + # total_quantity = kill_house_requests_third_letter.aggregate(total=Sum('accepted_real_quantity'))[ + # 'total'] + + kill_house_requests_third_letter = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date_one_day_ago, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + kill_house_requests_third_letter_quantity = kill_house_requests_third_letter.aggregate(total=Sum('quantity'))[ + 'total'] + kill_house_requests_third_letter_weight = kill_house_requests_third_letter.aggregate( + total=Sum(F('accepted_real_weight') * F('province_request__poultry_request__Index_weight')))[ + 'total'] + serializer_kill_house_requests_third_letter = KillHouseRequestForBarManagementSerializer( + kill_house_requests_third_letter, many=True) + + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date=date_one_day_ago).select_related( + 'killhouse_user') + kill_houses = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + ) + kill_house_ware_houses = KillHouseWareHouse.objects.filter(kill_house__in=kill_houses, date__date=date) + steward_allocations = StewardAllocation.objects.filter( + system_registration_code=True, + ware_house__in=kill_house_ware_houses, trash=False, + date__date=date).order_by('id') + + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + allocated_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_number_of_carcasses'))['total'] + allocated_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_weight_of_carcasses'))['total'] + remain_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))['total'] + remain_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))['total'] + + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date=date_one_day_ago).select_related( + 'killhouse_user') + kill_houses = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + ) + + serializer_kill_house_requests_fourth_part_two = KillHouseForAutomaticStewardAllocationSerializer(kill_houses, + context={ + 'request': request}, + many=True) + + allocations = StewardAllocation.objects.filter(trash=False, system_registration_code=True, + date__date=date).order_by('id') + real_number_of_carcasses = \ + allocations.aggregate(total=Sum('real_number_of_carcasses'))['total'] + real_weight_of_carcasses = \ + allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] + serializer_kill_house_requests_fourth_part_three = StewardAllocationSerializer(allocations, many=True) + + return Response({ + "serializer_poultry_requests_first_letter": serializer_poultry_requests_first_letter.data, + "serializer_poultry_requests_seconde_letter": serializer_poultry_requests_seconde_letter.data, + "serializer_kill_house_requests_third_letter": serializer_kill_house_requests_third_letter.data, + "kill_house_requests_third_letter_quantity": kill_house_requests_third_letter_quantity if kill_house_requests_third_letter_quantity != None else 0, + "kill_house_requests_third_letter_weight": int( + kill_house_requests_third_letter_weight) if kill_house_requests_third_letter_weight != None else 0, + "serializer_kill_house_requests_third_letter_part_two": len(kill_house_requests_third_letter_part_two), + "kill_house_requests_third_letter_part_two_quantity": kill_house_requests_third_letter_part_two_quantity if kill_house_requests_third_letter_part_two_quantity != None else 0, + "kill_house_requests_third_letter_part_two_weight": kill_house_requests_third_letter_part_two_weight if kill_house_requests_third_letter_part_two_weight != None else 0, + "serializer_kill_house_requests_third_letter_part_three": len(kill_house_requests_third_letter_part_three), + "serializer_kill_house_requests_fourth_part_one": { + "buyers": len(kill_house_ware_houses), + "allocations": len(steward_allocations), + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "allocated_total_number_of_carcasses": allocated_total_number_of_carcasses if allocated_total_number_of_carcasses != None else 0, + "allocated_total_weight_of_carcasses": allocated_total_weight_of_carcasses if allocated_total_weight_of_carcasses != None else 0, + "remain_total_number_of_carcasses": remain_total_number_of_carcasses if remain_total_number_of_carcasses != None else 0, + "remain_total_weight_of_carcasses": remain_total_weight_of_carcasses if remain_total_weight_of_carcasses != None else 0, + }, + "serializer_kill_house_requests_fourth_part_two": serializer_kill_house_requests_fourth_part_two.data, + "serializer_kill_house_requests_fourth_part_three": serializer_kill_house_requests_fourth_part_three.data, + "serializer_kill_house_requests_fourth_part_fourth": real_number_of_carcasses if real_number_of_carcasses != None else 0, + "serializer_kill_house_requests_fourth_part_fifth": real_weight_of_carcasses if real_weight_of_carcasses != None else 0, + "serializer_kill_house_requests_fourth_part_sixth": len(allocations), + }) + + +class StewardGuildsAllocationsForStatisticalProfileViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + serializer_class = StewardAllocationSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + allocations = StewardAllocation.objects.filter(trash=False, system_registration_code=True, + date__date=date).order_by('id') + real_number_of_carcasses = \ + allocations.aggregate(total=Sum('real_number_of_carcasses'))['total'] + real_weight_of_carcasses = \ + allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] + serializer_kill_house_requests_fourth_part_three = StewardAllocationSerializer(allocations, many=True) + + return Response({ + "real_number_of_carcasses": real_number_of_carcasses if real_number_of_carcasses != None else 0, + "real_weight_of_carcasses": real_weight_of_carcasses if real_weight_of_carcasses != None else 0, + "allocations": len(allocations), + }) + + +# kill_house_requests=KillHouseRequest.objects.filter(killhouse_user__id=5,trash=True,clearance_code__isnull=False,message__isnull=True) +# for kill_house_request in kill_house_requests: +# kill_house_request.message='عدم ارسال راننده توسط کشتارگاه' +# kill_house_request.bar_remover={ +# "date": str(kill_house_request.create_date.date()), +# "role":"KillHouse", +# "mobile": "09143488339", +# "full_name": "حامد صمدی" +# } +# kill_house_request.save() + + +class DetailOfKillingViewSet(viewsets.ViewSet): + permission_classes = [TokenHasReadWriteScope] + + def hatching_55_90_data(self, request): + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user__user=request.user) + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, left_over__gt=F('quantity') * 0.1, + chicken_age__range=(55, 90), + poultry__city_operator=city_operator.unit_name, ).order_by( + 'id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, left_over__gt=F('quantity') * 0.1, + chicken_age__range=(55, 90), + poultry__user__city=user.city).order_by('id') + else: + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, left_over__gt=F('quantity') * 0.1, + chicken_age__range=(55, 90)).order_by('id') + else: + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, left_over__gt=F('quantity') * 0.1, + chicken_age__range=(55, 90)).order_by('id') + min_list = [] + + all_poultry_hatching_quantity = hatching_between_50_70.aggregate(total=Sum('quantity'))['total'] + all_poultry_hatching_killed_quantity = hatching_between_50_70.aggregate(total=Sum('killed_quantity'))['total'] + all_poultry_hatching_left_over = hatching_between_50_70.aggregate(total=Sum('left_over'))['total'] + all_left_over_ninty_percent = \ + hatching_between_50_70.aggregate(total=Sum(F('quantity') * 90 / 100) - Sum(F('killed_quantity')))['total'] + archive_hatch = hatching_between_50_70.filter(archive=True, allow_hatching='True') + active_hatch = hatching_between_50_70.filter(archive=False, allow_hatching='pending') + archive_hatching_quantity = \ + archive_hatch.aggregate(total=Sum('quantity'))['total'] + left_over_active_hatch = \ + active_hatch.aggregate(total=Sum('quantity'))['total'] or 0 + for poultry_hatching in hatching_between_50_70: + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + min_list = sorted(min_list) + all_total_commitment = hatching_between_50_70.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = hatching_between_50_70.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = hatching_between_50_70.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + + return { + 'poultry': len(hatching_between_50_70), + 'hatching_quantity': all_poultry_hatching_quantity, + 'len_archive_hatching': len(archive_hatch), + 'archive_hatching_quantity': archive_hatching_quantity, + 'len_active_hatching': len(active_hatch), + 'active_hatching_quantity': left_over_active_hatch, + 'hatching_killed_quantity': all_poultry_hatching_killed_quantity, + 'hatching_killed_weight': int(all_total_killed_weight), + 'hatching_left_over': all_poultry_hatching_left_over, + 'hatching_left_over_ninty_percent': all_left_over_ninty_percent, + 'min_age': min_list[0] if len(min_list) > 0 else None, + 'max_age': min_list[len(min_list) - 1] if len(min_list) > 0 else None, + 'total_commitment': all_total_commitment, + 'governmental_quantity': all_governmental_quantity, + 'governmental_weight': int(all_governmental_killed_quantity), + 'free_quantity': all_free_quantity, + 'free_weight': all_free_killed_quantity, + 'out_province_killed_quantity': all_out_province_killed_quantity, + 'out_province_killed_weight': all_out_province_killed_weight + } + + def get_kill_house_for_detail(self, kill_req): + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=kill_req.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = kill_req.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_weighte = kill_req.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_governmental_quantity = \ + kill_req.filter(province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_governmental_weight = \ + kill_req.filter(province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_free_quantity = kill_req.filter(province_request__poultry_request__free_sale_in_province=True).aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_free_weight = kill_req.filter(province_request__poultry_request__free_sale_in_province=True).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + all_age = [] + + if kill_req: + for kill in kill_req: + # weight = kill.get('quantity') * kill.get( + # 'province_kill_request__province_request__poultry_request__Index_weight') + # all_weighte += weight + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + # difference_bars = kill_req.filter( + # Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')),quarantine_quantity__gt=0) + # + # + # final_real_quantity=-0 + # difference_bar = len(difference_bars) + # greater_bars_quantity = difference_bars.filter(quantity__gt=F('quarantine_quantity')) + # real_greater_bars_quantity = (greater_bars_quantity.aggregate(total=Sum('quarantine_quantity'))['total'] or 0 ) - (greater_bars_quantity.aggregate(total=Sum('quantity'))['total'] or 0 ) + # less_bars_quantity = difference_bars.filter(quantity__lt=F('quarantine_quantity')) + # real_less_bars_quantity = (less_bars_quantity.aggregate(total=Sum('quarantine_quantity'))['total'] or 0 ) - (less_bars_quantity.aggregate(total=Sum('quantity'))['total'] or 0 ) + # + # final_real_quantity = real_greater_bars_quantity + real_less_bars_quantity if real_greater_bars_quantity > 0 else (-1 * real_greater_bars_quantity) + real_less_bars_quantity + + difference_bars = kill_req.filter( + Q(accepted_real_quantity__gt=F('quarantine_quantity')) | Q( + accepted_real_quantity__lt=F('quarantine_quantity')), quarantine_quantity__gt=0) + + final_real_quantity = -0 + difference_bar = len(difference_bars) + greater_bars_quantity = difference_bars.filter(accepted_real_quantity__gt=F('quarantine_quantity')) + real_greater_bars_quantity = (greater_bars_quantity.aggregate(total=Sum('quarantine_quantity'))[ + 'total'] or 0) - ( + greater_bars_quantity.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0) + less_bars_quantity = difference_bars.filter(accepted_real_quantity__lt=F('quarantine_quantity')) + real_less_bars_quantity = (less_bars_quantity.aggregate(total=Sum('quarantine_quantity'))['total'] or 0) - ( + less_bars_quantity.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0) + + final_real_quantity = real_greater_bars_quantity + real_less_bars_quantity if real_greater_bars_quantity > 0 else ( + -1 * real_greater_bars_quantity) + real_less_bars_quantity + + hasnt_code = kill_req.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + has_code = kill_req.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + has_qarantine = kill_req.filter(quarantine_quantity__isnull=False) + all_has_qarantine = has_qarantine.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + all_age1 = sorted(all_age) + + return { + 'poultry_request': len(poultry_request), + 'poultry_request_quantity': total_requests_quantity if total_requests_quantity != None else 0, + 'poultry_request_weight': int(total_requests_weight) if total_requests_weight != None else 0, + 'min_age': all_age1[0] if len(all_age1) > 0 else '-', + 'max_age': all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + 'avg_age': int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + 'len_kill_request': len(kill_req), + 'kill_request_quantity': all_quantity if all_quantity != None else 0, + 'kill_request_weight': int(all_weighte), + 'avg_weight': round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + 'len_kill_request_has_code': len(has_code), + 'quantity_of_kill_request_has_code': all_quarantine_quantity_has_code if all_quarantine_quantity_has_code != None else 0, + 'len_kill_request_has_quarantine': len(has_qarantine), + 'quantity_of_kill_request_has_quarantine': all_has_qarantine if all_has_qarantine != None else 0, + 'len_kill_request_has_not_code': len(hasnt_code), + 'quantity_of_kill_request_has_not_code': all_quarantine_quantity_hasnt_code if all_quarantine_quantity_hasnt_code != None else 0, + 'difference_bar': difference_bar, + 'final_real_quantity': final_real_quantity, + 'all_governmental_quantity': all_governmental_quantity, + 'all_governmental_weight': all_governmental_weight, + 'all_free_quantity': all_free_quantity, + 'all_free_weight': all_free_weight, + + } + + def steward_ware_house_total_report_daily_broad_cast(self, steward): + number_of_steward1 = Steward.objects.filter( + pk__in=steward.values('steward') + ) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations1 = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild1 = guild_allocations1.values('guilds').distinct().count() if guild_allocations1 else 0 + + total_number_of_free_carcasses1 = steward.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] or 0 + total_free_weight_of_carcasses1 = steward.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] or 0 + total_number_of_carcasses1 = steward.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight_of_carcasses1 = steward.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + final_total_number_of_carcasses1 = \ + steward.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + final_total_weight_of_carcasses1 = \ + steward.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_remain_quantity1 = \ + steward.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + + total_remain_weight1 = \ + steward.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + + total_allocated_quantity1 = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight1 = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_quantity1 = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_weight1 = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + return { + "buyers": len(number_of_steward1), + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": 0, + "total_pre_cold_weight": 0, + "total_number_of_free_carcasses": total_number_of_free_carcasses1, + "total_free_weight_of_carcasses": total_free_weight_of_carcasses1, + "total_number_of_carcasses": total_number_of_carcasses1, + "total_weight_of_carcasses": int(total_weight_of_carcasses1), + "final_total_number_of_carcasses": final_total_number_of_carcasses1, + "final_total_weight_of_carcasses": int(final_total_weight_of_carcasses1), + "total_allocated_quantity": total_allocated_quantity1, + "total_allocated_weight": int(total_allocated_weight1), + "total_accepted_allocated_quantity": total_accepted_allocated_quantity1, + "total_accepted_allocated_weight": int(total_accepted_allocated_weight1), + "total_remain_quantity": total_remain_quantity1, + "total_remain_weight": int(total_remain_weight1), + "number_of_guild": number_of_guild1, + } + + def kill_house_ware_house_total_report_daily_broad_cast(self, kill): + number_of_kill_houses = KillHouse.objects.filter( + pk__in=kill.values('kill_house') + ) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill, receiver_state__in=('pending', 'accepted'), trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] or 0 + total_pre_cold_weight = \ + kill.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] or 0 + total_number_of_free_carcasses = kill.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] or 0 + total_free_weight_of_carcasses = kill.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] or 0 + total_number_of_carcasses = kill.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight_of_carcasses = kill.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + final_total_number_of_carcasses = \ + kill.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] or 0 + final_total_weight_of_carcasses = \ + kill.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] or 0 + + total_remain_quantity = \ + kill.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + + total_remain_weight = \ + kill.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + return { + "buyers": len(number_of_kill_houses), + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": total_pre_cold_quantity, + "total_pre_cold_weight": int(total_pre_cold_weight), + "total_number_of_free_carcasses": total_number_of_free_carcasses, + "total_free_weight_of_carcasses": int(total_free_weight_of_carcasses), + "total_number_of_carcasses": total_number_of_carcasses, + "total_weight_of_carcasses": int(total_weight_of_carcasses), + "final_total_number_of_carcasses": final_total_number_of_carcasses, + "final_total_weight_of_carcasses": int(final_total_weight_of_carcasses), + "total_allocated_quantity": total_allocated_quantity, + "total_allocated_weight": int(total_allocated_weight), + "total_accepted_allocated_quantity": total_accepted_allocated_quantity, + "total_accepted_allocated_weight": int(total_accepted_allocated_weight), + "total_remain_quantity": total_remain_quantity, + "total_remain_weight": int(total_remain_weight), + "number_of_guild": number_of_guild, + "number_of_steward": number_of_steward, + } + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + + date1 = datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + if 'role' in request.GET: + + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user__user=request.user) + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + out_province_request_cancel=False, + province_state='accepted', + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2) + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + province_request__poultry_request__poultry__user__city=user.city, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + out_province_request_cancel=False, + poultry__user__city=user.city, + province_state='accepted', + send_date__date__gte=date1, + send_date__date__lte=date2) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + out_province_request_cancel=False, + province_state='accepted', + send_date__date__gte=date1, + send_date__date__lte=date2) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + out_province_request_cancel=False, + province_state='accepted', + send_date__date__gte=date1, + send_date__date__lte=date2) + + kill_req = self.get_kill_house_for_detail(filtered_kill_reqs) + + filtered_kill_reqs_not_code_but_have_assigment = filtered_kill_reqs.filter( + Q(assignment_state_archive='True', vet_state='pending') + | Q(vet_state='accepted'), clearance_code__isnull=True) + + bar_government = filtered_kill_reqs.filter( + province_request__poultry_request__free_sale_in_province=False) + + accepted_real_quantity_bar_government = bar_government.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + accepted_real_wight_bar_government = bar_government.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) or 0 + + bar_government_quarantine_quantity = bar_government.filter(quarantine_quantity__isnull=False) + + accepted_real_quantity_bar_government_quarantine_quantity = bar_government_quarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + + bar_free = filtered_kill_reqs.filter(province_request__poultry_request__free_sale_in_province=True) + accepted_real_quantity_bar_free = bar_free.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight_bar_free = bar_free.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + bar_free_quarantine_quantity = bar_free.filter(quarantine_quantity__isnull=False) + + accepted_real_quantity_bar_free_quarantine_quantity = bar_free_quarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + + bar_free_has_code = len(bar_free.filter(clearance_code__isnull=False)) + + quantity_out_true_poultry_request = out_true_poultry_request.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + bar_complete_with_kill_house_and_vet = filtered_kill_reqs.filter( + trash=False) + bar_complete_with_vet = filtered_kill_reqs.filter( + vet_state='accepted') + accepted_real_quantity_with_kill_house_and_vet = bar_complete_with_kill_house_and_vet.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight_with_kill_house_and_vet = bar_complete_with_kill_house_and_vet.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity_with_kill_house_and_vet = bar_complete_with_vet.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight_with_kill_house_and_vet = bar_complete_with_vet.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + bar_complete_with_kill_house = filtered_kill_reqs.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_no_code = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight_no_code = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + if accepted_real_wight_with_kill_house_and_vet != None: + less_25 = (accepted_real_wight_with_kill_house_and_vet * 75) / 100 + else: + less_25 = 0 + + filtered_kill_reqs_not_assigment_all = filtered_kill_reqs.filter( + assignment_state_archive='pending', vet_state='pending') + + accepted_real_quantity_not_assigment_all = filtered_kill_reqs_not_assigment_all.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + accepted_real_wight_not_assigment_all = filtered_kill_reqs_not_assigment_all.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) or 0 + + filtered_kill_reqs_havent_kill_house = filtered_kill_reqs.filter( + assignment_state_archive='pending' + , vet_state='accepted') + + accepted_real_quantity_havent_kill_house = filtered_kill_reqs_havent_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight_havent_kill_house = filtered_kill_reqs_havent_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + accepted_real_weight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) or 0 + accepted_real_quantity_final1 = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + accepted_real_weight_final1 = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) or 0 + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + + kill_house_data = self.kill_house_ware_house_total_report_daily_broad_cast(kill_house_ware_houses) + + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + + steward = self.steward_ware_house_total_report_daily_broad_cast(steward_ware_houses) + return Response({ + 'age55_age90': self.hatching_55_90_data(request), + 'kill_request': kill_req, + 'free_and_government_kill_request': { + 'len_government': len(bar_government), + 'quantity_government': accepted_real_quantity_bar_government, + 'weight_government': int(accepted_real_wight_bar_government), + 'len_government_quarantine_quantity': len(bar_government_quarantine_quantity), + 'real_quantity_bar_government_quarantine_quantity': accepted_real_quantity_bar_government_quarantine_quantity, + 'len_free': len(bar_free), + 'quantity_free': accepted_real_quantity_bar_free, + 'weight_free': accepted_real_wight_bar_free, + 'len_free_quarantine_quantity': len(bar_free_quarantine_quantity), + 'real_quantity_bar_free_quarantine_quantity': accepted_real_quantity_bar_free_quarantine_quantity, + 'len_free_has_code': bar_free_has_code, + 'len_out_kill_request': len(out_true_poultry_request), + 'quantity_out_kill_request': quantity_out_true_poultry_request, + }, + 'complete_kill_request': { + 'len_complete_with_kill_house_and_vet': len(bar_complete_with_kill_house_and_vet), + 'quantity_with_kill_house_and_vet': accepted_real_quantity_with_kill_house_and_vet, + 'weight_with_kill_house_and_vet': int(accepted_real_wight_with_kill_house_and_vet), + "avg_weight": round( + accepted_real_wight_with_kill_house_and_vet / accepted_real_quantity_with_kill_house_and_vet, + 1) if accepted_real_wight_with_kill_house_and_vet > 0 else 0, + 'less_25': int(less_25), + 'len_complete_with_vet': len(bar_complete_with_vet), + 'quantity_complete_with_vet': all_vet_accepted_real_quantity_with_kill_house_and_vet, + 'weight_complete_with_vet': int(all_vet_accepted_real_weight_with_kill_house_and_vet), + 'len_complete_with_kill_house': len(bar_complete_with_kill_house), + 'quantity_final_kill_house': accepted_real_quantity_final, + 'weight_final_kill_house': int(accepted_real_wight_final), + 'len_kill_reqs_has_not_code': len(filtered_kill_reqs_not_code_but_have_assigment), + 'quantity_kill_reqs_has_not_code': accepted_real_quantity_no_code, + 'weight_kill_reqs_has_not_code': int(accepted_real_wight_no_code), + }, + 'kill_request_has_not_assigment': { + 'len_kill_reqs_not_assigment': len(filtered_kill_reqs_not_assigment_all), + 'quantity_kill_reqs_not_assigment': accepted_real_quantity_not_assigment_all, + 'weight_kill_reqs_not_assigment': int(accepted_real_wight_not_assigment_all), + 'len_kill_request_has_not_complete': len(filtered_kill_reqs_havent_kill_house), + 'quantity_kill_request_has_not_complete': accepted_real_quantity_havent_kill_house, + 'weight_kill_request_has_not_complete': int(accepted_real_wight_havent_kill_house), + }, + 'final_quantity_and_weight': { + 'final_quantity': accepted_real_quantity_final1, + 'final_weight': int(accepted_real_weight_final1), + }, + 'kill_house_ware_house_total_report_daily_broad_cast': kill_house_data, + 'steward_ware_house_total_report_daily_broad_cast': steward + + }) + + +class ComprehensiveReportOfTheSlaughterhouseViewSet(viewsets.ViewSet): + permission_classes = [AllowAny] + + def all_kill_request(self, date1, date2): + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).order_by( + '-create_date').select_related( + 'province_request__poultry_request__hatching', 'province_request__poultry_request').only( + 'province_kill_request__province_request__poultry_request__Index_weight', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'ware_house_accepted_real_quantity') + + all_kill_req_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + weight = filtered_kill_reqs.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] or 0 + + all_kill_req_quantity_reciver = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + all_kill_req_weight_reciver = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity') or 0 + + return { + "quantity_of_create_bar": all_kill_req_quantity, + "weight_of_create_bar": int(weight), + "quantity_of_receive_bar": all_kill_req_quantity_reciver, + "weight_of_receive_bar": int(all_kill_req_weight_reciver), + "weight_with_twenty_five_percent_receive": int( + (all_kill_req_weight_reciver * 75) / 100) if all_kill_req_weight_reciver > 0 else 0, + "quantity_warehouse": all_ware_house_accepted_real_quantity, + "weight_warehouse": int(all_ware_house_accepted_real_weight), + "quantity_percent_warehouse": int( + all_ware_house_accepted_real_quantity * 100 / all_kill_req_quantity_reciver) if all_ware_house_accepted_real_quantity > 0 else 0, + "weight_percent_warehouse": int( + all_ware_house_accepted_real_weight * 100 / all_kill_req_weight_reciver) if all_ware_house_accepted_real_weight > 0 else 0, + "quantity_percent_receive": int( + all_kill_req_quantity_reciver * 100 / all_kill_req_quantity) if all_kill_req_quantity_reciver > 0 else 0, + "weight_percent_receive": int( + (all_kill_req_weight_reciver * 100) / weight) if all_kill_req_weight_reciver > 0 else 0 + } + + def general_broadcast_information(self, tomorrow_date1, tomorrow_date2, filtered_kill_reqs, kill_free_info): + + number_of_kill_house = filtered_kill_reqs.values( + 'killhouse_user').distinct().count() if filtered_kill_reqs else 0 + + all_quantity_out_false = filtered_kill_reqs.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + weight = filtered_kill_reqs.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] or 0 + all_quantity_out_true = kill_free_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + all_weight_out_true = kill_free_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2, trash=False) + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] or 0 + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] or 0 + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + return { + "number_of_buyer": number_of_kill_house, + "quantity_of_kill_request_in_province": all_quantity_out_false, + "weight_of_kill_request_in_province": int(weight), + "quantity_of_kill_request_out_province": all_quantity_out_true, + "weight_of_kill_request_out_province": int(all_weight_out_true), + "quantity_carcasses": final_total_number_of_carcasses, + "weight_carcasses": int(final_total_weight_of_carcasses), + "allocated_quantity": total_allocated_quantity, + "allocated_weight": int(total_allocated_weight), + "accepted_allocated_quantity": total_accepted_allocated_quantity, + "accepted_allocated_weight": int(total_accepted_allocated_weight), + "remain_quantity": total_remain_quantity, + "remain_weight": int(total_remain_weight), + "percent_warehouse": int(( + total_allocated_quantity * 100) / final_total_number_of_carcasses) if total_allocated_quantity and final_total_number_of_carcasses > 0 else 0, + "number_of_stewards": number_of_steward, + "number_of_giulds": number_of_guild, + "date1": tomorrow_date1, + "date2": tomorrow_date2, + + } + + def kill_request_and_broadcast(self, tomorrow_date1, tomorrow_date2, filtered_kill_reqs, kill_free_info): + list1 = [] + kill_houses = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user__city').exclude( + out_province=True) + for kill_house in kill_houses: + kill_free_information = kill_free_info.filter(kill_house=kill_house) + tomorrow_kill_request = filtered_kill_reqs.filter(killhouse_user=kill_house) + if tomorrow_kill_request: + tomorrow_kill_request_not_assigment = tomorrow_kill_request.filter(assignment_state_archive='pending', + vet_state='accepted') + all_kill_req_quantity = tomorrow_kill_request.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + all_kill_req_quantity_reciver = tomorrow_kill_request.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + all_kill_req_weight_reciver = tomorrow_kill_request.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_quantity = tomorrow_kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + + weight = tomorrow_kill_request.aggregate( + total_quantity=Sum( + F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + 'total_quantity'] or 0 + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2, kill_house=kill_house, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] or 0 + + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] or 0 + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + all_kill_req_quantity_not_assigment = tomorrow_kill_request_not_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + all_kill_req_weight_not_assigment = tomorrow_kill_request_not_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + all_quantity_out_true = kill_free_information.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + all_weight_out_true = kill_free_information.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + twenty_five_percent = (int(all_kill_req_weight_reciver) * 75) / 100 + reciver_percent = int( + int(all_kill_req_quantity_reciver) * 100) / all_kill_req_quantity if all_kill_req_quantity_reciver > 0 else 0 + lashe_25_percent = int( + final_total_number_of_carcasses * 100 / all_kill_req_quantity_reciver) if final_total_number_of_carcasses > 0 else 0 + weight_lashe_25_percent = int( + final_total_weight_of_carcasses * 100 / all_kill_req_weight_reciver) if final_total_weight_of_carcasses > 0 else 0 + remain_percent = int(( + total_remain_quantity * 100) / all_ware_house_accepted_real_quantity) if total_remain_quantity and all_ware_house_accepted_real_quantity > 0 else 0 + all_num = number_of_steward + number_of_guild + hasnt_code = len( + tomorrow_kill_request.filter(assignment_state_archive='True', clearance_code__isnull=True)) + percent_hasnt_code = round(hasnt_code * 100 / len(tomorrow_kill_request)) if len( + tomorrow_kill_request) > 0 else 0 + has_code = len( + tomorrow_kill_request.filter(assignment_state_archive='pending', clearance_code__isnull=False)) + percent_has_code = round(has_code * 100 / len(tomorrow_kill_request)) if len( + tomorrow_kill_request) > 0 else 0 + + has_assignment = len( + tomorrow_kill_request.filter(assignment_state_archive='True')) + percent_has_assignment = round(has_assignment * 100 / len(tomorrow_kill_request)) if len( + tomorrow_kill_request) > 0 else 0 + hasnt_assignment = len( + tomorrow_kill_request.filter(assignment_state_archive='pending')) + percent_hasnt_assignment = round(hasnt_assignment * 100 / len(tomorrow_kill_request)) if len( + tomorrow_kill_request) > 0 else 0 + accepeted_bar = len( + tomorrow_kill_request.filter(bar_document_status__title='بدون مشکل')) + percent_accepeted_bar = round(accepeted_bar * 100 / has_assignment) if has_assignment > 0 else 0 + diffrent_bar = len( + tomorrow_kill_request.filter(bar_document_status__title='مغایرت دارد')) + percent_diffrent_bar = round(diffrent_bar * 100 / has_assignment) if has_assignment > 0 else 0 + no_quality = len( + tomorrow_kill_request.filter(bar_document_status__title='فاقد کیفیت')) + percent_no_quality = round(no_quality * 100 / has_assignment) if has_assignment > 0 else 0 + low_quality = len( + tomorrow_kill_request.filter(bar_document_status__title='کیفیت پایین')) + percent_low_quality = round(low_quality * 100 / has_assignment) if has_assignment > 0 else 0 + dict_1 = { + "name": kill_house.name, + "city": kill_house.kill_house_operator.user.city.name, + "kill_req_quantity": all_kill_req_quantity, + "kill_req_weight": int(weight), + "quantity_receiver": all_kill_req_quantity_reciver, + "weight_receiver": int(all_kill_req_weight_reciver), + "twenty_five_percent_weight": int(twenty_five_percent), + "receiver_percent": reciver_percent, + "quantity_of_carcasses": final_total_number_of_carcasses, + "weight_of_carcasses": int(final_total_weight_of_carcasses), + "quantity_of_lashe_percent": lashe_25_percent, + "weight_of_lashe_percent": int(weight_lashe_25_percent), + "quantity_out_province": all_quantity_out_true, + "weight_out_province": int(all_weight_out_true), + "total_number_of_carcasses": final_total_number_of_carcasses, + "total_weight_of_carcasses": int(final_total_weight_of_carcasses), + "allocated_quantity": total_allocated_quantity, + "allocated_weight": int(total_allocated_weight), + "accepted_allocated_quantity": total_accepted_allocated_quantity, + "accepted_allocated_weight": int(total_accepted_allocated_weight), + "remain_quantity": total_remain_quantity, + "remain_weight": int(total_remain_weight), + "remain_percent": remain_percent, + "steward_and_guild": all_num, + "len_kill_req_not_complete": len(tomorrow_kill_request_not_assigment), + "quantity_kill_req_not_complete": all_kill_req_quantity_not_assigment, + "weight_kill_req_not_complete": int(all_kill_req_weight_not_assigment), + "len_hasnt_code": hasnt_code, + "percent_hasnt_code": percent_hasnt_code, + "len_has_code": has_code, + "percent_has_code": percent_has_code, + "has_assignment": has_assignment, + "percent_has_assignment": percent_has_assignment, + "accepeted_bar": accepeted_bar, + "percent_accepeted_bar": percent_accepeted_bar, + "diffrent_bar": diffrent_bar, + "percent_diffrent_bar": percent_diffrent_bar, + "no_quality": no_quality, + "percent_no_quality": percent_no_quality, + "low_quality": low_quality, + "percent_low_quality": percent_low_quality, + "hasnt_assignment": hasnt_assignment, + "percent_hasnt_assignment": percent_hasnt_assignment, + + } + list1.append(dict_1) + return list1 + + def list(self, request): + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + tomorrow_date1 = date1 + timedelta(days=1) + tomorrow_date2 = date2 + timedelta(days=1) + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry').only( + 'killhouse_user', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'ware_house_accepted_real_weight', + 'ware_house_accepted_real_quantity', + 'killhouse_user__kill_house_operator__user__city__name') + + kill_free_info = KillHouseFreeBarInformation.objects.filter(trash=False, date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2).only( + 'weight_of_carcasses', 'number_of_carcasses') + kill_request = self.all_kill_request(date1, date2) + general_broadcast_informations = self.general_broadcast_information(tomorrow_date1, tomorrow_date2, + filtered_kill_reqs, kill_free_info) + kill_request_and_broadcasts = self.kill_request_and_broadcast(tomorrow_date1, tomorrow_date2, + filtered_kill_reqs, kill_free_info) + + return Response({ + "all_kill_request": kill_request, + "general_broadcast_informations": general_broadcast_informations, + "kill_request_and_broadcast": kill_request_and_broadcasts + } + ) + + +class DetailOfKillingDashboardView(viewsets.ViewSet): + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardEnterLoadInformationFilterSet + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + + date1 = datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + value = request.GET.get('value') + search = request.GET.get('search') + if request.GET.get('type') == 'assignment': + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + calculate_status=True, + non_receipt=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, assignment_state_archive='True').order_by( + '-create_date').select_related( + 'killhouse_user', + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + else: + + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + calculate_status=True, + non_receipt=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + user = SystemUserProfile.objects.get(user=request.user) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_request = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False).last() + if vet: + poultry_set = set() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + for vet_farm in vet_farms: + poultry_set.add(vet_farm.poultry) + poultries = list(poultry_set) + filtered_kill_request = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries + ) + + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_request = filtered_kill_request.filter( + province_request__poultry_request__poultry__address__city=user.city) + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + filtered_kill_request = filtered_kill_request.filter( + killhouse_user=kill_house) + elif request.GET['role'] == 'KillHouseVet': + kill_house = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house') + filtered_kill_request = filtered_kill_request.filter( + (Q(killhouse_user__id__in=kill_house) | Q(kill_request__slaughter_house__id__in=kill_house))) + else: + if request.GET.get('without_quarantine_code_state') == 'true': + filtered_kill_request = filtered_kill_request.filter( + clearance_code__isnull=False, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + ) + elif request.GET.get('without_bar_document') == "true": + filtered_kill_request = filtered_kill_request.filter( + assignment_state_archive='True', + bar_document_status__isnull=True, + ) + else: + filtered_kill_request = filtered_kill_request + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + filtered_kill_request = filtered_kill_request.filter( + build_query(self.filterset_class, value) + ) + + ware_house_bars = filtered_kill_request.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = filtered_kill_request.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + detail_of_killing = DetailOfKillingViewSet() + bars = dict(list(detail_of_killing.get_kill_house_for_detail(filtered_kill_request).items())[3:]) + dict1 = {**bars, + 'len_complete_with_vet': 0, + 'quantity_complete_with_vet': 0, + 'weight_complete_with_vet': 0, + 'ware_house_bars': len(ware_house_bars), + 'ware_house_bars_quantity': ware_house_bars_quantity, + 'ware_house_bars_weight': ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + 'len_complete_with_kill_house': len(bar_complete_with_kill_house), + 'quantity_final_kill_house': accepted_real_quantity_final, + 'weight_final_kill_house': int(accepted_real_wight_final), + + } + return Response(dict1) + + +class ParentCompanyDetailOfKillingDashboardView(viewsets.ViewSet): + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardEnterLoadInformationFilterSet + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + + date1 = datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + value = request.GET.get('value') + search = request.GET.get('search') + if request.GET.get('type') == 'assignment': + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, assignment_state_archive='True').order_by( + '-create_date').select_related( + 'killhouse_user', + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + else: + + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', + 'province_request__poultry_request', + 'add_car__driver', + ).only('province_request', 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date').values( + 'province_request', + 'province_request__poultry_request', + + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + if request.GET.get('without_quarantine_code_state') == 'true': + filtered_kill_request = filtered_kill_request.filter( + clearance_code__isnull=False, + quarantine_quantity__isnull=True, + quarantine_code_state__isnull=True, + ) + elif request.GET.get('without_bar_document') == "true": + filtered_kill_request = filtered_kill_request.filter( + assignment_state_archive='True', + bar_document_status__isnull=True, + ) + else: + filtered_kill_request = filtered_kill_request + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + filtered_kill_request = filtered_kill_request.filter( + build_query(self.filterset_class, value) + ) + + ware_house_bars = filtered_kill_request.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = filtered_kill_request.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + detail_of_killing = DetailOfKillingViewSet() + bars = dict(list(detail_of_killing.get_kill_house_for_detail(filtered_kill_request).items())[3:]) + dict1 = {**bars, + 'len_complete_with_vet': 0, + 'quantity_complete_with_vet': 0, + 'weight_complete_with_vet': 0, + 'ware_house_bars': len(ware_house_bars), + 'ware_house_bars_quantity': ware_house_bars_quantity, + 'ware_house_bars_weight': ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + 'len_complete_with_kill_house': len(bar_complete_with_kill_house), + 'quantity_final_kill_house': accepted_real_quantity_final, + 'weight_final_kill_house': int(accepted_real_wight_final), + + } + return Response(dict1) + + +class SlaughterHouseTransactionViewSet(viewsets.ModelViewSet): + queryset = SlaughterHouseTransaction.objects.all() + serializer_class = SlaughterHouseTransactionSerializer + permission_classes = [TokenHasReadWriteScope] + + +class KillHouseWageDashbordInWeightViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseWageSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user) + kill_houses = KillHouse.objects.filter(kill_house_operator=kill_house_operator, out_province=False, + trash=False) + # kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator,out_province=False,trash=False).first() + # serializer = self.serializer_class(kill_house) + + else: + kill_houses = KillHouse.objects.filter(out_province=False, trash=False) + serializer = self.serializer_class(kill_houses, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalWageInformationExclusiveKillerViewset(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalWageInformationKillHouseExclusiveKillerSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + kill_house_key = request.GET.get('kill_house_key') + if kill_house_key: + kill_house = KillHouse.objects.filter(key=kill_house_key, trash=False).first() + else: + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + serializer = self.serializer_class(kill_house).data + return Response(serializer, status=status.HTTP_200_OK) + + +class PoultryRequestLetterForProvinceVetViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestLetterForProvinceVetSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + + if 'order_code' in request.GET: + poultry_request = PoultryRequest.objects.get(order_code=int(request.GET['order_code']), trash=False) + serializer = PoultryRequestLetterForProvinceVetSerializer(poultry_request) + else: + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, + quantity__gt=F('remain_quantity'), + trash=False) + serializer = PoultryRequestLetterForProvinceVetSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceRequestLetterForProvinceViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseLetterForProvinceSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + # user=SystemUserProfile.objects.get(user=request.user,trash=False) + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + + province_kill_requests = ProvinceKillRequest.objects.filter(kill_request__recive_date__date=date, trash=False, + state__in=('pending', 'accepted'), + return_to_province=False) + kill_houses = KillHouse.objects.filter(pk__in=province_kill_requests.values_list('killhouse_user', flat=True)) + serializer = self.serializer_class(kill_houses, many=True, context={'date': date}) + if WageType.objects.filter(en_name='poultry-sell-out-province', status=True).exists(): + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, out=True, + out_province_request_cancel=False, + trash=False, state_process='accepted', + province_state='accepted', wage_pay=True) \ + .select_related('hatching', 'poultry', 'poultry__address__city', 'poultry__address__province', + 'poultry__user') \ + .order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, out=True, + out_province_request_cancel=False, + trash=False, state_process='accepted', + province_state='accepted') \ + .select_related('hatching', 'poultry', 'poultry__address__city', 'poultry__address__province', + 'poultry__user') \ + .order_by('-send_date') + + poultry_out = PoultryRequestoutProvinceSerializer(poultry_requests, many=True) + dict1 = { + 'allocation': serializer.data, + 'out_province': poultry_out.data, + } + return Response(dict1, status=status.HTTP_200_OK) + + +class KillHousetestSerializer: + pass + + +class KillHouseFortestViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHousetestSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + serializer = self.get_serializer(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DeleteKillHouseRequest(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.filter(trash=False) + serializer_class = KillHouseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def destroy(self, request, *args, **kwargs): + kill_house_request = KillHouseRequest.objects.get(trash=False, bar_code=request.GET['bar_code']) + if kill_house_request.assignment_state_archive == 'True': + kill_house_assignment = KillHouseAssignmentInformation.objects.get(kill_house_request=kill_house_request) + kill_house_assignment.trash = True + kill_house_assignment.save() + + kill_house_request.trash = True + kill_house_request.save() + update_kill_house_requests(kill_house_request.province_kill_request, + kill_house_request.province_request.poultry_request) + update_province_kill_requests(kill_house_request.province_request.poultry_request.hatching) + poultry_prediction(kill_house_request.province_request.poultry_request.hatching) + + if kill_house_request.ware_house_confirmation == True: + product = RolesProducts.objects.filter(trash=False, kill_house=kill_house_request.killhouse_user).first() + kill_house_requests_product_warehousing(product) + + return Response({'result': 'Success'}, status=status.HTTP_200_OK) + + +class DashboardEnterLoadInformationView(viewsets.ViewSet): + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardEnterLoadInformationFilterSet + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + date1 = datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + value = request.GET.get('value') + search = request.GET.get('search') + user = SystemUserProfile.objects.get(user=request.user) + kill_house = [] + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + for kill_house_vet in kill_house_vets: + kill_house.append(kill_house_vet.kill_house) + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if request.GET['role'] in ['CityOperator', 'CityJahad', 'CityPoultry']: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + assignment_state_archive='pending', + non_receipt=False, + trash=False, + + ).order_by('-kill_request__recive_date') + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + kill_house_requests = kill_house_requests.filter( + build_query(self.filterset_class, value) + ) + + first_quantity = kill_house_requests.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + first_weight = kill_house_requests.aggregate( + total_quantity=Sum(F('province_request__poultry_request__Index_weight') * F('quantity'))).get( + 'total_quantity') or 0 + vet_accepted_real_quantity = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + vet_accepted_real_weight = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + + dict1 = { + "lenKillHouseRequest": len(kill_house_requests), + 'firstQuantity': first_quantity, + 'firstWeight': int(first_weight), + 'vetAcceptedRealQuantity': vet_accepted_real_quantity, + 'vetAcceptedRealWeight': vet_accepted_real_weight, + } + return Response(dict1) + + +class DashboardDeleteBarView(viewsets.ViewSet): + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardEnterLoadInformationFilterSet + + def list(self, request, *args, **kwargs): + now = datetime.now().date() + date1 = datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + value = request.GET.get('value') + search = request.GET.get('search') + user = SystemUserProfile.objects.get(user=request.user) + kill_house_requests_list = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, trash=True, temporary_trash=False, + temporary_deleted=False).select_related('kill_request') + if request.GET['role'] == 'VetSupervisor': + kill_house_requests_list = kill_house_requests_list.filter( + province_request__poultry_request__poultry__address__province=user.province, + + ) + + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + + kill_house_requests_list = kill_house_requests_list.filter( + province_request__poultry_request__poultry__in=poultries, + ).select_related('kill_request') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + kill_house_requests_list = kill_house_requests_list.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).select_related('kill_request') + + elif request.GET['role'] in ['CityCommerce', 'CityVet', 'CityJahad', 'CityPoultry']: + kill_house_requests_list = kill_house_requests_list.filter( + + province_request__poultry_request__poultry__address__city=user.city, + + ).select_related('kill_request') + + elif request.GET['role'] == 'LiveStockSupport': + kill_house_requests_list = kill_house_requests_list.filter( + + province_request__poultry_request__freezing=True, + + ).select_related('kill_request') + + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + kill_house_requests_list = kill_house_requests_list.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house) | Q(killer__in=kill_house)), + + province_request__poultry_request__poultry__address__province=user.province, + ).select_related('kill_request') + + else: + kill_house_requests_list = kill_house_requests_list.filter( + + province_request__poultry_request__poultry__address__province=user.province, + ).select_related('kill_request') + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + kill_house_requests_list = kill_house_requests_list.filter( + build_query(self.filterset_class, value) + ) + + first_quantity = kill_house_requests_list.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + + first_weight = kill_house_requests_list.aggregate( + total_quantity=Sum(F('province_request__poultry_request__Index_weight') * F('quantity'))).get( + 'total_quantity') or 0 + len_has_code = len(kill_house_requests_list.filter(clearance_code__isnull=False)) + len_hasnt_code = len(kill_house_requests_list.filter(clearance_code__isnull=True)) + kill_house = kill_house_requests_list.values_list('kill_request__kill_house', flat=True).distinct() + + dict1 = { + "lenKillHouseRequest": len(kill_house_requests_list), + 'firstQuantity': first_quantity, + 'firstWeight': int(first_weight), + 'lenHasCode': len_has_code, + 'lenHasntCode': len_hasnt_code, + 'lenKillHouse': len(kill_house), + } + return Response(dict1) + + +class DahsnoardProvinceKillRequestViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestSerializer + permission_classes = [TokenHasReadWriteScope] + filterset_class = ProvinceKillRequestNewFilterSet + + # تابع مربوط به نمایش تخصیصات به کشتارگاها توسط استان + def list(self, request, *args, **kwargs): + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + if request.GET['role'] == 'KillHouse': + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, + trash=False) + + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter(Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house), + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False, + ).select_related( + 'province_request__poultry_request').order_by( + 'province_request__city_request_Poultry__poultry_request__send_date') + else: + trash = True if 'deleted_object' in request.GET else False + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request__poultry__user__province=user.province, + trash=trash, + delete_message__isnull=False if trash else True, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, temporary_trash=False, temporary_deleted=False, + ).select_related( + 'province_request__poultry_request__poultry', + 'province_request__city_request_Poultry__poultry_request__poultry__user', + 'province_request__city_request_Poultry__poultry_request__poultry__user__city', + 'kill_request__kill_house', + 'kill_request__kill_house__kill_house_operator__user', + 'kill_request__kill_house__system_address__city' + ).order_by('province_request__poultry_request__send_date') + if 'allocated_car_state' in request.GET: + province_kill_requests = province_kill_requests.filter(first_car_allocated_quantity=0) + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + province_kill_requests = province_kill_requests.filter( + build_query(self.filterset_class, value) + ) + kill_requests = KillHouseRequest.objects.filter(province_kill_request__in=province_kill_requests, trash=False) + accepted_province_kill_requests = province_kill_requests.filter(state='accepted') + pending_province_kill_requests = province_kill_requests.filter(state='pending') + rejected_province_kill_requests = province_kill_requests.filter(state='rejected') + + quantity = province_kill_requests.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + weight = province_kill_requests.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity') or 0 + + accepted_quantity = accepted_province_kill_requests.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + pending_quantity = pending_province_kill_requests.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + rejected_quantity = rejected_province_kill_requests.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + has_car = province_kill_requests.filter(first_car_allocated_quantity__gt=0) + has_car_quantity = has_car.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + has_car_weight = has_car.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity') or 0 + hasnt_car = province_kill_requests.filter(first_car_allocated_quantity=0) + hasnt_car_quantity = hasnt_car.aggregate( + total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity') or 0 + hasnt_car_weight = hasnt_car.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity') or 0 + real_quantity = kill_requests.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + real_weight = kill_requests.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + internal_dict_infos = { + "lenProvinceRequest": len(province_kill_requests), + "quantity": quantity, + "weight": int(weight), + "acceptedProvinceKillRequests": len(accepted_province_kill_requests), + "acceptedProvinceKillRequestsQuantity": accepted_quantity, + "pendingProvinceKillRequests": len(pending_province_kill_requests), + "pendingProvinceKillRequestsQuantity": pending_quantity, + "rejectedProvinceKillRequests": len(rejected_province_kill_requests), + "rejectedProvinceKillRequestsQuantity": rejected_quantity, + "lenHasCar": len(has_car), + "hasCarQuantity": has_car_quantity, + "hasCarWeight": has_car_weight, + "lenKillRequests": len(kill_requests), + "realQuantity": real_quantity, + "realWeight": real_weight, + "lenHasntCar": len(hasnt_car), + "hasntCarQuantity": hasnt_car_quantity, + "hasntCarWeight": hasnt_car_weight, + } + + return Response(internal_dict_infos, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.data['role'] + request.data.pop('role') + if 'type' in request.data.keys(): + if request.data['type'] == 'archive': + user_fullname = user.fullname + date = str(datetime.now()) + archive_province_kill_request_wage_threading = threading.Thread( + target=provincearchiveprovincekillrequestforwage, + args=( + request.data['province_kill_request_list'], request.data['message'], role, user_fullname, date + )) + archive_province_kill_request_wage_threading.start() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + + elif request.data['type'] == 'return_archive': + user_fullname = user.fullname + date = str(datetime.now().date()) + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key']) + province_kill_request.archive_by_province = False + if 'return_archive_message' in request.data.keys(): + province_kill_request.return_archive_message = request.data['return_archive_message'] + province_kill_request.returner = { + "fullname": user_fullname, + "date": date, + "role": role + } + province_kill_request.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + + else: + + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key']) + if province_kill_request.prev_total_amount == None: + province_kill_request.prev_total_amount = province_kill_request.total_amount + province_kill_request.total_amount_editor = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + province_kill_request.save() + serializer = self.serializer_class(province_kill_request) + serializer.update(instance=province_kill_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + if 'delete_allocation' in request.GET: + province_kill_request = ProvinceKillRequest.objects.get(key=request.GET['province_kill_request_key'], + trash=False) + if province_kill_request.quantity != province_kill_request.main_quantity: + return Response({"result": "برای تخصیص ماشین ثبت شده امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, + trash=False) + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= province_kill_request.total_killed_weight + # hatching.free_killed_quantity -= int(province_kill_request.main_quantity * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= province_kill_request.main_quantity + else: + hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight + # hatching.governmental_killed_quantity -= int( + # province_kill_request.main_quantity * poultry_request.Index_weight) + + hatching.governmental_quantity -= province_kill_request.total_killed_quantity + # hatching.governmental_quantity -= province_kill_request.main_quantity + # hatching.killed_quantity -= province_kill_request.main_quantity + hatching.save() + + if poultry_request.remain_quantity > 0: + # province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + else: + + # province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + # poultry_request.quantity -= province_kill_request.quantity + # poultry_request.first_quantity -= province_kill_request.quantity + # poultry_request.previous_quantity -= province_kill_request.quantity + # poultry_request.save() + # if poultry_request.quantity == 0: + # poultry_request.trash = True + # poultry_request.save() + # hatching.left_over += province_kill_request.quantity + # hatching.state = 'pending' + # hatching.allow_hatching = 'pending' + # hatching.save() + kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + kill_request.remain_quantity += province_kill_request.main_quantity + kill_request.save() + province_kill_request.delete_message = request.GET['message'] + province_kill_request.trash = True + province_kill_request.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + elif 'return_allocation_quantity' in request.GET: + + province_kill_request = ProvinceKillRequest.objects.get(key=request.GET['province_kill_request_key'], + trash=False) + if province_kill_request.quantity == 0: + return Response({"result": "باقی مانده تخصیص صفر است امکان بازگشت تعداد وجود ندارد"}, + status=status.HTTP_403_FORBIDDEN) + amount = province_kill_request.quantity + + poultry_request = PoultryRequest.objects.get(key=province_kill_request.province_request.poultry_request.key, + trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + + if province_kill_request.main_quantity - province_kill_request.quantity == 0: + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + # kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + # kill_request.remain_quantity += province_kill_request.main_quantity + # kill_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= province_kill_request.total_killed_weight + # hatching.free_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= amount + else: + hatching.governmental_killed_quantity -= province_kill_request.total_killed_weight + # hatching.governmental_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.governmental_quantity -= province_kill_request.total_killed_quantity + # hatching.governmental_quantity -= amount + # hatching.killed_quantity -= amount + hatching.save() + # province_kill_request.trash = True + province_kill_request.quantity = 0 + province_kill_request.total_killed_quantity = 0 + province_kill_request.total_killed_weight = 0 + province_kill_request.return_to_province = True + province_kill_request.save() + else: + + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + province_check.quantity += province_kill_request.main_quantity - province_kill_request.quantity + province_check.save() + poultry_request.remain_quantity += province_kill_request.main_quantity - province_kill_request.quantity + poultry_request.save() + # kill_request = KillRequest.objects.get(key=province_kill_request.kill_request.key) + # kill_request.remain_quantity += province_kill_request.main_quantity - province_kill_request.quantity + # kill_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= int(( + province_kill_request.main_quantity - province_kill_request.quantity) * poultry_request.Index_weight) + # hatching.free_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.free_quantity -= province_kill_request.total_killed_quantity + # hatching.free_quantity -= amount + else: + hatching.governmental_killed_quantity -= int(( + province_kill_request.main_quantity - province_kill_request.quantity) * poultry_request.Index_weight) + # hatching.governmental_killed_quantity -= int(amount * poultry_request.Index_weight) + hatching.governmental_quantity -= province_kill_request.main_quantity - province_kill_request.quantity + # hatching.governmental_quantity -= amount + # hatching.killed_quantity -= amount + hatching.save() + province_kill_request.main_quantity = province_kill_request.main_quantity - province_kill_request.quantity + province_kill_request.quantity = 0 + province_kill_request.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + queryset = ProvinceKillRequest.objects.get(key=request.GET['key']) + poultry_request = PoultryRequest.objects.get(key=queryset.province_request.poultry_request.key) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + check = KillHouseCheckRequest.objects.filter(province_kill_request=queryset, state='accepted') + if check.count() > 0: + return Response({"result": "can not delete"}, status=status.HTTP_403_FORBIDDEN) + province = ProvinceCheckOperatorRequest.objects.get(key=queryset.province_request.key) + province.quantity += queryset.quantity + province.save() + kill_request = KillRequest.objects.get(key=queryset.kill_request.key) + kill_request.remain_quantity += queryset.quantity + kill_request.save() + # queryset.delete() + poultry_request.remain_quantity += queryset.quantity + poultry_request.save() + if poultry_request.export == True: + hatching.export_killed_weight -= int(int(request.data['quantity']) * poultry_request.Index_weight) + hatching.export_killed_quantity -= int(request.data['quantity']) + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity -= queryset.total_killed_weight + # hatching.free_killed_quantity -= int(queryset.quantity * poultry_request.Index_weight) + hatching.free_quantity -= queryset.total_killed_quantity + else: + hatching.governmental_killed_quantity -= queryset.total_killed_weight + # hatching.governmental_killed_quantity -= int( + # queryset.quantity * poultry_request.Index_weight) + hatching.governmental_quantity -= queryset.total_killed_quantity + # hatching.killed_quantity -= queryset.total_killed_quantity + hatching.save() + queryset.delete() + + return Response(status=status.HTTP_200_OK) + + +class DashboardKillHouseFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeBarInformation.objects.all() + serializer_class = KillHouseFreeBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardKillHouseFreeBarInformationFilterSet + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type = request.GET['type'] + if request.GET['role'] in ['KillHouse', 'KillHouseVet']: + if request.GET['role'] == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house__in=kill_houses) | Q(exclusive_killer__in=kill_houses) | Q(public_killer__in=kill_houses), + buy_type=type, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False).order_by('-date') + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + buy_type=type, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + trash=False).order_by('-date') + + if date1: + kill_house_free_bar_info = kill_house_free_bar_info.filter(register_date__date__gte=date1, + register_date__date__lte=date2) + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + kill_house_free_bar_info = kill_house_free_bar_info.filter( + build_query(self.filterset_class, value) + ) + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + result = { + 'total_bars': len(kill_house_free_bar_info), + 'total_bars_quantity': quantity, + 'total_bars_live_Weight': live_weight, + 'total_bars_numberOfCarcasses': number_of_carcasses, + 'total_bars_weightOfCarcasses': weight_of_carcasses, + + 'entered_total_bars': len(entered_bars), + 'entered_total_bars_quantity': entered_quantity, + 'entered_total_bars_live_Weight': entered_live_weight, + 'entered_total_bars_numberOfCarcasses': entered_number_of_carcasses, + 'entered_total_bars_weightOfCarcasses': entered_weight_of_carcasses, + + 'not_entered_total_bars': len(not_entered_bars), + 'not_entered_total_bars_quantity': not_entered_quantity, + 'not_entered_total_bars_live_Weight': not_entered_live_weight, + 'not_entered_total_bars_numberOfCarcasses': not_entered_number_of_carcasses, + 'not_entered_total_bars_weightOfCarcasses': not_entered_weight_of_carcasses, + + } + else: + result = { + 'total_bars': len(kill_house_free_bar_info), + 'total_bars_quantity': quantity, + 'total_bars_live_Weight': live_weight, + 'total_bars_numberOfCarcasses': number_of_carcasses, + 'total_bars_weightOfCarcasses': weight_of_carcasses, + } + return Response(result, status=status.HTTP_200_OK) + + +class ParentCopmanyDashboardKillHouseFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = KillHouseFreeBarInformation.objects.all() + serializer_class = KillHouseFreeBarInformationSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardKillHouseFreeBarInformationFilterSet + + def list(self, request, *args, **kwargs): + + type = request.GET['type'] + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + buy_type=type, + trash=False).order_by('-date') + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + if type == 'live': + quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses__gt=0) + + entered_quantity = entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + entered_live_weight = entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + entered_number_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + entered_weight_of_carcasses = entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + not_entered_bars = kill_house_free_bar_info.filter(weight_of_carcasses=0) + + not_entered_quantity = not_entered_bars.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + not_entered_live_weight = not_entered_bars.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + not_entered_number_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + not_entered_weight_of_carcasses = not_entered_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + result = { + 'total_bars': len(kill_house_free_bar_info), + 'total_bars_quantity': quantity, + 'total_bars_live_Weight': live_weight, + 'total_bars_numberOfCarcasses': number_of_carcasses, + 'total_bars_weightOfCarcasses': weight_of_carcasses, + + 'entered_total_bars': len(entered_bars), + 'entered_total_bars_quantity': entered_quantity, + 'entered_total_bars_live_Weight': entered_live_weight, + 'entered_total_bars_numberOfCarcasses': entered_number_of_carcasses, + 'entered_total_bars_weightOfCarcasses': entered_weight_of_carcasses, + + 'not_entered_total_bars': len(not_entered_bars), + 'not_entered_total_bars_quantity': not_entered_quantity, + 'not_entered_total_bars_live_Weight': not_entered_live_weight, + 'not_entered_total_bars_numberOfCarcasses': not_entered_number_of_carcasses, + 'not_entered_total_bars_weightOfCarcasses': not_entered_weight_of_carcasses, + + } + else: + result = { + 'total_bars': len(kill_house_free_bar_info), + 'total_bars_quantity': quantity, + 'total_bars_live_Weight': live_weight, + 'total_bars_numberOfCarcasses': number_of_carcasses, + 'total_bars_weightOfCarcasses': weight_of_carcasses, + } + return Response(result, status=status.HTTP_200_OK) + + +class DashboardKillRequestViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + serializer_class = KillHouseFreeBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardKillRequestFilterSet + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + querysets = KillRequest.objects.filter( + recive_date__date__gte=date1, + recive_date__date__lte=date2, poultry__isnull=False, + trash=False).order_by( + 'recive_date') + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + querysets = querysets.filter(kill_house__in=kill_house).order_by('recive_date') + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + if 'direct_buying' in request.GET: + querysets = querysets.filter(market=False, + final_accept=True, + direct_buying_state__in=( + 'accepted', 'rejected', 'deleted', 'pending'), + export_status=False, trash=False + ) + if 'export' in request.GET: + if request.GET['type'] == 'pending': + querysets = querysets.filter(export_status=True, + export_state='pending' + ) + else: + querysets = querysets.filter(export_status=True, + export_state__in=( + 'accepted', 'rejected', 'deleted'), + ) + + if value and search == 'filter': + if value != 'undefined' and value.strip(): + querysets = querysets.filter( + build_query(self.filterset_class, value) + ) + quantity = querysets.aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity') or 0 + free_direct_buying_true_quantity = querysets.aggregate( + total_quantity=Sum('kill_capacity', filter=Q(free_direct_buying=True))).get( + 'total_quantity') or 0 + free_direct_buying_false_quantity = querysets.aggregate( + total_quantity=Sum('kill_capacity', filter=Q(free_direct_buying=False))).get( + 'total_quantity') or 0 + left_over = querysets.aggregate( + total_quantity=Sum('remain_quantity')).get( + 'total_quantity') or 0 + amount = querysets.aggregate( + total_quantity=Avg('amount')).get( + 'total_quantity') or 0 + index_wight = querysets.aggregate( + total_quantity=Avg('Index_weight')).get( + 'total_quantity') or 0 + dict1 = { + 'lenKillRequest': querysets.count(), + 'lenKillRequestHasFreeDirectBuying': querysets.filter(free_direct_buying=True).count(), + 'lenKillRequestHasntFreeDirectBuying': querysets.filter(free_direct_buying=False).count(), + 'quantity': quantity, + 'leftOver': left_over, + 'remainQuantity': quantity - left_over, + 'amount': amount, + 'indexWight': index_wight, + 'freeDirectBuyingTrueQuantity': free_direct_buying_true_quantity, + 'freeDirectBuyingFalseQuantity': free_direct_buying_false_quantity, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class InputBarsForKillHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForInputBarsSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + def list(self, request, *args, **kwargs): + quota = request.GET.get('quota') + if quota == 'governmental': + quota_filter = {'province_request__poultry_request__free_sale_in_province': False} + elif quota == 'free': + quota_filter = {'province_request__poultry_request__free_sale_in_province': True} + else: + quota_filter = None + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['date1']: + + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['type'] == 'entered': + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date') + else: + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=False, non_receipt=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date') + else: + + if request.GET['type'] == 'entered': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date') + else: + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, non_receipt=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date') + + if quota_filter: + kill_house_requests = kill_house_requests.filter(**quota_filter) + + if 'search' in request.GET: + kill_house_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_requests_list = ps.filter() + kill_house_requests = [] if len(kill_house_requests_list) == 0 else kill_house_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class InputBarsForKillHouseDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForInputBarsSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role in ('Steward', 'Guild'): + guild = Guilds.objects.get(user=user, active=True, trash=False) + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = StewardAllocation.objects.filter( + Q(to_steward=guild) | Q(to_guilds=guild), date__date__gte=date1, date__date__lte=date2, + trash=False, calculate_status=True, system_registration_code=True) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=guild) | Q(to_guilds=guild), + trash=False, calculate_status=True, system_registration_code=True) + entered_allocations = allocations.filter(receiver_state='accepted') + not_entered_allocations = allocations.filter(receiver_state='pending') + rejected_allocations = allocations.filter(receiver_state='rejected') + total_allocations_quantity = allocations.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + total_allocations_weight = allocations.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_entered_allocations_quantity = \ + entered_allocations.aggregate(total=Sum('real_number_of_carcasses'))['total'] or 0 + total_entered_allocations_weight = \ + entered_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_not_entered_allocations_quantity = \ + not_entered_allocations.aggregate(total=Sum('real_number_of_carcasses'))['total'] or 0 + total_not_entered_allocations_weight = \ + not_entered_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + total_rejected_allocations_quantity = \ + rejected_allocations.aggregate(total=Sum('real_number_of_carcasses'))['total'] or 0 + total_rejected_allocations_weight = \ + rejected_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + result = { + "total_bars": len(allocations), + "total_bars_quantity": total_allocations_quantity, + "total_bars_weight": total_allocations_weight, + "total_entered_bars": len(entered_allocations), + "total_entered_bars_quantity": total_entered_allocations_quantity, + "total_entered_bars_weight": total_entered_allocations_weight, + "total_not_entered_bars": len(not_entered_allocations), + "total_not_entered_bars_quantity": total_not_entered_allocations_quantity, + "total_not_entered_kill_house_requests_weight": total_not_entered_allocations_weight, + "total_rejected_bars": len(rejected_allocations), + "total_rejected_bars_quantity": total_rejected_allocations_quantity, + "total_rejected_bars_weight": total_rejected_allocations_weight, + } + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False, calculate_status=True).order_by('-kill_request__recive_date') + entered_kill_house_requests = kill_house_requests.filter(ware_house_confirmation=True) + not_entered_kill_house_requests = kill_house_requests.filter(ware_house_confirmation=False) + total_kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_quantity = \ + entered_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + total_entered_kill_house_requests_weight = \ + entered_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_entered_kill_house_requests_carcasses = \ + entered_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_quantity'))['total'] or 0 + total_entered_kill_house_requests_carcasses_weight = \ + entered_kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))['total'] or 0 + total_not_entered_kill_house_requests_quantity = \ + not_entered_kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + total_not_entered_kill_house_requests_weight = \ + not_entered_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + + result = { + "total_bars": len(kill_house_requests), + "total_bars_quantity": total_kill_house_requests_quantity, + "total_bars_weight": total_kill_house_requests_weight, + "total_entered_bars": len(entered_kill_house_requests), + "total_entered_bars_quantity": total_entered_kill_house_requests_quantity, + "total_entered_bars_weight": total_entered_kill_house_requests_weight, + "total_entered_bars_carcasses": total_entered_kill_house_requests_carcasses, + "total_entered_bars_carcasses_weight": total_entered_kill_house_requests_carcasses_weight, + "total_not_entered_bars": len(not_entered_kill_house_requests), + "total_not_entered_bars_quantity": total_not_entered_kill_house_requests_quantity, + "total_not_entered_kill_house_requests_weight": total_not_entered_kill_house_requests_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class BarDifferenceRequestViewSet(viewsets.ModelViewSet): + queryset = BarDifferenceRequest.objects.all() + serializer_class = BarDifferenceRequestSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = BarDifferenceRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'hatching__poultry__user__fullname', + 'hatching__poultry__user__mobile' + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + state = request.GET.get('state') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + filters = { + 'trash': False, + } + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + filters['kill_house'] = kill_house + if state == 'pending': + filters['state'] = 'pending' + else: + filters['state__in'] = ('accepted', 'rejected') + + if date1: + filters['create_date__date__gte'] = date1 + filters['create_date__date__lte'] = date2 + + bar_requests = BarDifferenceRequest.objects.filter(**filters).order_by('-id') + + if 'search' in request.GET: + bar_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bar_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bar_requests) + bar_requests_list = ps.filter() + bar_requests = [] if len(bar_requests_list) == 0 else bar_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(bar_requests) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(bar_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + hatching = PoultryHatching.objects.get(key=request.data['hatching_key'], trash=False) + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + images = None + acceptor_images = None + request.data.pop('hatching_key') + request.data.pop('kill_house_key') + if 'images' in request.data.keys(): + images = request.data['images'] + request.data.pop('images') + + if 'acceptor_images' in request.data.keys(): + acceptor_images = request.data['acceptor_images'] + request.data.pop('acceptor_images') + image_list = [] + acceptor_image_list = [] + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + bar_request = serializer.create(validated_data=request.data) + bar_request.hatching = hatching + bar_request.kill_house = kill_house + bar_request.register_fullname = user.fullname + bar_request.register_mobile = user.mobile + bar_request.weight = int(bar_request.quantity) * bar_request.hatching.poultry.real_killing_ave_weight + + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + + bar_request.violation_image = image_list + + if acceptor_images != None: + for acceptor_image in acceptor_images: + acceptor_image_list.append(send_image_to_server(acceptor_image)) + + bar_request.acceptor_image = acceptor_image_list + + bar_request.save() + send_sms_for_bar_difference_request(kill_house.kill_house_operator.user.mobile, request.data['quantity'], + hatching.poultry.unit_name) + send_ticket_for_bar_difference_request(user, kill_house.kill_house_operator.user, request.data['quantity'], + hatching.poultry.unit_name) + serializer_request = self.serializer_class(bar_request) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def update(self, request, pk=None, *args, **kwargs): + bar_request = BarDifferenceRequest.objects.get(key=request.data['bar_key']) + request.data.pop('bar_key') + if 'kill_house_check' in request.data.keys(): + request.data.pop('kill_house_check') + if request.data['state'] == 'accepted': + user = SystemUserProfile.objects.get(user=request.user, trash=False) + bar_request.acceptor_fullname = user.fullname + bar_request.acceptor_mobile = user.mobile + bar_request.acceptor_date = datetime.now() + # bar_request.weight = bar_request.quantity * bar_request.hatching.poultry.real_killing_ave_weight + bar_request.hatching.bar_difference_request_quantity += bar_request.quantity + bar_request.hatching.bar_difference_request_weight += bar_request.weight + bar_request.hatching.save() + bar_request.save() + + if 'images' in request.data.keys(): + images = request.data['images'] + request.data.pop('images') + image_list = [] + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + + bar_request.violation_image = image_list + if 'acceptor_images' in request.data.keys(): + acceptor_images = request.data['acceptor_images'] + request.data.pop('acceptor_images') + acceptor_images_list = [] + if acceptor_images != None: + for acceptor_image in acceptor_images: + acceptor_images_list.append(send_image_to_server(acceptor_image)) + + bar_request.acceptor_image = acceptor_images_list + serializer = self.serializer_class(bar_request) + serializer.update(instance=bar_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + bar_request = BarDifferenceRequest.objects.get(key=request.GET['bar_key'], trash=False) + if bar_request.state == 'accepted': + bar_request.hatching.bar_difference_request_quantity -= bar_request.quantity + bar_request.hatching.bar_difference_request_weight -= bar_request.weight + bar_request.hatching.save() + bar_request.trash = True + bar_request.save() + return Response({"result": "با موفقیت حذف شد."}, + status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def get_hatching_kill_ingo(request): + hatching = PoultryHatching.objects.get(key=request.GET['hatching_key']) + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + + total_quantity = 0 + total_weight = 0 + Province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + state__in=('pending', 'accepted'), + return_to_province=False, + province_request__poultry_request__hatching=hatching) + first_total_quantity = \ + Province_kill_requests.aggregate(total=Sum('main_quantity'))[ + 'total'] or 0 + + total_quantity = \ + Province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_weight = \ + Province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + difference_quantity = first_total_quantity - total_quantity + # kill_house_requests = KillHouseRequest.objects.filter(Q(killhouse_user=obj.kill_house) | Q(killer=obj.kill_house),trash=False, + # province_request__poultry_request__hatching=obj.hatching) + # + # + # total_quantity +=\ + # kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + # 'total'] or 0 + # total_weight +=\ + # kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + # 'total'] or 0 + + result = { + "first_total_quantity": first_total_quantity, + "total_quantity": total_quantity, + "difference_quantity": difference_quantity, + "total_weight": total_weight, + } + + return Response(result, + status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def dashboard_monitoring_bar_and_killing(request): + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else now + kill_house_free_bar = KillHouseFreeBarInformation.objects.filter(Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), + trash=False, + archive_wage=False, + ).only( + 'quantity', + 'live_weight', + 'number_of_carcasses', + 'weight_of_carcasses', + 'send_date', + 'type', + 'out' + ) + + kill_house_free_bar_aggregates = kill_house_free_bar.aggregate( + total_quantity_live=Sum('quantity', filter=Q(buy_type='live')), + total_weight_live=Sum('live_weight', filter=Q(buy_type='live')), + total_count=Count('id', filter=Q(buy_type='live')), + total_weight=Sum('weight_of_carcasses', filter=Q(buy_type='live')), + total_count_carcass=Count('id', filter=Q(buy_type='carcass')), + total_weight_carcass=Sum('weight_of_carcasses', filter=Q(buy_type='carcass')), + total_quantity_carcass=Sum('number_of_carcasses', filter=Q(buy_type='carcass')), + + ) + + if kill_house_free_bar_aggregates['total_quantity_live'] != 0: + ratio = round( + ((kill_house_free_bar_aggregates['total_weight_live'] or 0) / ( + kill_house_free_bar_aggregates['total_quantity_live'] + or 0)) + , 1) if (kill_house_free_bar_aggregates['total_quantity_live'] or 0) > 0 else 0 + else: + ratio = 0 + + province_kill_request = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + wage_pay=False, + archive_wage=False, + return_to_province=False, + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2). \ + select_related('province_request__poultry_request').only( + 'total_killed_quantity', + 'province_request__poultry_request__Index_weight', + ) + + province_kill_request_aggregates = province_kill_request.aggregate( + total_count=Count('id', filter=Q(first_car_allocated_quantity=0)), + total_quantity=Sum('total_killed_quantity', filter=Q(first_car_allocated_quantity=0)), + total_index_weight=Avg('province_request__poultry_request__Index_weight', + filter=Q(first_car_allocated_quantity=0)), + total_count_new=Count('id'), + total_quantity_new=Sum('total_killed_quantity'), + total_weight_new=Sum('total_killed_weight'), + total_index_weight_new=Avg('province_request__poultry_request__Index_weight'), + + ) + + poultry_request = PoultryRequest.objects.filter( + trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + temporary_trash=False, + temporary_deleted=False, send_date__date__gte=date1, + send_date__date__lte=date2 + ).only( + 'quantity', + 'Index_weight', + ).annotate( + item_weight=F('Index_weight') * F('quantity') + ) + + poultry_request_aggregates = poultry_request.aggregate( + total_count=Count('id', filter=Q(out=True)), + total_quantity=Sum('quantity', filter=Q(out=True)), + total_ave_weight=Avg('Index_weight', filter=Q(out=True)), + total_weight=Sum('item_weight', filter=Q(out=True)), + total_count_killing=Count('id'), + total_quantity_killing=Sum('quantity'), + total_ave_weight_killing=Avg('Index_weight'), + total_weight_killing=Sum('item_weight') + ) + + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + temporary_trash=False, + temporary_deleted=False, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).select_related('province_kill_request__province_request__poultry_request__Index_weight').only( + 'quantity', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'accepted_real_weight', + 'accepted_real_quantity', + ) + + kill_house_request_aggregates = kill_house_request.aggregate( + total_count=Count('id'), + total_quantity=Sum('accepted_real_quantity'), + total_quantity_has_quarantine=Sum('accepted_real_quantity', filter=Q(quarantine_quantity__gt=0)), + total_count_has_quarantine=Count('id', filter=Q(quarantine_quantity__gt=0)), + total_weight=Sum('accepted_real_weight'), + total_ave_weight=Avg('province_kill_request__province_request__poultry_request__Index_weight'), + total_ave_age=Avg('province_kill_request__province_request__poultry_request__hatching__chicken_age'), + total_quarantine=Count('id', filter=Q(quarantine_quantity__gt=0)), + total_quarantine_quantity=Sum('quarantine_quantity', filter=Q(quarantine_quantity__gt=0)), + total_quarantine_discharge_confirmation=Count('id', filter=Q(quarantine_quantity__gt=0, + assignment_state_archive='True')), + total_quarantine_discharge_confirmation_quantity=Sum('accepted_real_quantity', + filter=Q(quarantine_quantity__gt=0, + assignment_state_archive='True')), + + ) + + province_request_count = province_kill_request_aggregates['total_count_new'] or 0 + province_request_quantity = province_kill_request_aggregates['total_quantity_new'] or 0 + province_request_weight = province_kill_request_aggregates['total_weight_new'] or 0 + total_free_sell_count = kill_house_free_bar_aggregates['total_count'] or 0 + total_free_sell_quantity = kill_house_free_bar_aggregates['total_quantity_live'] or 0 + total_free_sell_weight = kill_house_free_bar_aggregates['total_weight_live'] or 0 + avgWeight = round( + (province_request_weight + total_free_sell_weight) / (province_request_quantity + total_free_sell_quantity), + 1) if (province_request_quantity + total_free_sell_quantity) > 0 else 0 + + result_dict = { + 'freeLiveBar': { + 'count': kill_house_free_bar_aggregates['total_count'] or 0, + 'quantity': kill_house_free_bar_aggregates['total_quantity_live'] or 0, + 'weight': kill_house_free_bar_aggregates['total_weight_live'] or 0, + 'weightCarcass': kill_house_free_bar_aggregates['total_weight_carcass'] or 0, + 'avgWeight': ratio, + }, + 'provinceKillRequestWithoutBar': { + 'count': province_kill_request_aggregates['total_count'] or 0, + 'quantity': province_kill_request_aggregates['total_quantity'] or 0, + 'indexWeight': round((province_kill_request_aggregates['total_index_weight'] or 0), 1), + }, + 'outLiveBar': { + 'count': poultry_request_aggregates['total_count'] or 0, + 'quantity': poultry_request_aggregates['total_quantity'] or 0, + 'weight': poultry_request_aggregates['total_weight'] or 0, + 'avgWeight': round((poultry_request_aggregates['total_ave_weight'] or 0), 1), + + }, + 'bar': { + 'count': kill_house_request_aggregates['total_count'] or 0, + 'count_has_quarantine': kill_house_request_aggregates['total_count_has_quarantine'] or 0, + 'quantity': kill_house_request_aggregates['total_quantity'] or 0, + 'quantity_has_quarantine': kill_house_request_aggregates['total_quantity_has_quarantine'] or 0, + 'weight': kill_house_request_aggregates['total_weight'] or 0, + 'avgWeight': round((kill_house_request_aggregates['total_ave_weight'] or 0), 1), + 'avgAge': int(kill_house_request_aggregates['total_ave_age'] or 0), + + 'total_quarantine': kill_house_request_aggregates['total_quarantine'] or 0, + 'total_quarantine_quantity': kill_house_request_aggregates['total_quarantine_quantity'] or 0, + 'total_quarantine_discharge_confirmation': kill_house_request_aggregates[ + 'total_quarantine_discharge_confirmation'] or 0, + 'total_quarantine_discharge_confirmation_quantity': kill_house_request_aggregates[ + 'total_quarantine_discharge_confirmation_quantity'] or 0, + + }, + 'killingInfo': { + 'count': province_request_count + total_free_sell_count, + 'quantity': province_request_quantity + total_free_sell_quantity, + 'weight': province_request_weight + total_free_sell_weight, + 'avgWeight': avgWeight, + }, + 'buyFreeCarcasses': { + 'count': kill_house_free_bar_aggregates['total_count_carcass'] or 0, + 'quantity': kill_house_free_bar_aggregates['total_quantity_carcass'] or 0, + 'weight': kill_house_free_bar_aggregates['total_weight_carcass'] or 0, + } + + } + return Response(result_dict, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def dashboarad_bar_for_kill_house(request): + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user=kill_house) | Q( + kill_request__slaughter_house=kill_house) | Q(killer=kill_house)), + (Q(trash=False) | Q(trash=True, clearance_code__isnull=False, temporary_trash=False, + temporary_deleted=False)), + + province_request__poultry_request__poultry__address__province=user.province, + ).select_related('kill_request') + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = kill_house_requests.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + + if 'search' in request.GET: + kill_house_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_requests) + kill_house_request_list = ps.filter() + kill_house_requests = [] if len(kill_house_request_list) == 0 else kill_house_request_list + kill_house_requests_aggregate = kill_house_requests.aggregate( + first_quantity=Sum('quantity'), + first_weight=Sum('quantity') * Avg('province_request__poultry_request__Index_weight'), + first_index_weight=Avg('province_request__poultry_request__Index_weight'), + accepted_real_quantity=Sum('accepted_real_quantity'), + accepted_real_weight=Sum('accepted_real_weight'), + assignment_state_archive_pending=Count('id', filter=Q(assignment_state_archive='pending')), + assignment_state_archive_accepted=Count('id', filter=Q(assignment_state_archive='accepted')), + clearance_code_count=Count('id', filter=Q(clearance_code__isnull=False)), + + ) + + result_dict = { + 'count': kill_house_requests.count(), + 'firstQuantity': kill_house_requests_aggregate['first_quantity'] or 0, + 'firstWeight': int(kill_house_requests_aggregate['first_weight'] or 0), + 'firstIndexWeight': round((kill_house_requests_aggregate['first_index_weight'] or 0), 1), + 'acceptedRealQuantity': kill_house_requests_aggregate['accepted_real_quantity'] or 0, + 'acceptedRealWeight': int(kill_house_requests_aggregate['accepted_real_weight'] or 0), + 'finalIndexWeight': round((kill_house_requests_aggregate['accepted_real_weight'] or 0) / + (kill_house_requests_aggregate['accepted_real_quantity'] or 0), 1) + if (kill_house_requests_aggregate['accepted_real_quantity'] or 0) > 0 else 0, + 'assignmentStateArchivePending': kill_house_requests_aggregate['assignment_state_archive_pending'] or 0, + 'assignmentStateArchiveAccepted': kill_house_requests_aggregate['assignment_state_archive_accepted'] or 0, + 'clearanceCodeCount': kill_house_requests_aggregate['clearance_code_count'] or 0, + + } + return Response(result_dict, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def dashboard_bar_difference_request(request): + filterset_class = BarDifferenceRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'hatching__poultry__user__fullname', + 'hatching__poultry__user__mobile' + ] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + # if request.GET['role'] == 'KillHouse': + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + # 'system_address__province').first() + # if request.GET['state'] == 'pending': + # bar_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, + # state='pending').order_by('id') + # else: + # bar_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, + # state__in=('accepted', 'rejected')).order_by('id') + # else: + # if request.GET['state'] == 'pending': + # bar_requests = BarDifferenceRequest.objects.filter(trash=False, state='pending').order_by('id') + # else: + # bar_requests = BarDifferenceRequest.objects.filter(trash=False, + # state__in=('accepted', 'rejected')).order_by('id') + + role = request.GET.get('role') + state = request.GET.get('state') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + filters = { + 'trash': False, + } + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + filters['kill_house'] = kill_house + if state == 'pending': + filters['state'] = 'pending' + else: + filters['state__in'] = ('accepted', 'rejected') + + if date1: + filters['create_date__date__gte'] = date1 + filters['create_date__date__lte'] = date2 + + bar_requests = BarDifferenceRequest.objects.filter(**filters).order_by('-id') + + if 'search' in request.GET: + bar_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=bar_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=bar_requests) + bar_requests_list = ps.filter() + bar_requests = [] if len(bar_requests_list) == 0 else bar_requests_list + + serializer = BarDifferenceRequestSerializer(bar_requests, many=True) + + bar_info_list = [item['bar_info'] for item in serializer.data] + + difference_quantity = sum(item["first_total_quantity"] for item in bar_info_list) - \ + sum(item["total_quantity"] for item in bar_info_list) + + bar_requests_aggregate = bar_requests.aggregate( + count=Count('id'), + weight=Sum('weight'), + quantity=Sum('quantity'), + ) + + result_dict = { + 'count': bar_requests_aggregate['count'] or 0, + 'weight': bar_requests_aggregate['weight'] or 0, + 'quantity': bar_requests_aggregate['quantity'] or 0, + "firstTotalQuantity": sum(item["first_total_quantity"] for item in bar_info_list), + "totalQuantity": sum(item["total_quantity"] for item in bar_info_list), + "differenceQuantity": difference_quantity, + "totalWeight": sum(item["total_weight"] for item in bar_info_list), + } + + return Response(result_dict, status=status.HTTP_200_OK) + + +class KillHousePerformanceDashboardViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).exclude(id__in=kill_house_ids).order_by( + 'id') + + serializer = KillHouseForPerformanceDashboardSerializer(kill_houses, many=True, + context={'date1': date1, 'date2': date2, }) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class NonReceiptKillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house = [] + kill_house_requests_list = [] + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + for kill_house_vet in kill_house_vets: + kill_house.append(kill_house_vet.kill_house) + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if request.GET['role'] in ['CityOperator', 'CityJahad', 'CityPoultry']: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True, + non_receipt=True, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + + ).order_by('-kill_request__recive_date') + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True, + non_receipt=True, + province_request__poultry_request__poultry__address__city=user.city + + ).order_by('-kill_request__recive_date') + + else: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + main_non_receipt=True, + non_receipt=True + + ).order_by('-kill_request__recive_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_requests_list = ps.filter() + kill_house_requests = [] if len(kill_house_requests_list) == 0 else kill_house_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now() + role = request.data.get('role') + message = request.data.get('message') + state = request.data.get('state') + key = request.data.get('key') + kill_house_request = KillHouseRequest.objects.get(key=key) + if kill_house_request.assignment_state_archive == 'True': + return Response({"result": "به دلیل وارد کردن اطلاعات بار امکان ثبت عدم وصول وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + kill_house_request.non_receipt_state = state + kill_house_request.message = message + kill_house_request.bar_remover = { + "full_name": user.fullname, + "role": role, + "mobile": user.mobile, + "date": str(now) + } + kill_house_request.trash = True if state == 'accepted' else False + kill_house_request.save() + if state == 'accepted': + update_kill_house_requests(kill_house_request.province_kill_request, + kill_house_request.province_request.poultry_request) + update_province_kill_requests(kill_house_request.province_request.poultry_request.hatching) + + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +class ReturnNonReceiptKillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseRequestForBarManagementSerializer + + def update(self, request, *args, **kwargs): + key = request.data.get('key') + kill_house_request = KillHouseRequest.objects.get(key=key) + trash = kill_house_request.trash + if kill_house_request.non_receipt_return: + return Response({"result": "عدم وصول برای این بار قبلا ثبت و لغو گردیده!"}) + kill_house_request.trash = False + kill_house_request.non_receipt = request.data['non_receipt'] + kill_house_request.non_receipt_return = request.data['non_receipt_return'] + kill_house_request.non_receipt_return_message = request.data['non_receipt_return_message'] + kill_house_request.save() + if trash: + update_kill_house_requests(kill_house_request.province_kill_request, + kill_house_request.province_request.poultry_request) + update_province_kill_requests(kill_house_request.province_request.poultry_request.hatching) + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_200_OK) + + +class DirectBuyingPaymentViewSet(viewsets.ModelViewSet): + queryset = DirectBuyingPayment.objects.all() + serializer_class = DirectBuyingPaymentSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = DirectBuyingPaymentFilterSet + filterset_fields = [ + + 'province_kill_request__kill_request__kill_house__name', + 'province_kill_request__kill_request__kill_house__kill_house_operator__user__fullname', + 'province_kill_request__kill_request__kill_house__kill_house_operator__user__first_name', + 'province_kill_request__kill_request__kill_house__kill_house_operator__user__last_name', + 'province_kill_request__kill_request__kill_house__kill_house_operator__user__mobile', + + ] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['province_kill_request_key']) + now = datetime.now() + image = request.data.pop('image', None) + request.data.pop('province_kill_request_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + payment = serializer.create(validated_data=request.data) + payment.province_kill_request = province_kill_request + payment.date = now + payment.payment_registrar = user.fullname + payment.payment_registrar_mobile = user.mobile + payment.image = send_image_to_server(image) + payment.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + province_kill_request = ProvinceKillRequest.objects.get(key=request.GET['province_kill_request_key']) + filter = {'trash': False, 'province_kill_request': province_kill_request} + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1: + filter['date1'] = datetime.strptime(str(date1), '%Y-%m-%d').date() + filter['date2'] = datetime.strptime(str(date2), '%Y-%m-%d').date() + payments = DirectBuyingPayment.objects.filter(**filter) + + if 'search' in request.GET: + payments_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=payments + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=payments) + payments_list = ps.filter() + payments = [] if len( + payments_list) == 0 else payments_list + + if request.GET.get('page'): + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(payments) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(payments, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + payment = DirectBuyingPayment.objects.get(key=request.data['key']) + image = request.data.pop('image', None) + if image: + payment.image = send_image_to_server(image) + payment.save() + serializer = self.serializer_class(payment) + serializer.update(instance=payment, validated_data=request.data) + + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + payment = DirectBuyingPayment.objects.get(key=request.GET['key']) + payment.trash = True + payment.save() + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class ProvinceKillRequestDirectBuyingViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + serializer_class = ProvinceKillRequestForDirectBuyingSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = ProvinceKillRequestFilterSet + filterset_fields = [ + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__poultry__address__city__name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + state = request.GET.get('status') + filter = { + 'trash': False, + 'payment_deadline': True, + 'return_to_province': False, + 'payment_deadline_archive': False if state == 'active' else True, + } + if date1: + filter['kill_request__recive_date__date__gte'] = datetime.strptime(date1, '%Y-%m-%d').date() + filter['kill_request__recive_date__date__lte'] = datetime.strptime(date2, '%Y-%m-%d').date() + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + filter['killhouse_user'] = kill_house + + elif role in ('CityJahad', 'CityOperator', 'CityCommerce', 'CityVet', 'CitySupervisor', 'CityPoultry'): + filter['kill_request__poultry__address__city'] = user.city + + province_kill_requests = ProvinceKillRequest.objects.filter(**filter).select_related('kill_request', + 'kill_request__poultry_hatching', + 'kill_request__poultry').only( + 'kill_request', 'kill_request__poultry_hatching', 'kill_request__poultry').order_by('payment_deadline_date') + + if 'search' in request.GET: + province_kill_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=province_kill_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=province_kill_requests) + province_kill_requests_list = ps.filter() + province_kill_requests = [] if len( + province_kill_requests_list) == 0 else province_kill_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(province_kill_requests) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(province_kill_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + province_kill_request = ProvinceKillRequest.objects.get(key=request.data['key']) + check = request.data.pop('check', None) + archive = request.data.pop('archive', None) + if 'final_accept' in request.data.keys(): + role = request.data.pop('role', None) + if request.data['final_accept'] == True: + province_kill_request.payment_deadline_state = 'checking' if role == 'KillHouse' else 'accepted' + province_kill_request.final_accept_registrar = user.fullname + province_kill_request.final_accept_registrar_mobile = user.mobile + province_kill_request.final_accept_date = datetime.now() + if role != 'KillHouse': + province_kill_request.payment_deadline_checker_fullname = user.fullname + province_kill_request.payment_deadline_checker_mobile = user.mobile + province_kill_request.payment_deadline_check_date = datetime.now() + province_kill_request.payment_deadline_archive_message = 'تایید و تسویه کامل' + province_kill_request.payment_deadline_archive = True + province_kill_request.save() + if check: + state = request.data.pop('state', None) + province_kill_request.payment_deadline_checker_fullname = user.fullname + province_kill_request.payment_deadline_checker_mobile = user.mobile + province_kill_request.payment_deadline_check_date = datetime.now() + province_kill_request.payment_deadline_archive = True if state == 'accepted' else False + province_kill_request.payment_deadline_state = state + + if province_kill_request.payment_deadline_state == 'rejected': + province_kill_request.final_accept = False + if archive: + province_kill_request.payment_deadline_checker_fullname = user.fullname + province_kill_request.payment_deadline_checker_mobile = user.mobile + province_kill_request.payment_deadline_check_date = datetime.now() + province_kill_request.payment_deadline_archive = True + province_kill_request.payment_deadline_state = 'archive' + + if 'extension_payment_deadline_days' in request.data.keys(): + province_kill_request.extension_payment_deadline_date = province_kill_request.payment_deadline_date + timedelta( + days=request.data['extension_payment_deadline_days']) + province_kill_request.kill_request.extension_payment_deadline_days = request.data[ + 'extension_payment_deadline_days'] + province_kill_request.kill_request.extension_payment_deadline_date = province_kill_request.extension_payment_deadline_date + province_kill_request.kill_request.save() + + province_kill_request.save() + serializer = self.serializer_class(province_kill_request) + serializer.update(instance=province_kill_request, validated_data=request.data) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class MarketKillRequestViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + serializer_class = KillRequestForDirectBuyingSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'poultry_request__chicken_breed', + 'poultry_request__order_code', + 'poultry_request__poultry__address__city__name', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__user__fullname', + + ] + + def calculate_province_kill_request_wage(self, kill_request): + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=kill_request.poultry_request) + + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + wage = wage_type.amount if wage_type.status == True else 0 + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + province_killrequest = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + kill_request=kill_request, + province_request=province_check, + quantity=kill_request.kill_capacity, + total_killed_quantity=kill_request.kill_capacity, + total_killed_weight=int(kill_request.kill_capacity * kill_request.poultry_request.Index_weight), + main_quantity=kill_request.kill_capacity, + wage=wage, + market=True, + payment_deadline=True, + payment_deadline_days=kill_request.payment_deadline_days, + payment_deadline_date=kill_request.payment_deadline_date, + state='accepted', + kill_house_price=kill_request.amount, + total_wage_amount=wage * int(kill_request.kill_capacity * kill_request.poultry_request.Index_weight), + ) + province_killrequest.save() + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_killrequest, + state='accepted' + ) + + kill_house_check.save() + vet_farm = VetFarm.objects.filter(trash=False, + poultry=province_killrequest.province_request.poultry_request.poultry).first() + bot_eitaa_for_each_province_kill_request(province_killrequest, vet_farm) + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_killrequest.union_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.union_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'company': + province_killrequest.company_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_killrequest.guilds_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.guilds_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'city': + province_killrequest.city_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_killrequest.wallet_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.wallet_share_percent = percentage_wage_type.percent + + else: + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + province_killrequest.save() + + def create(self, request, *args, **kwargs): + total_unpaid_wage = 0 + total_paid_wage = 0 + user = SystemUserProfile.objects.get(trash=False, user=request.user) + now = datetime.now() + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, market_buying=True, trash=False).exclude( + id__in=kill_house_ids).order_by('id', 'killer') + kill_house_for_killer = None + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + if kill_house.ware_house_remaining_weight_limitation_status: + if kill_house.total_remain_warehouse_governmental_weight > kill_house.ware_house_remaining_weight_limitation: + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_house.ware_house_remaining_percent_limitation_status: + if not check_kill_house_remain_limitation_weight(kill_house): + return Response({ + "result": "باقی مانده انبار شما از حداکثر محدودیت وزن باقی مانده روزانه انبار بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + with transaction.atomic(): + poultry_request = PoultryRequest.objects.select_for_update().get(key=request.data['poultry_request_key']) + if poultry_request.free_sale_in_province == True: + + if kill_house.quota: + kill_house_info = calculate_governmental_quota(kill_house) + if kill_house_info == 'not_allowed': + return Response({"result": " امکان خرید آزاد تا تکمیل تعهد دولتی وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + index_weight_category = IndexWeightCategory.objects.filter(trash=False, name='سبک').first() + light_max_value = index_weight_category.max_value if index_weight_category else 0 + if kill_house.market_buying_limitation: + kill_house_info = market_kill_request_share_quantity(kill_house, total_kill_houses=kill_houses) + kill_house_share = kill_house_info['kill_house_today_share'] + kill_house_buying = kill_house_info['kill_house_market_kill_requests_quantity'] + request.data[ + 'kill_capacity'] + if kill_house.market_light_capacity: + total_remain_light_weight = kill_house_info['total_remain_poultry_requests_quantity_light_weight'] + kill_house_market_kill_requests_quantity_light_weight = kill_house_info[ + 'kill_house_market_kill_requests_quantity_light_weight'] + real_kill_house_market_kill_requests_quantity_light_weight = kill_house_info['light_real_quantity'] + if poultry_request.Index_weight >= light_max_value: + if real_kill_house_market_kill_requests_quantity_light_weight > 0: + if total_remain_light_weight > real_kill_house_market_kill_requests_quantity_light_weight: + if real_kill_house_market_kill_requests_quantity_light_weight > kill_house_market_kill_requests_quantity_light_weight: + return Response({"result": "الویت با خرید و تکمیل نهایی سهمیه سبک می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if total_remain_light_weight > kill_house_market_kill_requests_quantity_light_weight: + return Response({"result": "الویت با خرید و تکمیل نهایی سهمیه سبک می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_house_share - kill_house_buying < 0: + return Response({"result": "حجم خریداری شده از سهمیه شما بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + kill_request = KillRequest.objects.filter(trash=False, poultry_request=poultry_request, + kill_house=kill_house, + market_final_accept=False).first() + # if poultry_request.remain_quantity < request.data['kill_capacity']: + # return Response({"result": "حجم وارد شده از باقی مانده قابل فروش بیشتر است !"}, + # status=status.HTTP_403_FORBIDDEN) + market_requests_quantity = KillRequest.objects.filter(poultry_request=poultry_request, trash=False, + market_state__in=('pending', 'accepted'), + market=True).aggregate( + total=Sum('kill_capacity'))['total'] or 0 + if market_requests_quantity + request.data['kill_capacity'] > poultry_request.quantity: + return Response({"result": "باقی مانده اعلام نیاز مرغدار کمتر از درخواست شماست!"}, + status=status.HTTP_403_FORBIDDEN) + + kill_house_purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=kill_house, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + if kill_house_purchase.limitation == True: + + if kill_house_purchase.limitation_number <= total_unpaid_wage - total_paid_wage: + if not ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + kill_request__recive_date__date=now.date(), + trash=False, + state__in=('pending', 'accepted')).exists(): + return Response({ + "result": "به علت بدهی امکان ثبت درخواست وحود ندارد لطفا بدهی خود را در پنل کارمزد ها تسویه کنید"}, + status=status.HTTP_403_FORBIDDEN) + + if kill_request: + kill_request.kill_capacity += request.data['kill_capacity'] + kill_request.remain_quantity += request.data['kill_capacity'] + kill_request.save() + market_poultry_request_remain_quantity(kill_request.poultry_request) + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + request.data.pop('poultry_request_key') + if kill_house.killer and kill_house.type == 'public': + percentage = KillHousePercentage.objects.filter(trash=False, kill_house=kill_house, + kill_house_for_killer__isnull=False).first() + kill_house_for_killer = percentage.kill_house_for_killer + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + market_kill_request = serializer.create(validated_data=request.data) + market_kill_request.kill_house = kill_house + market_kill_request.poultry_request = poultry_request + market_kill_request.poultry_hatching = poultry_request.hatching + market_kill_request.poultry = poultry_request.poultry + market_kill_request.recive_date = now + market_kill_request.chicken_breed = poultry_request.chicken_breed + market_kill_request.remain_quantity = market_kill_request.kill_capacity + market_kill_request.amount = poultry_request.amount + market_kill_request.Index_weight = poultry_request.Index_weight + market_kill_request.market = True + market_kill_request.payment_deadline = True + if kill_house_for_killer: + market_kill_request.slaughter_house = kill_house_for_killer + market_kill_request.market_expire_date_time = now + timedelta( + minutes=30) if market_code_state else now + timedelta(minutes=5) + if market_code_state: + market_kill_request.market_code_status = True + market_kill_request.payment_deadline_date = datetime.now() + timedelta( + days=request.data['payment_deadline_days']) + market_kill_request.save() + market_poultry_request_remain_quantity(market_kill_request.poultry_request) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + from django.db.models import Value + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + role = request.GET.get('role') + poultry_request_key = request.GET.get('poultry_request_key') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + # filter = { + # 'trash': False, + # 'market': True, + # } + filter = { + 'market': True + } + if date1: + filter['recive_date__date__gte'] = date1 + filter['recive_date__date__lte'] = date2 + + else: + filter['recive_date__date'] = now + + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + filter['kill_house'] = kill_house + + elif role in ('CityJahad', 'CityOperator', 'CityCommerce', 'CityVet', 'CitySupervisor', 'CityPoultry'): + filter['poultry__address__city'] = user.city + state_type = request.GET.get('type') + + if state_type and state_type != 'all': + filter['market_state'] = state_type + + if state_type in ('pending', 'accepted', 'rejected'): + filter['trash'] = False + elif state_type == 'deleted': + filter['trash'] = True + + if poultry_request_key: + filter['poultry_request__key'] = poultry_request_key + + kill_requests = KillRequest.objects.filter(**filter).select_related('poultry_hatching', 'poultry').only( + 'poultry_hatching', 'poultry').order_by( + Case( + When(market_state='pending', then=Value(0)), + default=Value(1) + ), + '-create_date' + ) + + if 'search' in request.GET: + kill_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_requests) + kill_requests_list = ps.filter() + kill_requests = [] if len( + kill_requests_list) == 0 else kill_requests_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_requests) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(kill_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + kill_request = KillRequest.objects.get(key=request.data['key']) + if kill_request.trash: + return Response({"result": "درخواست شما توسط کاربر حذف گردید!"}, status=status.HTTP_403_FORBIDDEN) + + if 'check' in request.data.keys(): + state = request.data['market_state'] + if state == 'accepted': + self.calculate_province_kill_request_wage(kill_request) + request.data.pop('check') + + if 'market_final_accept' in request.data.keys(): + # market_poultry_request_remain_quantity(kill_request.poultry_request) + poultry_request = kill_request.poultry_request + # market_requests_quantity = KillRequest.objects.filter(poultry_request=poultry_request, trash=False, + # market_state__in=('pending', 'accepted'), market=True, + # market_final_accept=True).aggregate( + # total=Sum('kill_capacity'))['total'] or 0 + # if market_requests_quantity + kill_request.kill_capacity > poultry_request.quantity: + # return Response({"result": "باقی مانده اعلام نیاز مرغدار کمتر از درخواست شماست!"}, + # status=status.HTTP_403_FORBIDDEN) + if market_code_state: + code = str(random.randint(10000, 99000)) + kill_request.market_code = code + kill_request.save() + market_sms = threading.Thread( + target=send_sms_fro_kill_request_market, + args=( + kill_request,)) + + market_sms.start() + kill_request.remain_quantity -= kill_request.kill_capacity + kill_request.save() + if 'kill_capacity' in request.data.keys(): + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, market_buying=True, trash=False).exclude( + id__in=kill_house_ids).order_by('id', 'killer') + if kill_request.kill_house.market_buying_limitation: + kill_house_info = market_kill_request_share_quantity(kill_request.kill_house, + total_kill_houses=kill_houses) + kill_house_share = kill_house_info['kill_house_today_share'] + kill_house_today_left_share = kill_house_info['kill_house_today_left_share'] + kill_house_buying = kill_house_info['kill_house_market_kill_requests_quantity'] + request.data[ + 'kill_capacity'] + if (kill_house_today_left_share + kill_request.kill_capacity) < request.data['kill_capacity']: + return Response({"result": "حجم خریداری شده از سهمیه شما بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + if kill_request.poultry_request.remain_quantity + kill_request.kill_capacity < request.data[ + 'kill_capacity']: + return Response({"result": "حجم وارد شده از باقی مانده قابل فروش بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + kill_request.remain_quantity = request.data['kill_capacity'] + if 'payment_deadline_days' in request.data.keys(): + kill_request.payment_deadline_date = datetime.now() + timedelta( + days=request.data['payment_deadline_days']) + if 'input_market_code' in request.data.keys(): + if request.data['input_market_code'] != kill_request.market_code: + return Response({"result": "کد وارد شده صحیح نمی باشد!"}, status=status.HTTP_403_FORBIDDEN) + kill_request.input_market_code = request.data['input_market_code'] + self.calculate_province_kill_request_wage(kill_request) + kill_request.market_state = 'accepted' + kill_request.save() + serializer = self.serializer_class(kill_request) + serializer.update(instance=kill_request, validated_data=request.data) + market_poultry_request_remain_quantity(kill_request.poultry_request) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + kill_request = KillRequest.objects.get(key=request.GET["key"]) + kill_request.trash = True + kill_request.market_state_message = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + kill_request.market_state = 'deleted' + kill_request.save() + market_poultry_request_remain_quantity(kill_request.poultry_request) + return Response(' با موفقیت حذف شد', status=status.HTTP_200_OK) + + +class MarketKillHouseViewSet(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseForCommonlyUsedSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def list(self, request, *args, **kwargs): + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by( + 'id', 'killer') + + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + kill_house = KillHouse.objects.get(key=request.data['key']) + serializer = self.serializer_class(kill_house) + serializer.update(instance=kill_house, validated_data=request.data) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseMarketInfoViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseMarketInfoSerializer + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, market_buying=True, trash=False).exclude( + id__in=kill_house_ids).order_by('id', 'killer') + if role == 'KillHouse': + user = SystemUserProfile.objects.get(trash=False, user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + serializer = self.serializer_class(kill_house, + context={'date1': date1, 'date2': date2, 'kill_houses': kill_houses}) + + else: + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + serializer = self.serializer_class(kill_houses, many=True, + context={'date1': date1, 'date2': date2, 'kill_houses': kill_houses}) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseMarketInfoDashboardViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + today = datetime.now().date() + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1: + total_poultry_requests_quantity = ( + PoultryRequest.objects.filter( + send_date__date__gte=date1, + send_date__date__lte=date2, + state_process='accepted', + province_state='accepted', + final_state__in=('pending', 'accepted'), + temporary_trash=False, + trash=False, + out=False, + market=True, + ).aggregate(total=Sum('quantity'))['total'] or 0 + ) + + else: + total_poultry_requests_quantity = ( + PoultryRequest.objects.filter( + send_date__date=today, + state_process='accepted', + province_state='accepted', + final_state__in=('pending', 'accepted'), + temporary_trash=False, + trash=False, + out=False, + market=True, + ).aggregate(total=Sum('quantity'))['total'] or 0 + ) + + exclusive_kill_house_ids = KillHousePercentage.objects.filter( + kill_house__type='exclusive', + trash=False + ).values_list('kill_house', flat=True) + + kill_houses = KillHouse.objects.filter( + out_province=False, + market_buying=True, + trash=False + ).exclude(id__in=exclusive_kill_house_ids).order_by('id', 'killer') + + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + dashboard_data = { + "kill_house_today_share": 0, + "market_light_share": 0, + "kill_house_market_kill_requests_quantity": 0, + "kill_house_market_kill_requests_quantity_first": 0, + "kill_house_market_kill_requests_quantity_final": 0, + "kill_house_today_left_share": 0, + "kill_house_market_kill_requests_quantity_weight": 0, + "kill_house_market_kill_requests_quantity_first_weight": 0, + "kill_house_market_kill_requests_quantity_final_weight": 0, + "total_kill_house_market_kill_requests_quantity_agreement_light_weight": 0, + "total_kill_house_market_kill_requests_quantity_light_weight": 0, + "total_kill_house_market_kill_requests_quantity_heavy_weight": 0, + } + + for kill_house in kill_houses: + if date1: + info = market_kill_request_share_quantity(kill_house, date1, date2, total_kill_houses=kill_houses) + else: + info = market_kill_request_share_quantity(kill_house, total_kill_houses=kill_houses) + for key in dashboard_data: + dashboard_data[key] += info.get(key, 0) or 0 + + result = {"total_poultry_requests_quantity": total_poultry_requests_quantity, **dashboard_data} + + return Response(result, status=200) + + +def make_fine_for_requests_cron(): + now = datetime.now().date() + fine = FinePermission.objects.filter(trash=False).first() + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, temporary_trash=False, + return_to_province=False, + kill_request__recive_date__date__lt=now, + first_car_allocated_quantity=0, + state__in=('pending', 'accepted')).select_related( + 'province_request__poultry_request__hatching') + if province_kill_requests: + for province_kill_request in province_kill_requests: + hatching = province_kill_request.province_request.poultry_request.hatching + province_kill_request.fine = True + province_kill_request.fine_amount = fine.in_province_allocations_fine_coefficient * province_kill_request.total_wage_amount + province_kill_request.fine_coefficient = fine.in_province_allocations_fine_coefficient + if province_kill_request.market: + province_kill_request.kill_request.market_state = 'deleted' + province_kill_request.kill_request.save() + province_kill_request.delete_message = "حذف تخصیص و اعمال جریمه به دلیل عدم ثبت خودرو در بازه مشخص" + province_kill_request.trash = True + province_kill_request.save() + update_province_kill_requests(hatching) + + kill_house_requests = KillHouseRequest.objects.filter( + Q(assignment_state_archive='pending') | Q(ware_house_confirmation=False), fine=False, trash=False, + kill_request__recive_date__date__lt=now, + temporary_trash=False).select_related('province_kill_request', 'province_request__poultry_request', + 'province_request__poultry_request__hatching') + empty_info_bars = kill_house_requests.filter(assignment_state_archive='pending', ware_house_confirmation=False) + not_completed_bars = kill_house_requests.filter(assignment_state_archive='pending', ware_house_confirmation=True) + not_entered_bars = kill_house_requests.filter(assignment_state_archive='True', ware_house_confirmation=False) + + if empty_info_bars: + for empty_info_bar in empty_info_bars: + poultry_request = empty_info_bar.province_request.poultry_request + hatching = empty_info_bar.province_request.poultry_request.hatching + province_kill_request = empty_info_bar.province_kill_request + empty_info_bar.fine = True + empty_info_bar.fine_amount = ( + fine.in_province_bars_fine_coefficient * empty_info_bar.accepted_real_weight) * province_kill_request.wage + empty_info_bar.fine_coefficient = fine.in_province_bars_fine_coefficient + empty_info_bar.message = 'لغو بار و اعمال جریمه به علت عدم تکمبل اطلاعات و ورود به انبار' + empty_info_bar.bar_remover = { + "date": str(datetime.now()), + "role": "system", + "mobile": "-", + "full_name": "system" + } + empty_info_bar.trash = True + empty_info_bar.save() + update_kill_house_requests(province_kill_request, poultry_request) + update_province_kill_requests(hatching) + + if not_completed_bars: + for not_completed_bar in not_completed_bars: + province_kill_request = not_completed_bar.province_kill_request + + not_completed_bar.fine = True + not_completed_bar.fine_amount = ( + fine.in_province_bars_fine_coefficient * not_completed_bar.accepted_real_weight) * province_kill_request.wage + not_completed_bar.fine_coefficient = fine.in_province_bars_fine_coefficient + not_completed_bar.message = 'اعمال جریمه به علت عدم تکمبل اطلاعات' + not_completed_bar.save() + + if not_entered_bars: + for not_entered_bar in not_entered_bars: + province_kill_request = not_entered_bar.province_kill_request + + not_entered_bar.ware_house_accepted_real_quantity = not_entered_bar.accepted_real_quantity + not_entered_bar.ware_house_accepted_real_weight = int(not_entered_bar.accepted_real_weight - ( + (not_entered_bar.accepted_real_weight * 25) / 100)) + not_entered_bar.weight_loss = 25 + poultry_prediction(not_entered_bar.province_request.poultry_request.poultry) + + not_entered_bar.ware_house_input_type = "loss_weight" + not_entered_bar.ware_house_confirmation = True + not_entered_bar.date_of_ware_house = str(datetime.now()) + not_entered_bar.fine = True + not_entered_bar.fine_amount = ( + fine.in_province_bars_fine_coefficient * not_entered_bar.accepted_real_weight) * province_kill_request.wage + not_entered_bar.fine_coefficient = fine.in_province_bars_fine_coefficient + not_entered_bar.message = 'اعمال جریمه به علت عدم ورود به انبار' + not_entered_bar.save() + product = RolesProducts.objects.filter(parent_product__product_id=2, + kill_house=not_entered_bar.killhouse_user).first() + kill_house_requests_product_warehousing(product) + + +# class KillHouseSalesInformationViewSet(APIView): +# permission_classes = [TokenHasReadWriteScope] +# +# def get(self, request): +# date1 = request.GET.get('date1') +# date2 = request.GET.get('date2') +# key = request.GET.get('key') +# kill_house = KillHouse.objects.get(key=key, trash=False) +# kill_house_request_filter = { +# 'killhouse_user': kill_house, +# 'ware_house_confirmation': True, +# 'trash': False, +# 'calculate_status': True, +# } +# kill_house_free_buying_bar_filter = { +# 'kill_house': kill_house, +# 'trash': False, +# 'calculate_status': True, +# } +# kill_house_allocation_filter = { +# 'trash': False, +# 'calculate_status': True, +# } +# +# kill_house_free_sale_bars_filter = { +# 'trash': False, +# 'calculate_status': True, +# } +# if date1: +# kill_house_request_filter['kill_request__recive_date__date__gte'] = datetime.strptime(date1, +# '%Y-%m-%d').date() - timedelta( +# days=1) +# kill_house_request_filter['kill_request__recive_date__date__lte'] = datetime.strptime(date2, +# '%Y-%m-%d').date() - timedelta( +# days=1) +# kill_house_free_buying_bar_filter['date__date__gte'] = date1 +# kill_house_free_buying_bar_filter['date__date__lte'] = date2 +# kill_house_allocation_filter['date__date__gte'] = date1 +# kill_house_allocation_filter['date__date__lte'] = date2 +# kill_house_free_sale_bars_filter['date__date__gte'] = date1 +# kill_house_free_sale_bars_filter['date__date__lte'] = date2 +# +# kill_house_requests = KillHouseRequest.objects.filter(**kill_house_request_filter) +# kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( +# **kill_house_free_buying_bar_filter).exclude(entered_message='ورود به انبار مجازی') +# kill_house_allocations = StewardAllocation.objects.filter( +# Q(kill_house=kill_house) | Q(to_kill_house=kill_house), **kill_house_allocation_filter) +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(**kill_house_free_sale_bars_filter) +# +# kill_house_requests_aggregates = kill_house_requests.aggregate( +# total_count=Count('id'), +# total_governmental_weight=Sum('ware_house_accepted_real_weight', +# filter=Q(province_request__poultry_request__free_sale_in_province=False)), +# total_free_weight=Sum('ware_house_accepted_real_weight', +# filter=Q(province_request__poultry_request__free_sale_in_province=True)), +# ) +# +# kill_house_free_buying_bars_aggregates = kill_house_free_buying_bars.aggregate( +# total_count=Count('id'), +# total_weight=Sum('weight_of_carcasses'), +# ) +# +# kill_house_allocations_aggregates = kill_house_allocations.aggregate( +# total_count=Count('id'), +# total_receive_governmental_weight=Sum('receiver_real_weight_of_carcasses', +# filter=Q(approved_price_status=True, receiver_state='accepted', +# kill_house__isnull=True, to_cold_house__isnull=True)), +# total_receive_free_weight=Sum('receiver_real_weight_of_carcasses', +# filter=Q(approved_price_status=False, receiver_state='accepted', +# kill_house__isnull=True, to_cold_house__isnull=True)), +# total_allocated_governmental_weight=Sum('receiver_real_weight_of_carcasses', +# filter=Q(approved_price_status=False, receiver_state='accepted', +# kill_house__isnull=False, to_cold_house__isnull=True)), +# total_allocated_free_weight=Sum('receiver_real_weight_of_carcasses', +# filter=Q(approved_price_status=False, receiver_state='accepted', +# kill_house__isnull=False, to_cold_house__isnull=True)), +# +# ) +# kill_house_free_sale_bars_aggregates = kill_house_free_sale_bars.aggregate( +# total_count=Count('id'), +# total_governmental_weight=Sum('real_weight_of_carcasses', +# filter=Q(sale_type='governmental')), +# total_free_weight=Sum('real_weight_of_carcasses', +# filter=Q(sale_type='free')), +# ) +# +# result = { +# "kill_house_request_governmental_weight": kill_house_requests_aggregates['total_governmental_weight'] or 0, +# "kill_house_request_free_weight": kill_house_requests_aggregates['total_free_weight'] or 0, +# "kill_house_free_buying_bars_weight": kill_house_free_buying_bars_aggregates['total_weight'] or 0, +# "total_receive_governmental_weight": kill_house_allocations_aggregates[ +# 'total_receive_governmental_weight'] or 0, +# "total_receive_free_weight": kill_house_allocations_aggregates['total_receive_free_weight'] or 0, +# "total_in_allocated_governmental_weight": kill_house_allocations_aggregates[ +# 'total_allocated_governmental_weight'] or 0, +# "total_in_allocated_free_weight": kill_house_allocations_aggregates['total_allocated_free_weight'] or 0, +# "total_out_allocated_free_weight": kill_house_free_sale_bars_aggregates['total_governmental_weight'] or 0, +# "total_out_free_weight": kill_house_free_sale_bars_aggregates['total_free_weight'] or 0, +# } +# +# return Response(result, status=200) +class KillHouseSalesInformationViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse=kill_house, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True, warehouse=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(input_warehouse=kill_house, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True).exclude( + entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, warehouse=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house=kill_house, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, warehouse=True) + + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, trash=False, warehouse=True) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + total_entered_kill_house_requests_carcasses_governmental_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_free_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + total_entered_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_sale__bar_carcasses_weight = \ + kill_house_free_Sale_bar_informations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_sale__bar_carcasses_governmental_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_free_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_governmental_weight = \ + kill_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_allocations_free_weight = \ + kill_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + + cold_house_allocations_weight = \ + cold_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + cold_house_allocations_governmental_weight = \ + cold_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + cold_house_allocations_free_weight = \ + cold_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + + total_governmental_input_weight = total_entered_kill_house_requests_carcasses_governmental_weight + total_free_input_weight = total_entered_kill_house_requests_carcasses_free_weight + total_entered_kill_house_free_bar_carcasses_weight + total_governmental_output_weight = total_kill_house_free_sale__bar_carcasses_governmental_weight + segmentations_governmental_weight + total_kill_house_allocations_governmental_weight + cold_house_allocations_governmental_weight + int(pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_kill_house_free_sale__bar_carcasses_free_weight + total_kill_house_allocations_free_weight + segmentations_free_weight + cold_house_allocations_free_weight + int(pos_free_allocated_weight / 1000) + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - kill_house.ware_house_archive_governmental_weight + total_free_remain_weight = ( + total_free_input_weight - total_free_output_weight) - kill_house.ware_house_archive_free_weight + + result = { + + "total_governmental_input_weight": int(total_governmental_input_weight), + "total_free_input_weight": int(total_free_input_weight), + "total_governmental_output_weight": int(total_governmental_output_weight), + "total_free_output_weight": int(total_free_output_weight), + "total_governmental_remain_weight": int(total_governmental_remain_weight), + "total_free_remain_weight": int(total_free_remain_weight), + "total_kill_house_free_sale__bar_carcasses_weight": int(total_kill_house_free_sale__bar_carcasses_weight), + "total_kill_house_allocations_weight": int(total_kill_house_allocations_weight), + "segmentations_weight": int(segmentations_weight), + "cold_house_allocations_weight": int(cold_house_allocations_weight), + "total_selling_in_province_governmental_weight": kill_house.total_selling_in_province_governmental_weight, + "total_selling_in_province_free_weight": kill_house.total_selling_in_province_free_weight, + "total_commitment_selling_in_province_governmental_weight": kill_house.total_commitment_selling_in_province_governmental_weight, + "total_commitment_selling_in_province_governmental_remain_weight": kill_house.total_commitment_selling_in_province_governmental_remain_weight, + "total_commitment_selling_in_province_free_weight": kill_house.total_commitment_selling_in_province_free_weight, + "total_commitment_selling_in_province_free_remain_weight": kill_house.total_commitment_selling_in_province_free_remain_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "ware_house_archive_governmental_weight": kill_house.ware_house_archive_governmental_weight, + "ware_house_archive_free_weight": kill_house.ware_house_archive_free_weight, + + } + + return Response(result, status=200) + + +class KillHouseForColdHouseAllocationViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseForColdHouseAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_filters = {'out_province': False, 'trash': False} + if role in ['CityJahad']: + kill_house_filters['kill_house_operator__user__city'] = user.city + kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by('id', 'killer') + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True, context={'date1': date1, 'date2': date2}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_houses, many=True, context={'date1': date1, 'date2': date2}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseForSegmentationViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseForSegmentationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_filters = {'out_province': False, 'trash': False} + if role in ['CityJahad']: + kill_house_filters['kill_house_operator__user__city'] = user.city + + kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by('id', 'killer') + + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True, context={'date1': date1, 'date2': date2}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_houses, many=True, context={'date1': date1, 'date2': date2}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseComparativeInformationViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseComparativeInformationSerializer + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + # kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + # 'kill_house', flat=True) + # kill_houses = KillHouse.objects.filter(out_province=False,killer=False,trash=False).exclude( + # id__in=kill_house_ids).order_by('id') + kill_houses = KillHouse.objects.filter(out_province=False, killer=False, trash=False).order_by('id') + codes = kill_houses.values_list('unique_identifier', flat=True) + code = ",".join(codes) + if date1: + url = f"https://rsibackend.rasadyar.com/app/send_transport_carcass_detail_for_rasadyaar/?code={code}&date1={date1}&date2={date2}" + else: + url = f"https://rsibackend.rasadyar.com/app/send_transport_carcass_detail_for_rasadyaar/?code={code}" + + response = requests.get(url) + rsi_data = response.json() + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + serializer = self.serializer_class(kill_houses, many=True, + context={'date1': date1, 'date2': date2, 'rsi_data': rsi_data}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def cancel_bar_and_province_request(request): + date_str = '2025-10-11' + date = datetime.now().date() - timedelta(days=1) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, ware_house_confirmation=False, + kill_request__recive_date__date__lte=date, + kill_request__recive_date__date__gte=date_str) + all_province_requests = kill_house_requests.values_list('province_kill_request', flat=True).distinct() + for kill_house_request in kill_house_requests: + kill_house_request.trash = True + kill_house_request.return_trash = True + kill_house_request.save() + update_kill_house_requests(kill_house_request.province_kill_request, + kill_house_request.province_request.poultry_request) + update_province_kill_requests( + kill_house_request.province_kill_request.province_request.poultry_request.hatching) + + for all_province_request in all_province_requests: + if not KillHouseRequest.objects.filter(trash=False, province_kill_request=all_province_request).exists(): + all_province_request.return_to_province = True + all_province_request.returner = {"date": str(datetime.today()), + "mobile": "09000000000", "fullname": "برگشت به دلیل حذف سیستمی بار"} + all_province_request.save() + + province_requests = ProvinceKillRequest.objects.filter(trash=False, first_car_allocated_quantity=0, + return_to_province=False, + kill_request__recive_date__date=datetime.now().date(), + ) + for province_request in province_requests: + province_request.trash = True + province_request.return_trash = True + province_request.save() + update_province_kill_requests(province_request.province_request.poultry_request.hatching) + + return HttpResponse('ok') + + +def cancel_bar_and_province_request_cron(): + date_str = '2025-10-11' + date = datetime.now().date() - timedelta(days=1) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, ware_house_confirmation=False, + kill_request__recive_date__date__lte=date, + kill_request__recive_date__date__gte=date_str) + all_province_requests = kill_house_requests.values_list('province_kill_request', flat=True).distinct() + for kill_house_request in kill_house_requests: + kill_house_request.trash = True + kill_house_request.return_trash = True + kill_house_request.save() + update_kill_house_requests(kill_house_request.province_kill_request, + kill_house_request.province_request.poultry_request) + update_province_kill_requests( + kill_house_request.province_kill_request.province_request.poultry_request.hatching) + + for all_province_request in all_province_requests: + if not KillHouseRequest.objects.filter(trash=False, province_kill_request=all_province_request).exists(): + all_province_request.return_to_province = True + all_province_request.returner = {"date": str(datetime.today()), + "mobile": "09000000000", "fullname": "برگشت به دلیل حذف سیستمی بار"} + all_province_request.save() + + province_requests = ProvinceKillRequest.objects.filter(trash=False, first_car_allocated_quantity=0, + return_to_province=False, + kill_request__recive_date__date=datetime.now().date(), + ) + for province_request in province_requests: + province_request.trash = True + province_request.return_trash = True + province_request.save() + update_province_kill_requests(province_request.province_request.poultry_request.hatching) + + +class ReturnProvinceKillRequestViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = ReturnProvinceKillRequestSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ReturnProvinceKillRequestFilterSet + filterset_fields = [ + 'province_request__poultry_request__order_code', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__address__city__name', + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + if role == 'KillHouse': + filters['killhouse_user__kill_house_operator__user'] = user + if date1: + filters['kill_request__recive_date__date__gte'] = date1 + filters['kill_request__recive_date__date__lte'] = date2 + + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), **filters).order_by('id') + + if 'search' in request.GET: + return_province_kill_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=return_province_kill_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=return_province_kill_requests) + return_province_kill_requests_list = ps.filter() + return_province_kill_requests = [] if len( + return_province_kill_requests_list) == 0 else return_province_kill_requests_list + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(return_province_kill_requests) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(return_province_kill_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def put(self, request): + return_province_kill_requests = ProvinceKillRequest.objects.get( + key=request.data['key']) + request.data.pop('key') + serializer = self.serializer_class(return_province_kill_requests) + serializer.update(instance=return_province_kill_requests, validated_data=request.data) + update_province_kill_requests(return_province_kill_requests.province_request.poultry_request.hatching) + poultry_prediction(return_province_kill_requests.province_request.poultry_request.hatching.poultry) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ReturnKillHouseRequestViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + serializer_class = KillHouseRequestForBarManagementSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + def list(self, request, *args, **kwargs): + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True)) + + else: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True) | Q(trash=True, return_trash=True)) + + if 'search' in request.GET: + kill_house_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_house_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_house_requests) + kill_house_request_list = ps.filter() + kill_house_requests = [] if len(kill_house_request_list) == 0 else kill_house_request_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + kill_house_requests = KillHouseRequest.objects.get(key=request.data['key']) + kill_house_requests.province_kill_request.trash = False + kill_house_requests.province_kill_request.return_trash = False + kill_house_requests.province_kill_request.return_to_province = False + kill_house_requests.province_kill_request.returner = None + kill_house_requests.province_kill_request.save() + request.data.pop('key') + serializer = self.serializer_class(kill_house_requests) + serializer.update(instance=kill_house_requests, validated_data=request.data) + update_kill_house_requests(kill_house_requests.province_kill_request, + kill_house_requests.province_request.poultry_request) + update_province_kill_requests(kill_house_requests.province_request.poultry_request.hatching) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ReturnRequestDashboardViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + + province_kill_request_filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + + kill_house_request_filters = {} + if date1: + province_kill_request_filters['kill_request__recive_date__date__gte'] = date1 + province_kill_request_filters['kill_request__recive_date__date__lte'] = date2 + kill_house_request_filters['kill_request__recive_date__date__gte'] = date1 + kill_house_request_filters['kill_request__recive_date__date__lte'] = date2 + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + province_kill_request_filters['killhouse_user'] = kill_house + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + else: + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), + **province_kill_request_filters).order_by('id') + + return_province_kill_requests_aggregates = return_province_kill_requests.aggregate( + total_count=Count('id'), + total_operator_return_count=Count('id', filter=Q(trash=False, return_to_province=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('total_killed_quantity'), + total_operator_return_quantity=Sum('main_quantity', filter=Q(trash=False, return_to_province=True)), + total_system_return_quantity=Sum('total_killed_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('total_killed_weight'), + total_operator_return_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight'), + filter=Q(trash=False, return_to_province=True)), + total_system_return_weight=Sum('total_killed_weight', filter=Q(trash=True, return_trash=True)), + + ) + return_kill_house_requests_aggregates = return_kill_house_requests.aggregate( + total_count=Count('id'), + total_non_receipt_count=Count('id', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('accepted_real_quantity'), + total_non_receipt_quantity=Sum('accepted_real_quantity', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_quantity=Sum('accepted_real_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('accepted_real_weight'), + total_non_receipt_weight=Sum('accepted_real_weight', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_weight=Sum('accepted_real_weight', filter=Q(trash=True, return_trash=True)), + ) + province_kill_request_total_operator_return_quantity = return_province_kill_requests_aggregates[ + 'total_operator_return_quantity'] or 0 + province_kill_request_total_system_return_quantity = return_province_kill_requests_aggregates[ + 'total_system_return_quantity'] or 0 + province_kill_request_total_quantity = province_kill_request_total_operator_return_quantity + province_kill_request_total_system_return_quantity + province_kill_request_total_operator_return_weight = return_province_kill_requests_aggregates[ + 'total_operator_return_weight'] or 0 + province_kill_request_total_system_return_weight = return_province_kill_requests_aggregates[ + 'total_system_return_weight'] or 0 + province_kill_request_total_weight = province_kill_request_total_operator_return_weight + province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight = return_kill_house_requests_aggregates[ + 'total_system_return_weight'] or 0 + total_return_weight_with_wage = province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight + result = { + "province_kill_request_total_count": return_province_kill_requests_aggregates['total_count'] or 0, + "province_kill_request_total_operator_return_count": return_province_kill_requests_aggregates[ + 'total_operator_return_count'] or 0, + "province_kill_request_total_system_return_count": return_province_kill_requests_aggregates[ + 'total_system_return_count'] or 0, + "province_kill_request_total_quantity": province_kill_request_total_quantity, + "province_kill_request_total_operator_return_quantity": province_kill_request_total_operator_return_quantity, + "province_kill_request_total_system_return_quantity": province_kill_request_total_system_return_quantity, + "province_kill_request_total_weight": province_kill_request_total_weight, + "province_kill_request_total_operator_return_weight": province_kill_request_total_operator_return_weight, + "province_kill_request_total_system_return_weight": province_kill_request_total_system_return_weight, + "kill_house_request_total_count": return_kill_house_requests_aggregates['total_count'] or 0, + "kill_house_request_total_non_receipt_count": return_kill_house_requests_aggregates[ + 'total_non_receipt_count'] or 0, + "kill_house_request_total_system_return_count": return_kill_house_requests_aggregates[ + 'total_system_return_count'] or 0, + "kill_house_request_total_quantity": return_kill_house_requests_aggregates['total_quantity'] or 0, + "kill_house_request_total_non_receipt_quantity": return_kill_house_requests_aggregates[ + 'total_non_receipt_quantity'] or 0, + "kill_house_request_total_system_return_quantity": return_kill_house_requests_aggregates[ + 'total_system_return_quantity'] or 0, + "kill_house_request_total_weight": return_kill_house_requests_aggregates['total_weight'] or 0, + "kill_house_request_total_non_receipt_weight": return_kill_house_requests_aggregates[ + 'total_non_receipt_weight'] or 0, + "kill_house_request_total_system_return_weight": kill_house_request_total_system_return_weight, + "total_return_weight_with_wage": total_return_weight_with_wage, + "total_return_wage": total_return_weight_with_wage * province_live_wage_type_amount, + } + + return Response(result, status=status.HTTP_200_OK) + + +# class KillHouseRemainWeightViewSet(GenericAPIView): +# permission_classes = [TokenHasReadWriteScope] +# +# def get(self, request): +# # چک کردن آیا کاربر بازه تاریخی دلخواه فرستاده یا نه +# start_date_param = request.query_params.get('date1', None) +# end_date_param = request.query_params.get('date2', None) +# +# if start_date_param and end_date_param: +# # بازه تاریخی دلخواه از ورودی کاربر +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() +# product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() +# +# # تبدیل string به date +# from datetime import datetime as dt +# start_date = dt.strptime(start_date_param, '%Y-%m-%d').date() +# end_date = dt.strptime(end_date_param, '%Y-%m-%d').date() +# +# # ساخت لیست تمام روزهای بین start_date و end_date +# days = [] +# current_day = start_date +# while current_day <= end_date: +# days.append(current_day) +# current_day += timedelta(days=1) +# +# kill_house_requests = KillHouseRequest.objects.filter( +# input_warehouse=kill_house, +# kill_request__recive_date__date__gte=start_date, +# kill_request__recive_date__date__lte=end_date, +# ware_house_confirmation=True, +# trash=False, +# calculate_status=True, +# warehouse=True +# ) +# +# kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( +# trash=False, +# calculate_status=True, +# warehouse=True, +# date__date__gte=start_date, +# date__date__lte=end_date, +# input_warehouse=kill_house +# ).exclude(entered_message='ورود به انبار مجازی') +# +# kill_house_allocations = StewardAllocation.objects.filter( +# kill_house=kill_house, +# trash=False, +# calculate_status=True, +# warehouse=True, +# receiver_state__in=('pending', 'accepted'), +# production_date__date__gte=start_date, +# production_date__date__lte=end_date +# ) +# +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( +# kill_house=kill_house, +# production_date__date__gte=start_date, +# production_date__date__lte=end_date, +# trash=False, +# calculate_status=True, +# warehouse=True +# ) +# +# segmentations = PosSegmentation.objects.filter( +# kill_house=kill_house, +# production_date__date__gte=start_date, +# production_date__date__lte=end_date, +# trash=False, +# warehouse=True +# ) +# +# transactions = ProductsTransactions.objects.filter( +# product=product, +# transaction__paid=True, +# transaction__date__date__gte=start_date, +# transaction__date__date__lte=end_date, +# trash=False, +# warehouse=True +# ) +# +# governmental_list = [] +# free_list = [] +# final_dict = {} +# +# for day in days: +# kill_house_requests_info = kill_house_requests.aggregate( +# total_kill_house_request_governmental_weight=Sum( +# 'ware_house_accepted_real_weight', +# filter=Q(province_request__poultry_request__free_sale_in_province=False, +# kill_request__recive_date__date=day) +# ), +# total_kill_house_request_free_weight=Sum( +# 'ware_house_accepted_real_weight', +# filter=Q(province_request__poultry_request__free_sale_in_province=True, +# kill_request__recive_date__date=day) +# ), +# ) +# +# kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( +# total_kill_house_free_buying_bars_weight=Sum( +# 'weight_of_carcasses', filter=Q(date__date=day) +# ) +# ) +# +# kill_house_allocations_info = kill_house_allocations.aggregate( +# total_kill_house_allocations_governmental_weight=Sum( +# 'real_weight_of_carcasses', +# filter=Q(quota='governmental', production_date__date=day) +# ), +# total_kill_house_allocations_free_weight=Sum( +# 'real_weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day) +# ), +# ) +# +# kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( +# total_kill_house_free_sale_bars_governmental_weight=Sum( +# 'real_weight_of_carcasses', +# filter=Q(quota='governmental', production_date__date=day) +# ), +# total_kill_house_free_sale_bars_free_weight=Sum( +# 'real_weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day) +# ), +# ) +# +# segmentations_info = segmentations.aggregate( +# segmentations_governmental_weight=Sum( +# 'weight', filter=Q(quota='governmental', production_date__date=day) +# ), +# segmentations_free_weight=Sum( +# 'weight', filter=Q(quota='free', production_date__date=day) +# ), +# ) +# +# pos_allocated_weight_info = transactions.aggregate( +# pos_governmental_allocated_weight=Sum( +# 'cur_weight', filter=Q(price_approved=True, transaction__date__date=day) +# ), +# pos_free_allocated_weight=Sum( +# 'cur_weight', filter=Q(price_approved=False, transaction__date__date=day) +# ), +# ) +# +# total_kill_house_request_governmental_weight = kill_house_requests_info[ +# 'total_kill_house_request_governmental_weight'] or 0 +# total_kill_house_request_free_weight = kill_house_requests_info[ +# 'total_kill_house_request_free_weight'] or 0 +# total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ +# 'total_kill_house_free_buying_bars_weight'] or 0 +# total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_governmental_weight'] or 0 +# total_kill_house_allocations_free_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_free_weight'] or 0 +# total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_governmental_weight'] or 0 +# total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_free_weight'] or 0 +# segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 +# segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 +# pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 +# pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 +# +# total_governmental_input = total_kill_house_request_governmental_weight +# total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight +# +# total_governmental_output = ( +# total_kill_house_allocations_governmental_weight + +# total_kill_house_free_sale_bars_governmental_weight + +# segmentations_governmental_weight + +# int(pos_governmental_allocated_weight / 1000) +# ) +# +# total_free_output = ( +# total_kill_house_allocations_free_weight + +# total_kill_house_free_sale_bars_free_weight + +# segmentations_free_weight + +# int(pos_free_allocated_weight / 1000) +# ) +# +# governmental_data = { +# 'day': day, +# 'amount': total_governmental_input - total_governmental_output, +# } +# free_data = { +# 'day': day, +# 'amount': total_free_input - total_free_output, +# } +# +# governmental_list.append(governmental_data) +# free_list.append(free_data) +# +# final_dict['governmental'] = governmental_list +# final_dict['free'] = free_list +# return Response(final_dict, status=status.HTTP_200_OK) +# +# # حالت پیش‌فرض: 3 روز اخیر (کد قبلی دست نخورده) +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() +# product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() +# today = datetime.now().date() +# yesterday = today - timedelta(days=1) +# two_days_ago = yesterday - timedelta(days=1) +# days = (two_days_ago, yesterday, today) +# +# archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False,date__date__gte=two_days_ago,date__date__lte=today) +# +# +# kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, +# kill_request__recive_date__date__gte=two_days_ago, +# kill_request__recive_date__date__lte=today, +# ware_house_confirmation=True, trash=False, +# calculate_status=True, warehouse=True) +# kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(trash=False, +# calculate_status=True, warehouse=True, +# date__date__gte=two_days_ago, +# date__date__lte=today, +# input_warehouse=kill_house) \ +# .exclude(entered_message='ورود به انبار مجازی') +# kill_house_allocations = StewardAllocation.objects.filter( +# kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, +# receiver_state__in=('pending', 'accepted'), production_date__date__gte=two_days_ago, +# production_date__date__lte=today) +# +# kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, +# production_date__date__gte=two_days_ago, +# production_date__date__lte=today, +# trash=False, +# calculate_status=True, +# warehouse=True) +# segmentations = PosSegmentation.objects.filter(kill_house=kill_house, production_date__date__gte=two_days_ago, +# production_date__date__lte=today, trash=False, +# warehouse=True) +# transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, +# transaction__date__date__gte=two_days_ago, +# transaction__date__date__lte=today, trash=False, +# warehouse=True) +# +# governmental_list = [] +# free_list = [] +# final_dict = {} +# +# for day in days: +# kill_house_requests_info = kill_house_requests.aggregate( +# total_kill_house_request_governmental_weight=Sum('ware_house_accepted_real_weight', filter=Q( +# province_request__poultry_request__free_sale_in_province=False, +# kill_request__recive_date__date=day)), +# total_kill_house_request_free_weight=Sum('ware_house_accepted_real_weight', filter=Q( +# province_request__poultry_request__free_sale_in_province=True, +# kill_request__recive_date__date=day)), +# +# ) +# +# kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( +# total_kill_house_free_buying_bars_weight=Sum('weight_of_carcasses', filter=Q(date__date=day))) +# +# kill_house_allocations_info = kill_house_allocations.aggregate( +# total_kill_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='governmental', +# production_date__date=day)), +# total_kill_house_allocations_free_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day)), +# +# ) +# +# kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( +# total_kill_house_free_sale_bars_governmental_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='governmental', +# production_date__date=day)), +# total_kill_house_free_sale_bars_free_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day)), +# +# ) +# +# segmentations_info = segmentations.aggregate( +# segmentations_governmental_weight=Sum('weight', +# filter=Q(quota='governmental', production_date__date=day)), +# segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), +# +# ) +# pos_allocated_weight_info = transactions.aggregate( +# pos_governmental_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=True, transaction__date__date=day)), +# pos_free_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=False, transaction__date__date=day)), +# +# ) +# +# archives_info = archives.aggregate( +# archives_governmental_weight=Sum('weight', +# filter=Q(quota='governmental', date__date=day)), +# archives_free_weight=Sum('weight', +# filter=Q(quota='free', date__date=day)), +# +# ) +# +# total_kill_house_request_governmental_weight = kill_house_requests_info[ +# 'total_kill_house_request_governmental_weight'] or 0 +# total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 +# total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ +# 'total_kill_house_free_buying_bars_weight'] or 0 +# total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_governmental_weight'] or 0 +# total_kill_house_allocations_free_weight = kill_house_allocations_info[ +# 'total_kill_house_allocations_free_weight'] or 0 +# total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_governmental_weight'] or 0 +# total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ +# 'total_kill_house_free_sale_bars_free_weight'] or 0 +# segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 +# segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 +# pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 +# pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 +# +# archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 +# archives_free_weight = archives_info['archives_free_weight'] or 0 +# +# total_governmental_input = total_kill_house_request_governmental_weight +# total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight +# total_governmental_output = total_kill_house_allocations_governmental_weight + total_kill_house_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( +# pos_governmental_allocated_weight / 1000) +# total_free_output = total_kill_house_allocations_free_weight + total_kill_house_free_sale_bars_free_weight + segmentations_free_weight + int( +# pos_free_allocated_weight / 1000) +# governmental_data = { +# 'day': day, +# 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, +# } +# free_data = { +# 'day': day, +# 'amount': (total_free_input - total_free_output) - archives_free_weight, +# } +# +# governmental_list.append(governmental_data) +# free_list.append(free_data) +# final_dict['governmental'] = governmental_list +# final_dict['free'] = free_list +# return Response(final_dict, status=status.HTTP_200_OK) +# +# # def get(self, request): +# # target_date = request.GET.get('date') +# # user = SystemUserProfile.objects.get(user=request.user, trash=False) +# # +# # kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() +# # +# # product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() +# # +# # today = datetime.now().date() if not target_date else datetime.strptime(target_date, "%Y-%m-%d").date() +# # month_ago = today - timedelta(days=30) +# # yesterday = today - timedelta(days=1) +# # two_days_ago = yesterday - timedelta(days=1) +# # +# # days = [month_ago + timedelta(days=i) for i in range(31)] +# # target_days = [two_days_ago ,yesterday , today] +# # +# # kill_house_requests = KillHouseRequest.objects.filter( +# # input_warehouse=kill_house, +# # kill_request__recive_date__date__gte=month_ago, +# # kill_request__recive_date__date__lte=today, +# # ware_house_confirmation=True, +# # trash=False, +# # calculate_status=True, +# # warehouse=True +# # ) +# # +# # kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( +# # trash=False, +# # calculate_status=True, +# # warehouse=True, +# # date__date__gte=month_ago, +# # date__date__lte=today, +# # input_warehouse=kill_house +# # ).exclude(entered_message='ورود به انبار مجازی') +# # +# # kill_house_allocations = StewardAllocation.objects.filter( +# # kill_house=kill_house, +# # trash=False, +# # calculate_status=True, +# # warehouse=True, +# # receiver_state__in=('pending', 'accepted'), +# # production_date__date__gte=month_ago, +# # production_date__date__lte=today +# # ) +# # +# # kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( +# # kill_house=kill_house, +# # production_date__date__gte=month_ago, +# # production_date__date__lte=today, +# # trash=False, +# # calculate_status=True, +# # warehouse=True +# # ) +# # +# # segmentations = PosSegmentation.objects.filter( +# # kill_house=kill_house, +# # production_date__date__gte=month_ago, +# # production_date__date__lte=today, +# # trash=False, +# # warehouse=True +# # ) +# # +# # transactions = ProductsTransactions.objects.filter( +# # product=product, +# # transaction__paid=True, +# # transaction__date__date__gte=month_ago, +# # transaction__date__date__lte=today, +# # trash=False, +# # warehouse=True +# # ) +# # archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False) +# # +# # +# # governmental_list = [] +# # free_list = [] +# # final_dict = {} +# # +# # for day in days: +# # kill_house_requests_info = kill_house_requests.aggregate( +# # total_kill_house_request_governmental_weight=Sum( +# # 'ware_house_accepted_real_weight', +# # filter=Q(province_request__poultry_request__free_sale_in_province=False, +# # kill_request__recive_date__date=day) +# # ), +# # total_kill_house_request_free_weight=Sum( +# # 'ware_house_accepted_real_weight', +# # filter=Q(province_request__poultry_request__free_sale_in_province=True, +# # kill_request__recive_date__date=day) +# # ), +# # ) +# # +# # kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( +# # total_kill_house_free_buying_bars_weight=Sum( +# # 'weight_of_carcasses', filter=Q(date__date=day) +# # ) +# # ) +# # +# # kill_house_allocations_info = kill_house_allocations.aggregate( +# # total_kill_house_allocations_governmental_weight=Sum( +# # 'real_weight_of_carcasses', +# # filter=Q(quota='governmental', production_date__date=day) +# # ), +# # total_kill_house_allocations_free_weight=Sum( +# # 'real_weight_of_carcasses', +# # filter=Q(quota='free', production_date__date=day) +# # ), +# # ) +# # +# # kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( +# # total_kill_house_free_sale_bars_governmental_weight=Sum( +# # 'real_weight_of_carcasses', +# # filter=Q(quota='governmental', production_date__date=day) +# # ), +# # total_kill_house_free_sale_bars_free_weight=Sum( +# # 'real_weight_of_carcasses', +# # filter=Q(quota='free', production_date__date=day) +# # ), +# # ) +# # +# # segmentations_info = segmentations.aggregate( +# # segmentations_governmental_weight=Sum( +# # 'weight', filter=Q(quota='governmental', production_date__date=day) +# # ), +# # segmentations_free_weight=Sum( +# # 'weight', filter=Q(quota='free', production_date__date=day) +# # ), +# # ) +# # +# # pos_allocated_weight_info = transactions.aggregate( +# # pos_governmental_allocated_weight=Sum( +# # 'cur_weight', filter=Q(price_approved=True, transaction__date__date=day) +# # ), +# # pos_free_allocated_weight=Sum( +# # 'cur_weight', filter=Q(price_approved=False, transaction__date__date=day) +# # ), +# # ) +# # +# # archives_info = archives.aggregate( +# # total_archive_governmental_weight=Sum('weight', filter=Q(date__date=day, quota='governmental')), +# # total_archive_free_weight=Sum('weight', filter=Q(date__date=day, quota='free')), +# # ) +# # +# # total_kill_house_request_governmental_weight = kill_house_requests_info['total_kill_house_request_governmental_weight'] or 0 +# # total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 +# # total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info['total_kill_house_free_buying_bars_weight'] or 0 +# # total_kill_house_allocations_governmental_weight = kill_house_allocations_info['total_kill_house_allocations_governmental_weight'] or 0 +# # total_kill_house_allocations_free_weight = kill_house_allocations_info['total_kill_house_allocations_free_weight'] or 0 +# # total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info['total_kill_house_free_sale_bars_governmental_weight'] or 0 +# # total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info['total_kill_house_free_sale_bars_free_weight'] or 0 +# # segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 +# # segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 +# # pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 +# # pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 +# # total_archive_governmental_weight = archives_info['total_archive_governmental_weight'] or 0 +# # total_archive_free_weight = archives_info['total_archive_free_weight'] or 0 +# # +# # total_governmental_input = total_kill_house_request_governmental_weight +# # total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight +# # +# # total_governmental_output = ( +# # total_kill_house_allocations_governmental_weight + +# # total_kill_house_free_sale_bars_governmental_weight + +# # segmentations_governmental_weight + +# # int(pos_governmental_allocated_weight / 1000) +# # ) +# # +# # total_free_output = ( +# # total_kill_house_allocations_free_weight + +# # total_kill_house_free_sale_bars_free_weight + +# # segmentations_free_weight + +# # int(pos_free_allocated_weight / 1000) +# # ) +# # +# # governmental_amount = ( +# # total_governmental_input - total_governmental_output) - total_archive_governmental_weight +# # free_amount = (total_free_input - total_free_output) - total_archive_free_weight +# # +# # governmental_data = { +# # 'day': day, +# # 'amount': governmental_amount, +# # 'active': True if day in target_days else False, +# # } +# # free_data = { +# # 'day': day, +# # 'amount': free_amount, +# # 'active': True if day in target_days else False, +# # } +# # +# # governmental_list.append(governmental_data) +# # free_list.append(free_data) +# # +# # final_dict['governmental'] = governmental_list +# # final_dict['free'] = free_list +# # +# # return Response(final_dict, status=status.HTTP_200_OK) + +class KillHouseRemainWeightViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + target_date = request.GET.get('date') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + today = datetime.now().date() if not target_date else datetime.strptime(target_date, "%Y-%m-%d").date() + month_ago = today - timedelta(days=30) + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + + days = [month_ago + timedelta(days=i) for i in range(31)] + target_days = {two_days_ago, yesterday, today} + req_vals = list( + KillHouseRequest.objects.filter( + input_warehouse=kill_house, + kill_request__recive_date__date__gte=month_ago, + kill_request__recive_date__date__lte=today, + ware_house_confirmation=True, + trash=False, + calculate_status=True, + warehouse=True + ).values( + "kill_request__recive_date__date", + "ware_house_accepted_real_weight", + "province_request__poultry_request__free_sale_in_province" + ) + ) + + free_buy_vals = list( + KillHouseFreeBarInformation.objects.filter( + trash=False, + calculate_status=True, + warehouse=True, + date__date__gte=month_ago, + date__date__lte=today, + input_warehouse=kill_house + ).exclude(entered_message='ورود به انبار مجازی') + .values("date__date", "weight_of_carcasses") + ) + + alloc_vals = list( + StewardAllocation.objects.filter( + kill_house=kill_house, + trash=False, + calculate_status=True, + warehouse=True, + receiver_state__in=('pending', 'accepted'), + production_date__date__gte=month_ago, + production_date__date__lte=today + ).values( + "production_date__date", + "quota", + "real_weight_of_carcasses" + ) + ) + + free_sale_vals = list( + KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + production_date__date__gte=month_ago, + production_date__date__lte=today, + trash=False, + calculate_status=True, + warehouse=True + ).values("production_date__date", "quota", "real_weight_of_carcasses") + ) + + seg_vals = list( + PosSegmentation.objects.filter( + kill_house=kill_house, + production_date__date__gte=month_ago, + production_date__date__lte=today, + trash=False, + warehouse=True + ).values("production_date__date", "quota", "weight") + ) + + pos_vals = list( + ProductsTransactions.objects.filter( + product=product, + transaction__paid=True, + transaction__date__date__gte=month_ago, + transaction__date__date__lte=today, + trash=False, + warehouse=True + ).values( + "transaction__date__date", + "price_approved", + "cur_weight" + ) + ) + + arch_vals = list( + WarehouseArchive.objects.filter( + kill_house=kill_house, + warehouse=True, + trash=False + ).values("date__date", "quota", "weight") + ) + + req_daily = {} + for r in req_vals: + d = r["kill_request__recive_date__date"] + w = r["ware_house_accepted_real_weight"] or 0 + if d not in req_daily: + req_daily[d] = {"governmental": 0, "free": 0} + if r["province_request__poultry_request__free_sale_in_province"]: + req_daily[d]["free"] += w + else: + req_daily[d]["governmental"] += w + + free_buy_daily = {} + for r in free_buy_vals: + d = r["date__date"] + w = r["weight_of_carcasses"] or 0 + free_buy_daily[d] = free_buy_daily.get(d, 0) + w + + alloc_daily = {} + for r in alloc_vals: + d = r["production_date__date"] + w = r["real_weight_of_carcasses"] or 0 + q = r["quota"] + if d not in alloc_daily: + alloc_daily[d] = {"governmental": 0, "free": 0} + alloc_daily[d][q] += w + + free_sale_daily = {} + for r in free_sale_vals: + d = r["production_date__date"] + w = r["real_weight_of_carcasses"] or 0 + q = r["quota"] + if d not in free_sale_daily: + free_sale_daily[d] = {"governmental": 0, "free": 0} + free_sale_daily[d][q] += w + + seg_daily = {} + for r in seg_vals: + d = r["production_date__date"] + w = r["weight"] or 0 + q = r["quota"] + if d not in seg_daily: + seg_daily[d] = {"governmental": 0, "free": 0} + seg_daily[d][q] += w + + pos_daily = {} + for r in pos_vals: + d = r["transaction__date__date"] + w = r["cur_weight"] or 0 + if d not in pos_daily: + pos_daily[d] = {"governmental": 0, "free": 0} + if r["price_approved"]: + pos_daily[d]["governmental"] += w + else: + pos_daily[d]["free"] += w + + arch_daily = {} + for r in arch_vals: + d = r["date__date"] + w = r["weight"] or 0 + q = r["quota"] + if d not in arch_daily: + arch_daily[d] = {"governmental": 0, "free": 0} + arch_daily[d][q] += w + + governmental_list = [] + free_list = [] + + for day in days: + gov_in = req_daily.get(day, {}).get("governmental", 0) + free_in = req_daily.get(day, {}).get("free", 0) + free_buy_daily.get(day, 0) + + gov_out = ( + alloc_daily.get(day, {}).get("governmental", 0) + + free_sale_daily.get(day, {}).get("governmental", 0) + + seg_daily.get(day, {}).get("governmental", 0) + + (pos_daily.get(day, {}).get("governmental", 0) // 1000) + ) + + free_out = ( + alloc_daily.get(day, {}).get("free", 0) + + free_sale_daily.get(day, {}).get("free", 0) + + seg_daily.get(day, {}).get("free", 0) + + (pos_daily.get(day, {}).get("free", 0) // 1000) + ) + + gov_remain = gov_in - gov_out - arch_daily.get(day, {}).get("governmental", 0) + free_remain = free_in - free_out - arch_daily.get(day, {}).get("free", 0) + + governmental_list.append({ + "day": day, + "amount": gov_remain if gov_remain > 0 else 0, + "active": day in target_days, + }) + + free_list.append({ + "day": day, + "amount": free_remain if free_remain > 0 else 0, + "active": day in target_days, + }) + + return Response({ + "governmental": governmental_list, + "free": free_list + }, status=status.HTTP_200_OK) + + +# class TotalKillHouseRemainWeightViewSet(GenericAPIView): +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = TotalKillHouseRemainWeightViewSetSerializer +# pagination_class = CustomPagination +# filter_backends = [DjangoFilterBackend] +# filterset_class = KillHouseFilterSet +# filterset_fields = [ +# 'name', +# 'kill_house_operator__user__mobile', +# 'kill_house_operator__user__fullname', +# 'kill_house_operator__user__first_name', +# 'kill_house_operator__user__last_name' +# +# ] +# +# def get(self, request): +# +# kill_house_filters = {'out_province': False, 'trash': False, 'total_remain_warehouse_weight__gt': 0} +# kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by('id', 'killer') +# +# if 'search' in request.GET: +# kill_house_list = [] +# if request.GET['search'] == 'filter': +# if request.GET['value'] != "" and request.GET['value'] != 'undefined': +# for item in self.filterset_fields: +# query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) +# if (self.filterset_class( +# data=query, +# queryset=kill_houses +# ) +# ).filter(): +# ps = self.filterset_class(data=query, queryset=kill_houses) +# kill_house_list = ps.filter() +# kill_houses = [] if len( +# kill_house_list) == 0 else kill_house_list +# +# page_size = request.query_params.get('page_size', None) +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(kill_houses) +# if page is not None: +# serializer = self.get_serializer(page, many=True) +# return self.get_paginated_response(serializer.data) +# +# serializer = self.serializer_class(kill_houses, many=True) +# return Response(serializer.data, status=status.HTTP_200_OK) +class TotalKillHouseRemainWeightViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalKillHouseRemainWeightViewSetSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + quota = request.GET.get("quota") + kill_house_filters = {'out_province': False, 'trash': False, 'total_remain_warehouse_weight__gt': 0} + kill_houses = KillHouse.objects.filter(**kill_house_filters).order_by('id', 'killer') + + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + all_data = TotalKillHouseRemainWeightViewSetSerializer(kill_houses, many=True).data + if quota in ("governmental", "free"): + filtered = [] + today = datetime.today().date() + two_days_ago = today - timedelta(days=2) + + for item in all_data: + info = item.get("info") + if not info: + continue + + for row in info.get(quota, []): + day = row["day"] + amount = row["amount"] + if amount > 0 and day < two_days_ago: + filtered.append(item) + break + + all_data = filtered + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(all_data) + if page is not None: + # serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(page) + + # serializer = self.serializer_class(kill_houses, many=True) + return Response(all_data, status=status.HTTP_200_OK) + + +class TotalKillHouseWarehouseArchiveDashboardViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalKillHouseWarehouseArchiveDashboardSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__mobile', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name' + + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + archives_filters = {"trash": False, "kill_house__isnull": False} + if date1: + archives_filters['create_date__date__gte'] = date1 + archives_filters['create_date__date__lte'] = date2 + + archives = WarehouseArchive.objects.filter(**archives_filters) + kill_houses = KillHouse.objects.filter(id__in=archives.values_list('kill_house__id', flat=True), trash=False) + if 'search' in request.GET: + kill_house_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len( + kill_house_list) == 0 else kill_house_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.get_serializer(page, many=True, context={'date1': date1, 'date2': date2}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_houses, many=True, context={'date1': date1, 'date2': date2}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def fix_wage(request): + kill_house_requests = KillHouseRequest.objects.filter(trash=True, return_trash=True) + kill_house_requests_values = kill_house_requests.values_list('province_kill_request__id', flat=True).distinct() + province_requests = ProvinceKillRequest.objects.filter(trash=True, id__in=kill_house_requests_values, + return_trash=True) + return HttpResponse(province_requests.count()) + + +class KillHouseLock(APIView): + + def get(self, request): + + wage_lock = False + ware_house_lock = False + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_purchase = KillHousePurchaseRequest.objects.filter(kill_house=kill_house).first() + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + slaughter_transactions = InternalTransaction.objects.filter(Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False) + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_unpaid_wage -= total_paid_wage + + if kill_house_purchase.limitation_number <= total_unpaid_wage: + wage_lock = True + + if kill_house.ware_house_remaining_weight_limitation_status: + if kill_house.total_remain_warehouse_governmental_weight > kill_house.ware_house_remaining_weight_limitation: + ware_house_lock = True + + if kill_house.ware_house_remaining_percent_limitation_status: + if not check_kill_house_remain_limitation_weight(kill_house): + ware_house_lock = True + + result = { + 'wage': total_unpaid_wage, + 'wage_lock': wage_lock, + 'ware_house_lock': ware_house_lock + } + + return Response (result,status=status.HTTP_200_OK) diff --git a/panel/ProvinceOperator/__init__.py b/panel/ProvinceOperator/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/ProvinceOperator/excel_processing.py b/panel/ProvinceOperator/excel_processing.py new file mode 100644 index 0000000..20da25d --- /dev/null +++ b/panel/ProvinceOperator/excel_processing.py @@ -0,0 +1,25023 @@ +from io import BytesIO +import openpyxl +import datetime +import jdatetime +from itertools import chain +from django.db.models import Case, When +from django.db.models import Value + +import requests +from oauth2_provider.models import AccessToken +from rest_framework.throttling import AnonRateThrottle, UserRateThrottle +from rest_framework.views import APIView +from rest_framework.response import Response + +from deposit_id import wage_counting_type +from general_urls import base_url_for_sms_report +from panel.CityOperator.serializers import CityOperatorForSubSectorTransactionsSerializer, \ + CityOperatorForSubSectorSerializer, CityOperatorForSubSectorSerializerForExcel +from panel.KillHouse.helpers import get_difference_carcasses_weight, get_kill_house_finance_info, \ + get_difference_carcasses_percent +from panel.ProvinceOperator.serializers import \ + GuildsPosMachineForTransactionsSerializer, PosMachineTransactionsForInspectionSerializer, \ + TotalWageInformationSerializer, CityGuildForSubSectorSerializerForExcel, InProvinceAllocationSerializer, \ + StewardFreeSaleBarInformationSerializer, RealGuildsForDashboardSerializer, \ + GuildsPosMachineForTransactionsNewSerializer +from panel.VetFarm.serializers import VetForSubSectorSerializer, VetForSubSectorSerializerForExcel +from panel.helper import build_query +from panel.helper_excel import Alignment_CELL, create_header, create_header_freez, excel_description, \ + create_value, merge_cells, cell_color_changer, get_kill_house_finance_info_by_date, \ + get_kill_house_distribution_info, get_kill_house_distribution_out_province_info, \ + all_get_kill_house_distribution_info, GREEN_CELL, VERY_LIGHT_GREEN_CELL, LIGHT_GREEN_CELL, \ + RED_CELL, convert_str_to_date +from django.http import HttpResponse, QueryDict +from openpyxl import Workbook +from openpyxl.styles import PatternFill, Alignment, Font +from openpyxl.utils import get_column_letter +from django.db.models import Q, Sum, F, Count, Avg + +from panel.KillHouse.serializers import \ + KillHouseForNewWageInormationSerializer, KillHouseFreeSaleBarInformationSerializer, \ + KillHouseForPerformanceDashboardSerializer, KillHouseForProvinceWareHouseDashboardSerializer, \ + KillRequestForDirectBuyingSerializer, ReturnProvinceKillRequestSerializer +from panel.ReportingPanel.helper import poultry_request_new_fields +from panel.convert_date import convert_to_shamsi +from panel.filterset import KillHouseFilterSet, KillHouseRequestFilterSet, InternalTransactionFilterSet, \ + PoultryRequestFilterSet, OutProvincePoultryRequestBuyerFilterSet, ChainCompanyFilterSet, ChainAllocationFilterSet, \ + StewardAllocationDashboardFilterSet, KillHouseFreeSaleBarInformationFilterSet, \ + StewardFreeSaleBarInformationFilterSet, KillRequestFilterSet, ReturnProvinceKillRequestFilterSet, \ + GuildsForPostationFilterSet +from panel.helper_excel import shamsi_date +from panel.models import ProvinceKillRequest, \ + ChainAllocation, KillHouseFreeBarInformation, InternalTransaction, ChainCompany, \ + KillHousePercentage, KillHouseRequest, PoultryRequest, KillHouseVet, VetCheckRequest, \ + KillHouseAssignmentInformation, VetFarm, Poultry, CityOperator, OutProvincePoultryRequestBuyer, Vet, \ + PoultryHatching, KillHouseFreeSaleBarInformation, WageType, PercentageOfWageType, KillHouseWareHouse, \ + StewardAllocation, RolesProducts, Guilds, SubSectorPercentageOfWageType, SubSectorTransactions, \ + StewardFreeBarInformation, StewardFreeSaleBarInformation, PosMachineTransactions, CityGuild, TotalWageInformation, \ + BarDifferenceRequest, BarDocumentStatus, KillRequest, POSTransactions, POSMachine, PosSegmentation, \ + ProductsTransactions, WarehouseArchive +from authentication.models import ( + SystemUserProfile, City, +) +from panel.models import ( + KillHouse, +) + + +def kill_house_total_transactions_wage_payid_super_admin_excel(request): + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + + excel_options = [ + 'ردیف', + 'تاریخ پرداخت', + 'نوع پرداخت', + 'نام پرداخت کننده', + 'تلفن پرداخت کننده', + 'شماره درخواست', + 'شماره پیگیری', + 'کد سفارش', + 'شماره کارت', + 'مبلغ تراکنش(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + 'سهم اصناف(ریال)', + 'سهم دامپزشک(ریال)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['B2'] = f'اطلاعات کلی تعرفه {from_date_1} تا {from_date_2}' + merge_range1 = 'B2:C2' + worksheet.merge_cells(merge_range1) + + worksheet['B2'].font = Font(color="C00000", bold=True) + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['B5'] = f'جزئیات {from_date_1} تا {from_date_2}' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + # worksheet['B2'] = 'اطلاعات کلی تعرفه(از 1403/01/01 به بعد)' + + worksheet['B2'].font = Font(color="C00000") + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['B5'] = f'جزئیات' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['C9'] = 'اتحادیه' + worksheet['C9'].font = Font(color="C00000") + worksheet['C9'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['C9'].fill = PatternFill(start_color="EEEAF2", fill_type="solid") + worksheet['C9'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + worksheet['C10'] = 'شرکت' + worksheet['C10'].font = Font(color="C00000") + worksheet['C10'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['C10'].fill = PatternFill(start_color="EEEAF2", fill_type="solid") + worksheet['C10'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + worksheet['C11'] = 'صنف' + worksheet['C11'].font = Font(color="C00000") + worksheet['C11'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['C11'].fill = PatternFill(start_color="EEEAF2", fill_type="solid") + worksheet['C11'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + worksheet['C12'] = 'دامپزشک' + worksheet['C12'].font = Font(color="C00000") + worksheet['C12'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['C12'].fill = PatternFill(start_color="EEEAF2", fill_type="solid") + worksheet['C12'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + header_list1 = [ + 'کل تعرفه (ریال)', + 'کل تعرفه پرداخت شده (ریال)', + 'تخفیف (ریال)', + 'کل تعرفه پرداخت نشده (ریال)', + + ] + + header_list2 = [ + 'کل وزن زنده کشتار داخل استان(کیلوگرم)', + 'وزن لاشه کشتار داخل استان(کیلوگرم)', + 'وزن توزیع لاشه کشتار داخل استان(کیلوگرم)', + 'تعرفه توزیع لاشه کشتار داخل استان(ریال)', + 'وزن توزیع لاشه به خارج استان(کیلوگرم)', + 'تعرفه توزیع لاشه به خارج استان(ریال)', + 'وزن لاشه ورودی به استان(کیلوگرم)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'وزن مرغ زنده ورودی به استان(کیلوگرم)', + 'تعرفه مرغ زنده ورودی به استان(ریال)', + + ] + header_list = [ + 'ردیف', + 'ماهیت', + 'خریدار', + 'کل تعرفه(ریال)', + 'کل تعرفه پرداخت شده(ریال)', + 'تخفیف(ریال)', + 'کل تعرفه پرداخت نشده(ریال)', + 'کل وزن زنده کشتار داخل استان(کیلوگرم)', + 'کل وزن لاشه کشتار داخل استان(کیلوگرم)', + 'کل توزیع لاشه داخل استان(کیلوگرم)', + 'تعرفه لاشه داخل استان(ریال)', + 'وزن توزیع لاشه به خارج استان(کیلوگرم)', + 'تعرفه توزیع لاشه به خارج استان(ریال)', + 'وزن لاشه ورودی به استان(کیلوگرم)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'وزن مرغ زنده ورودی به استان(کیلوگرم)', + 'تعرفه مرغ زنده ورودی به استان(ریال)', + + ] + for col_num, option in enumerate(header_list, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=14, column=col_num, value=option) + if option in ['کل تعرفه پرداخت نشده(ریال)']: + cell.fill = PatternFill(start_color="76933C", fill_type="solid") + else: + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[13].height = 45 + worksheet.column_dimensions[col_letter].width = 27 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + header_list5 = [ + 'سهم', + 'تعرفه توزیع لاشه داخل استان(ریال)', + 'تعرفه توزیع لاشه خارج استان(ریال)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'تعرفه مرغ زنده ورودی به استان(ریال)', + 'تعرفه کل(ریال)', + 'تعرفه پرداخت شده(ریال)', + 'تعرفه پرداخت نشده(ریال)', + + ] + create_header(worksheet, header_list5, 3, 8, height=35, width=18, border_style='thin') + + create_header(worksheet, header_list1, 4, 3, height=35, width=18, border_style='thin') + create_header(worksheet, header_list2, 3, 5, height=35, width=18, border_style='thin') + + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + type = 'total_wage_amount' + share_type = 'amount' + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + if 'date1' in request.GET: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + 'id') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + trash=False, state='accepted') + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses, status='completed', + trash=False) + + off = kill_houses.aggregate(total=Sum('off'))[ + 'total'] or 0 + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_amount + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = total_out_live_buying_province_carcasses_price * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_wage = total_pure_province_carcasses_price * company_province_kill_request_percent + company_free_buying_live_wage = total_out_live_buying_province_carcasses_price * company_free_buying_live_percent + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + # company_total_pure_paid_wage = company_total_paid_wage - (company_total_paid_wage * 0.08)) + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_wage = total_pure_province_carcasses_price * guilds_province_kill_request_percent + guilds_free_buying_live_wage = total_out_live_buying_province_carcasses_price * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_wage = total_pure_province_carcasses_price * other_province_kill_request_percent + other_free_buying_live_wage = total_out_live_buying_province_carcasses_price * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + + else: + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, calculate_status=True, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__in=kill_houses, status='completed', + trash=False) + + off = kill_houses.aggregate(total=Sum('off'))[ + 'total'] or 0 + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_amount + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = total_out_live_buying_province_carcasses_price * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_wage = total_pure_province_carcasses_price * company_province_kill_request_percent + company_free_buying_live_wage = total_out_live_buying_province_carcasses_price * company_free_buying_live_percent + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + # company_total_pure_paid_wage = company_total_paid_wage - (company_total_paid_wage * 0.08)) + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_wage = total_pure_province_carcasses_price * guilds_province_kill_request_percent + guilds_free_buying_live_wage = total_out_live_buying_province_carcasses_price * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_wage = total_pure_province_carcasses_price * other_province_kill_request_percent + other_free_buying_live_wage = total_out_live_buying_province_carcasses_price * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + + values_list = [ + total_price, + total_paid_wage, + off, + total_price - (total_paid_wage + off) + + ] + create_value(worksheet, values_list, 4, 4, border_style='thin') + + values_list2 = [ + total_province_live_weight, + total_province_carcasses_weight, + total_pure_province_carcasses_weight, + total_pure_province_carcasses_price, + total_out_selling_province_carcasses_weight, + total_out_selling_province_carcasses_price, + total_out_carcasses_buying_province_carcasses_weight, + total_out_carcasses_buying_province_carcasses_price, + total_out_live_buying_province_carcasses_weight, + total_out_live_buying_province_carcasses_price, + + ] + create_value(worksheet, values_list2, 6, 3, border_style='thin') + + values_union = [ + union_province_kill_request_wage, + union_free_sell_carcasses_wage, + union_free_buying_carcasses_wage, + union_free_buying_live_wage, + union_total_wage, + union_total_paid_wage, + union_total_unpaid_wage, + + ] + create_value(worksheet, values_union, 9, 4, border_style='thin') + + values_company = [ + company_province_kill_request_wage, + company_free_sell_carcasses_wage, + company_free_buying_carcasses_wage, + company_free_buying_live_wage, + company_total_wage, + company_total_paid_wage, + company_total_unpaid_wage, + + ] + create_value(worksheet, values_company, 10, 4, border_style='thin') + + values_guild = [ + guilds_province_kill_request_wage, + guilds_free_sell_carcasses_wage, + guilds_free_buying_carcasses_wage, + guilds_free_buying_live_wage, + guilds_total_wage, + guilds_total_paid_wage, + guilds_total_unpaid_wage, + + ] + create_value(worksheet, values_guild, 11, 4, border_style='thin') + + values_others = [ + other_province_kill_request_wage, + other_free_sell_carcasses_wage, + other_free_buying_carcasses_wage, + other_free_buying_live_wage, + other_total_wage, + other_total_paid_wage, + other_total_unpaid_wage, + + ] + create_value(worksheet, values_others, 12, 4, border_style='thin') + + l = 15 + m = 1 + + kill_houses = KillHouse.objects.filter(trash=False).exclude(out_province=True).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + all_finance_info_total_price = 0 + all_total_paid_wage = 0 + all_off = 0 + all_unpaid = 0 + finance_info_total_province_live_weight = 0 + finance_info_total_province_carcasses_weight = 0 + finance_info_total_pure_province_carcasses_price = 0 + finance_info_total_out_selling_province_carcasses_weight = 0 + finance_info_total_out_selling_province_carcasses_price = 0 + finance_info_total_out_carcasses_buying_province_carcasses_weight = 0 + finance_info_total_out_carcasses_buying_province_carcasses_price = 0 + finance_info_total_out_live_buying_province_carcasses_weight = 0 + finance_info_total_out_live_buying_province_carcasses_price = 0 + finance_info_total_pure_province_carcasses_weight = 0 + + for obj in kill_houses: + killer = 'کشتارگاه' if obj.killer == False else 'کشتارکن' + if obj.killer == True and obj.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=obj, trash=False) + killer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif obj.killer == True and obj.type == 'public': + killer_type = 'کشتارکن عمومی' + else: + killer_type = 'کشتارگاه' + total_paid_wage = 0 + if 'date1' in request.GET: + + finance_info = get_kill_house_finance_info_by_date(obj, date1, date2) + else: + finance_info = get_kill_house_finance_info(obj) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + if 'date1' in request.GET: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).exclude(union_share=0, company_share=0, + guilds_share=0).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=obj) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) | Q(killer=obj)), + archive_wage=False, + trash=False, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).select_related('province_kill_request').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity', 'accepted_real_quantity') + + kill_house_requests = kill_house_requests.filter(Q(killer=obj) | Q(killhouse_user=obj)).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, kill_house=obj, + archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', + 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + + slaughter_transactions = InternalTransaction.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house=obj, status='completed', + trash=False).only('union_share', + 'company_share', + 'guilds_share', 'amount') + + else: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ).exclude(union_share=0, company_share=0, + guilds_share=0).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=obj) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) | Q(killer=obj)), + archive_wage=False, + trash=False + ).select_related('province_kill_request').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity', 'accepted_real_quantity') + kill_house_requests = kill_house_requests.filter(Q(killer=obj) | Q(killhouse_user=obj)).select_related( + 'province_kill_request').only( + 'accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', + 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + + all_finance_info_total_price += finance_info['total_price'] + all_total_paid_wage += total_paid_wage + all_off += obj.off + all_unpaid += finance_info['total_price'] - (total_paid_wage + obj.off) + finance_info_total_province_live_weight += finance_info['total_province_live_weight'] + finance_info_total_province_carcasses_weight += finance_info['total_province_carcasses_weight'] + finance_info_total_pure_province_carcasses_weight += finance_info['total_pure_province_carcasses_weight'] + finance_info_total_pure_province_carcasses_price += finance_info['total_pure_province_carcasses_price'] + finance_info_total_out_selling_province_carcasses_weight += finance_info[ + 'total_out_selling_province_carcasses_weight'] + finance_info_total_out_selling_province_carcasses_price += finance_info[ + 'total_out_selling_province_carcasses_price'] + finance_info_total_out_carcasses_buying_province_carcasses_weight += finance_info[ + 'total_out_carcasses_buying_province_carcasses_weight'] + finance_info_total_out_carcasses_buying_province_carcasses_price += finance_info[ + 'total_out_carcasses_buying_province_carcasses_price'] + finance_info_total_out_live_buying_province_carcasses_weight += finance_info[ + 'total_out_live_buying_province_carcasses_weight'] + finance_info_total_out_live_buying_province_carcasses_price += finance_info[ + 'total_out_live_buying_province_carcasses_price'] + values_list3 = [ + m, + killer_type, + killer + '(' + obj.name + ')', + finance_info['total_price'], + total_paid_wage, + obj.off, + finance_info['total_price'] - (total_paid_wage + obj.off), + finance_info['total_province_live_weight'], + finance_info['total_province_carcasses_weight'], + finance_info['total_pure_province_carcasses_weight'], + finance_info['total_pure_province_carcasses_price'], + finance_info['total_out_selling_province_carcasses_weight'], + finance_info['total_out_selling_province_carcasses_price'], + finance_info['total_out_carcasses_buying_province_carcasses_weight'], + finance_info['total_out_carcasses_buying_province_carcasses_price'], + finance_info['total_out_live_buying_province_carcasses_weight'], + finance_info['total_out_live_buying_province_carcasses_price'], + + ] + create_value(worksheet, values_list3, l, 1, border_style='thin') + + l += 1 + m += 1 + if slaughter_transactions: + if obj not in kill_house_list: + kill_house_list.append(obj) + list2 = [ + 'مجموع==>', + '', + '', + all_finance_info_total_price, + all_total_paid_wage, + all_off, + all_unpaid, + finance_info_total_province_live_weight, + finance_info_total_province_carcasses_weight, + finance_info_total_pure_province_carcasses_weight, + finance_info_total_pure_province_carcasses_price, + finance_info_total_out_selling_province_carcasses_weight, + finance_info_total_out_selling_province_carcasses_price, + finance_info_total_out_carcasses_buying_province_carcasses_weight, + finance_info_total_out_carcasses_buying_province_carcasses_price, + finance_info_total_out_live_buying_province_carcasses_weight, + finance_info_total_out_live_buying_province_carcasses_price, + + ] + create_value(worksheet, list2, l, 1, border_style='thin', color='yellow') + + for kill_house in kill_house_list: + sheet_name = kill_house.name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[2].height = 27 + worksheet.freeze_panes = worksheet['A3'] + max_col = worksheet.max_column + range_str = f'A2:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 1 + m = 1 + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + kill_house = KillHouse.objects.get(id=kill_house.id, trash=False) + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + else: + kill_house = KillHouse.objects.get(key=kill_house.key, trash=False) + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + + for transaction in transactions: + if transaction.kill_house != None: + fullname = transaction.kill_house.kill_house_operator.user.fullname + mobile = transaction.kill_house.kill_house_operator.user.mobile + else: + fullname = transaction.chain_company.user.fullname + mobile = transaction.chain_company.user.mobile + date = convert_to_shamsi( + datetime=transaction.date + ) + type = 'دستی' if transaction.transaction_type == 'wage-gateway-manual' else 'آنلاین' + if request.GET['role'] == 'ProvinceOperator': + amout = transaction.union_share + elif request.GET['role'] == 'Company': + amout = transaction.company_share + elif request.GET['role'] == 'Guilds': + amout = transaction.guilds_share + else: + amout = transaction.amount + list1 = [ + m, + date, + type, + fullname, + mobile, + transaction.orderId, + transaction.saleReferenceId, + transaction.orderId, + transaction.cardHolderPan, + amout, + transaction.union_share, + transaction.company_share, + transaction.guilds_share, + transaction.other_share, + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش تعرفه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_transactions_wage_payid_excel(request): + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + + excel_options = [ + 'ردیف', + 'ماهیت تراکنش', + 'نوع تراکنش', + 'تاریخ پرداخت', + 'شماره پیگیری', + 'شماره درخواست', + 'پرداخت کننده', + 'تلفن پرداخت کننده', + 'شماره کارت', + 'مبلغ کل', + 'سهم اتحادیه(ریال)', + 'سهم صنف(ریال)', + 'سهم شرکت(ریال)', + 'سهم دامپزشک(ریال)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + + worksheet['B2'] = f'اطلاعات کلی تعرفه {from_date_1} تا {from_date_2}' + merge_range1 = 'B2:C2' + worksheet.merge_cells(merge_range1) + + worksheet['B2'].font = Font(color="C00000", bold=True) + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['B5'] = f'جزئیات ' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + # worksheet['B2'] = 'اطلاعات کلی تعرفه(از 1403/01/01 به بعد)' + + worksheet['B2'].font = Font(color="C00000") + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['B5'] = f'جزئیات' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'B8:C8' + + worksheet.merge_cells(merge_range1) + worksheet['B8'] = 'پرداختی های کشتارگاه ها' + + worksheet['B8'].font = Font(color="C00000", bold=True) + worksheet['B8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + header_list1 = [ + 'کل وزن', + 'کل تعرفه (ریال)', + 'کل تعرفه پرداخت شده (ریال)', + 'کل تعرفه پرداخت نشده (ریال)', + + ] + + header_list2 = [ + 'وزن کشتار روزانه (کیلوگرم)', + 'تعرفه کشتار روزانه (ریال)', + 'وزن منجمد (کیلوگرم)', + 'تعرفه منجمد (ریال)', + 'وزن زنجیره ها (کیلوگرم)', + 'تعرفه زنجیره ها (ریال)', + 'وزن مرغ زنده آزاد', + 'تعرفه مرغ زنده آزاد', + 'وزن لاشه آزاد', + 'تعرفه لاشه آزاد', + ] + header_list = [ + 'ردیف', + 'خریدار', + 'نام و نام خانوادگی مالک', + 'تلفن مالک', + 'شهر', + 'تعداد تراکنش ', + 'سهم شما از واریزی(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[8].height = 45 + worksheet.column_dimensions[col_letter].width = 27 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list1, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list2, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[5].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + + union_total_paid_wage = 0 + + company_total_paid_wage = 0 + + guilds_total_paid_wage = 0 + + freezing_province_kill_requests_total_wage = 0 + freezing_province_kill_requests_total_weight = 0 + + free_bars_live_total_wage = 0 + free_bars_live_total_weight = 0 + free_bars_carcases_total_wage = 0 + free_bars_carcases_total_weight = 0 + role = request.GET['role'] + user = SystemUserProfile.objects.get(key=request.GET['key']) + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=False + ) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + trash=False) + free_bars_live = free_bars.filter(buy_type='live', trash=False) + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_wage_amount'))[ + 'total'] or 0 + freezing_province_kill_request_total_wage = \ + freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + total_wage += province_kill_requests_total_wage + freezing_province_kill_request_total_wage + province_kill_requests_total_weight = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_province_kill_request_total_weight = \ + freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_weight += province_kill_requests_total_weight + freezing_province_kill_request_total_weight + kill_house_reqest_total_wage = \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + freezing_kill_house_reqest_total_wage = \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + total_wage += kill_house_reqest_total_wage + freezing_kill_house_reqest_total_wage + + kill_house_reqest_total_weight = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + freezing_kill_house_reqest_total_weight = \ + freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + total_weight += kill_house_reqest_total_weight + freezing_kill_house_reqest_total_weight + + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_live_total_wage + free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_weight += free_bars_live_total_weight + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_carcases_total_wage + free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_weight += free_bars_carcases_total_weight + + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + + elif role == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, state='accepted', + trash=False) + chain_allocations_total_wage = chain_allocations.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += chain_allocations_total_wage + chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_weight += chain_allocations_total_weight + + chain_company_transactions = InternalTransaction.objects.filter(chain_company=chain_company, + status='completed', trash=False) + total_paid_wage += chain_company_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + + + else: + + if role == 'ProvinceOperator': + type = 'union_share' + share_type = 'union_share' + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), trash=False, + first_car_allocated_quantity=0, + return_to_province=False, archive_wage=False, union_share__gt=0) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, + province_kill_request__union_share__gt=0) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + chain_allocations = ChainAllocation.objects.filter(union_share__gt=0, state='accepted', trash=False) + free_bars = KillHouseFreeBarInformation.objects.filter(union_share__gt=0, archive_wage=False, + trash=False) + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum(type))[ + 'total'] or 0 + province_kill_requests_total_wage += \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + freezing_province_kill_requests_total_wage = freezing_province_kill_requests.aggregate(total=Sum(type))[ + 'total'] or 0 + freezing_province_kill_requests_total_wage += \ + freezing_kill_house_requests.aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + + + elif role == 'Guilds': + type = 'guilds_share' + share_type = 'guilds_share' + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), trash=False, + first_car_allocated_quantity=0, + + return_to_province=False, archive_wage=False, guilds_share__gt=0) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, + province_kill_request__guilds_share__gt=0) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + chain_allocations = ChainAllocation.objects.filter(guilds_share__gt=0, state='accepted', trash=False) + free_bars = KillHouseFreeBarInformation.objects.filter(guilds_share__gt=0, archive_wage=False, + trash=False) + + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum(type))[ + 'total'] or 0 + province_kill_requests_total_wage += \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + + freezing_province_kill_requests_total_wage = freezing_province_kill_requests.aggregate(total=Sum(type))[ + 'total'] or 0 + freezing_province_kill_requests_total_wage += \ + freezing_kill_house_requests.aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + + + elif role == 'Company': + type = 'company_share' + share_type = 'company_share' + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), trash=False, + first_car_allocated_quantity=0, + return_to_province=False, archive_wage=False, company_share__gt=0) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, + province_kill_request__company_share__gt=0) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + chain_allocations = ChainAllocation.objects.filter(company_share__gt=0, state='accepted', trash=False) + free_bars = KillHouseFreeBarInformation.objects.filter(company_share__gt=0, archive_wage=False, + trash=False) + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum(type))[ + 'total'] or 0 + province_kill_requests_total_wage += \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + + freezing_province_kill_requests_total_wage = freezing_province_kill_requests.aggregate(total=Sum(type))[ + 'total'] or 0 + freezing_province_kill_requests_total_wage += \ + freezing_kill_house_requests.aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + + else: + type = 'total_wage_amount' + share_type = 'amount' + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), trash=False, archive_wage=False, + first_car_allocated_quantity=0, + return_to_province=False).exclude(union_share=0, company_share=0, guilds_share=0) + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False).exclude( + province_kill_request__union_share=0, province_kill_request__company_share=0, + province_kill_request__guilds_share=0) + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + chain_allocations = ChainAllocation.objects.filter(trash=False, state='accepted') + free_bars = KillHouseFreeBarInformation.objects.filter(archive_wage=False, trash=False) + total_slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', + status='completed', + trash=False) + total_chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', + status='completed', trash=False) + + union_province_kill_request_total_weight = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + union_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + union_province_kill_request_total_wage = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + union_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + union_chain_allocation_total_weight = \ + chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + union_chain_allocation_total_wage = \ + chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + union_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + union_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + total_slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + total_chain_company_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_weight = union_province_kill_request_total_weight + freezing_union_province_kill_request_total_weight + union_chain_allocation_total_weight + union_kill_house_free_live_bar_total_weight + union_kill_house_free_carcases_bar_total_weight + union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_chain_allocation_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_total_weight = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + company_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + company_province_kill_request_total_wage = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + company_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + company_chain_allocation_total_weight = \ + chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + company_chain_allocation_total_wage = \ + chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + + company_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + company_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + total_slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + total_chain_company_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_weight = company_province_kill_request_total_weight + freezing_company_province_kill_request_total_weight + company_chain_allocation_total_weight + company_kill_house_free_live_bar_total_weight + company_kill_house_free_carcases_bar_total_weight + company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_chain_allocation_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_total_weight = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_guilds_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + guilds_chain_allocation_total_weight = \ + chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + guilds_chain_allocation_total_wage = \ + chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + guilds_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + total_slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + total_chain_company_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_weight = guilds_province_kill_request_total_weight + freezing_guilds_province_kill_request_total_weight + guilds_chain_allocation_total_weight + guilds_kill_house_free_live_bar_total_weight + guilds_kill_house_free_carcases_bar_total_weight + guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_chain_allocation_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum(type))[ + 'total'] or 0 + province_kill_requests_total_wage += \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + + freezing_province_kill_requests_total_wage = freezing_province_kill_requests.aggregate(total=Sum(type))[ + 'total'] or 0 + freezing_province_kill_requests_total_wage += \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + + free_bars_live = free_bars.filter(buy_type='live', trash=False) + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) + + total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + + province_kill_requests_total_weight = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_kill_requests_total_weight += kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_province_kill_requests_total_weight = \ + freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_province_kill_requests_total_weight += \ + freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + + chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += chain_allocations_total_wage + chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_weight += chain_allocations_total_weight + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += free_bars_live_total_wage + free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_weight += free_bars_live_total_weight + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += free_bars_carcases_total_wage + free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_weight += free_bars_carcases_total_weight + slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ + 'total'] or 0 + chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', + status='completed', trash=False) + total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ + 'total'] or 0 + + values_list = [ + total_weight, + total_wage, + total_paid_wage, + total_wage - total_paid_wage, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + values_list2 = [ + province_kill_requests_total_weight, + province_kill_requests_total_wage, + freezing_province_kill_requests_total_weight, + freezing_province_kill_requests_total_wage, + chain_allocations_total_weight, + chain_allocations_total_wage, + free_bars_live_total_weight, + free_bars_live_total_wage, + free_bars_carcases_total_weight, + free_bars_carcases_total_wage, + + ] + for item in range(len(values_list2)): + cell = worksheet.cell(row=6, column=item + 3, value=values_list2[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l = 9 + m = 1 + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + union_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + company_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='kill_house', + guilds_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + payer_type='kill_house', + status='completed', + trash=False).values( + 'kill_house'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOperator': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + union_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + + elif request.GET['role'] == 'Company': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + company_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + elif request.GET['role'] == 'Guilds': + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + guilds_share__gt=0, + trash=False).values( + 'kill_house'), trash=False) + else: + kill_houses = KillHouse.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='kill_house', + trash=False).values( + 'kill_house'), trash=False) + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_houses) + kill_houses = ps.filter() + else: + kill_houses = kill_houses + for obj in kill_houses: + if 'date1' in request.GET: + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('id') + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=obj) | Q(parent_kill_house=obj), + status='completed', + trash=False).order_by('id') + total_paid_wage = 0 + + role = request.GET['role'] + if role in ['KillHouse', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'amount' + transactions = transactions + elif role == 'ProvinceOperator': + wage_type = 'union_share' + transactions = transactions.filter( + + union_share__gt=0, + ).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + transactions = transactions.filter( + + company_share__gt=0, + ).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + transactions = transactions.filter( + guilds_share__gt=0, + ).order_by('id') + else: + transactions = transactions + wage_type = 'wallet_share' + if transactions: + if obj not in kill_house_list: + kill_house_list.append(obj) + total_paid_wage += transactions.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + killer = 'کشتارگاه' if obj.killer == False else 'کشتارکن' + values_list3 = [ + m, + killer + '(' + obj.name + ')', + obj.kill_house_operator.user.fullname, + obj.kill_house_operator.user.mobile, + obj.kill_house_operator.user.city.name, + len(transactions), + total_paid_wage, + + ] + for item in range(len(values_list3)): + cell = worksheet.cell(row=l, column=item + 4, value=values_list3[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list3[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + m += 1 + for kill_house in kill_house_list: + sheet_name = kill_house.name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.01) + + l = 5 + m = 1 + header_list = [ + 'تعداد کل تراکنش ها', + 'مبلغ کل تراکنش(ریال)', + 'سهم کل اتحادیه(ریال)', + 'سهم کل صنف(ریال)', + 'سهم کل شرکت(ریال)', + 'سهم کل دامپزشک(ریال)', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + user = SystemUserProfile.objects.get(key=request.GET['key']) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + + else: + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + status='completed', + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + status='completed', + trash=False).order_by('id') + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + status='completed', + trash=False).order_by('id') + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('id') + + else: + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).order_by('id') + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + status='completed', + trash=False).order_by('id') + + else: + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + union_share__gt=0, + status='completed', + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + company_share__gt=0, + status='completed', + trash=False).order_by('id') + + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + guilds_share__gt=0, + status='completed', + trash=False).order_by('id') + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).exclude(guilds_share=0, company_share=0, union_share=0).order_by('id') + + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).order_by('id') + + for transaction in transactions: + if transaction.kill_house: + killer_type = 'کشتارگاه' if transaction.kill_house.killer == False else 'کشتارکن' + elif transaction.chain_company: + killer_type = 'شرکت زنجیره' + else: + killer_type = 'خارج استان' + l += 1 + payer_date = jdatetime.date.fromgregorian( + day=transaction.date.day, + month=transaction.date.month, + year=transaction.date.year + ) + + if transaction.kill_house != None: + fullname = transaction.kill_house.kill_house_operator.user.fullname + mobile = transaction.kill_house.kill_house_operator.user.mobile + elif transaction.chain_company is not None: + fullname = transaction.chain_company.user.fullname + mobile = transaction.chain_company.user.mobile + else: + fullname = transaction.user.fullname + mobile = transaction.user.mobile + type = 'دستی' if transaction.transaction_type == 'wage-gateway-manual' else 'آنلاین' + + list1 = [ + m, + killer_type, + type, + str(payer_date), + transaction.refId, + transaction.orderId, + fullname, + mobile, + transaction.cardHolderPan, + transaction.amount, + transaction.union_share, + transaction.guilds_share, + transaction.company_share, + transaction.other_share + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + total_amount = \ + transactions.aggregate(total=Sum('amount'))['total'] or 0 + total_union_share = \ + transactions.aggregate(total=Sum('union_share'))['total'] or 0 + total_guilds_share = \ + transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + total_company_share = \ + transactions.aggregate(total=Sum('company_share'))['total'] or 0 + total_other_share = \ + transactions.aggregate(total=Sum('other_share'))['total'] or 0 + + value_header_list = [ + m - 1, + total_amount, + total_union_share, + total_guilds_share, + total_company_share, + total_other_share, + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount, + total_union_share, + total_guilds_share, + total_company_share, + total_other_share, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت شده کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_wage_excel_new(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + sheet_names2 = [ + 'اطلاعات کلی', + 'تخصیصات بدون بار', + 'بارهای روزانه', + 'مرغ زنده خارج استان', + 'خرید لاشه خارج استان', + # 'فروش لاشه خارج استان', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + total_wage_information = TotalWageInformation.objects.filter(trash=False).first() + if not total_wage_information: + total_wage_information = TotalWageInformation.objects.create() + serialized_wage_data = TotalWageInformationSerializer( + total_wage_information, + context={'request': request} + ).data.get('wage_info', {}) + serializer_finance_info = serialized_wage_data.get('finance_info') + effective_wage_counting_type = serialized_wage_data.get('wage_counting_type', wage_counting_type) + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'اطلاعات کلی': + finance_info = serializer_finance_info or {} + if not finance_info and date1 and date2: + finance_info = get_kill_house_finance_info_by_date(kill_house, date1, date2) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + excel_description(worksheet, 'A3', f'اطلاعات کلی تعرفه از تاریخ{from_date_1} تا {from_date_2}', + color='red', row2='C3') + excel_description(worksheet, 'A4', f'{kill_house.name}', color='red', row2='B4') + + if effective_wage_counting_type == 'carcass': + header_list1 = [ + 'کل وزن لاشه داخل استان', + 'وزن مر غ زنده خارج از استان', + 'وزن لاشه خرید خارج از استان', + 'کل تعرفه', + + ] + create_header(worksheet, header_list1, 4, 4, height=50, width=19, border_style='thin', color='C4D79B') + value_list1 = [ + finance_info.get('total_province_carcasses_weight', 0), + finance_info.get('total_out_live_buying_province_carcasses_weight', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_weight', 0), + finance_info.get('total_price', 0), + ] + create_value(worksheet, value_list1, 5, 4, border_style='thin') + + header_list2 = [ + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج استان استان', + 'تعرفه خرید لاشه خارج استان', + 'تعرفه خرید مرغ زنده خارج استان', + 'کل وزن زنده کشتار داخل استان(کیلوگرم)', + 'وزن لاشه کشتار داخل استان(کیلوگرم)', + 'وزن توزیع لاشه داخل استان(کیلوگرم)', + 'تعرفه توزیع لاشه داخل استان(ریال)', + 'وزن توزیع لاشه به خارج استان(کیلوگرم)', + 'تعرفه توزیع لاشه به خارج استان(ریال)', + 'وزن لاشه ورودی به استان(کیلوگرم)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'وزن مرغ زنده ورودی به استان(کیلوگرم)', + 'تعرفه مرغ زنده ورودی به استان(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 1, 9, height=50, width=19, border_style='thin', color='E26B0A') + value_list2 = [ + finance_info.get('province_live_wage_amount', 0), + finance_info.get('free_sell_carcesses_weight_amount', 0), + finance_info.get('free_buying_carcesses_weight_amount', 0), + finance_info.get('free_buying_live_weight_amount', 0), + + finance_info.get('total_province_live_weight', 0), + finance_info.get('total_province_carcasses_weight', 0), + + finance_info.get('total_pure_province_carcasses_weight', 0), + finance_info.get('total_pure_province_carcasses_price', 0), + finance_info.get('total_out_selling_province_carcasses_weight', 0), + finance_info.get('total_out_selling_province_carcasses_price', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_weight', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_price', 0), + finance_info.get('total_out_live_buying_province_carcasses_weight', 0), + finance_info.get('total_out_live_buying_province_carcasses_price', 0), + + ] + create_value(worksheet, value_list2, 10, 1, border_style='thin') + else: + header_list1 = [ + 'کل وزن لاشه داخل استان', + 'وزن مر غ زنده خارج از استان', + 'وزن لاشه خرید خارج از استان', + 'کل تعرفه', + + ] + create_header(worksheet, header_list1, 4, 4, height=50, width=19, border_style='thin', color='C4D79B') + value_list1 = [ + finance_info.get('total_province_carcasses_weight', 0), + finance_info.get('total_out_live_buying_province_carcasses_weight', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_weight', 0), + finance_info.get('total_price', 0), + ] + create_value(worksheet, value_list1, 5, 4, border_style='thin') + + header_list2 = [ + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج استان استان', + 'تعرفه خرید لاشه خارج استان', + 'تعرفه خرید مرغ زنده خارج استان', + 'کل وزن زنده کشتار داخل استان(کیلوگرم)', + # 'وزن لاشه کشتار داخل استان(کیلوگرم)', + # 'وزن توزیع لاشه داخل استان(کیلوگرم)', + 'تعرفه کشتار داخل استان(ریال)', + 'وزن توزیع لاشه به خارج استان(کیلوگرم)', + 'تعرفه توزیع لاشه به خارج استان(ریال)', + 'وزن لاشه ورودی به استان(کیلوگرم)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'وزن مرغ زنده ورودی به استان(کیلوگرم)', + 'تعرفه مرغ زنده ورودی به استان(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 1, 9, height=50, width=19, border_style='thin', color='E26B0A') + value_list2 = [ + finance_info.get('province_live_wage_amount', 0), + finance_info.get('free_sell_carcesses_weight_amount', 0), + finance_info.get('free_buying_carcesses_weight_amount', 0), + finance_info.get('free_buying_live_weight_amount', 0), + + finance_info.get('total_province_live_weight', 0), + # finance_info['total_province_carcasses_weight'], + + finance_info.get('total_pure_province_carcasses_price', 0), + # finance_info['total_pure_province_carcasses_price'], + finance_info.get('total_out_selling_province_carcasses_weight', 0), + finance_info.get('total_out_selling_province_carcasses_price', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_weight', 0), + finance_info.get('total_out_carcasses_buying_province_carcasses_price', 0), + finance_info.get('total_out_live_buying_province_carcasses_weight', 0), + finance_info.get('total_out_live_buying_province_carcasses_price', 0), + + ] + create_value(worksheet, value_list2, 10, 1, border_style='thin') + # excel_description(worksheet, 'D13', 'اطلاعات بار', size='16', row2='F13') + # header_list3 = [ + # 'تعداد بارهای ایجاد شده', + # 'مجموع تعداد قطعه بارها', + # 'مجموع وزن زنده بارها', + # 'مجموع تعداد نهایی در کشتارگاه', + # 'مجموع وزن نهایی در کشتار گاه', + # 'ملاک قطعه کشتار شده', + # 'ملاک وزن زنده کشتار شده', + # 'تعرفه پایه', + # 'وزن لاشه', + # 'مجموع تعرفه های بار', + # + # ] + # create_header(worksheet, header_list3, 1, 14, height=50, width=19, border_style='thin', color='0070C0') + # kill_house_requests_quantity = \ + # kill_house_requests.aggregate(total=Sum('quantity'))['total'] or 0 + # kill_house_requests_accepted_real_weight = \ + # kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + # kill_house_requests_accepted_real_quantity = \ + # kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + # kill_house_requests_wight = \ + # kill_house_requests.aggregate(total=Sum( + # F('quantity') * F('province_kill_request__province_request__poultry_request__Index_weight')))[ + # 'total'] or 0 + # + # kill_house_requests_accepted_real_wight = \ + # kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + # assignment = KillHouseAssignmentInformation.objects.filter( + # kill_house_request__in=kill_house_requests, trash=False) + # + # assignment_net_weight = \ + # assignment.aggregate(total=Sum('net_weight'))['total'] or 0 + # assignment_real_quantity = \ + # assignment.aggregate(total=Sum('real_quantity'))['total'] or 0 + # value_list3 = [ + # len(kill_house_requests), + # kill_house_requests_quantity, + # kill_house_requests_wight, + # assignment_real_quantity, + # assignment_net_weight, + # kill_house_requests_accepted_real_quantity, + # kill_house_requests_accepted_real_weight, + # province_live_wage_type.amount, + # kill_house_requests_accepted_real_wight * 0.75, + # province_live_wage_type.amount * (kill_house_requests_accepted_real_wight * 0.75), + # + # ] + # create_value(worksheet, value_list3, 15, 1, border_style='thin') + # + # excel_description(worksheet, 'B17', 'تخصیصات بدون بار', size='16', row2='F17') + # header_list4 = [ + # 'تعداد سفارشات', + # 'تعداد کل', + # 'وزن کل', + # 'تعرفه', + # 'وزن لاشه ملاک تعرفه', + # 'کل تعرفه', + # + # ] + # create_header(worksheet, header_list4, 2, 18, height=50, width=19, border_style='thin', color='00B050') + # + # province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), + # return_to_province=False, + # archive_wage=False, + # first_car_allocated_quantity=0, + # kill_request__recive_date__date__gte=date1, + # kill_request__recive_date__date__lte=date2, + # trash=False).order_by( + # 'kill_request__recive_date') + # + # total_weight = \ + # province_kill_request.aggregate(total=Sum('total_killed_weight'))[ + # 'total'] or 0 + # total_killed_quantity = \ + # province_kill_request.aggregate(total=Sum('total_killed_quantity'))[ + # 'total'] or 0 + # + # value_list4 = [ + # len(province_kill_request), + # total_killed_quantity, + # total_weight, + # province_live_wage_type.amount, + # total_weight * 0.75, + # province_live_wage_type.amount * (total_weight * 0.75), + # + # ] + # create_value(worksheet, value_list4, 19, 2, border_style='thin') + # + # excel_description(worksheet, 'C22', 'فروش لاشه خارج استان', size='16', row2='F22') + # header_list5 = [ + # 'تعداد کل لاشه', + # 'حجم کل لاشه', + # 'وزن کل لاشه', + # 'تعرفه', + # 'مبلغ کل تعرفه', + # + # ] + # create_header(worksheet, header_list5, 3, 23, height=50, width=19, border_style='thin', color='B1A0C7') + # free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, date__date__gte=date1, + # date__date__lte=date2, + # kill_house=kill_house).order_by('-date') + # + # total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + # 'total'] or 0 + # total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + # 'total'] or 0 + # + # value_list5 = [ + # len(free_sales), + # total_quantity, + # total_weight, + # free_sell_carcesses_weight_wage_type.amount, + # total_weight * free_sell_carcesses_weight_wage_type.amount, + # ] + # create_value(worksheet, value_list5, 24, 3, border_style='thin') + # + # excel_description(worksheet, 'C26', 'خرید مرغ زنده خارج استان', size='16', row2='F26') + # header_list6 = [ + # 'تعداد خریداران', + # 'تعداد کل', + # 'وزن کل', + # 'تعرفه', + # 'مبلغ کل', + # + # ] + # create_header(worksheet, header_list6, 3, 27, height=50, width=19, border_style='thin') + # kill_house_free_bar_info_live = kill_house_free_bar_info.filter(buy_type='live') + # + # total_quantity = \ + # kill_house_free_bar_info_live.aggregate(total=Sum('quantity'))[ + # 'total'] or 0 + # total_weight = \ + # kill_house_free_bar_info_live.aggregate(total=Sum('live_weight'))[ + # 'total'] or 0 + # + # value_list6 = [ + # len(kill_house_free_bar_info_live), + # total_quantity, + # total_weight, + # free_buying_live_weight_wage_type.amount, + # total_weight * free_buying_live_weight_wage_type.amount, + # ] + # create_value(worksheet, value_list6, 28, 3, border_style='thin') + # + # excel_description(worksheet, 'C30', 'خرید لاشه خارج استان', size='16', row2='F30') + # header_list7 = [ + # 'تعداد خرید', + # 'وزن کل', + # 'تعرفه', + # 'مبلغ کل', + # + # ] + # create_header(worksheet, header_list7, 3, 31, height=50, width=19, border_style='thin', color='C4D79B') + # kill_house_free_bar_info_carcass = kill_house_free_bar_info.filter(buy_type='carcass') + # total_weight = \ + # kill_house_free_bar_info_carcass.aggregate(total=Sum('weight_of_carcasses'))[ + # 'total'] or 0 + # + # value_list7 = [ + # len(kill_house_free_bar_info_carcass), + # total_weight, + # free_buying_carcesses_weight_wage_type.amount, + # total_weight * free_buying_carcesses_weight_wage_type.amount, + # + # ] + # create_value(worksheet, value_list7, 32, 3, border_style='thin') + elif sheet_name == 'تخصیصات بدون بار': + worksheet['H3'] = 'در این قسمت تخصیصات فاقد بار نمایش داده میشود' + merge_range1 = 'H3:K3' + worksheet.merge_cells(merge_range1) + worksheet['H3'].font = Font(color="C00000", bold=True) + worksheet['H3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + if 'date1' in request.GET: + + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by( + 'kill_request__recive_date') + else: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + state__in=('pending', 'accepted'), + wage_pay=False, + archive_wage=False, + return_to_province=False, + first_car_allocated_quantity=0, + trash=False).order_by( + 'kill_request__recive_date') + if effective_wage_counting_type == 'carcass': + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن لاشه ملاک تعرفه', + 'جمع کل تعرفه', + ] + else: + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن ملاک تعرفه', + 'جمع کل تعرفه', + ] + for col_num, option in enumerate(header_list, 3): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + if effective_wage_counting_type == 'carcass': + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن لاشه ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + else: + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + for province_kill in province_kill_request: + + kill_date_1 = shamsi_date(province_kill.province_request.poultry_request.send_date) + + if province_kill.kill_request.slaughter_house is not None: + kill_place = province_kill.kill_request.slaughter_house.name + else: + kill_place = province_kill.kill_request.kill_house.name + + total_amount = province_kill.total_wage_amount + if effective_wage_counting_type == 'carcass': + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight * 0.75, + province_live_wage_amount, + (province_kill.total_killed_weight * 0.75) * province_live_wage_amount, + + ] + else: + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight, + province_live_wage_amount, + (province_kill.total_killed_weight) * province_live_wage_amount, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_weight = \ + province_kill_request.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_killed_quantity = \ + province_kill_request.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_wage_amount = \ + province_kill_request.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + if effective_wage_counting_type == 'carcass': + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight * 0.75, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 3, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + if effective_wage_counting_type == 'carcass': + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight * 0.75, + province_live_wage_amount, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight, + province_live_wage_amount, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بارهای روزانه': + + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_reqs = KillHouseRequest.objects.filter(Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False, + + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__wage', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', 'killer').values('message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + 'province_kill_request__wage', + ) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + if effective_wage_counting_type == 'carcass': + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وزن ملاک تعرفه', + 'تعرفه(ریال)', + 'تعرفه کل بار', + + ] + else: + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وزن ملاک تعرفه', + 'تعرفه(ریال)', + 'تعرفه کل بار', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + if effective_wage_counting_type == 'carcass': + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + ' قطعه کشتار شده', + ' وزن کشتار شده', + 'وزن لاشه ملاک تعرفه', + 'مجموع تعرفه های بار', + + ] + else: + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + ' قطعه کشتار شده', + ' وزن کشتار شده', + 'وزن ملاک تعرفه', + 'مجموع تعرفه های بار', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + total_amount = 0 + weight_amount = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + if effective_wage_counting_type == 'carcass': + accepted_real_weight_kill = kill['accepted_real_weight'] * 0.75 + total_amount += (kill['accepted_real_weight'] * 0.75) * province_live_wage_amount + weight_amount += kill['accepted_real_weight'] * 0.75 + else: + total_amount += (kill['accepted_real_weight']) * province_live_wage_amount + weight_amount += kill['accepted_real_weight'] + accepted_real_weight_kill = kill['accepted_real_weight'] + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + accepted_real_weight_kill, + province_live_wage_amount, + (accepted_real_weight_kill) * province_live_wage_amount, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + all_weighte, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + weight_amount, + total_amount + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + weight_amount, + province_live_wage_amount, + total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'مرغ زنده خارج استان': + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'live' + date_type = 'buy' + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = 'create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'register_date__date__gte': date1, + 'register_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + excel_options = [ + 'ردیف', + 'کدسفارش', + 'تاریخ خرید', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'نوع خرید', + 'استان/شهر', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'وضعیت دامپزشک', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'حجم تایید شده', + 'وزن تایید شده', + 'تایید/رد کننده', + 'تاریخ تایید/ رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type1 = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type1} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name \ + if kill_house_free_bar_info.first() else '' + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + if kill.exclusive_killer: + killer_type = f'کشتارکن اختصاصی {kill.kill_house.name}' + kill_house_name = kill.exclusive_killer.name + kill_house_mobile = kill.exclusive_killer.kill_house_operator.user.mobile + + elif kill.kill_house.killer == True and kill.kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + + else: + killer_type = 'کشتارگاه' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + bar_code = str(kill.bar_code) if kill.bar_code else '-' + list1 = [ + m, + bar_code, + str(date_of_buy), + killer_type, + kill_house_name, + kill_house_mobile, + kill.poultry_name, + kill.poultry_mobile, + buy_type, + f'{kill.province} / {kill.city}', + kill.vet_farm_name, + kill.vet_farm_mobile, + state, + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + kill.kill_house_vet_quantity, + kill.kill_house_vet_weight, + kill.acceptor_rejector, + str(date_of_reject_accepted) + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + m - 1, + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + int(bar_number_of_carcasses), + int(bar_weight_of_carcasses), + int(bar_kill_house_vet_quantity), + bar_kill_house_vet_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'خرید لاشه خارج استان': + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'carcass' + date_type = 'buy' + bar_state = request.GET.get('bar_state') + kill_house_free_bar_info_list = [] + role = request.GET.get('role') + kill_houses = None + order_by_type = 'create_date' + + if role in ['KillHouse', 'KillHouseVet']: + if role == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters = { + 'create_date__date__gte': date1, + 'create_date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False + } + + if kill_houses is not None: + filters['kill_house__in'] = kill_houses + + if type: + filters['buy_type'] = type + if type == 'live': + if bar_state: + if bar_state == 'entered': + filters['weight_of_carcasses__gt'] = 0 + else: + filters['weight_of_carcasses'] = 0 + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(**filters).order_by(order_by_type) + + excel_options = [ + 'ردیف', + 'کدسفارش', + 'تاریخ خرید', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'نوع خرید', + 'استان/شهر', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'وضعیت دامپزشک', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'حجم تایید شده', + 'وزن تایید شده', + 'تایید/رد کننده', + 'تاریخ تایید/ رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type1 = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type1} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name \ + if kill_house_free_bar_info.first() else '' + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + if kill.exclusive_killer: + killer_type = f'کشتارکن اختصاصی {kill.kill_house.name}' + kill_house_name = kill.exclusive_killer.name + kill_house_mobile = kill.exclusive_killer.kill_house_operator.user.mobile + + elif kill.kill_house.killer == True and kill.kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + + else: + killer_type = 'کشتارگاه' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + bar_code = str(kill.bar_code) if kill.bar_code else '-' + list1 = [ + m, + bar_code, + str(date_of_buy), + killer_type, + kill_house_name, + kill_house_mobile, + kill.poultry_name, + kill.poultry_mobile, + buy_type, + f'{kill.province} / {kill.city}', + kill.vet_farm_name, + kill.vet_farm_mobile, + state, + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + kill.kill_house_vet_quantity, + kill.kill_house_vet_weight, + kill.acceptor_rejector, + str(date_of_reject_accepted) + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + m - 1, + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + int(bar_number_of_carcasses), + int(bar_weight_of_carcasses), + int(bar_kill_house_vet_quantity), + bar_kill_house_vet_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای کشتارگاه {kill_house.name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def payment_transactions_province_excel(request): + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + + ] + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', payer_type='kill_house', + trash=False).order_by('-date') + else: + transactions = InternalTransaction.objects.filter( + status='completed', payer_type='kill_house', + trash=False).order_by('-date') + + if request.GET['role'] == 'ProvinceOperator': + transactions = transactions.filter(union_share__gt=0) + elif request.GET['role'] == 'Company': + transactions = transactions.filter(company_share__gt=0) + elif request.GET['role'] == 'Guilds': + transactions = transactions.filter(guilds_share__gt=0) + elif request.GET['role'] == 'SuperAdmin': + transactions = transactions.filter().exclude(guilds_share=0, company_share=0, union_share=0) + else: + transactions = transactions + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = filterset_class(data=query, queryset=transactions) + transactions = ps.filter() + + excel_options = [ + 'ردیف', + 'ماهیت تراکنش', + 'نوع تراکنش', + 'تاریخ پرداخت', + 'شماره پیگیری', + 'شماره درخواست', + 'پرداخت کننده', + 'تلفن پرداخت کننده', + 'شماره کارت', + 'مبلغ کل', + 'سهم اتحادیه(ریال)', + 'سهم صنف(ریال)', + 'سهم شرکت(ریال)', + 'سهم دامپزشک(ریال)', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد کل تراکنش ها', + 'مبلغ کل تراکنش(ریال)', + 'سهم کل اتحادیه(ریال)', + 'سهم کل صنف(ریال)', + 'سهم کل شرکت(ریال)', + 'سهم کل دامپزشک(ریال)', + + ] + if base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + + excel_description(worksheet, 'B2', + f'گزارش ریز تراکنش ها استان {province} از تاریخ {from_date_1} تا {from_date_2}', color='red', + row2='C3') + + + + else: + excel_description(worksheet, 'B2', f'گزارش ریز تراکنش ها استان {province}', color='red', + row2='C3') + + create_header(worksheet, header_list, 5, 2, height=20) + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.01) + + l = 5 + m = 1 + role = request.GET['role'] + for transaction in transactions: + if transaction.kill_house: + killer_type = 'کشتارگاه' if transaction.kill_house.killer == False else 'کشتارکن' + elif transaction.chain_company: + killer_type = 'شرکت زنجیره' + else: + killer_type = 'خارج استان' + l += 1 + payer_date = jdatetime.date.fromgregorian( + day=transaction.date.day, + month=transaction.date.month, + year=transaction.date.year + ) + + if transaction.kill_house != None: + fullname = transaction.kill_house.kill_house_operator.user.fullname + mobile = transaction.kill_house.kill_house_operator.user.mobile + elif transaction.chain_company is not None: + fullname = transaction.chain_company.user.fullname + mobile = transaction.chain_company.user.mobile + else: + fullname = transaction.user.fullname + mobile = transaction.user.mobile + type = 'دستی' if transaction.transaction_type == 'wage-gateway-manual' else 'آنلاین' + + list1 = [ + m, + killer_type, + type, + str(payer_date), + transaction.refId, + transaction.orderId, + fullname, + mobile, + transaction.cardHolderPan, + transaction.amount, + transaction.union_share, + transaction.guilds_share, + transaction.company_share, + transaction.other_share + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + total_amount = \ + transactions.aggregate(total=Sum('amount'))['total'] or 0 + total_union_share = \ + transactions.aggregate(total=Sum('union_share'))['total'] or 0 + total_guilds_share = \ + transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + total_company_share = \ + transactions.aggregate(total=Sum('company_share'))['total'] or 0 + total_other_share = \ + transactions.aggregate(total=Sum('other_share'))['total'] or 0 + + value_header_list = [ + m - 1, + total_amount, + total_union_share, + total_guilds_share, + total_company_share, + total_other_share, + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount, + total_union_share, + total_guilds_share, + total_company_share, + total_other_share, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="ریز تراکنش ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def general_free_bar_excel(request): + value_header_list2_pending1 = [] + value_header_list2_accepted = [] + value_header_list2_rejected = [] + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + excel_options = [ + + 'درخواست های جدید', + 'تایید شده', + 'رد شده', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + header_list_main = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + + for name in excel_options: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + user = SystemUserProfile.objects.get(key=request.GET['key']) + poultry_requests = PoultryRequest.objects.filter( + send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False, out=True).order_by('-send_date') + if sheet_name == 'درخواست های جدید': + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries + ).order_by('-send_date') + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + out=True, + ).order_by('-send_date') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + + out=True, + ).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + out=True + ).order_by('-send_date') + else: + poultry_requests = poultry_requests + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=poultry_requests) + poultry_requests = ps.filter() + + poultry_requests_accepted = poultry_requests + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای جدید خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + + # if ProvinceKillRequest.objects.filter( + # province_request__city_request_Poultry__poultry_request=poultry_request, + # state='accepted').exists(): + # age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + # else: + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info != None else '-', + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + value_header_list2_accepted.extend(value_header_list2) + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تایید شده': + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + ).order_by('-send_date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + ).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + poultry_requests = poultry_requests.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + ).order_by('-send_date') + + else: + poultry_requests = poultry_requests + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=poultry_requests) + poultry_requests = ps.filter() + + poultry_requests_accepted = poultry_requests + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تایید شده خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + state='accepted').exists(): + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info['driverCar'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info \ + or poultry_request.out_province_driver_info[ + 'driverPelak'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info \ + or poultry_request.out_province_driver_info['driverName'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info[ + 'driverMobile'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info[ + 'driverhealthCode'] != None else '-', + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + value_header_list2_pending1.extend(value_header_list2) + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'رد شده': + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + poultry_requests = poultry_requests.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, ).order_by('-send_date') + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_requests = poultry_requests.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + ).order_by('-send_date') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = poultry_requests.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + ).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + poultry_requests = poultry_requests.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True)).order_by('-send_date') + else: + poultry_requests = poultry_requests + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=poultry_requests) + poultry_requests = ps.filter() + + poultry_requests_accepted = poultry_requests + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای حذف /رد شده خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + state='accepted').exists(): + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info['driverCar'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info \ + or poultry_request.out_province_driver_info[ + 'driverPelak'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info \ + or poultry_request.out_province_driver_info['driverName'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info[ + 'driverMobile'] != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info or \ + poultry_request.out_province_driver_info[ + 'driverhealthCode'] != None else '-', + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + value_header_list2_rejected.extend(value_header_list2) + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['E3'] = f'اطلاعات بارهای جدید خارج استان از تاریخ {from_date_1} تا {from_date_2}' + merge_range1 = 'E3:J3' + worksheet.merge_cells(merge_range1) + + worksheet['E3'].font = Font(color="C00000", bold=True) + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['E8'] = f'اطلاعات بارهای تایید شده خارج استان از تاریخ {from_date_1} تا {from_date_2}' + merge_range2 = 'E8:J8' + worksheet.merge_cells(merge_range2) + + worksheet['E8'].font = Font(color="C00000", bold=True) + worksheet['E8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['E13'] = f'اطلاعات بارهای رد شده خارج استان از تاریخ {from_date_1} تا {from_date_2}' + merge_range3 = 'E13:J13' + worksheet.merge_cells(merge_range3) + + worksheet['E13'].font = Font(color="C00000", bold=True) + worksheet['E13'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + for col_num, option in enumerate(header_list_main, 5): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[4].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + + for col_num, option in enumerate(header_list_main, 5): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[9].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + + for col_num, option in enumerate(header_list_main, 5): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=14, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[14].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + + for item in range(len(value_header_list2_pending1)): + cell = worksheet.cell(row=5, column=item + 5, value=value_header_list2_pending1[item]) + value = value_header_list2_pending1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for item in range(len(value_header_list2_accepted)): + cell = worksheet.cell(row=10, column=item + 5, value=value_header_list2_accepted[item]) + value = value_header_list2_accepted[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + for item in range(len(value_header_list2_rejected)): + cell = worksheet.cell(row=15, column=item + 5, value=value_header_list2_rejected[item]) + value = value_header_list2_rejected[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کلی بار های خارج از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def out_province_poultry_request_buyers_excel(request): + filterset_class = OutProvincePoultryRequestBuyerFilterSet + filterset_fields = [ + 'user__national_id', + 'user__base_order', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'unit_name', + + ] + + buyers = OutProvincePoultryRequestBuyer.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=buyers + ) + ).filter(): + ps = filterset_class(data=query, queryset=buyers) + buyers = ps.filter() + + excel_options = [ + 'ردیف', + 'نام کامل', + 'موبایل', + 'استان', + 'شهر', + 'ماهیت خریدار', + 'نام واحد', + 'تعداد درخواست ها', + 'حجم درخواست ها(قطعه)', + 'وزن درخواست ها(کیلوگرم)', + 'وضعیت', + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد کل خریداران', + 'مجموع تعداد درخواست ها', + 'مجموع حجم درخواست ها', + 'مجموع وزن درخواست ها', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + + worksheet.merge_cells(merge_range1) + worksheet['B2'].font = red_font + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_requests = 0 + all_total_quantity = 0 + all_total_weight = 0 + for buyer in buyers: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True, out_province_request_cancel=False) | Q(state_process='accepted', province_state='accepted', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False), trash=False, + out=True, out_province_poultry_request_buyer=buyer) + all_poultry_requests += len(poultry_requests) + total_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + all_total_quantity += total_quantity + total_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + all_total_weight += total_weight + l += 1 + active = 'فعال' if buyer.active == True else 'غیرفعال' + type = 'کشتارکن' if buyer.type == 'killer' else 'کشتارگاه' + list1 = [ + m, + buyer.user.fullname, + buyer.user.mobile, + buyer.user.province.name, + buyer.user.city.name, + type, + buyer.unit_name if buyer.unit_name is not None else '-', + len(poultry_requests), + total_quantity, + total_weight, + active + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + value_header_list = [ + len(buyers), + all_poultry_requests, + all_total_quantity, + all_total_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + all_poultry_requests, + all_total_quantity, + all_total_weight, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="خریداران خارج استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def chain_company_buyers_excel(request): + filterset_class = ChainCompanyFilterSet + filterset_fields = [ + 'user__national_id', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'name', + + ] + + chain_companies = ChainCompany.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=chain_companies + ) + ).filter(): + ps = filterset_class(data=query, queryset=chain_companies) + chain_companies = ps.filter() + + excel_options = [ + 'ردیف', + 'نام شرکت', + 'مدیر عامل', + 'موبایل مدیر عامل', + 'شهر', + 'تعداد سفارشات', + 'حجم سفارشات(قطعه)', + 'وزن سفارشات(قطعه)', + + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد شرکت ها', + 'مجموع تعداد سفارشات', + 'مجموع حجم سفارشات', + 'مجموع وزن سفارشات', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + + worksheet.merge_cells(merge_range1) + worksheet['B2'].font = red_font + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_requests = 0 + all_total_quantity = 0 + all_total_weight = 0 + for buyer in chain_companies: + + chain_allocations = ChainAllocation.objects.filter(chain_company=buyer, state='accepted', trash=False).order_by( + '-id') + + total_quantity = chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + all_poultry_requests += len(chain_allocations) + + all_total_quantity += total_quantity + + all_total_weight += total_weight + l += 1 + + list1 = [ + m, + buyer.name, + buyer.user.fullname, + buyer.user.mobile, + buyer.user.city.name, + len(chain_allocations), + total_quantity, + total_weight + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + value_header_list = [ + len(chain_companies), + all_poultry_requests, + all_total_quantity, + all_total_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + + '', + '', + '', + all_poultry_requests, + all_total_quantity, + all_total_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="شرکت زنجیره.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_chain_excel(request): + now = datetime.datetime.now() + + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else now + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + ).order_by('id') + if request.GET['state'] == 'accepted': + if request.GET['role'] == "ChainCompany": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + chain_allocations = chain_allocations.filter(chain_company__user=user, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__address__city=user.city, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + city_operator = CityOperator.objects.get(user=user, trash=False) + chain_allocations = chain_allocations.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] == "VetFarm": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__in=poultry, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + else: + chain_allocations = chain_allocations.filter(state__in=('accepted', 'pending'), + trash=False).order_by('-id') + state1 = 'تایید شده' + else: + if request.GET['role'] == "ChainCompany": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + chain_allocations = chain_allocations.filter(chain_company__user=user, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + chain_allocations = chain_allocations.filter(poultry_hatching__poultry__address__city=user.city, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + city_operator = CityOperator.objects.get(user=user, trash=False) + chain_allocations = chain_allocations.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, temporary_deleted=False).order_by('-id') + elif request.GET['role'] == "VetFarm": + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + chain_allocations = chain_allocations.filter( + poultry_hatching__poultry__in=poultry, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, temporary_deleted=False).order_by('-id') + else: + chain_allocations = chain_allocations.filter( + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, temporary_deleted=False).order_by('-id') + state1 = 'رد شده' + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=chain_allocations + ) + ).filter(): + ps = filterset_class(data=query, queryset=chain_allocations) + chain_allocations = ps.filter() + + excel_options = [ + 'ردیف', + 'وضعیت', + ' تاریخ سفارش', + 'نوع فروش', + 'ثبت کننده سفارش', + 'تلفن ثبت کننده سفارش', + 'خریدار', + 'تلفن خریدار', + 'مرغداری', + 'تلفن مرغداری', + 'شرکت زنجیره', + ' تلفن شرکت زنجیره', + 'کد بهداشتی', + 'کد قرنطینه', + 'راننده ', + 'تلفن راننده ', + 'خودرو', + 'پلاک', + 'حجم', + 'میانگین وزن', + 'وزن', + 'حذف/رد کننده', + 'تلفن حذف/رد کننده', + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if state1 == 'تایید شده': + for col_num, option in enumerate(excel_options[:21], 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + else: + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {state1} شرکت زنجیره' + if chain_allocations.exists(): + name = chain_allocations.first().poultry_hatching.poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_age = [] + + all_quantity = chain_allocations.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_weighte = chain_allocations.aggregate( + total=Sum('weight'))[ + 'total'] or 0 + has_code = 0 + if chain_allocations: + for chain_allocation in chain_allocations: + age = (chain_allocation.poultry_hatching.chicken_age) + all_age.append(age) + chain_date = jdatetime.date.fromgregorian( + day=chain_allocation.date.day, + month=chain_allocation.date.month, + year=chain_allocation.date.year + ) + + if chain_allocation.quarantine_code: + has_code += 1 + + remover_fullname = '-' + remover_mobile = '-' + if chain_allocation.state == 'accepted': + state = 'تایید شده' + elif chain_allocation.state == 'rejected': + state = 'رد شده' + remover_fullname = chain_allocation.seconder['fullname'] if chain_allocation.seconder else None + remover_mobile = chain_allocation.seconder['mobile'] if chain_allocation.seconder else None + elif chain_allocation.state == 'pending': + state = 'در انتظار تایید' + else: + state = 'حذف شده' + remover_fullname = chain_allocation.remover['fullname'] if chain_allocation.remover else None + remover_mobile = chain_allocation.remover['mobile'] if chain_allocation.remover else None + out_province = 'خارج استان' if chain_allocation.out_province == True else 'داخل استان' + + full_name_registerer = chain_allocation.registerer['fullname'] if chain_allocation.registerer else '-' + mobile_registerer = chain_allocation.registerer['mobile'] if chain_allocation.registerer else '-' + + if chain_allocation.kill_house is not None: + buyer_fullname = chain_allocation.kill_house.name + buyer_mobile = chain_allocation.kill_house.kill_house_operator.user.mobile + else: + buyer_fullname = chain_allocation.buyer_name + buyer_mobile = chain_allocation.buyer_mobile + + list1 = [ + m, + state, + str(chain_date), + out_province, + full_name_registerer, + mobile_registerer, + buyer_fullname, + buyer_mobile, + chain_allocation.poultry_hatching.poultry.unit_name, + chain_allocation.poultry_hatching.poultry.user.mobile, + chain_allocation.company_name, + chain_allocation.company_user_mobile, + chain_allocation.health_code if chain_allocation.health_code else '-', + chain_allocation.quarantine_code if chain_allocation.quarantine_code else '-', + chain_allocation.driver_name if chain_allocation.driver_name else '-', + chain_allocation.driver_mobile if chain_allocation.driver_mobile else '-', + chain_allocation.type_car if chain_allocation.type_car else '-', + chain_allocation.pelak if chain_allocation.pelak else '-', + chain_allocation.quantity, + chain_allocation.index_weight, + chain_allocation.weight, + remover_fullname, + remover_mobile, + ] + m += 1 + if state1 == 'تایید شده': + for item in range(len(list1) - 2): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(chain_allocations), + all_quantity, + all_weighte, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + '', + all_weighte, + '', + '', + + ] + if state1 == 'تایید شده': + for item in range(len(list2) - 2): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="بار های شرکت زنجیره.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def general_city_operator(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + city_operator_list = [] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + city_operators = CityOperator.objects.filter(trash=False).exclude(unit_name='اتحادیه استان (فاقد تعاونی)') + + row_list2 = len(city_operators) + 7 + province = city_operators.last().user.province.name + worksheet[f'F1'] = f'گزارش اطلاعات کلی جوجه ریزی و کشتار تعاونی های استان {province}' + worksheet[f'F1'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'F1'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'F1:I2' + worksheet.merge_cells(merge_range1) + + worksheet[f'D{row_list2}'] = f'اطلاعات کشتار به تفکیک تعاونی ها از تاریخ {from_date_1} تا {from_date_2}' + worksheet[f'D{row_list2}'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'D{row_list2}'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'D{row_list2}:J{row_list2 + 1}' + worksheet.merge_cells(merge_range1) + + header_list1 = [ + 'تعاونی', + 'شهر', + 'کاربر', + 'تلفن کاربر', + 'تعداد فارم', + 'تعداد کل جوجه ریزی', + 'حجم کل جوجه ریزی', + 'حجم کل کشتارشده', + 'وزن کل کشتارشده', + 'میانگین وزنی', + 'حجم کل فروش خارج از استان', + 'وزن کل فروش خارج از استان', + 'وزن کل لاشه', + 'تعداد جوجه ریزی فعال', + 'حجم جوجه ریزی فعال', + 'مانده در سالن', + + 'تعداد درخواست کشتار تعاونی', + 'حجم درخواست کشتار تعاونی', + 'درصد نسبت به حجم کل', + 'تعداد خرید مستقیم', + 'حجم خرید مستقیم', + 'درصد نسبت به حجم کل', + 'تعداد درخواست کشتار کاربر سایر', + 'حجم کشتار کاربر سایر', + 'درصد نسبت به حجم کل', + 'تعداد گزارشات کاربر تعاونی', + 'تعداد گزارشات کاربر ادمین', + 'کل گزارشات', + 'درصد فعالیت کاربر نسبت به جوجه ریزی ها', + 'درصد فعالیت ادمین نسبت به جوجه ریزی ها', + 'درصد فعالیت نسبت به کل گزارشات کاربران', + 'درصد فعالیت نسبت به کاربر ادمین', + ] + + for col_num, option in enumerate(header_list1, 2): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + l = 4 + row_list = len(city_operators) + 12 + row_city = len(city_operators) + 10 + len_poultry = 0 + len_all_hatching = 0 + all_hathcing_quantitya_all = 0 + all_province_requests_quantity = 0 + all_province_requests_weight = 0 + len_hatching = 0 + all_hatching_quantity = 0 + all_hatching_lest_over = 0 + all_out_poultry_request_quantity = 0 + all_out_poultry_request_weight = 0 + city_operator_poultry_request_quantity_all = 0 + city_operator_poultry_request_weight_all = 0 + direct_bying_poultry_request_quantity_all = 0 + direct_bying_poultry_request_weight_all = 0 + province_operaor_poultry_request_quantity_all = 0 + province_operaor_poultry_request_weight_all = 0 + city_operator_name = city_operators.values_list('user__fullname', flat=True).distinct() + city_operator_all_violation_all = PoultryHatching.objects.filter(trash=False, violation_reporter__isnull=False, + violation_reporter__in=city_operator_name).count() + all_admin_all_violation = 0 + for city_operator in city_operators: + poultry_request = PoultryRequest.objects.filter(trash=False, + out_province_request_cancel=False, + province_state='accepted', + poultry__city_operator=city_operator.unit_name) + poultry = Poultry.objects.filter(trash=False, city_operator=city_operator.unit_name) + out_poultry_request = poultry_request.filter(out=True) + city_operator_poultry_request = poultry_request.filter(direct_buying=False, registrar__role='CityOperator') + province_operaor_poultry_request = poultry_request.filter(~Q(registrar__role='CityOperator'), + direct_buying=False) + direct_bying_poultry_request = poultry_request.filter(direct_buying=True) + + province_requests = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name + , return_to_province=False, + state__in=('accepted', 'pending')) + + province_requests_quantity = \ + province_requests.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + + province_requests_weight = \ + province_requests.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + + kill_requests = KillHouseRequest.objects.filter(trash=False, province_kill_request__in=province_requests) + all_hatching = PoultryHatching.objects.filter(trash=False, poultry__in=poultry) + all_violation = all_hatching.filter(violation_reporter__isnull=False) + city_operator_all_violation = all_violation.filter(violation_reporter=city_operator.user.fullname).count() + admin_all_violation = all_violation.filter(~Q(violation_reporter=city_operator.user.fullname)).count() + + hathcing_quantity_all = \ + all_hatching.aggregate( + total=Sum(F('quantity')))[ + 'total'] or 0 + out_poultry_request_quantity_all = \ + out_poultry_request.aggregate( + total=Sum(F('quantity')))[ + 'total'] or 0 + out_poultry_request_weight_all = \ + out_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + hatching = all_hatching.filter(archive=False, allow_hatching='pending') + hatching_quantity = \ + hatching.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + hatching_lest_over = \ + hatching.aggregate( + total=Sum('left_over'))[ + 'total'] or 0 + city_operator_poultry_request_quantity = \ + city_operator_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + city_operator_poultry_request_weight = \ + city_operator_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + quantity_all = \ + poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + direct_bying_poultry_request_quantity = \ + direct_bying_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + direct_bying_poultry_request_weight = \ + direct_bying_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + province_operaor_poultry_request_quantity = \ + province_operaor_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + province_operaor_poultry_request_weight = \ + province_operaor_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + all_report = city_operator_all_violation + admin_all_violation + all_admin_all_violation += admin_all_violation + list1 = [ + city_operator.unit_name, + city_operator.user.city.name, + city_operator.user.fullname, + city_operator.user.mobile, + len(poultry), + len(all_hatching), + hathcing_quantity_all, + province_requests_quantity, + province_requests_weight, + round(province_requests_weight / province_requests_quantity, + 1) if province_requests_quantity > 0 else 0, + out_poultry_request_quantity_all, + out_poultry_request_weight_all, + province_requests_weight * 0.75, + len(hatching), + hatching_quantity, + hatching_lest_over, + city_operator_poultry_request_quantity, + city_operator_poultry_request_weight, + round((city_operator_poultry_request_weight * 100) / quantity_all) if quantity_all > 0 else 0, + direct_bying_poultry_request_quantity, + direct_bying_poultry_request_weight, + round((direct_bying_poultry_request_weight * 100) / quantity_all) if quantity_all > 0 else 0, + province_operaor_poultry_request_quantity, + province_operaor_poultry_request_weight, + round((province_operaor_poultry_request_weight * 100) / quantity_all) if quantity_all > 0 else 0, + city_operator_all_violation, + admin_all_violation, + city_operator_all_violation + admin_all_violation, + str(round(city_operator_all_violation * 100 / len(all_hatching), 1) if len(all_hatching) > 0 else 0), + str(round(admin_all_violation * 100 / len(all_hatching), 1) if len(all_hatching) > 0 else 0), + str(round(city_operator_all_violation * 100 / city_operator_all_violation_all, + 1) if city_operator_all_violation_all > 0 else 0), + str(round(city_operator_all_violation * 100 / all_report, 1) if all_report > 0 else 0), + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + len_poultry += len(poultry) + len_all_hatching += len(all_hatching) + all_hathcing_quantitya_all += hathcing_quantity_all + all_province_requests_quantity += province_requests_quantity + all_province_requests_weight += province_requests_weight + len_hatching += len(hatching) + all_hatching_quantity += hatching_quantity + all_hatching_lest_over += hatching_lest_over + all_out_poultry_request_quantity += out_poultry_request_quantity_all + all_out_poultry_request_weight += out_poultry_request_weight_all + province_requests_date = province_requests.filter( + province_request__poultry_request__send_date__date__gte=date1 + , province_request__poultry_request__send_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name + ) + city_operator_poultry_request_quantity_all += city_operator_poultry_request_quantity + city_operator_poultry_request_weight_all += city_operator_poultry_request_weight + direct_bying_poultry_request_quantity_all += direct_bying_poultry_request_quantity + direct_bying_poultry_request_weight_all += direct_bying_poultry_request_weight + province_operaor_poultry_request_quantity_all += province_operaor_poultry_request_quantity + province_operaor_poultry_request_weight_all += province_operaor_poultry_request_weight + + list2 = [ + 'ردیف', + 'ماهیت', + 'خریدار', + 'نام و نام خانوادگی مالک', + 'تلفن مالک', + 'شهر', + 'تعداد سفارش', + 'حجم سفارش', + 'تعداد بار ', + 'حجم بار', + 'وزن بار', + 'وزن لاشه', + ] + if province_requests_date: + if city_operator not in city_operator_list: + city_operator_list.append(city_operator) + kill_houses1 = province_requests_date.values_list('killhouse_user', flat=True).distinct() + + for col_num, option in enumerate(list2, 2): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=row_list, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + if option in ['تعداد سفارش', 'حجم سفارش', 'تعداد بار ', 'حجم بار', 'وزن بار', 'وزن لاشه']: + cell.fill = PatternFill(start_color="FF0000", fill_type="solid") + # worksheet.row_dimensions[row_list].height = 35 + worksheet.column_dimensions[col_letter].width = 17 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + m = 1 + kill_houses = KillHouse.objects.filter(id__in=kill_houses1) + len_province_requests_kill = 0 + all_province_quantity = 0 + len_kill_requests_date = 0 + all_accepted_assignment_real_quantity = 0 + all_accepted_assignment_real_weight = 0 + all_ware_house_accepted_real_weight = 0 + for kill_house in kill_houses: + province_requests_kill = province_requests_date.filter(killhouse_user=kill_house) + + province_quantity = \ + province_requests_kill.aggregate( + total=Sum('main_quantity'))[ + 'total'] or 0 + + kill_requests_date = kill_requests.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + killhouse_user=kill_house, + province_kill_request__in=province_requests_kill) + + accepted_assignment_real_quantity = \ + kill_requests_date.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + accepted_assignment_real_weight = \ + kill_requests_date.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + len_province_requests_kill += len(province_requests_kill) + all_province_quantity += province_quantity + len_kill_requests_date += len(kill_requests_date) + all_accepted_assignment_real_quantity += accepted_assignment_real_quantity + all_accepted_assignment_real_weight += int(accepted_assignment_real_weight) + all_ware_house_accepted_real_weight += int(accepted_assignment_real_weight) * 0.75 + # killer='کشتارگاه' if kill_house.killer == False else 'کشتارکن' + if kill_house.killer == True and kill_house.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + killer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif kill_house.killer == True and kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + else: + killer_type = 'کشتارگاه' + list1 = [ + m, + killer_type, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + kill_house.kill_house_operator.user.city.name, + len(province_requests_kill), + province_quantity, + len(kill_requests_date), + accepted_assignment_real_quantity, + int(accepted_assignment_real_weight), + int(accepted_assignment_real_weight) * 0.75, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row_list + 1, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + row_list += 1 + m += 1 + + else: + row_list += 5 + worksheet[f'F{row_city}'] = f'{city_operator.unit_name}' + worksheet[f'F{row_city}'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'F{row_city}'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'F{row_city}:H{row_city + 1}' + worksheet.merge_cells(merge_range1) + + row_city += len(kill_houses) + 5 + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + len_province_requests_kill, + all_province_quantity, + len_kill_requests_date, + all_accepted_assignment_real_quantity, + all_accepted_assignment_real_weight, + all_ware_house_accepted_real_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=row_city - 2, column=item + 2, value=list2[item]) + value = list2[item] + cell.font = Font(size=10, bold=True, color='FFFFFF') + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + list2 = [ + 'مجموع==>', + '', + '', + '', + len_poultry, + len_all_hatching, + all_hathcing_quantitya_all, + all_province_requests_quantity, + all_province_requests_weight, + round(all_province_requests_weight / all_province_requests_quantity, + 1) if all_province_requests_quantity > 0 else 0, + all_out_poultry_request_quantity, + all_out_poultry_request_weight, + all_province_requests_weight * 0.75, + len_hatching, + all_hatching_quantity, + all_hatching_lest_over, + city_operator_poultry_request_quantity_all, + city_operator_poultry_request_weight_all, + '', + direct_bying_poultry_request_quantity_all, + direct_bying_poultry_request_weight_all, + '', + province_operaor_poultry_request_quantity_all, + province_operaor_poultry_request_weight_all, + '', + city_operator_all_violation_all, + all_admin_all_violation, + all_admin_all_violation + city_operator_all_violation_all, + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 1, 2, color='green') + for city_operator in city_operator_list: + sheet_name = city_operator.unit_name + sheet_name1 = sheet_name.split(' ')[-2] + ' ' + sheet_name.split(' ')[-1] + worksheet = workbook.create_sheet(f'تعاونی {sheet_name1}') + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', 'killer').values( + 'ware_house_confirmation', 'ware_house_accepted_real_quantity', 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + ) + if 'key' in request.GET: + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter( + killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + + else: + filtered_kill_reqs = filtered_kill_request + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های داری سند', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی {sheet_name}' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + red_font = Font(color="C00000", bold=True) + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:F1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + if kill['assignment_state_archive'] == 'True': + all_assignment_state_archive_state += 1 + assignment_state_archive_state = 'وارد شده است' + else: + assignment_state_archive_state = 'وارد نشده است' + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if kill[ + 'accepted_real_weight'] != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + state_delete, + assignment_state_archive_state, + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + ware_house_accepted_real_weight, + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(all_weight_loss / len_weight_loss, 2) if all_weight_loss > 0 else 0 + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + all_assignment_state_archive_state, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + all_weight_loss + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + all_ware_house_accepted_real_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" پایش تعاونی ها .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_transactions_wage_payid_admin_x_excel(request): + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__mobile', + 'system_address__city__name', + + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + + excel_options = [ + 'ردیف', + 'تاریخ پرداخت', + 'نوع پرداخت', + 'نام پرداخت کننده', + 'تلفن پرداخت کننده', + 'شماره درخواست', + 'شماره پیگیری', + 'کد سفارش', + 'شماره کارت', + 'مبلغ تراکنش(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + 'سهم اصناف(ریال)', + 'سهم دامپزشک(ریال)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['B2'] = f'اطلاعات کلی تعرفه {from_date_1} تا {from_date_2}' + merge_range1 = 'B2:C2' + worksheet.merge_cells(merge_range1) + + worksheet['B2'].font = Font(color="C00000", bold=True) + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['B5'] = f'جزئیات {from_date_1} تا {from_date_2}' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + # worksheet['B2'] = 'اطلاعات کلی تعرفه(از 1403/01/01 به بعد)' + + worksheet['B2'].font = Font(color="C00000") + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['B5'] = f'جزئیات' + + worksheet['B5'].font = Font(color="C00000", bold=True) + worksheet['B5'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + header_list1 = [ + 'کل تعرفه (ریال)', + 'سهم اتحادیه', + 'سهم شرکت', + 'سهم صنف', + 'سهم دامپزشک', + 'کل تعرفه پرداخت شده (ریال)', + 'سهم پرداخت شده اتحادیه (ریال)', + 'سهم پرداخت شده شرکت (ریال)', + 'سهم پرداخت شده اصناف (ریال)', + 'سهم پرداخت شده دامپزشک (ریال)', + 'مجموع تخفیفات (ریال)', + 'کل تعرفه پرداخت نشده (ریال)', + + 'سهم پرداخت نشده اتحادیه (ریال)', + 'سهم پرداخت نشده شرکت (ریال)', + 'سهم پرداخت نشده اصناف (ریال)', + 'سهم پرداخت نشده دامپزشک (ریال)', + ] + + for col_num, option in enumerate(header_list1, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + try: + total_wage = TotalWageInformation.objects.get(trash=False) + except: + total_wage = TotalWageInformation() + total_wage.save() + serializer_total_wage_information = TotalWageInformationSerializer(total_wage, + context={'request': request}).data + + wage_info = serializer_total_wage_information.get('wage_info', {}) + shares = wage_info.get('shares', []) + company_data = next((item for item in shares if item["name"] == "شرکت"), None) + etehadiye_data = next((item for item in shares if item["name"] == "اتحادیه"), None) + sanf_protein_data = next((item for item in shares if item["name"] == "صنف پروتئین"), None) + dampezshk_data = next((item for item in shares if item["name"] == "دامپزشک"), None) + + values_list = [ + wage_info.get('total_wage', 0), + etehadiye_data['total_wage'], + company_data['total_wage'], + sanf_protein_data['total_wage'], + dampezshk_data['total_wage'], + wage_info.get('total_paid_wage', 0), + etehadiye_data['total_paid_wage'], + company_data['total_paid_wage'], + sanf_protein_data['total_paid_wage'], + dampezshk_data['total_paid_wage'], + wage_info.get('off', 0), + wage_info.get('total_unpaid_wage', 0), + etehadiye_data['total_unpaid_wage'], + company_data['total_unpaid_wage'], + sanf_protein_data['total_unpaid_wage'], + dampezshk_data['total_unpaid_wage'], + ] + create_value(worksheet, values_list, 3, 4, border_style='thin') + kill_houses = KillHouse.objects.filter(trash=False).exclude(out_province=True).order_by('id') + + kill_houses = KillHouseForNewWageInormationSerializer(kill_houses, many=True, context={'request': request}).data + if wage_info['wage_counting_type'] == 'carcass': + l = 15 + m = 1 + header_list2 = [ + "وزن کل فروش به خارج از استان ", + "تعرفه کل فروش به خارج از استان(ریال)", + "کل وزن زنده کشتار داخل استان(کیلوگرم)", + "کل وزن لاشه کشتار داخل استان(کیلوگرم)", + "وزن توزیع لاشه داخل استان(کیلوگرم)", + "تعرفه توزیع لاشه داخل استان(ریال)", + "وزن توزیع لاشه به خارج از استان(کیلوگرم)", + "تعرفه توزیع لاشه به خارج از استان(ریال)", + "وزن لاشه ورودی به استان(کیلوگرم)", + "تعرفه لاشه ورودی به استان(ریال)", + "وزن مرغ زنده ورودی به استان(کیلوگرم)", + "تعرفه مرغ زنده ورودی به استان(ریال)", + "وزن خرید های بازگشتی(کیلوگرم)", + "تعرفه خرید های بازگشتی(ریال)", + + ] + values_list2 = [ + wage_info.get('out_province_poultry_request_weight', 0), + wage_info.get('out_province_poultry_request_wage', 0), + wage_info.get('total_province_live_weight', 0), + wage_info.get('total_province_carcasses_weight', 0), + wage_info.get('province_kill_requests_total_weight', 0), + wage_info.get('province_kill_requests_total_wage', 0), + wage_info.get('free_bars_out_province_carcases_total_weight', 0), + wage_info.get('free_bars_out_province_carcases_total_wage', 0), + wage_info.get('free_bars_carcases_total_weight', 0), + wage_info.get('free_bars_carcases_total_wage', 0), + wage_info.get('free_bars_live_total_weight', 0), + wage_info.get('free_bars_live_total_wage', 0), + wage_info.get('return_total_province_live_weight', 0), + wage_info.get('total_return_pure_province_carcasses_price', 0), + + ] + header_list5 = [ + 'سهم', + 'تعرفه فروش مرغ زنده به خارج از استان(ریال)', + 'تعرفه توزیع لاشه به داخل استان(ریال)', + 'تعرفه توزیع لاشه خارج استان(ریال)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'تعرفه مرغ زنده ورودی به استان(ریال)', + 'تعرفه کل(ریال)', + 'تعرفه پرداخت شده(ریال)', + 'تعرفه پرداخت نشده(ریال)', + + ] + header_list = [ + 'ردیف', + 'کشتارگاه', + 'کل تعرفه (ریال)', + 'سهم اتحادیه (ریال)', + 'سهم شرکت (ریال)', + 'سهم صنف (ریال)', + 'سهم دامپزشک (ریال)', + + 'کل تعرفه پرداخت شده (ریال)', + 'سهم اتحادیه از واریزی(ریال)', + 'سهم شرکت از واریزی(ریال)', + 'سهم اصناف از واریزی(ریال)', + 'سهم دامپزشک از واریزی(ریال)', + 'تخفیفات (ریال)', + + 'کل تعرفه پرداخت نشده (ریال)', + ' سهم اتحادیه پرداخت نشده', + ' سهم شرکت پرداخت نشده', + 'سهم صنف پرداخت نشده', + 'سهم دامپزشک پرداخت نشده', + 'کل وزن زنده کشتار داخل استان', + 'وزن لاشه کشتار داخل استان', + 'وزن توزیع لاشه کشتار داخل استان', + 'تعرفه توزیع لاشه کشتار داخل استان', + 'وزن توزیع لاشه به خارج استان', + 'تعرفه توزیع لاشه به خارج استان', + 'وزن لاشه ورودی به استان', + 'تعرفه لاشه ورودی به استان', + 'وزن مرغ زنده ورودی به استان', + 'تعرفه مرغ زنده ورودی به استان', + 'وزن خریدهای بازگشتی', + 'تعرفه خریدهای بازگشتی', + + ] + + for kill_house in kill_houses: + wage_info2 = kill_house.get('wage_info', {}) + shares2 = kill_house.get('shares', []) + company_data2 = next((item for item in shares2 if item["name"] == "شرکت"), None) + etehadiye_data2 = next((item for item in shares2 if item["name"] == "اتحادیه"), None) + sanf_protein_data2 = next((item for item in shares2 if item["name"] == "صنف پروتئین"), None) + dampezshk_data2 = next((item for item in shares2 if item["name"] == "دامپزشک"), None) + values_list3 = [ + m, + kill_house['name'], + wage_info2['total_wage'], + etehadiye_data2['total_wage'], + company_data2['total_wage'], + sanf_protein_data2['total_wage'], + dampezshk_data2['total_wage'], + wage_info2.get('total_paid_wage', 0), + etehadiye_data2['total_paid_wage'], + company_data2['total_paid_wage'], + sanf_protein_data2['total_paid_wage'], + dampezshk_data2['total_paid_wage'], + wage_info2.get('off', 0), + wage_info2.get('total_unpaid_wage', 0), + etehadiye_data2['total_unpaid_wage'], + company_data2['total_unpaid_wage'], + sanf_protein_data2['total_unpaid_wage'], + dampezshk_data2['total_unpaid_wage'], + wage_info2.get('total_province_live_weight', 0), + wage_info2.get('total_province_carcasses_weight', 0), + wage_info2.get('province_kill_requests_total_weight', 0), + wage_info2.get('province_kill_requests_total_wage', 0), + wage_info2.get('free_bars_out_province_carcases_total_weight', 0), + wage_info2.get('free_bars_out_province_carcases_total_wage', 0), + wage_info2.get('free_bars_carcases_total_weight', 0), + wage_info2.get('free_bars_carcases_total_wage', 0), + wage_info2.get('free_bars_live_total_weight', 0), + wage_info2.get('free_bars_live_total_wage', 0), + wage_info2.get('return_total_province_live_weight', 0), + wage_info2.get('total_return_pure_province_carcasses_price', 0), + + ] + for item in range(len(values_list3)): + cell = worksheet.cell(row=l, column=item + 1, value=values_list3[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list3[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + m += 1 + if int(wage_info2.get('total_paid_wage')) > 0: + if kill_house not in kill_house_list: + kill_house_list.append({"name": kill_house['name']}) + list2 = [ + "مجموع==>", "", + sum(kill_house.get('wage_info', {}).get('total_wage', 0) for kill_house in kill_houses), + sum(next( + (item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "اتحادیه"), + 0) for kill_house in kill_houses), + sum(next((item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "شرکت"), + 0) for kill_house in kill_houses), + sum(next((item.get("total_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), 0) for kill_house in kill_houses), + sum(next( + (item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "دامپزشک"), + 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('total_paid_wage', 0) for kill_house in kill_houses), + sum(next((item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "اتحادیه"), 0) for kill_house in kill_houses), + sum(next( + (item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "شرکت"), + 0) for kill_house in kill_houses), + sum(next((item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), 0) for kill_house in kill_houses), + sum(next((item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "دامپزشک"), 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('off', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('total_unpaid_wage', 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "اتحادیه"), 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "شرکت"), 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "دامپزشک"), 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('total_province_live_weight', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('total_province_carcasses_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('province_kill_requests_total_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('province_kill_requests_total_wage', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_out_province_carcases_total_weight', 0) for + kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_out_province_carcases_total_wage', 0) for kill_house + in kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_carcases_total_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_carcases_total_wage', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_live_total_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_live_total_wage', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('return_total_province_live_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('total_return_pure_province_carcasses_price', 0) for kill_house + in kill_houses), + ] + else: + l = 15 + m = 1 + header_list2 = [ + "وزن کل فروش به خارج از استان ", + "تعرفه کل فروش به خارج از استان(ریال)", + "کل وزن زنده کشتار داخل استان(کیلوگرم)", + "تعرفه کشتار داخل استان(کیلوگرم)", + "وزن توزیع لاشه به خارج از استان(کیلوگرم)", + "تعرفه توزیع لاشه به خارج از استان(ریال)", + "وزن لاشه ورودی به استان(کیلوگرم)", + "تعرفه لاشه ورودی به استان(ریال)", + "وزن مرغ زنده ورودی به استان(کیلوگرم)", + "تعرفه مرغ زنده ورودی به استان(ریال)", + "وزن خرید های بازگشتی(کیلوگرم)", + "تعرفه خرید های بازگشتی(ریال)", + + ] + values_list2 = [ + wage_info.get('out_province_poultry_request_weight', 0), + wage_info.get('out_province_poultry_request_wage', 0), + wage_info.get('total_province_live_weight', 0), + wage_info.get('province_kill_requests_total_wage', 0), + wage_info.get('free_bars_out_province_carcases_total_weight', 0), + wage_info.get('free_bars_out_province_carcases_total_wage', 0), + wage_info.get('free_bars_carcases_total_weight', 0), + wage_info.get('free_bars_carcases_total_wage', 0), + wage_info.get('free_bars_live_total_weight', 0), + wage_info.get('free_bars_live_total_wage', 0), + wage_info.get('return_total_province_live_weight', 0), + wage_info.get('total_return_pure_province_carcasses_price', 0), + + ] + header_list5 = [ + 'سهم', + 'تعرفه فروش مرغ زنده به خارج از استان(ریال)', + 'تعرفه کشتار داخل استان(ریال)', + 'تعرفه توزیع لاشه خارج استان(ریال)', + 'تعرفه لاشه ورودی به استان(ریال)', + 'تعرفه مرغ زنده ورودی به استان(ریال)', + 'تعرفه کل(ریال)', + 'تعرفه پرداخت شده(ریال)', + 'تعرفه پرداخت نشده(ریال)', + + ] + header_list = [ + 'ردیف', + 'کشتارگاه', + 'کل تعرفه (ریال)', + 'سهم اتحادیه (ریال)', + 'سهم شرکت (ریال)', + 'سهم صنف (ریال)', + 'سهم دامپزشک (ریال)', + + 'کل تعرفه پرداخت شده (ریال)', + 'سهم اتحادیه از واریزی(ریال)', + 'سهم شرکت از واریزی(ریال)', + 'سهم اصناف از واریزی(ریال)', + 'سهم دامپزشک از واریزی(ریال)', + 'تخفیفات (ریال)', + + 'کل تعرفه پرداخت نشده (ریال)', + ' سهم اتحادیه پرداخت نشده', + ' سهم شرکت پرداخت نشده', + 'سهم صنف پرداخت نشده', + 'سهم دامپزشک پرداخت نشده', + + 'کل وزن زنده کشتار داخل استان', + 'تعرفه کشتار داخل استان', + 'وزن توزیع لاشه به خارج استان', + 'تعرفه توزیع لاشه به خارج استان', + 'وزن لاشه ورودی به استان', + 'تعرفه لاشه ورودی به استان', + 'وزن مرغ زنده ورودی به استان', + 'تعرفه مرغ زنده ورودی به استان', + 'وزن خریدهای بازگشتی', + 'تعرفه خریدهای بازگشتی', + + ] + for kill_house in kill_houses: + wage_info2 = kill_house.get('wage_info', {}) + shares2 = kill_house.get('shares', []) + company_data2 = next((item for item in shares2 if item["name"] == "شرکت"), None) + etehadiye_data2 = next((item for item in shares2 if item["name"] == "اتحادیه"), None) + sanf_protein_data2 = next((item for item in shares2 if item["name"] == "صنف پروتئین"), None) + dampezshk_data2 = next((item for item in shares2 if item["name"] == "دامپزشک"), None) + values_list3 = [ + m, + kill_house['name'], + wage_info2['total_wage'], + etehadiye_data2['total_wage'], + company_data2['total_wage'], + sanf_protein_data2['total_wage'], + dampezshk_data2['total_wage'], + wage_info2.get('total_paid_wage', 0), + etehadiye_data2['total_paid_wage'], + company_data2['total_paid_wage'], + sanf_protein_data2['total_paid_wage'], + dampezshk_data2['total_paid_wage'], + wage_info2.get('off', 0), + wage_info2.get('total_unpaid_wage', 0), + etehadiye_data2['total_unpaid_wage'], + company_data2['total_unpaid_wage'], + sanf_protein_data2['total_unpaid_wage'], + dampezshk_data2['total_unpaid_wage'], + + wage_info2.get('total_province_live_weight', 0), + wage_info2.get('province_kill_requests_total_wage', 0), + wage_info2.get('free_bars_out_province_carcases_total_weight', 0), + wage_info2.get('free_bars_out_province_carcases_total_wage', 0), + wage_info2.get('free_bars_carcases_total_weight', 0), + wage_info2.get('free_bars_carcases_total_wage', 0), + wage_info2.get('free_bars_live_total_weight', 0), + wage_info2.get('free_bars_live_total_wage', 0), + wage_info2.get('return_total_province_live_weight', 0), + wage_info2.get('total_return_pure_province_carcasses_price', 0), + + ] + for item in range(len(values_list3)): + cell = worksheet.cell(row=l, column=item + 1, value=values_list3[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list3[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + m += 1 + if int(wage_info2.get('total_paid_wage')) > 0: + if kill_house not in kill_house_list: + kill_house_list.append({"name": kill_house['name']}) + list2 = [ + "مجموع==>", + "", + sum(kill_house.get('wage_info', {}).get('total_wage', 0) for kill_house in kill_houses), + sum(next( + (item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "اتحادیه"), + 0) for kill_house in kill_houses), + sum(next((item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "شرکت"), + 0) + for kill_house in kill_houses), + sum(next( + (item.get("total_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), + 0) for kill_house in kill_houses), + sum(next( + (item.get("total_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "دامپزشک"), + 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('total_paid_wage', 0) for kill_house in kill_houses), + sum(next( + (item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "اتحادیه"), + 0) for kill_house in kill_houses), + sum(next( + (item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if item["name"] == "شرکت"), + 0) + for kill_house in kill_houses), + sum(next((item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), 0) for kill_house in kill_houses), + sum(next( + (item.get("total_paid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "دامپزشک"), + 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('off', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('total_unpaid_wage', 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "اتحادیه"), 0) for kill_house in kill_houses), + sum(next( + (item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "شرکت"), + 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "صنف پروتئین"), 0) for kill_house in kill_houses), + sum(next((item.get("total_unpaid_wage", 0) for item in kill_house.get("shares", []) if + item["name"] == "دامپزشک"), 0) for kill_house in kill_houses), + + sum(kill_house.get('wage_info', {}).get('total_province_live_weight', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('province_kill_requests_total_wage', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_out_province_carcases_total_weight', 0) for + kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_out_province_carcases_total_wage', 0) for kill_house + in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_carcases_total_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_carcases_total_wage', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_live_total_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('free_bars_live_total_wage', 0) for kill_house in kill_houses), + sum(kill_house.get('wage_info', {}).get('return_total_province_live_weight', 0) for kill_house in + kill_houses), + sum(kill_house.get('wage_info', {}).get('total_return_pure_province_carcasses_price', 0) for kill_house + in kill_houses), + ] + + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=9, bold=True) + cell.fill = PatternFill(start_color="FFFF00", fill_type="solid") + for col_num, option in enumerate(header_list, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=14, column=col_num, value=option) + if option in ['کل تعرفه (ریال)', 'سهم شرکت (ریال)', 'سهم اتحادیه (ریال)', 'سهم صنف (ریال)', + 'سهم دامپزشک (ریال)']: + cell.fill = PatternFill(start_color="76933C", fill_type="solid") + elif option in ['کل تعرفه پرداخت نشده (ریال)', 'کل تعرفه پرداخت نشده (ریال)', ' سهم شرکت پرداخت نشده', + 'سهم دامپزشک پرداخت نشده', + ' سهم اتحادیه پرداخت نشده', 'سهم صنف پرداخت نشده']: + cell.fill = PatternFill(start_color="E26B0A", fill_type="solid") + elif option in ['تعداد بار', 'حجم بار', 'وزن بار']: + cell.fill = PatternFill(start_color="163CB6", fill_type="solid") + elif option in ['تعداد تخصیص بدون بار', 'حجم تخصیص بدون بار', 'وزن تخصیص بدون بار', ]: + cell.fill = PatternFill(start_color="476DE7", fill_type="solid") + else: + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[14].height = 45 + worksheet.column_dimensions[col_letter].width = 27 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + create_value(worksheet, values_list2, 6, 3, border_style='thin') + for col_num, option in enumerate(header_list2, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[5].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + for col_num, option in enumerate(header_list5, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="1E487B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[8].height = 25 + worksheet.column_dimensions[col_letter].width = 20 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + values_union = [ + etehadiye_data['name'], + etehadiye_data['out_province_poultry_request_wage'], + etehadiye_data['province_kill_request_wage'], + etehadiye_data['free_sell_carcasses_wage'], + etehadiye_data['free_buying_carcasses_wage'], + etehadiye_data['free_buying_live_wage'], + etehadiye_data['total_wage'], + etehadiye_data['total_paid_wage'], + etehadiye_data['total_unpaid_wage'], + + ] + for item in range(len(values_union)): + cell = worksheet.cell(row=9, column=item + 1, value=values_union[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_union[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + values_company = [ + company_data['name'], + company_data['out_province_poultry_request_wage'], + company_data['province_kill_request_wage'], + company_data['free_sell_carcasses_wage'], + company_data['free_buying_carcasses_wage'], + company_data['free_buying_live_wage'], + company_data['total_wage'], + company_data['total_paid_wage'], + company_data['total_unpaid_wage'], + + ] + for item in range(len(values_company)): + cell = worksheet.cell(row=10, column=item + 1, value=values_company[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_company[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + values_guild = [ + sanf_protein_data['name'], + sanf_protein_data['out_province_poultry_request_wage'], + sanf_protein_data['province_kill_request_wage'], + sanf_protein_data['free_sell_carcasses_wage'], + sanf_protein_data['free_buying_carcasses_wage'], + sanf_protein_data['free_buying_live_wage'], + sanf_protein_data['total_wage'], + sanf_protein_data['total_paid_wage'], + sanf_protein_data['total_unpaid_wage'], + + ] + for item in range(len(values_guild)): + cell = worksheet.cell(row=11, column=item + 1, value=values_guild[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_guild[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + values_other = [ + dampezshk_data['name'], + dampezshk_data['out_province_poultry_request_wage'], + dampezshk_data['province_kill_request_wage'], + dampezshk_data['free_sell_carcasses_wage'], + dampezshk_data['free_buying_carcasses_wage'], + dampezshk_data['free_buying_live_wage'], + dampezshk_data['total_wage'], + dampezshk_data['total_paid_wage'], + dampezshk_data['total_unpaid_wage'], + + ] + for item in range(len(values_other)): + cell = worksheet.cell(row=12, column=item + 1, value=values_other[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_other[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + for kill_house in kill_house_list: + sheet_name = kill_house['name'] + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[2].height = 27 + worksheet.freeze_panes = worksheet['A3'] + max_col = worksheet.max_column + range_str = f'A2:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 1 + m = 1 + kill_house = KillHouse.objects.get(name=sheet_name, trash=False) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('id') + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).order_by('id') + + for transaction in transactions: + if transaction.kill_house != None: + fullname = transaction.kill_house.kill_house_operator.user.fullname + mobile = transaction.kill_house.kill_house_operator.user.mobile + else: + fullname = transaction.chain_company.user.fullname + mobile = transaction.chain_company.user.mobile + date = convert_to_shamsi( + datetime=transaction.date + ) + type = 'دستی' if transaction.transaction_type == 'wage-gateway-manual' else 'آنلاین' + if request.GET['role'] == 'ProvinceOperator': + amout = transaction.union_share + elif request.GET['role'] == 'Company': + amout = transaction.company_share + elif request.GET['role'] == 'Guilds': + amout = transaction.guilds_share + else: + amout = transaction.amount + list1 = [ + m, + date, + type, + fullname, + mobile, + transaction.orderId, + transaction.saleReferenceId, + transaction.orderId, + transaction.cardHolderPan, + amout, + transaction.union_share, + transaction.company_share, + transaction.guilds_share, + transaction.other_share, + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش تعرفه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def buy_outside_the_province_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() if 'start' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() if 'end' in request.GET else now + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer').values('kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + ) + + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(system_address__province=user.province, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_reqs.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_reqs.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_reqs + else: + filtered_kill_reqs = filtered_kill_reqs + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + 'کشور مقصد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_age = [] + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['document_status'] if kill['document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{weight_loss}', + export_country, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity') or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code1.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + hasnt_code = filtered_kill_reqs.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + int(all_weighte), + round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}', + '' + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if request.GET['role'] == 'KillHouse': + name = filtered_kill_request.first()['killhouse_user__name'] + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + elif 'state' in request.GET: + if request.GET['state'] == 'bar_pending': + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل نشده.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل شده.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_request_report_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filterset_class = PoultryRequestFilterSet + filterset_fields = poultry_request_new_fields + filtered_poultry_request = PoultryRequest.objects.filter( + trash=False, + send_date__date__gte=date1, + send_date__date__lte=date2 + ).select_related('poultry', 'poultry__user', 'hatching', 'poultry__user__city').only('freezing', 'remain_quantity', + 'amount', + 'key', 'poultry', + 'send_date', + 'hatching__date', + 'create_date', 'order_code', + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__user__city__name', + 'hatching__quantity', + 'quantity', + 'hatching__left_over', + 'hatching__chicken_breed', + 'poultry__address__province__name', + 'Index_weight', + 'hatching__quantity', 'union', + 'direct_buying', + 'free_sale_in_province', + 'export').values( + 'key', 'poultry', 'remain_quantity', + 'send_date', + 'hatching__date', + 'create_date', 'order_code', + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__user__city__name', + 'hatching__quantity', + 'quantity', + 'hatching__left_over', + 'hatching__chicken_breed', 'poultry__address__province__name', 'Index_weight', 'amount', 'hatching__quantity', + 'union', 'direct_buying', 'free_sale_in_province', 'freezing', 'export').order_by( + '-send_date') + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_poultry_reqs = filtered_poultry_request.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_reqs = filtered_poultry_request.filter(poultry__user__city=user.city) + else: + filtered_poultry_reqs = filtered_poultry_request + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_reqs) + filtered_poultry_reqs = ps.filter() + + excel_options = [ + 'ردیف', 'کد سفارش', 'نام واحد', 'نام و نام خانوادگی مرغدار', 'موبایل', 'آدرس', 'تاریخ جوجه ریزی', + 'تعداد کل جوجه ریزی', 'سن مرغ', 'تعداد درخواست کشتار', 'وزن درخواست کشتار', 'میانگین وزنی', 'فروش', + 'کشتار', 'قیمت مرغ زنده', 'تعداد تخصیصی به خریدار', 'مانده قابل تخصیص', 'تعداد قطعه باقی مانده در سالن', + 'نژاد', 'تاریخ درخواست کشتار', 'دامپزشک فارم', 'تلفن دامپزشک فارم', 'وضعیت درخواست', 'خریدار', + 'تعداد تخصیصی قطعه', 'وزن تخصیصی', 'تاریخ تخصیص', 'نوع تخصیص', 'آدرس', 'محل کشتار', 'وضعییت تخصیص به خریدار', + 'تعداد بار ایجاد شده', 'تعداد قطعه تخصیصی به بار', 'وزن تخصیصی به بار', 'مانده قطعه قابل تخصیص', + 'مانده وزن قابل تخصیص', 'ماشین', 'راننده', 'تلفن', 'کد بهداشتی حمل و نقل', 'کد رهگیری سامانه قرنطینه', + 'تعداد ثبت شده در قرنطینه', 'تعداد قطعه بار', 'وزن بار', 'وضعیت بار', 'تعداد تخلیه', 'وزن تخلیه', + 'تاریخ تخلیه کشتارگاه', 'دامپزشک کشتارگاه', 'تلفن دامپزشک کشتارگاه', 'اطلاعات تکمیلی قطعه', + 'اطلاعات تکمیلی وزن', 'کاربر کشتارگاه', 'تلفن کاربرکشتارگاه', + ] + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد درخواست های کشتار', 'مجموع قطعه درخواست های کشتار', 'مجموع وزن درخواست های کشتار', + 'تعداد تخصیص به خریداران', 'تعداد قطعه تخصیصی به خریداران', 'وزن تخصیصی به خریداران', + 'مانده قابل تخصیص', 'تعداد بار ایجاد شده', 'تعداد قطعه بار های ایجاد شده', + 'وزن بارهای ایجاد شده', 'تعداد قطعه قابل تخصیص به بار', 'تعداد بارهای دارای کد قرنطینه', + 'مجموع تعداد قطعه ثبت شده در قرنطینه', 'تعداد بارهای تخلیه شده', 'تعداد قطعه بارهای تخلیه شده', + 'وزن بارهای تخلیه شده', 'تعداد بار های تکمیل شده', 'تعداد قطعه بارهای تکمیل شده', + 'وزن بارهای تکمیل شده', + ] + + # برای بالای هدر + + create_header(worksheet, header_list, 4, 2, 21, 16.01) + + if filtered_poultry_reqs.exists(): + province = filtered_poultry_reqs.first()['poultry__address__province__name'] + excel_description(worksheet, 'A2', f' استان {province}', color='red') + + excel_description(worksheet, 'A1', 'گزارش روند پرونده های کشتار مرغ گوشتی', size=11, color='red', row2='C1') + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + bar_list2 = 0 + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request__key__in=filtered_poultry_reqs.values('key'), + trash=False, return_to_province=False, state__in=('pending', 'accepted')).select_related( + 'kill_request__kill_house', 'killhouse_user__kill_house_operator', + 'killhouse_user__kill_house_operator__user', 'killhouse_user__kill_house_operator__address', + 'killhouse_user').only('kill_request__slaughter_house', 'kill_request__slaughter_house__name', 'state', + 'key', 'create_date', + 'kill_request__kill_house', 'main_quantity', 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', 'killhouse_user__killer', + 'province_request__poultry_request__Index_weight', 'quantity', + 'province_request__poultry_request__union', + 'province_request__poultry_request__direct_buying', ).values( + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', 'key', 'create_date', + 'kill_request__kill_house', + 'main_quantity', + 'killhouse_user__name', + 'killhouse_user__killer', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', + 'province_request__poultry_request__Index_weight', + 'province_request__poultry_request__union', + 'province_request__poultry_request__direct_buying', + 'state', 'quantity') + + kill_house_requestss = KillHouseRequest.objects.filter( + province_kill_request__key__in=province_kill_requests.values('key'), + trash=False).select_related('add_car__driver', + 'killhouse_user').only( + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__user__fullname', 'killhouse_user', + 'province_kill_request__province_request__poultry_request__Index_weight', 'key', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'traffic_code', 'create_date', + 'clearance_code', + 'killhouse_user__killer', + 'accepted_real_quantity', 'accepted_real_weight', + 'quantity', 'province_request__poultry_request__Index_weight', 'vet_state', + 'assignment_state_archive', 'vet_accepted_real_weight', 'vet_accepted_real_quantity', + 'vet_state', 'accepted_real_weight', 'accepted_assignment_real_weight', + 'accepted_assignment_real_quantity').values('vet_state', 'vet_accepted_real_weight', + 'vet_accepted_real_quantity', + 'quarantine_quantity', 'vet_state', 'assignment_state_archive', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'key', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'traffic_code', + 'create_date', + 'clearance_code', + 'killhouse_user__killer', + 'accepted_real_quantity', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user', + 'accepted_real_weight', + 'killhouse_user__kill_house_operator__user__mobile', + 'quantity', 'quarantine_quantity', + 'province_request__poultry_request__Index_weight', + 'accepted_real_weight', 'accepted_assignment_real_weight', + 'accepted_assignment_real_quantity') + poultry_ids = [req.get('poultry') for req in filtered_poultry_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + for filtered_poultry_req in filtered_poultry_reqs: + + state_p = 'در انتظار تخصیص استان' + if filtered_poultry_req.get('quantity') != filtered_poultry_req.get('remain_quantity'): + state_p = 'تخصیص داده شد' + vet_farm_id = filtered_poultry_req.get('poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + + age = (filtered_poultry_req.get('send_date').date() - filtered_poultry_req.get( + "hatching__date").date()).days + 1 + gregorian_date = convert_to_shamsi(day=filtered_poultry_req.get("hatching__date").day, + month=filtered_poultry_req.get("hatching__date").month, + year=filtered_poultry_req.get("hatching__date").year + ) + date_of_kill = convert_to_shamsi(day=filtered_poultry_req.get('create_date').day, + month=filtered_poultry_req.get('create_date').month, + year=filtered_poultry_req.get('create_date').year) + + if filtered_poultry_req['free_sale_in_province'] == False: + + sale_type = 'دولتی' + elif filtered_poultry_req['export']: + sale_type = 'صادرات' + + else: + sale_type = 'آزاد' + + province_kill_reqs = province_kill_requests.filter( + province_request__poultry_request__key=filtered_poultry_req.get('key')) + freez_state = 'منجمد' if filtered_poultry_req['freezing'] == True else 'عادی' + list1 = [ + m, + str(filtered_poultry_req.get('order_code')), + filtered_poultry_req.get('poultry__unit_name'), + filtered_poultry_req.get('poultry__user__fullname'), + filtered_poultry_req.get('poultry__user__mobile'), + filtered_poultry_req.get('poultry__user__city__name'), + str(gregorian_date), + filtered_poultry_req.get('hatching__quantity'), + str(age), + filtered_poultry_req.get('quantity'), + int(filtered_poultry_req.get('quantity') * filtered_poultry_req.get('Index_weight')), + filtered_poultry_req.get('Index_weight'), + sale_type, + freez_state, + filtered_poultry_req.get('amount'), + filtered_poultry_req.get('quantity') - filtered_poultry_req.get('remain_quantity'), + filtered_poultry_req.get('remain_quantity'), + filtered_poultry_req.get('hatching__left_over'), + + filtered_poultry_req.get('hatching__chicken_breed'), + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=20) + + state_s = 'در انتظار تخصیص استان' + m += 1 + + if province_kill_reqs.exists(): + quantity_kill_house_request = kill_house_requestss.filter(province_request__poultry_request__key= + filtered_poultry_req['key']) + + if len(province_kill_reqs) > 1: + if len(quantity_kill_house_request) <= 1: + s = len(province_kill_reqs) - 1 + merge_cells(worksheet, l, s, cell1='A', cell2='V') + + # TODO : جایی که باید انجام بشه + if quantity_kill_house_request.exists(): + if len(quantity_kill_house_request) > 1: + s = len(quantity_kill_house_request) - 1 + merge_cells(worksheet, l, s, cell1='A', cell2='V') + + for province_kill_req in province_kill_reqs: + + if province_kill_req['state'] == 'pending': + state_s = 'درانتظار تایید' + + elif province_kill_req['state'] == 'accepted': + state_s = ' تایید شده' + elif province_kill_req['state'] == 'rejected': + state_s = 'رد شده' + + date_of_inner_bar = '-' + + code = '-' + + time = convert_to_shamsi(day=province_kill_req.get('create_date').day, + month=province_kill_req.get('create_date').month, + year=province_kill_req.get('create_date').year) + + if province_kill_req.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + else: + killers = 'کشتارکن' + + kill_house_requests = kill_house_requestss.filter( + province_kill_request__key=province_kill_req['key']) + + all_quantity_of_bar = kill_house_requests.aggregate( + total_quantity=Sum('quantity'))['total_quantity'] or 0 + + bar_weight = int(all_quantity_of_bar * province_kill_req[ + 'province_request__poultry_request__Index_weight']) if all_quantity_of_bar > 0 else 0 + remain_province = int(province_kill_req.get('quantity') * province_kill_req[ + 'province_request__poultry_request__Index_weight']) + + if province_kill_req['province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif province_kill_req[ + 'province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + + slaughter_house__name = province_kill_req.get( + 'kill_request__slaughter_house__name') if province_kill_req.get( + 'kill_request__slaughter_house') is not None else '-' + list1 = [ + state_p, + killers + '(' + province_kill_req.get('killhouse_user__name') + ')', + province_kill_req.get('main_quantity'), + int(province_kill_req.get('main_quantity') * province_kill_req.get( + 'province_request__poultry_request__Index_weight')), + str(time), + type, + province_kill_req.get('killhouse_user__kill_house_operator__address__city__name'), + slaughter_house__name, + state_s, + len(kill_house_requests), + all_quantity_of_bar, + bar_weight, + province_kill_req.get('quantity'), + remain_province, + ] + + create_value(worksheet, list1, l, 23, border_style='thin', m=m - 1, height=20) + + if kill_house_requests.exists(): + + if len(kill_house_requests) > 1: + s = len(kill_house_requests) - 1 + + letters = ["W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG", "AH", "AI", "AJ"] + merge_cells(worksheet, l, s, lst=letters) + + for kill_house_request in kill_house_requests: + + bar_list2 += 1 + kil_house_vet = KillHouseVet.objects.filter( + kill_house=kill_house_request.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + if (kill_house_request['assignment_state_archive'] == 'True' and kill_house_request[ + 'vet_state'] == 'pending') or kill_house_request[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + all_quantity_of_bar += kill_house_request['quantity'] + vet_quantity = kill_house_request['vet_accepted_real_quantity'] + vet_wight = kill_house_request['vet_accepted_real_weight'] + kill_house_driver_name = kill_house_request.get('add_car__driver__driver_name') + kill_house_driver_mobile = kill_house_request.get('add_car__driver__driver_mobile') + kill_house_driver_type_car = kill_house_request.get('add_car__driver__type_car') + kill_house_traffic_code = kill_house_request.get('traffic_code') + vet_checks = VetCheckRequest.objects.filter( + kill_house_request__key=kill_house_request.get('key')).only( + 'create_date').values('create_date').first() + + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill_house_request.get('key')).only('real_quantity', + 'net_weight', + 'create_date').values( + 'real_quantity', 'net_weight', 'create_date').first() + if assignment: + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + if kill_house_request.get('clearance_code'): + code = kill_house_request.get('clearance_code') + + quarantine_quantity = kill_house_request['quarantine_quantity'] if kill_house_request[ + 'quarantine_quantity'] else '-' + + list1 = [ + kill_house_driver_type_car, + kill_house_driver_name, + kill_house_driver_mobile, + kill_house_traffic_code, + code, + quarantine_quantity, + kill_house_request['quantity'], + int(kill_house_request['accepted_real_weight']), + state, + vet_quantity, + vet_wight, + str(date_of_inner_bar), + kill_house_vet_name, + kill_house_vet_mobile, + kill_house_request['accepted_assignment_real_quantity'], + int(kill_house_request['accepted_assignment_real_weight']), + kill_house_request['killhouse_user__kill_house_operator__user__fullname'], + kill_house_request['killhouse_user__kill_house_operator__user__mobile'], + ] + create_value(worksheet, list1, l, 37, border_style='thin', m=m - 1) + l += 1 + else: + list1 = ['-'] * 18 + create_value(worksheet, list1, l, 37, border_style='thin', m=m - 1) + l += 1 + + + else: + list1 = ['-'] * 32 + create_value(worksheet, list1, l, 23, border_style='thin', m=m - 1) + l += 1 + + aggregates = filtered_poultry_reqs.aggregate( + total_quantity=Sum('quantity'), + total_remain_quantity=Sum('remain_quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')), + total_hatching=Sum('hatching__quantity'), + total_left_over=Sum('hatching__left_over'), + ) + all_poultry_request = aggregates['total_quantity'] or 0 + all_remain_quantity = aggregates['total_remain_quantity'] or 0 + all_wight = aggregates['total_weight'] or 0 + all_hatching = aggregates['total_hatching'] or 0 + all_hatching_left_over = aggregates['total_left_over'] or 0 + sum_province_to_kill_house = all_poultry_request - all_remain_quantity + + aggregates_province_kill_req = province_kill_requests.aggregate( + total_main_quantity=Sum('main_quantity'), + total_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight')), + total_quantity=Sum('quantity') + ) + all_main_quantity = aggregates_province_kill_req['total_main_quantity'] or 0 + all_wight_killer = aggregates_province_kill_req['total_weight'] or 0 + sum_all_remain_quantity_of_bar = aggregates_province_kill_req['total_quantity'] or 0 + + bar_list = len(kill_house_requestss) + aggregates_kill_req = kill_house_requestss.aggregate( + total_quantity=Sum('quantity'), + total_weight=Sum('quantity'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + ) + + sum_all_quantity_of_bar = aggregates_kill_req['total_quantity'] or 0 + sum_all_weight_of_bar = aggregates_kill_req['total_weight'] or 0 + all_qarantine = aggregates_kill_req['total_quarantine_quantity'] or 0 + all_kill_house_request_has_qarantite = len(kill_house_requestss.filter(clearance_code__isnull=False)) + all_vet_quantity = aggregates_kill_req['total_vet_accepted_real_quantity'] or 0 + all_vet_wight = aggregates_kill_req['total_vet_accepted_real_weight'] or 0 + + all_assigment = kill_house_requestss.filter(assignment_state_archive='True') + + vet_state_accepted = len(kill_house_requestss.filter(vet_state='accepted')) + + all_assignment_quantity = all_assigment.aggregate( + total_quantity=Sum('accepted_assignment_real_quantity'))['total_quantity'] or 0 + + all_assignment_weight = all_assigment.aggregate( + total_quantity=Sum('accepted_assignment_real_weight'))['total_quantity'] or 0 + all_reamin_province = sum_all_remain_quantity_of_bar + + value_header_list = [ + len(filtered_poultry_reqs), + all_poultry_request, + all_wight, + len(province_kill_requests), + all_main_quantity, + all_wight_killer, + all_remain_quantity, + bar_list, + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + sum_all_remain_quantity_of_bar, + all_kill_house_request_has_qarantite, + all_qarantine, + vet_state_accepted, + all_vet_quantity, + all_vet_wight, + len(all_assigment), + all_assignment_quantity, + all_assignment_weight, + + ] + create_value(worksheet, value_header_list, 3, 4) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + all_hatching, + '', + all_poultry_request, + all_wight, + '', + '', + '', + '', + sum_province_to_kill_house, + all_remain_quantity, + all_hatching_left_over, + '', + '', + '', + '', + '', + '', + all_main_quantity, + all_wight_killer, + '', + '', + '', + '', + '', + '', + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + sum_all_remain_quantity_of_bar, + all_reamin_province, + '', + '', + '', + '', + '', + all_qarantine, + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + '', + all_vet_quantity, + all_vet_wight, + '', + '', + '', + all_assignment_quantity, + all_assignment_weight, + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="روند پرونده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def transacion_out_request_excel(request): + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_fullname', + 'payer_mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name', + 'user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'out_province_poultry_request_buyer__user__fullname', + 'out_province_poultry_request_buyer__user__first_name', + 'out_province_poultry_request_buyer__user__last_name', + 'out_province_poultry_request_buyer__user__mobile', + + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['type'] == 'poultry': + transactions = InternalTransaction.objects.filter( + payer_type='poultry', + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + type_transactions = 'مرغدار' + + else: + transactions = InternalTransaction.objects.filter( + payer_type='buyer', + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + type_transactions = 'خریدار' + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = filterset_class(data=query, queryset=transactions) + transactions = ps.filter() + excel_options = [ + 'ردیف', + 'کد سفارش', + 'پرداخت کننده', + 'تلفن پرداخت کننده', + 'تاریخ پرداخت', + 'مبلغ کل تراکنش(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + 'سهم صنف(ریال)', + 'سهم دیگر(ریال)', + 'شماره پیگیری', + 'شماره سفارش', + ] + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد تراکنش ها', + 'مبلغ کل(ریال)', + 'سهم اتحادیه(ریال)', + 'سهم شرکت(ریال)', + 'سهم صنف(ریال)', + 'سهم دیگر(ریال)', + ] + + # برای بالای هدر + + create_header(worksheet, header_list, 4, 2, 21, 16.01) + + excel_description(worksheet, 'A1', f'تراکنش های خارج از استان {type_transactions}', size=11, color='red', row2='C1') + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + new_row = 7 + for transaction in transactions: + if transaction.kill_house != None: + fullname = transaction.kill_house.kill_house_operator.user.fullname + mobile = transaction.kill_house.kill_house_operator.user.mobile + elif transaction.out_province_poultry_request_buyer != None: + fullname = transaction.out_province_poultry_request_buyer.user.fullname + mobile = transaction.out_province_poultry_request_buyer.user.mobile + elif transaction.chain_company != None: + fullname = transaction.chain_company.user.fullname + mobile = transaction.chain_company.user.mobile + + else: + fullname = transaction.user.fullname + mobile = transaction.user.mobile + + order_codes = transaction.poultry_request.filter(trash=False) + + if order_codes: + + for order in order_codes: + + list11 = [ + m, + str(order.order_code), + ] + create_value(worksheet, list11, new_row, 1, m=m, border_style='thin', height=25) + + if len(order_codes) > 1: + merge_cells(worksheet, l, len(order_codes) - 1, cell1='C', cell2='L') + print(l) + list1 = [ + fullname, + mobile, + str(convert_to_shamsi(datetime=transaction.date)), + transaction.amount, + transaction.union_share, + transaction.company_share, + transaction.guilds_share, + transaction.other_share, + str(transaction.refId), + str(transaction.orderId), + + ] + create_value(worksheet, list1, l, 3, m=m, border_style='thin', height=25) + m += 1 + new_row = new_row + 1 + + + + else: + list1 = [ + m, + '-', + fullname, + mobile, + str(convert_to_shamsi(datetime=transaction.date)), + transaction.amount, + transaction.union_share, + transaction.company_share, + transaction.guilds_share, + transaction.other_share, + str(transaction.refId), + str(transaction.orderId), + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=20) + m += 1 + l += len(order_codes) + + all_amount = \ + transactions.aggregate( + total=Sum('amount'))[ + 'total'] or 0 + all_union_share = \ + transactions.aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + all_company_share = \ + transactions.aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + all_guilds_share = \ + transactions.aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + all_other_share = \ + transactions.aggregate( + total=Sum('other_share'))[ + 'total'] or 0 + value_header_list = [ + len(transactions), + all_amount, + all_union_share, + all_company_share, + all_guilds_share, + all_other_share + + ] + create_value(worksheet, value_header_list, 3, 4) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + all_amount, + all_union_share, + all_company_share, + all_guilds_share, + all_other_share, + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" تراکنش های خارج استان {type_transactions} .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def from_allocation_to_distribution_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_houses = KillHouse.objects.filter(trash=False, active=True).order_by('id') + province_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), + return_to_province=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + kill_house_requests = KillHouseRequest.objects.filter( + province_kill_request__key__in=province_requests.values('key'), + trash=False) + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + date__date__gte=date1, date__date__lte=date2, + trash=False) + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + kill_house_free_bars = KillHouseFreeSaleBarInformation.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2) + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + sheet_name = 'اطلاعات کلی' + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + worksheet = workbook.create_sheet(sheet_name) + + killhouse_user = kill_house_requests.values_list('killhouse_user__id', flat=True).distinct() + if sheet_name == 'اطلاعات کلی': + excel_options = [ + 'ردیف', + 'نام واحد', + 'مالک', + 'تلفن مالک', + 'ماهیت', + 'تعداد سفارشات', + 'حجم سفارشات', + 'وزن سفارشات', + 'تعداد تخصیصات دولتی', + 'حجم تخصیصات دولتی', + 'وزن تخصیصات دولتی', + ' میانگین وزن تخصیصات دولتی', + ' تعداد تخصیصات آزاد', + 'حجم تخصیصات آزاد', + ' وزن تخصیصات آزاد', + ' میانگین وزن تخصیصات آزاد', + + 'تعداد خرید مستقیم', + 'حجم خرید مستقیم', + 'وزن خرید مستقیم', + ' میانگین وزن خرید مستقیم', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + ' میانگین وزن بار ایجاد شده', + 'تعداد بار تخلیه شده', + 'حجم بار تخلیه شده', + 'وزن بار تخلیه شده', + ' میانگین وزن بار تخلیه شده', + 'تعداد بار ورودی به انبار', + 'حجم تقریبی بار ورودی به انبار', + 'وزن بار ورودی به انبار', + ' میانگین وزن بار ورودی به انبار', + 'تعداد توزیع درون استان', + 'حجم تقریبی توزیع درون استان', + 'وزن توزیع درون استان', + ' میانگین وزن توزیع درون استان', + 'تعداد توزیع خارج استان', + 'حجم تقریبی توزیع خارج استان', + 'وزن توزیع خارج استان', + ' میانگین وزن توزیع خارج استان', + + 'حجم تقریبی مانده در انبار', + 'وزن مانده در انبار', + ' میانگین وزن مانده در انبار', + + ] + header_list = [ + 'ردیف', + 'نام واحد', + 'مالک', + 'تلفن مالک', + 'ماهیت', + 'تعداد سفارشات', + 'حجم سفارشات', + 'وزن سفارشات', + 'میانگین وزن سفارشات', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + + 'تعداد بار ورودی به انبار', + 'حجم تقریبی بار ورودی به انبار', + 'وزن بار ورودی به انبار', + 'تعداد توزیع درون استان', + 'حجم تقریبی توزیع درون استان', + 'وزن توزیع درون استان', + 'تعداد توزیع خارج استان', + 'حجم تقریبی توزیع خارج استان', + 'وزن توزیع خارج استان', + + 'حجم تقریبی مانده در انبار', + 'وزن مانده در انبار', + ] + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 4, 2, 21, 16.01, color='blue') + province = kill_houses.first().kill_house_operator.user.province.name + excel_description(worksheet, 'A1', f' گزارش عملکرد خریداران استان {province}', size=11, color='red', row2='C1') + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + header_row = 3 + l = 3 + excel_description(worksheet, 'I1', 'اطلاعات کلی کشتار', color='red', row2='K1') + all_len_province_kill_request = 0 + all_quantity_province_kill_request = 0 + all_weight_province_kill_request = 0 + for kill_house in kill_houses: + cell_color_changer(worksheet, l, 5, 8, 'FBFEE2') + percentage = KillHousePercentage.objects.filter(kill_house=kill_house).select_related( + 'kill_house_for_killer', + 'kill_house').first() + if percentage: + if percentage.kill_house_for_killer != None: + place = percentage.kill_house_for_killer.name + else: + place = percentage.kill_house.name + else: + place = kill_house.name + killer_type = 'کشتارگاه' + if kill_house.killer == True: + type = 'کشتارکن' + if kill_house.type == 'public': + killer_type = f'{type} عمومی ' + else: + killer_type = f' {type} اختصاصی ({place})' + + # all + province_kill_request = province_requests.filter(killhouse_user=kill_house) + + # goveerment + province_kill_request_goverment = province_kill_request.filter( + province_request__poultry_request__free_sale_in_province=False) + quantity_province_kill_request_goverment = \ + province_kill_request_goverment.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_goverment = \ + province_kill_request_goverment.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + # cell_color_changer(worksheet, l, 9, 13, 'EBF1DE') + # free + province_kill_request_free = province_kill_request.filter( + province_request__poultry_request__free_sale_in_province=True) + quantity_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + # cell_color_changer(worksheet, l, 13, 17, 'DDD9C4') + # direct_buying + province_kill_request_direct_buying = province_kill_request.filter( + province_request__poultry_request__direct_buying=True) + quantity_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + # cell_color_changer(worksheet, l, 17, 21, 'C5D9F1') + # all + len_province_kill_request = len(province_kill_request_goverment) + \ + len(province_kill_request_free) + len(province_kill_request_direct_buying) + quantity_province_kill_request = quantity_province_kill_request_goverment + quantity_province_kill_request_free + \ + quantity_province_kill_request_direct_buying + + weight_province_kill_request = weight_province_kill_request_goverment + weight_province_kill_request_free + \ + weight_province_kill_request_direct_buying + # cell_color_changer(worksheet, l, 6, 9, 'C5D9F1') + # all_len_province_kill_request += len_province_kill_request + # all_quantity_province_kill_request += quantity_province_kill_request + # all_weight_province_kill_request += weight_province_kill_request + # bar + kill_house_request = kill_house_requests.filter(Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) | Q(killer=kill_house))) + + kill_house_request = kill_house_request.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)) + quantity_kill_house_request = \ + kill_house_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + weight_kill_house_request = \ + kill_house_request.aggregate( + total=Sum(F('quantity') * F('province_request__poultry_request__Index_weight')))[ + 'total'] or 0 + cell_color_changer(worksheet, l, 13, 16, 'D8E4BC') + + # ware_house_confirmation + ware_house_confirmation = kill_house_request.filter(ware_house_confirmation=True) + quantity_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + weight_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + cell_color_changer(worksheet, l, 16, 19, 'E6B8B7') + # in_province + kill_house_ware_house = kill_house_ware_houses.filter(kill_house=kill_house) + steward_allocation = steward_allocations.filter(ware_house__in=kill_house_ware_house) + total_allocated_quantity = \ + steward_allocation.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight = \ + steward_allocation.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + # cell_color_changer(worksheet, l, 19, 22, 'EBF1DE') + # out_province + kill_house_free_bar = kill_house_free_bars.filter(kill_house=kill_house) + total_quantity = kill_house_free_bar.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = kill_house_free_bar.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + cell_color_changer(worksheet, l, 22, 25, '95B3D7') + # remain_ + + total_remain_quantity = \ + kill_house_ware_house.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + total_remain_weight = \ + kill_house_ware_house.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + cell_color_changer(worksheet, l, 25, 27, 'DA9694') + value_header_list = [ + m, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + killer_type, + len_province_kill_request, + quantity_province_kill_request, + weight_province_kill_request, + str(round(weight_province_kill_request / quantity_province_kill_request, + 1) if weight_province_kill_request > 0 else 0), + len(kill_house_request), + quantity_kill_house_request, + weight_kill_house_request, + + len(ware_house_confirmation), + quantity_kill_house_request_ware_house, + weight_kill_house_request_ware_house, + + len(steward_allocation), + total_allocated_quantity, + total_allocated_weight, + + len(kill_house_free_bar), + total_quantity, + total_weight, + + total_remain_quantity, + total_remain_weight, + + ] + create_value(worksheet, value_header_list, l, 4, border_style='thin') + l += 1 + header_row += 1 + m += 1 + l += 3 + create_header_freez(worksheet, excel_options, 1, l, l + 1, 20) + m = 1 + excel_description(worksheet, f'I{l - 1}', 'جزئیات کشتار', color='red', row2=f'K{l - 1}') + for kill_house in kill_houses: + percentage = KillHousePercentage.objects.filter(kill_house=kill_house).select_related( + 'kill_house_for_killer', + 'kill_house').first() + if percentage: + if percentage.kill_house_for_killer != None: + place = percentage.kill_house_for_killer.name + else: + place = percentage.kill_house.name + else: + place = kill_house.name + killer_type = 'کشتارگاه' + if kill_house.killer == True: + type = 'کشتارکن' + if kill_house.type == 'public': + killer_type = f'{type} عمومی ' + else: + killer_type = f' {type} اختصاصی ({place})' + + # all + province_kill_request = province_requests.filter(killhouse_user=kill_house) + + # goveerment + province_kill_request_goverment = province_kill_request.filter( + province_request__poultry_request__free_sale_in_province=False) + quantity_province_kill_request_goverment = \ + province_kill_request_goverment.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_goverment = \ + province_kill_request_goverment.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 9, 13, 'EBF1DE') + # free + province_kill_request_free = province_kill_request.filter( + province_request__poultry_request__free_sale_in_province=True) + quantity_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 13, 17, 'DDD9C4') + # direct_buying + province_kill_request_direct_buying = province_kill_request.filter( + province_request__poultry_request__direct_buying=True) + quantity_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 17, 21, 'C5D9F1') + # all + len_province_kill_request = len(province_kill_request_goverment) + \ + len(province_kill_request_free) + len(province_kill_request_direct_buying) + quantity_province_kill_request = quantity_province_kill_request_goverment + quantity_province_kill_request_free + \ + quantity_province_kill_request_direct_buying + + weight_province_kill_request = weight_province_kill_request_goverment + weight_province_kill_request_free + \ + weight_province_kill_request_direct_buying + cell_color_changer(worksheet, l + 1, 6, 9, 'C5D9F1') + all_len_province_kill_request += len_province_kill_request + all_quantity_province_kill_request += quantity_province_kill_request + all_weight_province_kill_request += weight_province_kill_request + # bar + kill_house_request = kill_house_requests.filter(Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + Q(killer__isnull=True) | Q(killer=kill_house))) + + kill_house_request = kill_house_request.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)) + quantity_kill_house_request = \ + kill_house_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + weight_kill_house_request = \ + kill_house_request.aggregate( + total=Sum(F('quantity') * F('province_request__poultry_request__Index_weight')))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 21, 25, 'EBF1DE') + # assignment_state_archive + assignment_state_archive = kill_house_request.filter(assignment_state_archive='True') + quantity_kill_house_request_assignment = \ + assignment_state_archive.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + weight_kill_house_request_assignment = \ + assignment_state_archive.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 25, 29, 'DDD9C4') + # ware_house_confirmation + ware_house_confirmation = kill_house_request.filter(ware_house_confirmation=True) + quantity_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + weight_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + cell_color_changer(worksheet, l + 1, 29, 33, 'C5D9F1') + # in_province + kill_house_ware_house = kill_house_ware_houses.filter(kill_house=kill_house) + steward_allocation = steward_allocations.filter(ware_house__in=kill_house_ware_house) + total_allocated_quantity = \ + steward_allocation.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight = \ + steward_allocation.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 33, 37, 'EBF1DE') + # out_province + kill_house_free_bar = kill_house_free_bars.filter(kill_house=kill_house) + total_quantity = kill_house_free_bar.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = kill_house_free_bar.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 37, 41, 'DDD9C4') + # remain_ + + total_remain_quantity = \ + kill_house_ware_house.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + total_remain_weight = \ + kill_house_ware_house.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + cell_color_changer(worksheet, l + 1, 41, 44, 'C5D9F1') + list1 = [ + m, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + killer_type, + len_province_kill_request, + quantity_province_kill_request, + weight_province_kill_request, + + len(province_kill_request_goverment), + quantity_province_kill_request_goverment, + weight_province_kill_request_goverment, + str(round(weight_province_kill_request_goverment / quantity_province_kill_request_goverment, + 1) if weight_province_kill_request_goverment > 0 else 0), + len(province_kill_request_free), + quantity_province_kill_request_free, + weight_province_kill_request_free, + str(round(weight_province_kill_request_free / quantity_province_kill_request_free, + 1) if weight_province_kill_request_free > 0 else 0), + len(province_kill_request_direct_buying), + quantity_province_kill_request_direct_buying, + weight_province_kill_request_direct_buying, + str(round(weight_province_kill_request_direct_buying / quantity_province_kill_request_direct_buying, + 1) if weight_province_kill_request_direct_buying > 0 else 0), + len(kill_house_request), + quantity_kill_house_request, + weight_kill_house_request, + str(round(weight_kill_house_request / quantity_kill_house_request, + 1) if weight_kill_house_request > 0 else 0), + len(assignment_state_archive), + quantity_kill_house_request_assignment, + weight_kill_house_request_assignment, + str(round(weight_kill_house_request_assignment / quantity_kill_house_request_assignment, + 1) if weight_kill_house_request_assignment > 0 else 0), + len(ware_house_confirmation), + quantity_kill_house_request_ware_house, + weight_kill_house_request_ware_house, + str(round(weight_kill_house_request_ware_house / quantity_kill_house_request_ware_house, + 1) if weight_kill_house_request_ware_house > 0 else 0), + len(steward_allocation), + total_allocated_quantity, + total_allocated_weight, + str(round(total_allocated_weight / total_allocated_quantity, + 1) if total_allocated_weight > 0 else 0), + len(kill_house_free_bar), + total_quantity, + total_weight, + str(round(int(total_weight) / total_quantity, + 1) if total_weight > 0 and total_quantity > 0 else 0), + total_remain_quantity, + total_remain_weight, + str(round(total_remain_weight / total_remain_quantity, + 1) if total_remain_weight > 0 else 0), + + ] + create_value(worksheet, list1, l + 1, 1, border_style='thin', height=25) + + m += 1 + + l += 1 + province_kill_request_goverment1 = province_requests.filter( + province_request__poultry_request__free_sale_in_province=False) + quantity_province_kill_request_goverment = \ + province_kill_request_goverment1.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_goverment = \ + province_kill_request_goverment1.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_kill_request_free = province_requests.filter( + province_request__poultry_request__free_sale_in_province=True) + quantity_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_free = \ + province_kill_request_free.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_kill_request_direct_buying = province_requests.filter( + province_request__poultry_request__direct_buying=True) + quantity_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + weight_province_kill_request_direct_buying = \ + province_kill_request_direct_buying.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + quantity_kill_house_request = \ + kill_house_requests.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + weight_kill_house_request = \ + kill_house_requests.aggregate( + total=Sum(F('quantity') * F('province_request__poultry_request__Index_weight')))[ + 'total'] or 0 + # assignment_state_archive + assignment_state_archive = kill_house_requests.filter(assignment_state_archive='True') + quantity_kill_house_request_assignment = \ + assignment_state_archive.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + weight_kill_house_request_assignment = \ + assignment_state_archive.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + ware_house_confirmation = kill_house_requests.filter(ware_house_confirmation=True) + quantity_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + weight_kill_house_request_ware_house = \ + ware_house_confirmation.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_quantity = kill_house_free_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = kill_house_free_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] or 0 + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] or 0 + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + all_len_province_kill_request, + all_quantity_province_kill_request, + all_weight_province_kill_request, + len(province_kill_request_goverment1), + quantity_province_kill_request_goverment, + weight_province_kill_request_goverment, + str(round(weight_province_kill_request_goverment / quantity_province_kill_request_goverment, + 1) if weight_province_kill_request_goverment > 0 else 0), + len(province_kill_request_free), + quantity_province_kill_request_free, + weight_province_kill_request_free, + str(round(weight_province_kill_request_free / quantity_province_kill_request_free, + 1) if weight_province_kill_request_free > 0 else 0), + len(province_kill_request_direct_buying), + quantity_province_kill_request_direct_buying, + weight_province_kill_request_direct_buying, + str(round(weight_province_kill_request_direct_buying / quantity_province_kill_request_direct_buying, + 1) if weight_province_kill_request_direct_buying > 0 else 0), + len(kill_house_requests), + quantity_kill_house_request, + weight_kill_house_request, + str(round(weight_kill_house_request / quantity_kill_house_request, + 1) if weight_kill_house_request > 0 else 0), + len(assignment_state_archive), + quantity_kill_house_request_assignment, + weight_kill_house_request_assignment, + str(round(weight_kill_house_request_assignment / quantity_kill_house_request_assignment, + 1) if weight_kill_house_request_assignment > 0 else 0), + len(ware_house_confirmation), + quantity_kill_house_request_ware_house, + weight_kill_house_request_ware_house, + str(round(weight_kill_house_request_ware_house / quantity_kill_house_request_ware_house, + 1) if weight_kill_house_request_ware_house > 0 else 0), + len(steward_allocations), + total_allocated_quantity, + total_allocated_weight, + str(round(total_allocated_weight / total_allocated_quantity, + 1) if total_allocated_weight > 0 else 0), + len(kill_house_free_bars), + total_quantity, + total_weight, + str(round(total_weight / total_quantity, + 1) if total_weight > 0 else 0), + total_remain_quantity, + total_remain_weight, + str(round(total_remain_weight / total_remain_quantity, + 1) if total_remain_weight > 0 else 0), + + ] + create_value(worksheet, list2, l + 1, 1, color='green') + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + all_len_province_kill_request, + all_quantity_province_kill_request, + all_weight_province_kill_request, + str(round(all_weight_province_kill_request / all_quantity_province_kill_request, + 1) if all_weight_province_kill_request > 0 else 0), + + len(kill_house_requests), + quantity_kill_house_request, + weight_kill_house_request, + + len(ware_house_confirmation), + quantity_kill_house_request_ware_house, + weight_kill_house_request_ware_house, + + len(steward_allocations), + total_allocated_quantity, + total_allocated_weight, + + len(kill_house_free_bars), + total_quantity, + total_weight, + + total_remain_quantity, + total_remain_weight, + + ] + create_value(worksheet, list2, header_row - 1, 4, color='blue') + for kill_house_id in killhouse_user: + kill_house = KillHouse.objects.get(trash=False, id=kill_house_id) + sheet_name = kill_house.name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + filtered_kill_reqs = kill_house_requests.filter( + killhouse_user=kill_house).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + 'کشور مقصد', + + ] + + from_date_1 = shamsi_date(date1) + + to_date_1 = shamsi_date(date2) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + header_list3 = [ + 'درصد بارهای دارای کد قرنطینه', + 'درصد تعداد بارهای احراز شده از قرنطینه', + 'درصد تعداد بارهای تکمیل شده کشتارگاه', + 'درصد وزن نهایی در کشتارگاه نسبت به وزن کل', + 'درصد بارهای فاقد کد قرنطینه', + 'درصد بارهای اختلاف دار در قرنطینه و رصدیار', + 'درصد تعداد بارهای ورودی به انبار', + 'درصد وزن لاشه ها در انبار نسبت به وزن کل', + 'درصد وزن لاشه در انبار نسبت به وزن نهایی در کشتارگاه', + + ] + create_header(worksheet, header_list, 9, 2, height=21.8) + + create_header(worksheet, header_list2, 6, 2, height=21.8, color='green') + + create_header(worksheet, header_list3, 6, 5, height=43, color='orange', text_color='0D0D0D') + create_header_freez(worksheet, excel_options, 1, 8, 9, height=21, len_with=True) + + excel_description(worksheet, 'B1', + f'گزارش بارهای ایجاد شده کشتارگاه {kill_house.name} در فرآیند کشتار مرغ گوشتی', color='red', + row2='E1') + + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + excel_description(worksheet, 'B2', f'استان {name}', color='red', row2='D2') + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + + l = 8 + m = 1 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs['total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 3, 6) + value_header_list2 = [ + f'%{round((has_code * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((has_qarantine * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((len(bar_complete) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_net_weighte) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((len(hasnt_code1) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((difference_bar * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((all_state_ware_house_confirmation * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_net_weighte), 2) if int(all_net_weighte) > 0 else 0}' + ] + create_value(worksheet, value_header_list2, 6, 6) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}', + '' + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" گزارش عملکرد خریداران.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def all_distribution_province(request): + sheet_names2 = [ + 'اطلاعات کلی', + 'تخصیصات کشتارگاه به مباشر و صنف', + 'تخصیصات مباشر به صنف', + # 'تخصیصات مباشر به مباشر', + 'تخصیصات صنف به صنف', + 'تخصیصات سرد خانه', + 'عملکرد مباشرین', + 'تراکنش های صنوف', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'اطلاعات کلی': + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'B2', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='E2') + excel_description(worksheet, 'B1', f'اطلاعات کلی', row2='E1') + header_list2 = [ + 'ماهیت', + 'اطلاعات فروشنده', + 'مانده در انبار قبل از توزیع', + 'وزن ورودی به انبار فروشنده ', + 'تعداد کل توزیع شده', + ' وزن کل خروجی از انبار (توزیع شده)', + 'کل وزن فروش به خارج از استان', + 'تعداد توزیع به مباشرین', + 'وزن توزیع به مباشرین', + 'تعداد توزیع به صنف', + 'وزن توزیع به صنف', + 'درصد توزیع فروشنده', + 'مانده انبار', + + ] + create_header(worksheet, header_list2, 3, 4, border_style='thin', width=20) + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + l = 5 + for kill_house in kill_houses: + if kill_house.killer == True and kill_house.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + killer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif kill_house.killer == True and kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + else: + killer_type = 'کشتارگاه' + if 'date1' in request.GET and request.GET['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() + kill_house_request = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, + calculate_status=True + , kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( + kill_house=kill_house, trash=False, + calculate_status=True, date__date__gte=date1, + date__date__lte=date2, ware_house=True) + allocations = StewardAllocation.objects.filter( + receiver_state__in=('pending', 'accepted'), + trash=False, date__date__gte=date1, + date__date__lte=date2, kill_house=kill_house).order_by('id') + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False, calculate_status=True, date__date__gte=date1, + date__date__lte=date2, ) + else: + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + + trash=False, calculate_status=True) + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter( + kill_house=kill_house, trash=False, + calculate_status=True, ware_house=True) + kill_house_request = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=True, trash=False, + calculate_status=True + ) + allocations = StewardAllocation.objects.filter( + trash=False, kill_house=kill_house, receiver_state__in=('pending', 'accepted')).order_by('id') + kill_house_to_stw = allocations.filter(allocation_type='killhouse_steward') + quantity_allocations = allocations.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + quantity_kill_house_free_sale_bars = kill_house_free_sale_bars.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + + weight_allocations = allocations.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + weight_kill_house_free_sale_bars = kill_house_free_sale_bars.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + quantity_kill_house_to_stw = kill_house_to_stw.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + weight_kill_house_to_stw = kill_house_to_stw.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + kill_house_to_guild = allocations.filter(allocation_type='killhouse_guild') + quantity_kill_house_to_guild = kill_house_to_guild.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + + weight_kill_house_to_guild = kill_house_to_guild.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + ware_house_accepted_real_weight = kill_house_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity') or 0 + + weight_of_carcasses = kill_house_free_buying_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + product = RolesProducts.objects.filter(trash=False, kill_house=kill_house).first() + if product: + total_remain_weight = product.total_remain_weight + else: + total_remain_weight = 0 + + list1 = [ + killer_type, + f"{kill_house.name}-{kill_house.kill_house_operator.user.mobile}-{kill_house.kill_house_operator.user.city.name}", + ((weight_allocations + weight_kill_house_free_sale_bars) - ( + ware_house_accepted_real_weight + weight_of_carcasses) + total_remain_weight), + ware_house_accepted_real_weight + weight_of_carcasses, + len(allocations), + weight_allocations + weight_kill_house_free_sale_bars, + weight_kill_house_free_sale_bars, + len(kill_house_to_stw), + weight_kill_house_to_stw, + len(kill_house_to_guild), + weight_kill_house_to_guild, + f"%{int((weight_allocations + weight_kill_house_free_sale_bars) * 100 / (ware_house_accepted_real_weight + weight_of_carcasses)) if (ware_house_accepted_real_weight + weight_of_carcasses) > 0 else 0}", + total_remain_weight + + ] + create_value(worksheet, list1, l, 3, border_style='thin', width=20) + l += 1 + l += 7 + create_header(worksheet, header_list2, 3, l, border_style='thin', width=20) + stewards = Guilds.objects.filter(trash=False, steward=True) + for steward in stewards: + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + Q(to_steward=steward) | Q(steward=steward), + trash=False, date__date__gte=date1, + date__date__lte=date2, calculate_status=True + ).order_by('id') + guild_steward_free_buying_bars = StewardFreeBarInformation.objects.filter( + Q(guild=steward) | Q(steward=steward), trash=False, date__date__gte=date1, + date__date__lte=date2) + guild_steward_free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + Q(guild=steward) | Q(steward=steward), trash=False, date__date__gte=date1, + date__date__lte=date2) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=steward) | Q(steward=steward), + trash=False, calculate_status=True).order_by('id') + + guild_steward_free_buying_bars = StewardFreeBarInformation.objects.filter( + Q(guild=steward) | Q(steward=steward), trash=False) + guild_steward_free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + Q(guild=steward) | Q(steward=steward), trash=False) + product = RolesProducts.objects.filter(trash=False, guild=steward).first() + if product: + total_remain_weight = product.total_remain_weight + else: + total_remain_weight = 0 + recive_allocation = allocations.filter(to_steward=steward, receiver_state='accepted') + allocate_allocation = allocations.filter(steward=steward) + real_weight_of_carcasses = recive_allocation.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + number_of_carcasses_guild_steward_free_buying_bars = guild_steward_free_buying_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_guild_steward_free_buying_bars = guild_steward_free_sale_bars.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + number_of_carcasses_guild_steward_free_buying_bars = guild_steward_free_sale_bars.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + real_number_of_carcasses_allocate_allocation = allocate_allocation.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + real_weight_of_carcasses_allocate_allocation = allocate_allocation.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + kill_house_to_stw = allocations.filter(allocation_type='steward_steward') + quantity_kill_house_to_stw = kill_house_to_stw.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + weight_kill_house_to_stw = kill_house_to_stw.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + kill_house_to_guild = allocations.filter(allocation_type='steward_guild') + quantity_kill_house_to_guild = kill_house_to_guild.aggregate( + total_quantity=Sum('real_number_of_carcasses')).get( + 'total_quantity') or 0 + weight_kill_house_to_guild = kill_house_to_guild.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + if real_weight_of_carcasses + real_weight_of_carcasses_allocate_allocation > 0: + list1 = [ + 'مباشر', + f"{steward.guilds_name}-{steward.user.mobile}-{steward.user.city.name}", + ((real_weight_of_carcasses + weight_guild_steward_free_buying_bars) - ( + real_weight_of_carcasses_allocate_allocation + number_of_carcasses_guild_steward_free_buying_bars) + total_remain_weight), + real_weight_of_carcasses + weight_guild_steward_free_buying_bars, + len(allocations), + real_weight_of_carcasses_allocate_allocation + number_of_carcasses_guild_steward_free_buying_bars, + weight_guild_steward_free_buying_bars, + len(kill_house_to_stw), + weight_kill_house_to_stw, + len(kill_house_to_guild), + weight_kill_house_to_guild, + f"%{int((real_weight_of_carcasses_allocate_allocation + number_of_carcasses_guild_steward_free_buying_bars) * 100 / (real_weight_of_carcasses + weight_guild_steward_free_buying_bars)) if (real_weight_of_carcasses + weight_guild_steward_free_buying_bars) > 0 else 0}", + total_remain_weight + + ] + create_value(worksheet, list1, l + 1, 3, border_style='thin', width=20) + l += 1 + l += 5 + list5 = ['شهر'] + kill_house_name = KillHouse.objects.filter(trash=False, out_province=False).order_by('id').values_list( + 'name', flat=True) + list5.extend(kill_house_name) + list5.append('مجموع') + create_header(worksheet, list5, 3, l, border_style='thin', width=20) + cities = City.objects.filter(trash=False).order_by('id') + for city in cities: + if 'date1' in request.GET and request.GET['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() + result = get_kill_house_distribution_info(city, date1, date2) + result1 = all_get_kill_house_distribution_info(city, date1, date2) + else: + result = get_kill_house_distribution_info(city) + result1 = all_get_kill_house_distribution_info(city) + + create_value(worksheet, result, l + 1, 3, border_style='thin', width=20) + create_value(worksheet, [result1], l + 1, int(len(list5) + 2), border_style='thin', width=20) + l += 1 + if 'date1' in request.GET: + + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + result = get_kill_house_distribution_out_province_info(date1, date2) + else: + result = get_kill_house_distribution_out_province_info() + create_value(worksheet, result, l + 1, 3, border_style='thin', width=20) + + elif sheet_name == 'تخصیصات کشتارگاه به مباشر و صنف': + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, date__date__gte=date1, + date__date__lte=date2, kill_house__isnull=False, calculate_status=True).order_by('id') + else: + allocations = StewardAllocation.objects.filter( + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, kill_house__isnull=False, calculate_status=True).order_by('id') + + excel_options = [ + 'ردیف', + 'نام کشتارگاه', + 'نام مالک', + 'شماره مالک', + 'شهر مالک', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'شهر خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'تخصیصات کشتارگاه به مباشرین ', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + buyer_city = allocation.to_steward.user.city.name + elif allocation.allocation_type == 'killhouse_guild': + allocation_type = 'کشتارگاه به صنف' + buyer_name = allocation.to_guilds.guilds_name if allocation.to_guilds else '-' + buyer_mobile = allocation.to_guilds.user.mobile if allocation.to_guilds else '-' + buyer_city = allocation.to_guilds.user.city.name if allocation.to_guilds else '-' + + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + buyer_city = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = '' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + allocation.kill_house.name, + allocation.kill_house.kill_house_operator.user.fullname, + allocation.kill_house.kill_house_operator.user.mobile, + allocation.kill_house.kill_house_operator.user.city.name, + str(convert_to_shamsi(datetime=allocation.date)), + allocation_type, + buyer_name, + buyer_mobile, + buyer_city, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.weight_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + allocation.registration_code, + system_registration_code, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تخصیصات سرد خانه': + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + allocation_type='ColdHouse', + trash=False, date__date__gte=date1, + date__date__lte=date2, kill_house__isnull=False, calculate_status=True).order_by('id') + else: + allocations = StewardAllocation.objects.filter( + allocation_type='ColdHouse', + trash=False, kill_house__isnull=False, calculate_status=True).order_by('id') + + excel_options = [ + 'ردیف', + 'فروشنده', + 'نام فروشنده', + 'شماره فروشنده', + 'شهر فروشنده', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'شهر خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'تخصیصات سردخانه', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + buyer_city = allocation.to_steward.user.city.name + elif allocation.allocation_type == 'killhouse_guild': + allocation_type = 'کشتارگاه به صنف' + buyer_name = allocation.to_guilds.guilds_name + buyer_mobile = allocation.to_guilds.user.mobile + buyer_city = allocation.to_guilds.user.city.name + elif allocation.allocation_type == 'ColdHouse': + allocation_type = 'کشتارگاه به سردخانه' + if allocation.to_cold_house.kill_house: + buyer_name = allocation.to_cold_house.kill_house.name + buyer_mobile = allocation.to_cold_house.kill_house.kill_house_operator.user.mobile + buyer_city = allocation.to_cold_house.kill_house.kill_house_operator.user.city.name + else: + buyer_name = allocation.to_cold_house.live_stock_support.user.name + buyer_mobile = allocation.to_cold_house.live_stock_support.user.mobile + buyer_city = allocation.to_cold_house.live_stock_support.user.city.name + elif allocation.allocation_type == 'killhouse_killhouse': + allocation_type = 'کشتارگاه به کشتارگاه' + buyer_name = allocation.to_kill_house.kill_house.name + buyer_mobile = allocation.to_kill_house.kill_house_operator.user.mobile + buyer_city = allocation.to_kill_house.kill_house_operator.user.city.name + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + buyer_city = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = 'آزاد' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + allocation.kill_house.name, + allocation.kill_house.kill_house_operator.user.fullname, + allocation.kill_house.kill_house_operator.user.mobile, + allocation.kill_house.kill_house_operator.user.city.name, + str(convert_to_shamsi(datetime=allocation.date)), + allocation_type, + buyer_name, + buyer_mobile, + buyer_city, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.weight_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + allocation.registration_code, + system_registration_code, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تخصیصات مباشر به صنف': + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + allocation_type='steward_guild', + trash=False, date__date__gte=date1, + date__date__lte=date2, calculate_status=True).order_by('id') + else: + allocations = StewardAllocation.objects.filter( + allocation_type='steward_guild', + trash=False, calculate_status=True).order_by('id') + + excel_options = [ + 'ردیف', + 'فروشنده', + 'نام فروشنده', + 'شماره فروشنده', + 'شهر فروشنده', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'شهر خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'تخصیصات مباشر به صنف ', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + buyer_city = allocation.to_steward.user.city.name + elif allocation.allocation_type == 'killhouse_guild' or allocation.allocation_type == 'steward_guild': + allocation_type = 'مباشر به صنف' + buyer_name = allocation.to_guilds.guilds_name + buyer_mobile = allocation.to_guilds.user.mobile + buyer_city = allocation.to_guilds.user.city.name + + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + buyer_city = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = '' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + allocation.steward.guilds_name, + allocation.steward.user.fullname, + allocation.steward.user.mobile, + allocation.steward.user.city.name, + str(convert_to_shamsi(datetime=allocation.date)), + allocation_type, + buyer_name, + buyer_mobile, + buyer_city, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.weight_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + allocation.registration_code, + system_registration_code, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تخصیصات صنف به صنف': + + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + allocation_type='guild_guild', + trash=False, date__date__gte=date1, + date__date__lte=date2, calculate_status=True).order_by('id') + else: + allocations = StewardAllocation.objects.filter( + allocation_type='guild_guild', + trash=False, calculate_status=True).order_by('id') + + excel_options = [ + 'ردیف', + 'فروشنده', + 'نام فروشنده', + 'شماره فروشنده', + 'شهر فروشنده', + 'تاریخ ثبت', + 'نوع تخصیص', + 'خریدار', + 'تلفن خریدار', + 'شهر خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تخصیصات', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'تخصیصات صنف به صنف ', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for allocation in allocations: + l += 1 + if allocation.allocation_type == 'killhouse_steward': + allocation_type = 'کشتارگاه به مباشر' + buyer_name = allocation.to_steward.guilds_name + buyer_mobile = allocation.to_steward.user.mobile + buyer_city = allocation.to_steward.user.city.name + elif allocation.allocation_type == 'killhouse_guild' or allocation.allocation_type == 'steward_guild' or \ + allocation.allocation_type == 'guild_guild': + allocation_type = 'صنف به صنف' + buyer_name = allocation.to_guilds.guilds_name + buyer_mobile = allocation.to_guilds.user.mobile + buyer_city = allocation.to_guilds.user.city.name + + else: + allocation_type = '' + buyer_name = '' + buyer_mobile = '' + buyer_city = '' + + if allocation.sell_type == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = '' + system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + list1 = [ + m, + allocation.steward.guilds_name, + allocation.steward.user.fullname, + allocation.steward.user.mobile, + allocation.steward.user.city.name, + str(convert_to_shamsi(datetime=allocation.date)), + allocation_type, + buyer_name, + buyer_mobile, + buyer_city, + sell_type, + allocation.amount, + allocation.total_amount, + allocation.weight_of_carcasses, + allocation.receiver_real_weight_of_carcasses, + allocation.registration_code, + system_registration_code, + state, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + total_amount_allocations = allocations.aggregate( + total_quantity=Sum('total_amount')).get( + 'total_quantity') or 0 + number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + len(allocations), + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount_allocations, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + # elif sheet_name == 'تخصیصات مباشر به مباشر': + # + # if 'date1' in request.GET and request.GET['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() + # + # allocations = StewardAllocation.objects.filter( + # allocation_type='steward_guild', + # trash=False, date__date__gte=date1, + # date__date__lte=date2, kill_house__isnull=False, calculate_status=True).order_by('id') + # else: + # allocations = StewardAllocation.objects.filter( + # allocation_type='steward_guild', + # trash=False, kill_house__isnull=False, calculate_status=True).order_by('id') + # + # excel_options = [ + # 'ردیف', + # 'نام کشتارگاه', + # 'نام مالک', + # 'شماره مالک', + # 'شهر مالک', + # 'تاریخ ثبت', + # 'نوع تخصیص', + # 'خریدار', + # 'تلفن خریدار', + # 'شهر خریدار', + # 'نوع فروش', + # 'قیمت هر کیلو(ریال)', + # 'قیمت کل', + # 'حجم تخصیصی', + # 'وزن تخصیصی', + # 'حجم تایید شده', + # 'وزن تایید شده', + # 'کد احراز', + # 'وضعیت کد احراز', + # 'وضعیت', + # + # ] + # + # blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + # red_font = Font(color="C00000", bold=True) + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from_date_1 = shamsi_date(date1) + # to_date_1 = shamsi_date(date2) + # worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + # header_list2 = [ + # 'تعداد تخصیصات', + # 'قیمت کل', + # 'حجم تخصیصی', + # 'وزن تخصیصی', + # 'حجم تایید شده', + # 'وزن تایید شده', + # + # ] + # + # for col_num, option in enumerate(header_list2, 5): + # cell = worksheet.cell(row=2, column=col_num, value=option) + # cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + # cell.fill = PatternFill(start_color="00B050", fill_type="solid") + # cell.font = Font(size=9, bold=True, color='D9FFFFFF') + # worksheet.row_dimensions[2].height = 20.8 + # create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + # + # excel_description(worksheet, 'A1', f'تخصیصات مباشر به صنف ', size=11, color='red', + # row2='D1') + # + # worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + # merge_range1 = 'B1:D1' + # merge_range2 = 'B2:D2' + # merge_range = 'B3:D3' + # worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range) + # worksheet.merge_cells(merge_range2) + # worksheet['B1'].font = red_font + # worksheet['B3'].font = Font(size=11) + # worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + # + # l = 5 + # m = 1 + # + # if allocations: + # for allocation in allocations: + # l += 1 + # if allocation.allocation_type == 'killhouse_steward' : + # allocation_type = 'کشتارگاه به مباشر' + # buyer_name = allocation.to_steward.guilds_name + # buyer_mobile = allocation.to_steward.user.mobile + # buyer_city = allocation.to_steward.user.city.name + # elif allocation.allocation_type == 'killhouse_guild' or allocation.allocation_type == 'steward_guild': + # allocation_type = 'کشتارگاه به صنف' + # buyer_name = allocation.to_guilds.guilds_name + # buyer_mobile = allocation.to_guilds.user.mobile + # buyer_city = allocation.to_guilds.user.city.name + # + # else: + # allocation_type = '' + # buyer_name = '' + # buyer_mobile = '' + # buyer_city = '' + # + # if allocation.sell_type == 'exclusive': + # sell_type = 'اختصاصی' + # else: + # sell_type = '' + # system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + # state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + # list1 = [ + # m, + # allocation.kill_house.name, + # allocation.kill_house.kill_house_operator.user.fullname, + # allocation.kill_house.kill_house_operator.user.mobile, + # allocation.kill_house.kill_house_operator.user.city.name, + # str(convert_to_shamsi(datetime=allocation.date)), + # allocation_type, + # buyer_name, + # buyer_mobile, + # buyer_city, + # sell_type, + # allocation.amount, + # allocation.total_amount, + # allocation.number_of_carcasses, + # allocation.weight_of_carcasses, + # allocation.receiver_real_number_of_carcasses, + # allocation.receiver_real_weight_of_carcasses, + # allocation.registration_code, + # system_registration_code, + # state, + # + # ] + # m += 1 + # create_value(worksheet,list1,l+1,1,height=20,width=30) + # + # total_amount_allocations = allocations.aggregate( + # total_quantity=Sum('total_amount')).get( + # 'total_quantity') or 0 + # number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('number_of_carcasses')).get( + # 'total_quantity') or 0 + # weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('weight_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_number_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + # 'total_quantity') or 0 + # + # value_header_list2 = [ + # len(allocations), + # total_amount_allocations, + # number_of_carcasses_allocations, + # weight_of_carcasses_allocations, + # receiver_real_number_of_carcasses_allocations, + # receiver_real_weight_of_carcasses_allocations, + # + # ] + # for item in range(len(value_header_list2)): + # cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + # value = value_header_list2[item] + # # Check if the value is a number before formatting + # if isinstance(value, (int, float)): + # if value != 0: + # cell.number_format = '#,###' # Apply general number format + # else: + # cell.value = value # Keep as text for other values + # + # cell.alignment = Alignment(horizontal='center') + # cell.font = Font(size=10, bold=True) + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # total_amount_allocations, + # number_of_carcasses_allocations, + # weight_of_carcasses_allocations, + # receiver_real_number_of_carcasses_allocations, + # receiver_real_weight_of_carcasses_allocations, + # '', + # '', + # '', + # + # ] + # for item in range(len(list2)): + # cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + # value = list2[item] + # if isinstance(value, (int, float)): + # cell.number_format = '#,###' # Apply general number format + # else: + # cell.value = value # Keep as text for other values + # + # cell.alignment = Alignment(horizontal='center') + # cell.font = Font(size=10, bold=True) + # cell.font = Font(bold=True) + # cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'عملکرد مباشرین': + if 'date1' in request.GET and request.GET['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() + + allocations = StewardAllocation.objects.filter( + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, date__date__gte=date1, + date__date__lte=date2, calculate_status=True).order_by('id') + else: + allocations = StewardAllocation.objects.filter( + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, calculate_status=True).order_by('id') + user_value = list(allocations.values_list('to_steward__user__user', flat=True).distinct()) + user_value2 = list(allocations.values_list('to_guilds__user__user', flat=True).distinct()) + user_value3 = list(set(user_value + user_value2)) + excel_options = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'شهر خریدار', + 'وزن تخصیصی', + 'وزن تایید شده', + 'تخصیص دهنده', + + ] + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد مباشرین', + 'وزن تخصیصی', + 'وزن تایید شده', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'عملکرد مباشرین', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if allocations: + for user in user_value3: + user_new = SystemUserProfile.objects.filter(trash=False, user=user).first() + guilds = Guilds.objects.filter(trash=False, user=user_new).first() + new_allocation = allocations.filter(Q(to_steward=guilds) | Q(to_guilds=guilds)) + kill_house_name = new_allocation.values_list('kill_house__name', flat=True).distinct() + kill_house_names = [str(name) for name in kill_house_name if name is not None] + + if kill_house_names: + kill_house_name_str = ' / '.join(set(kill_house_names)) + else: + kill_house_name_str = '-' + weight_of_carcasses_allocations = new_allocation.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = new_allocation.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = new_allocation.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + if guilds: + l += 1 + + list1 = [ + m, + guilds.guilds_name if guilds else '-', + user_new.mobile if user_new else '-', + user_new.city.name if user_new else '-', + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + kill_house_name_str + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_number_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_number_of_carcasses')).get( + 'total_quantity') or 0 + receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + 'total_quantity') or 0 + # + value_header_list2 = [ + len(user_value3), + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + + + # elif sheet_name == 'تخصیصات مباشرین به صنوف': + # + # if 'date1' in request.GET and request.GET['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() + # + # allocations = StewardAllocation.objects.filter(allocation_type__in=('steward_guild', 'steward_steward'), + # trash=False, date__date__gte=date1, + # date__date__lte=date2, calculate_status=True + # ).order_by('id') + # else: + # allocations = StewardAllocation.objects.filter(allocation_type__in=('steward_guild', 'steward_steward'), + # trash=False, calculate_status=True).order_by('id') + # + # excel_options = [ + # 'ردیف', + # 'ماهیت', + # 'نام مالک', + # 'شماره مالک', + # 'شهر مالک', + # 'تاریخ ثبت', + # 'نوع تخصیص', + # 'خریدار', + # 'تلفن خریدار', + # 'شهر خریدار', + # 'نوع فروش', + # 'قیمت هر کیلو(ریال)', + # 'قیمت کل', + # 'حجم تخصیصی', + # 'وزن تخصیصی', + # 'حجم تایید شده', + # 'وزن تایید شده', + # 'کد احراز', + # 'وضعیت کد احراز', + # 'وضعیت', + # + # ] + # + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + # red_font = Font(color="C00000", bold=True) + # if 'date1' in request.GET: + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # from_date_1 = shamsi_date(date1) + # to_date_1 = shamsi_date(date2) + # worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + # header_list2 = [ + # 'تعداد تخصیصات', + # 'قیمت کل', + # 'حجم تخصیصی', + # 'وزن تخصیصی', + # 'حجم تایید شده', + # 'وزن تایید شده', + # + # ] + # + # for col_num, option in enumerate(header_list2, 5): + # cell = worksheet.cell(row=2, column=col_num, value=option) + # cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + # cell.fill = PatternFill(start_color="00B050", fill_type="solid") + # cell.font = Font(size=9, bold=True, color='D9FFFFFF') + # worksheet.row_dimensions[2].height = 20.8 + # create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + # + # excel_description(worksheet, 'A1', f'تخصیصات کشتارگاه به صنف ', size=11, color='red', + # row2='D1') + # + # worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + # merge_range1 = 'B1:D1' + # merge_range2 = 'B2:D2' + # merge_range = 'B3:D3' + # worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range) + # worksheet.merge_cells(merge_range2) + # worksheet['B1'].font = red_font + # worksheet['B3'].font = Font(size=11) + # worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + # + # l = 5 + # m = 1 + # + # if allocations: + # for allocation in allocations: + # l += 1 + # if allocation.allocation_type == 'killhouse_steward': + # allocation_type = 'کشتارگاه به مباشر' + # buyer_name = allocation.to_steward.guilds_name + # buyer_mobile = allocation.to_steward.user.mobile + # buyer_city = allocation.to_steward.user.city.name + # elif allocation.allocation_type == 'killhouse_guild': + # allocation_type = 'کشتارگاه به صنف' + # buyer_name = allocation.to_guilds.guilds_name + # buyer_mobile = allocation.to_guilds.user.mobile + # buyer_city = allocation.to_guilds.user.city.name + # elif allocation.allocation_type == 'steward_guild': + # allocation_type = 'مباشر به صنف' + # buyer_name = allocation.to_guilds.guilds_name + # buyer_mobile = allocation.to_guilds.user.mobile + # buyer_city = allocation.to_guilds.user.city.name + # elif allocation.allocation_type == 'steward_steward': + # allocation_type = 'مباشر به مباشر' + # buyer_name = allocation.to_steward.guilds_name + # buyer_mobile = allocation.to_steward.user.mobile + # buyer_city = allocation.to_steward.user.city.name + # else: + # allocation_type = '' + # buyer_name = '' + # buyer_mobile = '' + # buyer_city = '' + # + # if allocation.sell_type == 'exclusive': + # sell_type = 'اختصاصی' + # else: + # sell_type = '' + # system_registration_code = 'ارسال شده' if allocation.system_registration_code == True else 'ارسال نشده' + # state = 'در انتظار تایید' if allocation.state == 'pending' else 'تایید شده' + # type = 'مباشر' if allocation.steward.steward == True else 'صنف' + # list1 = [ + # m, + # type, + # allocation.steward.user.fullname, + # allocation.steward.user.mobile, + # allocation.steward.user.city.name, + # str(convert_to_shamsi(datetime=allocation.date)), + # allocation_type, + # buyer_name, + # buyer_mobile, + # buyer_city, + # sell_type, + # allocation.amount, + # allocation.total_amount, + # allocation.number_of_carcasses, + # allocation.weight_of_carcasses, + # allocation.receiver_real_number_of_carcasses, + # allocation.receiver_real_weight_of_carcasses, + # allocation.registration_code, + # system_registration_code, + # state, + # + # ] + # m += 1 + # create_value(worksheet, list1, l + 1, 1, height=20, width=30) + # + # total_amount_allocations = allocations.aggregate( + # total_quantity=Sum('total_amount')).get( + # 'total_quantity') or 0 + # number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('number_of_carcasses')).get( + # 'total_quantity') or 0 + # weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('weight_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_number_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_number_of_carcasses')).get( + # 'total_quantity') or 0 + # receiver_real_weight_of_carcasses_allocations = allocations.aggregate( + # total_quantity=Sum('receiver_real_weight_of_carcasses')).get( + # 'total_quantity') or 0 + # + # value_header_list2 = [ + # len(allocations), + # total_amount_allocations, + # number_of_carcasses_allocations, + # weight_of_carcasses_allocations, + # receiver_real_number_of_carcasses_allocations, + # receiver_real_weight_of_carcasses_allocations, + # + # ] + # for item in range(len(value_header_list2)): + # cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + # value = value_header_list2[item] + # # Check if the value is a number before formatting + # if isinstance(value, (int, float)): + # if value != 0: + # cell.number_format = '#,###' # Apply general number format + # else: + # cell.value = value # Keep as text for other values + # + # cell.alignment = Alignment(horizontal='center') + # cell.font = Font(size=10, bold=True) + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # '', + # total_amount_allocations, + # number_of_carcasses_allocations, + # weight_of_carcasses_allocations, + # receiver_real_number_of_carcasses_allocations, + # receiver_real_weight_of_carcasses_allocations, + # '', + # '', + # '', + # + # ] + # for item in range(len(list2)): + # cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + # value = list2[item] + # if isinstance(value, (int, float)): + # cell.number_format = '#,###' # Apply general number format + # else: + # cell.value = value # Keep as text for other values + # + # cell.alignment = Alignment(horizontal='center') + # cell.font = Font(size=10, bold=True) + # cell.font = Font(bold=True) + # cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تراکنش های صنوف': + + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + guilds = Guilds.objects.filter( + id__in=PosMachineTransactions.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + pos__guild__isnull=False, + paid=True + ).values_list('pos__guild__id', flat=True).distinct() + ) + else: + guilds = Guilds.objects.filter( + id__in=PosMachineTransactions.objects.filter( + trash=False, + pos__guild__isnull=False, + paid=True + ).values_list('pos__guild__id', flat=True).distinct() + ) + + serializer = GuildsPosMachineForTransactionsSerializer(guilds, many=True, context={'request': request}) + + excel_options = [ + 'ردیف', + 'نام واحد صنفی', + 'موبایل', + 'شهر', + 'تعداد تراکنش ها', + 'مبلغ کل تراکنش ها', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد تراکنش ها', + 'تعداد صنوف', + 'مبلغ کل تراکنش ها', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'تراکنش های صنف ', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if serializer.data: + for data in serializer.data: + l += 1 + + list1 = [ + m, + data['guilds_name'], + data['user']['mobile'], + data['user']['city']['name'], + data['transaction']['len_transaction'], + data['transaction']['total_price'], + data['transaction']['total_carcasses_weight'], + data['transaction']['real_allocated_weight'], + data['transaction']['total_remain_weight'], + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + pos = PosMachineTransactions.objects.filter(trash=False, pos__guild__in=guilds, paid=True) + total_price = pos.aggregate(total=Sum('price'))[ + 'total'] or 0 + + value_header_list2 = [ + len(pos), + len(guilds), + total_price, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + len_transaction = sum(item['transaction'].get('len_transaction', 0) for item in serializer.data) + total_price = sum(item['transaction'].get('total_price', 0) for item in serializer.data) + total_carcasses_weight = sum( + item['transaction'].get('total_carcasses_weight', 0) for item in serializer.data) + real_allocated_weight = sum(item['transaction'].get('real_allocated_weight', 0) for item in serializer.data) + total_remain_weight = sum(item['transaction'].get('total_remain_weight', 0) for item in serializer.data) + + list2 = [ + 'مجموع==>', + '', + '', + '', + len_transaction, + total_price, + total_carcasses_weight, + real_allocated_weight, + total_remain_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="توزیع .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def login_user_excel(request): + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + accesstokens = AccessToken.objects.filter(created__date__gte=date1, created__date__lte=date2).select_related( + 'user').order_by('-id') + else: + accesstokens = AccessToken.objects.filter(created__date__gt='2024-12-15').select_related('user').order_by('-id') + excel_options = [ + 'ردیف', + 'نام و نام خانوادگی کاربر', + 'موبایل کاربر', + 'تاریخ ورود به سیستم', + 'توکن', + 'نقش', + 'شهرستان', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 1, 2, 20, width=30) + + l = 2 + for accesstoken in accesstokens: + user = SystemUserProfile.objects.get(user=accesstoken.user) + role_list = [role.name for role in user.role.all()] + date = convert_to_shamsi(datetime=accesstoken.created) + list1 = [ + m, + user.fullname, + user.mobile, + str(date), + accesstoken.token, + str(role_list), + user.city.name if user.city else '-' + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=20) + m += 1 + l += 1 + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="لاگین .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def sub_section_of_cooperative_share_detail(request): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + + # return Response(total_pure_province_carcasses_weight) + internal_total_pure_province_carcasses_weight = ( + total_pure_province_carcasses_weight / total_province_carcasses_weight) * total_province_carcasses_weight + external_total_pure_province_carcasses_weight = total_province_carcasses_weight - internal_total_pure_province_carcasses_weight + + total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + + union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_free_sell_carcasses_wage + hatching_killing_percent = (( + out_province_poultry_request_quantity + total_province_live_quantity) / hatching_quantity) * 100 + + city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request + city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request + city_out_province_sell_carcasses = union_free_sell_carcasses_wage * city_percent_out_sell_carcasses + city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_sell_carcasses + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False) + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + city_total_remain_wage_amount = city_total_wage - city_deposit + + excel_options = [ + 'ردیف', + 'تعاونی', + 'شهر', + 'کاربر', + 'موبایل کاربر', + 'تعداد فارم', + 'تعداد کل جوجه ریزی', + 'حجم کل جوجه ریزی', + 'حجم کل کشتار شده داخل استان', + 'وزن کل کشتار شده داخل استان', + 'وزن لاشه کشتار شده داخل استان', + 'وزن لاشه توزیع داخل استان', + 'وزن لاشه توزیع خارج استان', + 'حجم فروش خارج از استان', + 'وزن فروش خارج از استان', + 'حجم کل کشتار شده', + 'درصد کشتار شده نسبت به جوجه ریزی', + 'تعرفه زنده خارج از استان', + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج از استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد فارم', + 'تعداد کل جوجه ریزی', + 'حجم کل جوجه ریزی', + 'حجم کل کشتارشده داخل استان', + 'وزن کل کشتار شده داخل استان', + 'وزن لاشه کشتار شده داخل استان', + 'وزن کل لاشه توزیع داخل استان', + 'وزن کل لاشه توزیع خارج استان', + 'حجم کل فروش به خارج استان', + 'وزن کل فروش به خارج از استان', + 'حجم کل کشتار شده', + 'درصد کشتار شده نسبت به جوجه ریزی', + 'تعرفه زنده خارج از استان(اتحادیه)', + 'تعرفه کشتار و توزیع داخل استان(اتحادیه)', + 'تعرفه کشتار و توزیع خارج ازاستان(اتحادیه)', + 'کل تعرفه سهم اتحادیه استان', + 'تعرفه سهم زیر بخش ها', + 'واریزی اتحادیه به زیر بخش ها', + 'مانده تعرفه', + ] + create_header(worksheet, header_list, 4, 2, 21, 16.01) + + excel_description(worksheet, 'A1', 'گزارش جزئیات تعرفه سهم تعاونی ها', size=11, color='red', row2='C1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + city_operators = CityOperator.objects.filter(address__province=user.province, trash=False) + if 'operators' in request.GET: + + serializer = CityOperatorForSubSectorTransactionsSerializer(city_operators, many=True, + context={'request': request}) + else: + serializer = CityOperatorForSubSectorSerializer(city_operators, many=True, context={'request': request}) + for data in serializer.data: + list1 = [ + m, + data['unit_name'], + data['user']['city'], + data['user']['fullname'], + data['user']['mobile'], + data['wage_info']['poultries'], + data['wage_info']['hatchings'], + data['wage_info']['hatchings_quantity'], + data['wage_info']['total_province_kill_requests_quantity'], + data['wage_info']['total_province_kill_requests_weight'], + data['wage_info']['total_province_carcasses_weight'], + data['wage_info']['total_pure_internal_province_carcasses_weight'], + data['wage_info']['total_pure_external_province_carcasses_weight'], + data['wage_info']['out_province_poultry_request_quantity'], + data['wage_info']['out_province_poultry_request_weight'], + data['wage_info']['total_killed_quantity'], + data['wage_info']['hatching_killing_percent'], + data['wage_info']['out_province_poultry_request_amount'], + data['wage_info']['total_pure_internal_province_carcasses_amount'], + data['wage_info']['total_pure_external_province_carcasses_amount'], + data['wage_info']['total_wage_amount'], + data['wage_info']['city_deposit'], + data['wage_info']['total_remain_wage_amount'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + + value_header_list = [ + len(poultries), + len(hatchings), + hatching_quantity, + total_province_live_quantity, + total_province_live_weight, + total_province_carcasses_weight, + internal_total_pure_province_carcasses_weight, + external_total_pure_province_carcasses_weight, + out_province_poultry_request_quantity, + out_province_poultry_request_weight, + out_province_poultry_request_quantity + total_province_live_quantity, + hatching_killing_percent, + union_free_sell_carcasses_wage, + + union_province_kill_request_wage, + union_out_province_poultry_request_amount, + + union_total_wage, + city_total_wage, + city_deposit, + city_total_remain_wage_amount, + + ] + create_value(worksheet, value_header_list, 3, 4) + + poultries = sum(item['wage_info'].get('poultries', 0) for item in serializer.data) + hatchings = sum(item['wage_info'].get('hatchings', 0) for item in serializer.data) + hatchings_quantity = sum(item['wage_info'].get('hatchings_quantity', 0) for item in serializer.data) + total_province_kill_requests_quantity = sum( + item['wage_info'].get('total_province_kill_requests_quantity', 0) for item in serializer.data) + total_province_kill_requests_weight = sum( + item['wage_info'].get('total_province_kill_requests_weight', 0) for item in serializer.data) + total_province_carcasses_weight = sum( + item['wage_info'].get('total_province_carcasses_weight', 0) for item in serializer.data) + total_pure_internal_province_carcasses_weight = sum( + item['wage_info'].get('total_pure_internal_province_carcasses_weight', 0) for item in serializer.data) + total_pure_external_province_carcasses_weight = sum( + item['wage_info'].get('total_pure_external_province_carcasses_weight', 0) for item in serializer.data) + out_province_poultry_request_quantity = sum( + item['wage_info'].get('out_province_poultry_request_quantity', 0) for item in serializer.data) + out_province_poultry_request_weight = sum( + item['wage_info'].get('out_province_poultry_request_weight', 0) for item in serializer.data) + total_killed_quantity = sum(item['wage_info'].get('total_killed_quantity', 0) for item in serializer.data) + hatching_killing_percent = sum(item['wage_info'].get('hatching_killing_percent', 0) for item in serializer.data) + out_province_poultry_request_amount = sum( + item['wage_info'].get('out_province_poultry_request_amount', 0) for item in serializer.data) + total_pure_internal_province_carcasses_amount = sum( + item['wage_info'].get('total_pure_internal_province_carcasses_amount', 0) for item in serializer.data) + total_pure_external_province_carcasses_amount = sum( + item['wage_info'].get('total_pure_external_province_carcasses_amount', 0) for item in serializer.data) + total_wage_amount = sum(item['wage_info'].get('total_wage_amount', 0) for item in serializer.data) + city_deposit = sum(item['wage_info'].get('city_deposit', 0) for item in serializer.data) + total_remain_wage_amount = sum(item['wage_info'].get('total_remain_wage_amount', 0) for item in serializer.data) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + poultries, + hatchings, + hatchings_quantity, + total_province_kill_requests_quantity, + total_province_kill_requests_weight, + total_province_carcasses_weight, + total_pure_internal_province_carcasses_weight, + total_pure_external_province_carcasses_weight, + out_province_poultry_request_quantity, + out_province_poultry_request_weight, + total_killed_quantity, + hatching_killing_percent, + out_province_poultry_request_amount, + total_pure_internal_province_carcasses_amount, + total_pure_external_province_carcasses_amount, + total_wage_amount, + city_deposit, + total_remain_wage_amount, + + ] + create_value(worksheet, list2, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جزئیات تعرفه سهم تعاونی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def city_operator_for_sub_sector_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + city_operators = CityOperator.objects.filter(address__province=user.province, trash=False) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعرفه زنده خارج از استان', + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه', + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + + internal_total_pure_province_carcasses_weight = ( + total_pure_province_carcasses_weight / total_province_carcasses_weight) * total_province_carcasses_weight + external_total_pure_province_carcasses_weight = total_province_carcasses_weight - internal_total_pure_province_carcasses_weight + + total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + + union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_free_sell_carcasses_wage + hatching_killing_percent = (( + out_province_poultry_request_quantity + total_province_live_quantity) / hatching_quantity) * 100 + + city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request + city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request + city_out_province_sell_carcasses = union_free_sell_carcasses_wage * city_percent_out_sell_carcasses + city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_sell_carcasses + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False) + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + city_total_remain_wage_amount = city_total_wage - city_deposit + + value_header_list = [ + city_out_province_poultry_request, + city_province_kill_request_wage, + city_out_province_sell_carcasses, + city_total_wage, + city_deposit, + city_total_remain_wage_amount, + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'تعاونی', + 'شهر', + 'کاربر', + 'موبایل کاربر', + + 'تعرفه زنده خارج از استان', + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج از استان', + 'مجموع تعرفه', + ' تعداد دفعات واریز', + 'مجموع واریزی اتحادیه', + 'مانده تعرفه', + ] + + # excel_description(worksheet, 'A1', 'گزارش جزئیات تعرفه سهم تعاونی ها', size=11, color='red', row2='C1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + + if 'operators' in request.GET: + serializer = CityOperatorForSubSectorTransactionsSerializer(city_operators, many=True, + context={'request': request}) + else: + serializer = CityOperatorForSubSectorSerializer(city_operators, many=True, context={'request': request}) + # todo:مقادیر باید درست شه + for data in serializer.data: + list1 = [ + m, + data['unit_name'], + data['user']['city'], + data['user']['fullname'], + data['user']['mobile'], + + data['wage_info']['out_province_poultry_request_amount'], + data['wage_info']['total_pure_internal_province_carcasses_amount'], + data['wage_info']['total_pure_external_province_carcasses_weight'], + data['wage_info']['total_wage_amount'], + data['wage_info']['number_of_city_deposit'], + data['wage_info']['city_deposit'], + data['wage_info']['total_remain_wage_amount'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + for city_operator in city_operators: + if SubSectorTransactions.objects.filter(trash=False, city_operator=city_operator).exists(): + sheet_name = city_operator.unit_name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + role_type = request.GET['type'] + excel_options = [ + 'ردیف', + 'تعاونی', + 'شهر', + 'کاربر', + 'موبایل کاربر', + 'تاریخ واریز', + 'شماره حساب مبدا', + 'شماره حساب مقصد', + 'نوع تراکنش', + 'مبلغ تراکنش', + ] + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.01) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + excel_description(worksheet, 'A3', + f'واریزی های {city_operator.unit_name} از تاریخ{from_date_1} تا {from_date_2}', + color='red', row2='C3') + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_operator__isnull=False, + trash=False, + city_operator=city_operator).order_by( + '-date') + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + vet__isnull=False, + trash=False).order_by('-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_guild__isnull=False, + trash=False, + city_operator=city_operator).order_by( + '-date') + + + else: + excel_description(worksheet, 'A4', f'{city_operator.unit_name}', color='red', row2='B4') + + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(city_operator__isnull=False, + trash=False, + city_operator=city_operator).order_by( + '-date') + + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(vet__isnull=False, + trash=False).order_by( + '-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(city_guild__isnull=False, + trash=False).order_by('-date') + l = 7 + m = 1 + for operator_transaction in operator_transactions: + if operator_transaction.type == 'online': + type = "آنلاین" + elif operator_transaction.type == 'bank': + type = "توسط بانک" + else: + type = 'دستی' + list1 = [ + m, + operator_transaction.city_operator.unit_name, + operator_transaction.city_operator.user.city.name, + operator_transaction.city_operator.user.fullname, + operator_transaction.city_operator.user.mobile, + str(shamsi_date(operator_transaction.date)), + operator_transaction.from_account, + operator_transaction.to_account, + type, + operator_transaction.amount, + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + amount = operator_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + header_list1 = [ + 'تعداد تراکنش ها', + 'مبلغ تراکنش ها', + + ] + create_header(worksheet, header_list1, 5, 3, border_style='thin', color='C4D79B', height=25) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + amount, + + ] + create_value(worksheet, list2, l + 1, 1, border_style='thin', color='yellow') + list3 = [ + len(operator_transactions), + amount, + + ] + create_value(worksheet, list3, 4, 5, border_style='thin') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="واریزی ها سهم تعاونی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def vet_for_sub_sector_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + sheet_list = [ + 'اطلاعات کلی', + 'واریزی ها' + ] + + for sheet_name in sheet_list: + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعرفه زنده خارج از استان', + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه فروش به خارج استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه', + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + total_quantity = 0 + total_weight = 0 + total_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', + trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', + trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm__isnull=False, + quarantine_code__isnull=False, + send_date__date__gte=date1, + send_date__date__lte=date2) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm__isnull=False, + clearance_code__isnull=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False, + date__date__gte=date1, date__date__lte=date2) + + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm__isnull=False, + quarantine_code__isnull=False) + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm__isnull=False, + clearance_code__isnull=False, + trash=False, calculate_status=True + ) + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False) + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + other_out_poultry_request_percent = percentages_wage_type.filter( + wage_type__en_name='poultry-sell-out-province', + share_type__en_name='other').first().percent / 100 + other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent + other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent + + other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent + + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_quantity += province_live_quantity + out_province_poultry_request_quantity + total_weight += province_live_weight + out_province_poultry_request_weight + + province_carcasses_weight = province_live_weight * 0.75 + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent() + external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight + + total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount + total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount + + vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_remain_wage = total_wage - vet_deposit_amount + + value_header_list = [ + total_pure_internal_province_carcasses_amount, + total_pure_external_province_carcasses_amount, + out_province_poultry_request_amount, + total_wage, + vet_deposit_amount, + total_remain_wage, + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'کاربر', + 'موبایل کاربر', + 'شهر', + + 'حجم کشتار (دارای کد قرنطینه)', + 'وزن کشتار (دارای کد قرنطینه)', + 'تعرفه کشتار و توزیع داخل استان (ریال)', + 'تعرفه کشتار و توزیع خارج استان (ریال)', + 'تعرفه فروش به خارج استان (ریال)', + 'مجموع تعرفه (ریال)', + 'تعداد دفعات واریز', + 'مجموع واریزی اتحادیه(ریال)', + 'مانده تعرفه(ریال)', + + ] + + # excel_description(worksheet, 'A1', 'گزارش جزئیات تعرفه سهم تعاونی ها', size=11, color='red', row2='C1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + + vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by( + 'id') + serializer = VetForSubSectorSerializerForExcel(vet, many=True, context={'request': request}) + for data in serializer.data: + list1 = [ + m, + data['user']['fullname'], + data['user']['mobile'], + data['user']['city'], + data['wage_info']['total_quantity'], + data['wage_info']['total_weight'], + data['wage_info']['total_pure_internal_province_carcasses_amount'], + data['wage_info']['total_pure_external_province_carcasses_amount'], + data['wage_info']['out_province_poultry_request_amount'], + data['wage_info']['total_wage'], + data['wage_info']['number_of_deposit'], + data['wage_info']['vet_deposit_amount'], + data['wage_info']['total_remain_wage'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + else: + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + role_type = request.GET['type'] + excel_options = [ + 'ردیف', + 'کاربر', + 'موبایل کاربر', + 'شهر', + 'تاریخ واریز', + 'شماره حساب مبدا', + 'شماره حساب مقصد', + 'نوع تراکنش', + 'مبلغ تراکنش', + ] + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.01) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + excel_description(worksheet, 'A3', + f'واریزی ها از تاریخ{from_date_1} تا {from_date_2}', + color='red', row2='C3') + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_operator__isnull=False, + trash=False, + ).order_by( + '-date') + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + vet__isnull=False, + trash=False).order_by('-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_guild__isnull=False, + trash=False, + ).order_by( + '-date') + + + else: + excel_description(worksheet, 'A4', f'واریزی های سهم دامپزشک', color='red', row2='B4') + + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(city_operator__isnull=False, + trash=False, + ).order_by( + '-date') + + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(vet__isnull=False, + trash=False).order_by( + '-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(city_guild__isnull=False, + trash=False).order_by('-date') + l = 7 + m = 1 + for operator_transaction in operator_transactions: + if operator_transaction.type == 'online': + type = "آنلاین" + elif operator_transaction.type == 'bank': + type = "توسط بانک" + else: + type = 'دستی' + list1 = [ + m, + operator_transaction.vet.user.fullname, + operator_transaction.vet.user.mobile, + operator_transaction.vet.user.city.name, + str(shamsi_date(operator_transaction.date)), + operator_transaction.from_account, + operator_transaction.to_account, + type, + operator_transaction.amount, + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + amount = operator_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + header_list1 = [ + 'تعداد تراکنش ها', + 'مبلغ تراکنش ها', + + ] + create_header(worksheet, header_list1, 5, 3, border_style='thin', color='C4D79B', height=25) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + amount, + + ] + create_value(worksheet, list2, l + 1, 1, border_style='thin', color='yellow') + list3 = [ + len(operator_transactions), + amount, + + ] + create_value(worksheet, list3, 4, 5, border_style='thin') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="واریزی ها سهم دامپزشک فارم.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def guild_for_sub_sector_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + sheet_list = [ + 'اطلاعات کلی', + 'واریزی ها' + ] + + for sheet_name in sheet_list: + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'کل وزن دریافتی', + 'کل وزن فروش رفته', + 'تعرفه فروش به خارج استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه', + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', + trash=False).first().amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + if date1: + + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__isnull=False, + calculate_status=True, + temporary_trash=False, temporary_deleted=False, + receiver_state='accepted', date__date__gte=date1, + date__date__lte=date2) + transactions = PosMachineTransactions.objects.filter(paid=True, trash=False, date__date__gte=date1, + date__date__lte=date2) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild__isnull=False, + date__date__gte=date1, date__date__lte=date2) + else: + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__isnull=False, + calculate_status=True, + temporary_trash=False, temporary_deleted=False, + receiver_state='accepted') + transactions = PosMachineTransactions.objects.filter(paid=True, trash=False) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild__isnull=False) + allocations_weight = allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + transactions_weight = transactions.aggregate(total=Sum('weight'))[ + 'total'] or 0 + transactions_weight = transactions_weight / 1000 if transactions_weight > 0 else 0 + total_wage = transactions_weight * (province_live_wage_amount * other_province_kill_request_percent) + + sub_transactions_amount = sub_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + remain_wage = total_wage - sub_transactions_amount + + value_header_list = [ + allocations_weight, + transactions_weight, + total_wage, + sub_transactions_amount, + remain_wage + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'کاربر', + 'موبایل کاربر', + 'شهر', + 'کل وزن دریافتی', + 'کل وزن فروش رفته', + 'مجموع تعرفه (ریال)', + 'مجموع واریزی اتحادیه(ریال)', + 'مانده تعرفه(ریال)', + + ] + + # excel_description(worksheet, 'A1', 'گزارش جزئیات تعرفه سهم تعاونی ها', size=11, color='red', row2='C1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + + city_guilds = CityGuild.objects.filter(trash=False) + serializer = CityGuildForSubSectorSerializerForExcel(city_guilds, many=True, context={'request': request}) + for data in serializer.data: + list1 = [ + m, + data['user']['fullname'], + data['user']['mobile'], + data['user']['city'], + data['wage_info']['buy_weight'], + data['wage_info']['sell_weight'], + data['wage_info']['total_wage'], + data['wage_info']['guild_deposit'], + data['wage_info']['remain_wage'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + else: + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + role_type = request.GET['type'] + excel_options = [ + 'ردیف', + 'کاربر', + 'موبایل کاربر', + 'شهر', + 'تاریخ واریز', + 'شماره حساب مبدا', + 'شماره حساب مقصد', + 'نوع تراکنش', + 'مبلغ تراکنش', + ] + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.01) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + excel_description(worksheet, 'A3', + f'واریزی ها از تاریخ{from_date_1} تا {from_date_2}', + color='red', row2='C3') + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_operator__isnull=False, + trash=False, + ).order_by( + '-date') + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + vet__isnull=False, + trash=False).order_by('-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_guild__isnull=False, + trash=False, + ).order_by( + '-date') + + + else: + excel_description(worksheet, 'A4', f'واریزی های سهم صنف', color='red', row2='B4') + + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(city_operator__isnull=False, + trash=False, + ).order_by( + '-date') + + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(vet__isnull=False, + trash=False).order_by( + '-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(city_guild__isnull=False, + trash=False).order_by('-date') + l = 7 + m = 1 + for operator_transaction in operator_transactions: + if operator_transaction.type == 'online': + type = "آنلاین" + elif operator_transaction.type == 'bank': + type = "توسط بانک" + else: + type = 'دستی' + list1 = [ + m, + operator_transaction.city_guild.user.fullname, + operator_transaction.city_guild.user.mobile, + operator_transaction.city_guild.user.city.name, + str(shamsi_date(operator_transaction.date)), + operator_transaction.from_account, + operator_transaction.to_account, + type, + operator_transaction.amount, + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + amount = operator_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + header_list1 = [ + 'تعداد تراکنش ها', + 'مبلغ تراکنش ها', + + ] + create_header(worksheet, header_list1, 5, 3, border_style='thin', color='C4D79B', height=25) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + amount, + + ] + create_value(worksheet, list2, l + 1, 1, border_style='thin', color='yellow') + list3 = [ + len(operator_transactions), + amount, + + ] + create_value(worksheet, list3, 4, 5, border_style='thin') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="واریزی ها سهم صنف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def all_guilds_transaction_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + filterset_class = GuildsForPostationFilterSet + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + + if date1 and date2: + date1 = datetime.datetime.strptime(date1, '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(date2, '%Y-%m-%d').date() + + guilds = Guilds.objects.filter( + Q( + id__in=PosMachineTransactions.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + pos__guild__isnull=False, + paid=True + ).values_list('pos__guild__id', flat=True) + ) | + Q( + id__in=StewardAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + to_guilds__isnull=False, + to_cold_house__isnull=True, + temporary_trash=False, + trash=False, + calculate_status=True + ).values_list('to_guilds__id', flat=True) + ) + ).annotate( + transaction_count=Count( + 'guild_pos__roles_products_pos_transactions', + filter=Q( + guild_pos__roles_products_pos_transactions__trash=False, + guild_pos__roles_products_pos_transactions__paid=True, + guild_pos__roles_products_pos_transactions__date__date__gte=date1, + guild_pos__roles_products_pos_transactions__date__date__lte=date2 + ), + distinct=True + ) + ).order_by('-transaction_count') + + else: + guilds = Guilds.objects.filter( + Q( + id__in=PosMachineTransactions.objects.filter( + trash=False, + paid=True, + pos__guild__isnull=False + ).values_list('pos__guild__id', flat=True) + ) | + Q( + id__in=StewardAllocation.objects.filter( + to_guilds__isnull=False, + to_cold_house__isnull=True, + temporary_trash=False, + trash=False, + calculate_status=True + ).values_list('to_guilds__id', flat=True) + ) + ).annotate( + transaction_count=Count( + 'guild_pos__roles_products_pos_transactions', + filter=Q( + guild_pos__roles_products_pos_transactions__trash=False, + guild_pos__roles_products_pos_transactions__paid=True + ), + distinct=True + ) + ).order_by('-transaction_count') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + build_query(filterset_class.Meta.fields, value) + ) + serializer = GuildsPosMachineForTransactionsNewSerializer(guilds, many=True, context={'request': request}) + + excel_options = [ + 'ردیف', + 'نام واحد صنفی', + 'موبایل', + 'شهر', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + 'تعداد تراکنش ها', + 'مبلغ کل تراکنش ها', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + header_list2 = [ + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + 'تعداد تراکنش ها', + 'مبلغ کل تراکنش ها', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'مدیریت انبار صنوف', size=11, color='red', + row2='D1') + l = 5 + m = 1 + datas = serializer.data + + datas = sorted(datas, key=lambda x: x['transaction']['total_carcasses_weight'], reverse=True) + for data in datas: + l += 1 + + list1 = [ + m, + data['guilds_name'], + data['user']['mobile'], + data['user']['city']['name'], + data['transaction']['total_carcasses_weight'], + str(data['transaction']['real_allocated_weight']), + data['transaction']['total_remain_weight'], + data['transaction']['len_transaction'], + data['transaction']['total_price'], + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + len_transaction = sum(item['transaction'].get('len_transaction', 0) for item in serializer.data) + total_price = sum(item['transaction'].get('total_price', 0) for item in serializer.data) + total_carcasses_weight = sum(item['transaction'].get('total_carcasses_weight', 0) for item in serializer.data) + real_allocated_weight = sum(item['transaction'].get('real_allocated_weight', 0) for item in serializer.data) + total_remain_weight = sum(item['transaction'].get('total_remain_weight', 0) for item in serializer.data) + + list2 = [ + 'مجموع==>', + '', + '', + '', + total_carcasses_weight, + real_allocated_weight, + total_remain_weight, + len_transaction, + total_price, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + value_header_list2 = [ + total_carcasses_weight, + real_allocated_weight, + total_remain_weight, + len_transaction, + total_price, + + ] + create_value(worksheet, value_header_list2, 3, 5) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت انبار صنوف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def detail_guilds_transaction_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + guild = Guilds.objects.get(key=request.GET['key']) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = PosMachineTransactions.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, pos__guild=guild, + paid=True).order_by('-date') + else: + transactions = PosMachineTransactions.objects.filter(trash=False, pos__guild=guild, + paid=True).order_by('-date') + + serializer = PosMachineTransactionsForInspectionSerializer(transactions, many=True) + + excel_options = [ + 'ردیف', + 'وضعیت تراکنش', + 'تاریخ تراکنش', + 'محصول', + 'قیمت واحد', + 'وزن (گرم)', + 'مبلغ(ریال)', + 'از سرویس', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + header_list2 = [ + 'تعداد تراکنش ها', + 'وزن کل(گرم)', + 'مبلغ کل تراکنش ها(ریال)', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + if guild: + name = guild.guilds_name + else: + name = '' + excel_description(worksheet, 'A1', f'تراکنش های صنف {name}', size=11, color='red', + row2='D1') + + l = 5 + m = 1 + + for data in serializer.data: + l += 1 + paid = 'موفق' if data['paid'] == True else 'ناموفق' + posProvider = 'سامان کیش' if data['posProvider'] == "SEP" else '-' + date = '-' + if data['date']: + try: + date = datetime.datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S.%f') + except ValueError: + date = datetime.datetime.strptime(str(data['date']), '%Y-%m-%dT%H:%M:%S') + date = shamsi_date(date, in_value=True) + list1 = [ + m, + paid, + str(date), + (data.get('product') or {}).get('name') or '-', + data.get('price') or 0, + data.get('weight') or 0, + data.get('current_price') or 0, + posProvider, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + pos = PosMachineTransactions.objects.filter(trash=False, pos__guild=guild, paid=True) + total_price = pos.aggregate(total=Sum('price'))[ + 'total'] or 0 + weight = sum(item['weight'] for item in serializer.data) + + value_header_list2 = [ + len(pos), + weight, + total_price, + + ] + create_value(worksheet, value_header_list2, 3, 5) + + len_transaction = sum(item['price'] for item in serializer.data) + total_carcasses_weight = sum(item['current_price'] for item in serializer.data) + + list2 = [ + 'مجموع==>', + '', + '', + '', + len_transaction, + weight, + total_carcasses_weight, + '' + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های صنف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +class GetExcel(APIView): + throttle_classes = [AnonRateThrottle, UserRateThrottle] + + def get(self, request): + excel_name = request.GET.get('name') + return Response(f'https://{base_url_for_sms_report}backend.rasadyaar.ir/{excel_name}/?{request.query_params}') + + +def management_hatching_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + poultry_hatching = PoultryHatching.objects.filter(state__in=('pending', 'complete'), archive=False, + allow_hatching='pending', + trash=False).order_by('-chicken_age').select_related( + 'poultry') + + excel_options = [ + 'ردیف', + 'شهرستان', + 'نام واحد', + 'نام مالک', + 'تاریخ جوجه ریزی', + 'تعداد جوجه ریزی', + 'سن', + 'نود درصد جوجه ریزی', + 'مانده در سالن', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + header_list2 = [ + 'تعداد کل جوجه ریزی', + 'تعداد قطعه بین 42تا 50روزگی', + 'تعداد قطعه بین 51تا 54روزگی', + 'تعداد قطعه بین 55تا 60روزگی', + 'تعداد قطعه بالای 60روزگی', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 9, 10, 20) + + # excel_description(worksheet, 'A1', f'تراکنش های صنف {name}', size=11, color='red', + # row2='D1') + + l = 8 + m = 1 + + for data in poultry_hatching: + l += 1 + age = data.chicken_age + if age > 60: + color = RED_CELL + elif 60 > age > 54: + color = LIGHT_GREEN_CELL + elif 54 > age > 49: + color = GREEN_CELL + elif 49 > age > 47: + color = VERY_LIGHT_GREEN_CELL + else: + color = None + list1 = [ + m, + data.poultry.address.city.name, + data.poultry.unit_name, + data.poultry.user.fullname, + convert_to_shamsi(date=data.date), + data.quantity, + data.chicken_age, + int(data.quantity * 0.9), + data.left_over + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, m=m, item_num=6, item_color=color, border_style='thin') + + quantity = poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + beetwen_43_50 = poultry_hatching.filter(chicken_age__range=(43, 50)).aggregate(total=Sum('quantity'))[ + 'total'] or 0 + beetwen_51_54 = poultry_hatching.filter(chicken_age__range=(51, 54)).aggregate(total=Sum('quantity'))[ + 'total'] or 0 + beetwen_55_60 = poultry_hatching.filter(chicken_age__range=(55, 60)).aggregate(total=Sum('quantity'))[ + 'total'] or 0 + gt_60 = poultry_hatching.filter(chicken_age__gt=60).aggregate(total=Sum('quantity'))[ + 'total'] or 0 + value_header_list2 = [ + quantity, + beetwen_43_50, + beetwen_51_54, + beetwen_55_60, + gt_60 + + ] + create_value(worksheet, value_header_list2, 3, 5) + # + # len_transaction = sum(item['price'] for item in serializer.data) + # total_carcasses_weight = sum(item['current_price'] for item in serializer.data) + # + + left_over = poultry_hatching.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + quantity, + '', + int(quantity * 0.9), + left_over + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های صنف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def user_without_role_excel(request): + users = SystemUserProfile.objects.filter(role__isnull=True, trash=False).only('fullname', 'create_date', + 'fullname').order_by('-create_date') + excel_options = [ + 'ردیف', + 'نام و نام خانوادگی کاربر', + 'موبایل کاربر', + 'تاریخ ایجاد کاربر', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 1, 2, 20, width=30) + + l = 2 + for user in users: + list1 = [ + m, + user.fullname, + user.mobile, + convert_to_shamsi(date=user.create_date), + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=20) + m += 1 + l += 1 + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کاربران پایه .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def sub_section_of_cooperative_share_detail_with_date_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + + # return Response(total_pure_province_carcasses_weight) + internal_total_pure_province_carcasses_weight = (( + total_pure_province_carcasses_weight / total_province_carcasses_weight) if total_province_carcasses_weight > 0 else 0) * total_province_carcasses_weight + external_total_pure_province_carcasses_weight = total_province_carcasses_weight - internal_total_pure_province_carcasses_weight + + total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings, + send_date__date__gte=date1, + send_date__date__lte=date2) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + + union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_free_sell_carcasses_wage + hatching_killing_percent = (( + out_province_poultry_request_quantity + total_province_live_quantity) / hatching_quantity) * 100 + + city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request + city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request + city_out_province_sell_carcasses = union_free_sell_carcasses_wage * city_percent_out_sell_carcasses + city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_sell_carcasses + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2) + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + city_total_remain_wage_amount = city_total_wage - city_deposit + + excel_options = [ + 'ردیف', + 'تعاونی', + 'شهر', + 'کاربر', + 'موبایل کاربر', + 'تعداد فارم', + 'تعداد کل جوجه ریزی', + 'حجم کل جوجه ریزی', + 'حجم کل کشتار شده داخل استان', + 'وزن کل کشتار شده داخل استان', + 'وزن لاشه کشتار شده داخل استان', + 'وزن لاشه توزیع داخل استان', + 'وزن لاشه توزیع خارج استان', + 'حجم فروش خارج از استان', + 'وزن فروش خارج از استان', + 'حجم کل کشتار شده', + 'درصد کشتار شده نسبت به جوجه ریزی', + 'تعرفه زنده خارج از استان', + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج از استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد فارم', + 'تعداد کل جوجه ریزی', + 'حجم کل جوجه ریزی', + 'حجم کل کشتارشده داخل استان', + 'وزن کل کشتار شده داخل استان', + 'وزن لاشه کشتار شده داخل استان', + 'وزن کل لاشه توزیع داخل استان', + 'وزن کل لاشه توزیع خارج استان', + 'حجم کل فروش به خارج استان', + 'وزن کل فروش به خارج از استان', + 'حجم کل کشتار شده', + 'درصد کشتار شده نسبت به جوجه ریزی', + 'تعرفه زنده خارج از استان(اتحادیه)', + 'تعرفه کشتار و توزیع داخل استان(اتحادیه)', + 'تعرفه کشتار و توزیع خارج ازاستان(اتحادیه)', + 'کل تعرفه سهم اتحادیه استان', + 'تعرفه سهم زیر بخش ها', + 'واریزی اتحادیه به زیر بخش ها', + 'مانده تعرفه', + ] + create_header(worksheet, header_list, 4, 2, 21, 16.01) + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + excel_description(worksheet, 'A1', + f'گزارش جزئیات تعرفه سهم تعاونی ها ار تاریخ {from_date_1} تا تاریخ {from_date_2}', size=11, + color='red', row2='E1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + # user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + city_operators = CityOperator.objects.filter(trash=False) + if 'operators' in request.GET: + + serializer = CityOperatorForSubSectorTransactionsSerializer(city_operators, many=True, + context={'request': request}) + else: + serializer = CityOperatorForSubSectorSerializerForExcel(city_operators, many=True, context={'request': request}) + if serializer.data: + for data in serializer.data: + list1 = [ + m, + data['unit_name'], + data['user']['city'], + data['user']['fullname'], + data['user']['mobile'], + data['wage_info']['poultries'], + data['wage_info']['hatchings'], + data['wage_info']['hatchings_quantity'], + data['wage_info']['total_province_kill_requests_quantity'], + data['wage_info']['total_province_kill_requests_weight'], + data['wage_info']['total_province_carcasses_weight'], + data['wage_info']['total_pure_internal_province_carcasses_weight'], + data['wage_info']['total_pure_external_province_carcasses_weight'], + data['wage_info']['out_province_poultry_request_quantity'], + data['wage_info']['out_province_poultry_request_weight'], + data['wage_info']['total_killed_quantity'], + data['wage_info']['hatching_killing_percent'], + data['wage_info']['out_province_poultry_request_amount'], + data['wage_info']['total_pure_internal_province_carcasses_amount'], + data['wage_info']['total_pure_external_province_carcasses_amount'], + data['wage_info']['total_wage_amount'], + data['wage_info']['city_deposit'], + data['wage_info']['total_remain_wage_amount'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + + value_header_list = [ + len(poultries), + len(hatchings), + hatching_quantity, + total_province_live_quantity, + total_province_live_weight, + total_province_carcasses_weight, + internal_total_pure_province_carcasses_weight, + external_total_pure_province_carcasses_weight, + out_province_poultry_request_quantity, + out_province_poultry_request_weight, + out_province_poultry_request_quantity + total_province_live_quantity, + hatching_killing_percent, + union_free_sell_carcasses_wage, + + union_province_kill_request_wage, + union_out_province_poultry_request_amount, + + union_total_wage, + city_total_wage, + city_deposit, + city_total_remain_wage_amount, + + ] + create_value(worksheet, value_header_list, 3, 4) + + poultries = sum(item['wage_info'].get('poultries', 0) for item in serializer.data) + hatchings = sum(item['wage_info'].get('hatchings', 0) for item in serializer.data) + hatchings_quantity = sum(item['wage_info'].get('hatchings_quantity', 0) for item in serializer.data) + total_province_kill_requests_quantity = sum( + item['wage_info'].get('total_province_kill_requests_quantity', 0) for item in serializer.data) + total_province_kill_requests_weight = sum( + item['wage_info'].get('total_province_kill_requests_weight', 0) for item in serializer.data) + total_province_carcasses_weight = sum( + item['wage_info'].get('total_province_carcasses_weight', 0) for item in serializer.data) + total_pure_internal_province_carcasses_weight = sum( + item['wage_info'].get('total_pure_internal_province_carcasses_weight', 0) for item in serializer.data) + total_pure_external_province_carcasses_weight = sum( + item['wage_info'].get('total_pure_external_province_carcasses_weight', 0) for item in serializer.data) + out_province_poultry_request_quantity = sum( + item['wage_info'].get('out_province_poultry_request_quantity', 0) for item in serializer.data) + out_province_poultry_request_weight = sum( + item['wage_info'].get('out_province_poultry_request_weight', 0) for item in serializer.data) + total_killed_quantity = sum(item['wage_info'].get('total_killed_quantity', 0) for item in serializer.data) + hatching_killing_percent = sum(item['wage_info'].get('hatching_killing_percent', 0) for item in serializer.data) + out_province_poultry_request_amount = sum( + item['wage_info'].get('out_province_poultry_request_amount', 0) for item in serializer.data) + total_pure_internal_province_carcasses_amount = sum( + item['wage_info'].get('total_pure_internal_province_carcasses_amount', 0) for item in serializer.data) + total_pure_external_province_carcasses_amount = sum( + item['wage_info'].get('total_pure_external_province_carcasses_amount', 0) for item in serializer.data) + total_wage_amount = sum(item['wage_info'].get('total_wage_amount', 0) for item in serializer.data) + city_deposit = sum(item['wage_info'].get('city_deposit', 0) for item in serializer.data) + total_remain_wage_amount = sum(item['wage_info'].get('total_remain_wage_amount', 0) for item in serializer.data) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + poultries, + hatchings, + hatchings_quantity, + total_province_kill_requests_quantity, + total_province_kill_requests_weight, + total_province_carcasses_weight, + total_pure_internal_province_carcasses_weight, + total_pure_external_province_carcasses_weight, + out_province_poultry_request_quantity, + out_province_poultry_request_weight, + total_killed_quantity, + hatching_killing_percent, + out_province_poultry_request_amount, + total_pure_internal_province_carcasses_amount, + total_pure_external_province_carcasses_amount, + total_wage_amount, + city_deposit, + total_remain_wage_amount, + + ] + create_value(worksheet, list2, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جزئیات تعرفه سهم تعاونی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def vet_for_sub_sector_with_date_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by('id') + serializer = VetForSubSectorSerializer(vet, many=True, context={'request': request}) + + excel_options = [ + 'ردیف', + 'کاربر', + 'شهر', + 'حجم کشتار (دارای کد قرنطینه)', + 'وزن کشتار (دارای کد قرنطینه)', + 'تعرفه کشتارو توزیع داخل استان (ریال)', + 'تعرفه کشتارو توزیع خارج از استان (ریال)', + 'تعرفه فروش به خارج از استان (ریال)', + 'مجموع تعرفه (ریال)', + 'تعداد دفعات واریز', + 'مجموع واریزی اتحادیه (ریال)', + 'مانده تعرفه (ریال)' + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعرفه کشتار و توزیع داخل استان', + 'تعرفه کشتار و توزیع خارج استان', + 'تعرفه فروش به خارج استان', + 'مجموع تعرفه', + 'واریزی اتحادیه', + 'مانده تعرفه' + ] + create_header(worksheet, header_list, 4, 2, 21, 16.01) + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + excel_description(worksheet, 'A1', + f'گزارش جزئیات تعرفه سهم تعاونی ها ار تاریخ {from_date_1} تا تاریخ {from_date_2}', size=11, + color='red', row2='E1') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + # user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + + if serializer.data: + for data in serializer.data: + list1 = [ + m, + data['user']['fullname'], # کاربر + data['user']['city'], # شهر + data['wage_info']['province_live_quantity'], # حجم کشتار (دارای کد قرنطینه) 🔺 + data['wage_info']['province_live_weight'], # وزن کشتار (دارای کد قرنطینه) + data['wage_info']['total_pure_internal_province_carcasses_amount'], + # تعرفه کشتارو توزیع داخل استان (ریال) + data['wage_info']['total_pure_external_province_carcasses_amount'], + # تعرفه کشتارو توزیع خارج از استان (ریال) + data['wage_info']['out_province_poultry_request_amount'], # تعرفه فروش به خارج از استان (ریال) + data['wage_info']['total_wage'], # مجموع تعرفه (ریال) + data['wage_info']['number_of_deposit'], # تعداد دفعات واریز + data['wage_info']['vet_deposit_amount'], # مجموع واریزی اتحادیه (ریال) + data['wage_info']['total_remain_wage'] # مانده تعرفه (ریال) + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + total_quantity = 0 + total_weight = 0 + total_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + other_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='other').first().percent / 100 + other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent + other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent + + other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm__isnull=False, + ) + # quarantine_code__isnull=False) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm__isnull=False, + # clearance_code__isnull=False, + clearance_code__isnull=False, + trash=False, calculate_status=True + ) + + province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + total_quantity += province_live_quantity + out_province_poultry_request_quantity + total_weight += province_live_weight + out_province_poultry_request_weight + + province_carcasses_weight = province_live_weight * 0.75 + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent() + external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight + + total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount + total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount + + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False) + vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_remain_wage = total_wage - vet_deposit_amount + value_header_list = [ + total_pure_internal_province_carcasses_amount, # تعرفه کشتار و توزیع داخل استان + total_pure_external_province_carcasses_amount, # تعرفه کشتار و توزیع خارج استان + out_province_poultry_request_amount, # تعرفه فروش به خارج استان + total_wage, # مجموع تعرفه + vet_deposit_amount, # واریزی اتحادیه + total_remain_wage # مانده تعرفه + ] + create_value(worksheet, value_header_list, 3, 4) + + # list2 = [ + # 'مجموع==>', + # '', + # '', + # '', + # '', + # poultries, + # hatchings, + # hatchings_quantity, + # total_province_kill_requests_quantity, + # total_province_kill_requests_weight, + # total_province_carcasses_weight, + # total_pure_internal_province_carcasses_weight, + # total_pure_external_province_carcasses_weight, + # out_province_poultry_request_quantity, + # out_province_poultry_request_weight, + # total_killed_quantity, + # hatching_killing_percent, + # out_province_poultry_request_amount, + # total_pure_internal_province_carcasses_amount, + # total_pure_external_province_carcasses_amount, + # total_wage_amount, + # city_deposit, + # total_remain_wage_amount, + # + # ] + # create_value(worksheet, list2, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جزئیات تعرفه سهم تعاونی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def dashboard_monitoring_bar_and_killing_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else now + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + sheet_names2 = ['اطلاعات کشتار', 'اطلاعات بار', 'تخصیصات بدون بار', 'خرید زنده خارج از استان', + 'خرید لاشه خارج استان', + 'فروش زنده به خارج استان', 'اطلاعات کشتارگاه ها'] + for name in sheet_names2: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'اطلاعات کشتار': + filtered_province_kill_reqs = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2).select_related( + 'poultry', 'poultry__user').order_by( + '-send_date') + excel_options = [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'فروش', + 'نام و نام خانوادگی مرغدار', + 'نام فارم', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'مانده در سالن', + 'میانگین وزنی هر قطعه(کیلوگرم)', + 'وزن کل درخواست(کیلوگرم)', + 'قیمت هرکیلو مرغ زنده(ریال)', + 'تایید شده', + ] + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد درخواست', + 'مجموع تعداد قطعه', + 'وزن تقریبی کل درخواست', + 'مجموع مانده در سالن', + 'میانگین سنی', + ] + create_header(worksheet, header_list, 4, 2, height=17) + + excel_description(worksheet, 'A2', 'درخواست کشتار مرغداران', size=11, row2='B2') + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', color='red', + row2='C3') + m = 1 + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=23, width=21.01) + l = 4 + all_quantity = 0 + all_wight = 0 + all_left_over = 0 + all_age = [] + if filtered_province_kill_reqs: + for filtered_poultry_kill_request in filtered_province_kill_reqs: + all_quantity += filtered_poultry_kill_request.quantity + all_wight += int( + filtered_poultry_kill_request.quantity * filtered_poultry_kill_request.Index_weight) + l += 1 + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '-' + if filtered_poultry_kill_request.kill_house_list is not None: + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '/' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + + if age not in all_age: + all_age.append(age) + + sale_type = 'دولتی' if filtered_poultry_kill_request.free_sale_in_province == False else 'آزاد' + all_left_over += filtered_poultry_kill_request.hatching.left_over + + list1 = [ + m, + str(filtered_poultry_kill_request.order_code), + str(date_of_create), + str(date_of_kill), + sale_type, + filtered_poultry_kill_request.poultry.user.fullname, + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + str(age), + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.hatching.left_over, + filtered_poultry_kill_request.Index_weight, + int(filtered_poultry_kill_request.quantity * filtered_poultry_kill_request.Index_weight), + filtered_poultry_kill_request.amount, + state + ] + m += 1 + create_value(worksheet, list1, l + 1, 1) + all_age1 = sorted(all_age) + value_header_list = [ + len(filtered_province_kill_reqs), + all_quantity, + all_wight, + all_left_over, + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + + ] + create_value(worksheet, value_header_list, 3, 4) + elif sheet_name == 'اطلاعات بار': + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'province_kill_request__kill_house_price', + 'price', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'province_kill_request__kill_house_price', + 'price', + 'bar_document_status__title' + ) + + filtered_kill_reqs = filtered_kill_request + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + 'اختلاف مجوز', + + ] + + from_date_1 = shamsi_date(date1) + + to_date_1 = shamsi_date(date2) + + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + header_list3 = [ + 'درصد بارهای دارای کد قرنطینه', + 'درصد تعداد بارهای احراز شده از قرنطینه', + 'درصد تعداد بارهای تکمیل شده کشتارگاه', + 'درصد وزن نهایی در کشتارگاه نسبت به وزن کل', + 'درصد بارهای فاقد کد قرنطینه', + 'درصد بارهای اختلاف دار در قرنطینه و رصدیار', + 'درصد تعداد بارهای ورودی به انبار', + 'درصد وزن لاشه ها در انبار نسبت به وزن کل', + 'درصد وزن لاشه در انبار نسبت به وزن نهایی در کشتارگاه', + + ] + create_header(worksheet, header_list, 9, 2, height=21.8) + + create_header(worksheet, header_list2, 6, 2, height=21.8, color='green') + + create_header(worksheet, header_list3, 6, 5, height=43, color='orange', text_color='0D0D0D') + create_header_freez(worksheet, excel_options, 1, 8, 9, height=21, len_with=True) + + excel_description(worksheet, 'B1', 'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی', color='red', + row2='D1') + + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + excel_description(worksheet, 'B2', f'استان {name}', color='red', row2='D2') + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + + l = 8 + m = 1 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else quarantine_quantity + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 3, 6) + value_header_list2 = [ + f'%{round((has_code * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((has_qarantine * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((len(bar_complete) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_net_weighte) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((len(hasnt_code1) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((difference_bar * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((all_state_ware_house_confirmation * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_net_weighte), 2) if int(all_net_weighte) > 0 else 0}' + ] + create_value(worksheet, value_header_list2, 6, 6) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'تخصیصات بدون بار': + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', + trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', + trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', + trash=False).first().amount + worksheet['H3'] = 'در این قسمت تخصیصات فاقد بار نمایش داده میشود' + merge_range1 = 'H3:K3' + worksheet.merge_cells(merge_range1) + worksheet['H3'].font = Font(color="C00000", bold=True) + worksheet['H3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + province_kill_request = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by( + 'kill_request__recive_date') + + if wage_counting_type == 'carcass': + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن لاشه ملاک تعرفه', + 'جمع کل تعرفه', + ] + else: + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن ملاک تعرفه', + 'جمع کل تعرفه', + ] + for col_num, option in enumerate(header_list, 3): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + if wage_counting_type == 'carcass': + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن لاشه ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + else: + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + for province_kill in province_kill_request: + + kill_date_1 = shamsi_date(province_kill.province_request.poultry_request.send_date) + + if province_kill.kill_request.slaughter_house is not None: + kill_place = province_kill.kill_request.slaughter_house.name + else: + kill_place = province_kill.kill_request.kill_house.name + + total_amount = province_kill.total_wage_amount + if wage_counting_type == 'carcass': + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight * 0.75, + province_live_wage_amount, + (province_kill.total_killed_weight * 0.75) * province_live_wage_amount, + + ] + else: + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight, + province_live_wage_amount, + (province_kill.total_killed_weight) * province_live_wage_amount, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_weight = \ + province_kill_request.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_killed_quantity = \ + province_kill_request.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_wage_amount = \ + province_kill_request.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + if wage_counting_type == 'carcass': + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight * 0.75, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 3, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + if wage_counting_type == 'carcass': + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight * 0.75, + province_live_wage_amount, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight, + province_live_wage_amount, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'خرید زنده خارج از استان': + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'live' + if request.GET['role'] in ['KillHouse', 'KillHouseVet']: + if request.GET['role'] == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + + excel_options = [ + 'ردیف', + 'کدسفارش', + 'تاریخ خرید', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'نوع خرید', + 'استان/شهر', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'وضعیت دامپزشک', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'حجم تایید شده', + 'وزن تایید شده', + 'تایید/رد کننده', + 'تاریخ تایید/ رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + if kill.exclusive_killer: + killer_type = f'کشتارکن اختصاصی {kill.kill_house.name}' + kill_house_name = kill.exclusive_killer.name + kill_house_mobile = kill.exclusive_killer.kill_house_operator.user.mobile + + elif kill.kill_house.killer == True and kill.kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + + else: + killer_type = 'کشتارگاه' + kill_house_name = kill.kill_house.name + kill_house_mobile = kill.kill_house.kill_house_operator.user.mobile + bar_code = str(kill.bar_code) if kill.bar_code else '-' + list1 = [ + m, + bar_code, + str(date_of_buy), + killer_type, + kill_house_name, + kill_house_mobile, + kill.poultry_name, + kill.poultry_mobile, + buy_type, + f'{kill.province} / {kill.city}', + kill.vet_farm_name, + kill.vet_farm_mobile, + state, + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + kill.kill_house_vet_quantity, + kill.kill_house_vet_weight, + kill.acceptor_rejector, + str(date_of_reject_accepted) + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, height=20, width=30) + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + m - 1, + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + int(bar_number_of_carcasses), + int(bar_weight_of_carcasses), + int(bar_kill_house_vet_quantity), + bar_kill_house_vet_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'خرید لاشه خارج استان': + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + type = 'carcass' + if request.GET['role'] in ['KillHouse', 'KillHouseVet']: + if request.GET['role'] == 'KillHouse': + kill_houses = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + else: + kill_house_ids = KillHouseVet.objects.filter(vet__user=user, trash=False).values_list('kill_house', + flat=True) + kill_houses = KillHouse.objects.filter(id__in=kill_house_ids, trash=False) + + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + else: + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + buy_type=type, + trash=False).order_by('-date') + + excel_options = [ + 'ردیف', + 'وضعیت دامپزشک', + 'کشتارگاه', + 'فروشنده', + 'نوع خرید', + 'استان/شهر', + 'تاریخ خرید', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'ماشین', + 'راننده', + 'تلفن راننده', + 'کدقرنطینه', + 'تعداد قطعه زنده', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه (کیلوگرم)', + 'حجم تایید شده', + 'وزن تایید شده', + 'تایید/رد کننده', + 'تاریخ تایید/ رد', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list2 = [ + 'تعداد بارها', + ' تعداد بار های درانتظار تایید', + 'مجموع قطعه زنده در انتظار تایید', + 'مجموع وزن زنده (کیلوگرم) درانتظار تایید', + 'مجموع تعداد لاشه درانتظار تایید', + 'مجموع وزن لاشه (کیلوگرم) درانتظار تایید', + + ' تعداد بار های رد شده', + 'مجموع قطعه زنده رد شده', + 'مجموع وزن زنده (کیلوگرم) رد شده', + 'مجموع تعداد لاشه رد شده', + 'مجموع وزن لاشه (کیلوگرم) رد شده', + + ' تعداد بار های تایید شده', + 'مجموع قطعه زنده تایید شده', + 'مجموع وزن زنده (کیلوگرم) تایید شده', + 'مجموع تعداد لاشه تایید شده', + 'مجموع وزن لاشه (کیلوگرم) تایید شده', + 'حجم تایید شده دامپزشک', + 'وزن تایید شده دامپزشک', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + type = 'زنده' if type == 'live' else 'لاشه' + worksheet['B1'] = f'گزارش بار {type} خرید از استان' + + if kill_house_free_bar_info.exists(): + name = kill_house_free_bar_info.first().kill_house.kill_house_operator.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if kill_house_free_bar_info: + for kill in kill_house_free_bar_info: + l += 1 + + if kill.kill_house_vet_state == 'accepted': + state = 'تایید شده' + elif kill.kill_house_vet_state == 'pending': + state = 'درانتظار تایید' + else: + state = 'رد شده' + + if kill.buy_type == 'live': + buy_type = 'زنده' + else: + buy_type = 'لاشه' + + date_of_buy = jdatetime.date.fromgregorian( + day=kill.date.day, + month=kill.date.month, + year=kill.date.year + ) + + if kill.date_of_accept_reject: + date_of_reject_accepted = jdatetime.date.fromgregorian( + day=kill.date_of_accept_reject.day, + month=kill.date_of_accept_reject.month, + year=kill.date_of_accept_reject.year + ) + else: + date_of_reject_accepted = '-' + + list1 = [ + m, + state, + kill.kill_house.name, + kill.poultry_name, + buy_type, + f'{kill.province} / {kill.city}', + str(date_of_buy), + kill.vet_farm_name, + kill.vet_farm_mobile, + kill.car, + kill.driver_name, + kill.driver_mobile, + kill.bar_clearance_code, + kill.quantity, + kill.live_weight, + kill.number_of_carcasses, + kill.weight_of_carcasses, + kill.kill_house_vet_quantity, + kill.kill_house_vet_weight, + kill.acceptor_rejector, + str(date_of_reject_accepted) + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + bar_pending = kill_house_free_bar_info.filter(kill_house_vet_state='pending') + bar_pending_quantity = bar_pending.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_pending_live_weight = bar_pending.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_pending_number_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_pending_weight_of_carcasses = bar_pending.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_rejected = kill_house_free_bar_info.filter(kill_house_vet_state='rejected') + bar_rejected_quantity = bar_rejected.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_rejected_live_weight = bar_rejected.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_rejected_number_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_rejected_weight_of_carcasses = bar_rejected.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + + bar_accepted = kill_house_free_bar_info.filter(kill_house_vet_state='accepted') + bar_accepted_quantity = bar_accepted.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_accepted_live_weight = bar_accepted.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_accepted_number_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_weight_of_carcasses = bar_accepted.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_quantity = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_accepted_kill_house_vet_weight = bar_accepted.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + bar_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + bar_live_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('live_weight')).get( + 'total_quantity') or 0 + bar_number_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('number_of_carcasses')).get( + 'total_quantity') or 0 + bar_weight_of_carcasses = kill_house_free_bar_info.aggregate( + total_quantity=Sum('weight_of_carcasses')).get( + 'total_quantity') or 0 + bar_kill_house_vet_quantity = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_quantity')).get( + 'total_quantity') or 0 + bar_kill_house_vet_weight = kill_house_free_bar_info.aggregate( + total_quantity=Sum('kill_house_vet_weight')).get( + 'total_quantity') or 0 + + value_header_list2 = [ + m - 1, + len(bar_pending), + int(bar_pending_quantity), + int(bar_pending_live_weight), + int(bar_pending_number_of_carcasses), + int(bar_pending_weight_of_carcasses), + + len(bar_rejected), + int(bar_rejected_quantity), + int(bar_rejected_live_weight), + int(bar_rejected_number_of_carcasses), + int(bar_rejected_weight_of_carcasses), + + len(bar_accepted), + int(bar_accepted_quantity), + int(bar_accepted_live_weight), + int(bar_accepted_number_of_carcasses), + int(bar_accepted_weight_of_carcasses), + int(bar_accepted_kill_house_vet_quantity), + int(bar_accepted_kill_house_vet_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + bar_quantity, + bar_live_weight, + int(bar_number_of_carcasses), + int(bar_weight_of_carcasses), + int(bar_kill_house_vet_quantity), + bar_kill_house_vet_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'فروش زنده به خارج استان': + + state = 'accepted' + user = SystemUserProfile.objects.get(key=request.GET['key']) + name_bar = '' + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + if state == 'pending': + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + name_bar = 'حذف/رد شده' + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + name_bar = 'حذف/رد شده' + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + name_bar = 'رد شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + poultry_requests_accepted = poultry_requests.filter(province_state='accepted') + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {name_bar} خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + state='accepted').exists(): + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info != None else '-', + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).exclude( + id__in=kill_house_ids).order_by( + 'id') + + serializer = KillHouseForPerformanceDashboardSerializer(kill_houses, many=True, + context={'date1': date1, 'date2': date2, }).data + + excel_options = [ + 'ردیف', + 'ماهیت', + 'کشتارگاه / کشتارکن', + 'مالک', + 'تلفن', + 'شهر', + 'تعداد بار داخل استان', + 'حجم بار داخل استان', + 'وزن بار داخل استان', + 'تعداد بار خارج استان', + 'حجم بار خارج استان', + 'وزن بار خارج استان', + 'وزن تخصیصات بدون بار', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بار داخل استان', + 'حجم بار داخل استان', + 'وزن بار داخل استان', + 'تعداد بار خارج استان', + 'حجم بار خارج استان', + 'وزن بار خارج استان', + 'وزن تخصیصات بدون بار', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'اطلاعات کشتارگاه ها' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + if serializer: + for data in serializer: + killer = 'کشتارگاه' if data['killer'] == False else 'کشتارکن' + list1 = [ + m, + killer, + data['name'], + data['kill_house_operator']['user']['fullname'], + data['kill_house_operator']['user']['mobile'], + data['kill_house_operator']['user']['city'], + data['killing_info']['kill_house_requests_count'], + data['killing_info']['kill_house_requests_quantity'], + data['killing_info']['kill_house_requests_weight'], + data['killing_info']['kill_house_free_bar_count'], + data['killing_info']['kill_house_free_bar_quantity'], + data['killing_info']['kill_house_free_bar_weight'], + data['killing_info']['province_kill_requests_quantity'], + + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + total_kill_house_requests_count = sum( + data.get('killing_info', {}).get('kill_house_requests_count', 0) for data in serializer + ) + total_kill_house_requests_quantity = sum( + data.get('killing_info', {}).get('kill_house_requests_quantity', 0) for data in serializer + ) + total_kill_house_requests_weight = sum( + data.get('killing_info', {}).get('kill_house_requests_weight', 0) for data in serializer + ) + total_kill_house_free_bar_count = sum( + data.get('killing_info', {}).get('kill_house_free_bar_count', 0) for data in serializer + ) + total_kill_house_free_bar_quantity = sum( + data.get('killing_info', {}).get('kill_house_free_bar_quantity', 0) for data in serializer + ) + total_kill_house_free_bar_weight = sum( + data.get('killing_info', {}).get('kill_house_free_bar_weight', 0) for data in serializer + ) + total_province_kill_requests_quantity = sum( + data.get('killing_info', {}).get('province_kill_requests_quantity', 0) for data in serializer + ) + + # ایجاد لیست از مقادیر جمع‌زده شده + totals_list = [ + total_kill_house_requests_count, + total_kill_house_requests_quantity, + total_kill_house_requests_weight, + total_kill_house_free_bar_count, + total_kill_house_free_bar_quantity, + total_kill_house_free_bar_weight, + total_province_kill_requests_quantity + ] + for item in range(len(totals_list)): + cell = worksheet.cell(row=3, column=item + 6, value=totals_list[item]) + value = totals_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + total_kill_house_requests_count, + total_kill_house_requests_quantity, + total_kill_house_requests_weight, + total_kill_house_free_bar_count, + total_kill_house_free_bar_quantity, + total_kill_house_free_bar_weight, + total_province_kill_requests_quantity + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="داشبورد.xlsx"'.encode( # noqa + 'utf-8') + response.write(output.getvalue()) + return response + + +def steward_allocation_excel(request): + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + value = request.GET.get('value') + search = request.GET.get('search') + kill_house_key = request.GET.get('kill_house_key') + steward_key = request.GET.get('steward_key') + allocations_type = request.GET.get('type') + trash = request.GET.get('trash') + return_trash = request.GET.get('return_trash') + filters = { + 'to_cold_house__isnull': True, + 'calculate_status': True, + } + if trash == 'true': + filters['trash'] = True + filters['active_expire_date_time'] = True + else: + filters['trash'] = False + if allocations_type == 'KillHouse': + filters['kill_house__isnull'] = False + elif allocations_type == 'Steward': + filters['steward__isnull'] = False + if return_trash == 'true': + filters['return_trash'] = True + filters['trash'] = False + if kill_house_key and kill_house_key != 'all': + filters['kill_house__key'] = kill_house_key + if steward_key and steward_key != 'all': + filters['steward__key'] = steward_key + + if date1: + filters['date__date__gte'] = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + filters['date__date__lte'] = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + filters['kill_house'] = kill_house + elif role == 'Steward': + steward = Guilds.objects.get(user=user, trash=False) + filters['steward'] = steward + allocations = StewardAllocation.objects.filter(**filters).order_by('-date') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + allocations = allocations.filter( + build_query(StewardAllocationDashboardFilterSet, value) + ) + serializer = InProvinceAllocationSerializer(allocations, many=True).data + + excel_options = [ + 'ردیف', + 'تاریخ ثبت', + 'نوع تخصیص', + 'فروشنده', + 'تلفن فروشنده', + 'شهر فروشنده', + 'خریدار', + 'تلفن خریدار', + 'شماره واسط خریدار', + 'شهر خریدار', + 'پوز مباشر', + 'پوز صنف', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد توزیع', + 'وزن کل توزیع', + 'وزن توزیع به مباشر', + 'وزن توزیع به صنف', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + if trash == 'true': + excel_description(worksheet, 'A1', f'تخصیصات حذف شده', size=11, color='red', + row2='D1') + elif return_trash == 'true': + excel_description(worksheet, 'A1', f'تخصیصات برگشت داده شده', size=11, color='red', + row2='D1') + else: + excel_description(worksheet, 'A1', f'تخصیصات صورت گرفته', size=11, color='red', + row2='D1') + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if serializer: + for allocation in serializer: + l += 1 + + allocation_type = allocation.get('allocation_type', '') + + seller_name = '' + seller_mobile = '' + seller_city = '' + buyer_name = '' + buyer_mobile = '' + buyer_city = '' + + kill_house = (allocation or {}).get('kill_house', {}) or {} + steward = allocation.get('steward', {}) or {} + kill_house_operator = kill_house.get('kill_house_operator', {}) or {} + kill_house_user = kill_house_operator.get('user', {}) or {} + kill_house_user_city = kill_house_user.get('city', {}) or {} + + if allocation_type == 'killhouse_steward': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + seller_city = kill_house_user_city.get('city_name', '') + allocation_type = 'کشتارگاه به مباشر' + + to_steward = allocation.get('to_steward', {}) + buyer_name = to_steward.get('guilds_name', '') + buyer_mobile = to_steward.get('user', {}).get('mobile', '') + buyer_city = to_steward.get('user', {}).get('city_name', '') + + elif allocation_type == 'killhouse_guild': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + seller_city = kill_house_user_city.get('city_name', '') + allocation_type = 'کشتارگاه به صنف' + + to_guilds = allocation.get('to_guilds', {}) + if to_guilds: + buyer_name = to_guilds.get('guilds_name', '') + buyer_mobile = to_guilds.get('user', {}).get('mobile', '') + buyer_city = to_guilds.get('user', {}).get('city_name', '') + elif allocation_type == 'steward_guild': + seller_name = steward.get('guilds_name', '') + seller_mobile = steward.get('user', {}).get('mobile', '') + seller_city = steward.get('user', {}).get('city_name', '') + allocation_type = 'مباشر به صنف' + + to_guilds = allocation.get('to_guilds', {}) + if to_guilds: + buyer_name = to_guilds.get('guilds_name', '') + buyer_mobile = to_guilds.get('user', {}).get('mobile', '') + buyer_city = to_guilds.get('user', {}).get('city_name', '') + elif allocation_type == 'steward_steward': + seller_name = steward.get('guilds_name', '') + seller_mobile = steward.get('user', {}).get('mobile', '') + seller_city = steward.get('user', {}).get('city_name', '') + allocation_type = 'مباشر به مباشر' + + to_steward = allocation.get('to_steward', {}) + buyer_name = to_steward.get('guilds_name', '') + buyer_mobile = to_steward.get('user', {}).get('mobile', '') + buyer_city = to_steward.get('user', {}).get('city_name', '') + + elif allocation_type == 'killhouse_killhouse': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + seller_city = kill_house_user_city.get('city_name', '') + allocation_type = 'کشتارگاه به کشتارگاه' + + to_kill_house = allocation.get('to_kill_house', {}) + buyer_name = to_kill_house.get('name', '') + buyer_mobile = to_kill_house.get('kill_house_operator', {}).get('user', {}).get('mobile', '') + buyer_city = to_kill_house.get('kill_house_operator', {}).get('user', {}).get('city', {}).get( + 'city_name', '') + + if allocation['sell_type'] == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = 'آزاد' + system_registration_code = 'ارسال شده' if allocation['system_registration_code'] == True else 'ارسال نشده' + if allocation['state'] == 'pending': + state = 'در انتظار تایید' + elif trash == 'true': + state = 'حذف شده' + elif return_trash == 'true': + state = 'برگشت داده شده' + else: + state = 'تایید شده' + try: + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S.%f') + except ValueError: + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S') + list1 = [ + m, + str(shamsi_date(date, set_datetime=True)), + allocation_type, + seller_name, + seller_mobile, + seller_city, + buyer_name, + buyer_mobile, + allocation.get('interface_number') or '-', + buyer_city, + allocation.get('steward_pos_status') or 'ندارد', + allocation.get('guild_pos_status') or 'ندارد', + sell_type, + allocation.get('amount', 0), + allocation.get('total_amount', 0), + allocation.get('weight_of_carcasses', 0), + allocation.get('receiver_real_weight_of_carcasses', 0), + str(allocation.get('registration_code') or '-'), + system_registration_code, + state, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + total_amount = sum( + allocation.get('total_amount', 0) for allocation in serializer) + + weight_of_carcasses_allocations = sum( + allocation.get('weight_of_carcasses', 0) for allocation in serializer) + + receiver_real_weight_of_carcasses_allocations = sum( + allocation.get('receiver_real_weight_of_carcasses', 0) for allocation in serializer) + + allocations_aggregates = allocations.aggregate( + total_count=Count('id'), + total_weight=Sum('real_weight_of_carcasses'), + total_steward_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward__isnull=False)), + total_guild_weight=Sum('real_weight_of_carcasses', filter=Q(to_guilds__isnull=False)), + ) + + value_header_list2 = [ + allocations_aggregates['total_count'] or 0, + int(allocations_aggregates['total_weight'] or 0), + int(allocations_aggregates['total_steward_weight'] or 0), + int(allocations_aggregates['total_guild_weight'] or 0), + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="توزیع داخل استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def sevrence_kill_house_steward_allocation_excel(request): + filterset_class = StewardAllocationDashboardFilterSet + + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + value = request.GET.get('value') + search = request.GET.get('search') + allocations_type = request.GET.get('type') + filters = { + 'trash': False, + 'to_cold_house__isnull': True + } + if allocations_type == 'KillHouse': + filters['kill_house__isnull'] = False + elif allocations_type == 'Steward': + filters['steward__isnull'] = False + + if date1: + filters['date__date__gte'] = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + filters['date__date__lte'] = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocations = StewardAllocation.objects.filter(**filters) + if value and search == 'filter': + if value != 'undefined' and value.strip(): + allocations = allocations.filter( + build_query(filterset_class, value) + ) + serializer = InProvinceAllocationSerializer(allocations, many=True).data + + kill_house_names = list({(allocation.get('kill_house') or {}).get('name') + for allocation in serializer if (allocation.get('kill_house') or {}).get('name')}) + + excel_options = [ + 'ردیف', + 'تاریخ ثبت', + 'نوع تخصیص', + 'فروشنده', + 'تلفن فروشنده', + 'خریدار', + 'تلفن خریدار', + 'نوع فروش', + 'قیمت هر کیلو(ریال)', + 'قیمت کل', + 'وزن تخصیصی', + 'وزن تایید شده', + 'کد احراز', + 'وضعیت کد احراز', + 'وضعیت', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + l = 5 + m = 1 + + if serializer: + for kill_house_name in kill_house_names: + kill_house = KillHouse.objects.get(trash=False, name=kill_house_name) + sheet_name = kill_house.name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد توزیع', + 'وزن کل توزیع', + 'وزن توزیع به مباشر', + 'وزن توزیع به صنف', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'توزیع داخل استان کشتارگاه {sheet_name}', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + red_font = Font(color="C00000", bold=True) + + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + allocations = allocations.filter(kill_house=kill_house) + serializer1 = InProvinceAllocationSerializer(allocations, many=True).data + for allocation in serializer1: + l += 1 + + allocation_type = allocation.get('allocation_type', '') + + seller_name = '' + seller_mobile = '' + buyer_name = '' + buyer_mobile = '' + + kill_house = allocation.get('kill_house', {}) + kill_house_operator = kill_house.get('kill_house_operator', {}) + kill_house_user = kill_house_operator.get('user', {}) + + if allocation_type == 'killhouse_steward': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + allocation_type = 'کشتارگاه به مباشر' + + to_steward = allocation.get('to_steward', {}) + buyer_name = to_steward.get('guilds_name', '') + buyer_mobile = to_steward.get('user', {}).get('mobile', '') + + elif allocation_type == 'killhouse_guild': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + allocation_type = 'کشتارگاه به صنف' + + to_guilds = allocation.get('to_guilds', {}) + if to_guilds: + buyer_name = to_guilds.get('guilds_name', '') + buyer_mobile = to_guilds.get('user', {}).get('mobile', '') + + elif allocation_type == 'killhouse_killhouse': + seller_name = kill_house.get('name', '') + seller_mobile = kill_house_user.get('mobile', '') + allocation_type = 'کشتارگاه به کشتارگاه' + + to_kill_house = allocation.get('to_kill_house', {}) + buyer_name = to_kill_house.get('name', '') + buyer_mobile = to_kill_house.get('kill_house_operator', {}).get('user', {}).get('mobile', '') + + if allocation['sell_type'] == 'exclusive': + sell_type = 'اختصاصی' + else: + sell_type = 'آزاد' + system_registration_code = 'ارسال شده' if allocation[ + 'system_registration_code'] == True else 'ارسال نشده' + state = 'در انتظار تایید' if allocation['state'] == 'pending' else 'تایید شده' + try: + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S.%f') + except ValueError: + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S') + list1 = [ + m, + str(shamsi_date(date)), + allocation_type, + seller_name, + seller_mobile, + buyer_name, + buyer_mobile, + sell_type, + allocation.get('amount', 0), + allocation.get('total_amount', 0), + allocation.get('weight_of_carcasses', 0), + allocation.get('receiver_real_weight_of_carcasses', 0), + str(allocation.get('registration_code') or '-'), + system_registration_code, + state, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + if isinstance(value, int): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + total_amount = sum( + allocation.get('total_amount', 0) for allocation in serializer1) + + weight_of_carcasses_allocations = sum( + allocation.get('weight_of_carcasses', 0) for allocation in serializer1) + + receiver_real_weight_of_carcasses_allocations = sum( + allocation.get('receiver_real_weight_of_carcasses', 0) for allocation in serializer1) + + allocations_aggregates = allocations.aggregate( + total_count=Count('id'), + total_weight=Sum('real_weight_of_carcasses'), + total_steward_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward__isnull=False)), + total_guild_weight=Sum('real_weight_of_carcasses', filter=Q(to_guilds__isnull=False)), + ) + + value_header_list2 = [ + allocations_aggregates['total_count'] or 0, + int(allocations_aggregates['total_weight'] or 0), + int(allocations_aggregates['total_steward_weight'] or 0), + int(allocations_aggregates['total_guild_weight'] or 0), + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + total_amount, + weight_of_carcasses_allocations, + receiver_real_weight_of_carcasses_allocations, + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="توزیع داخل استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def free_sale_out_province_excel(request): + filterset_fields = [ + 'type_car', + 'pelak', + 'clearance_code', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'buyer__fullname', + 'buyer__first_name', + 'buyer__last_name', + 'buyer__mobile', + 'buyer__unit_name', + 'buyer_name', + 'buyer_mobile', + 'province', + 'city', + + ] + + filterset_class = KillHouseFreeSaleBarInformationFilterSet + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if 'type' in request.GET: + role = request.GET['role'] + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + if role in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + elif role in ['CityJahad', 'CityPoultry', 'CityOperator']: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + else: + if role in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + trash=False) + + + elif role in ['CityJahad', 'CityPoultry', 'CityOperator']: + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__system_address__city=user.city, + trash=False) + + + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False) + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + if 'search' in request.GET: + kill_house_free_sale_bar_info_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined' and request.GET['value'].strip(): + + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_house_free_sale_bar_info + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_house_free_sale_bar_info) + kill_house_free_sale_bar_info_list = ps.filter() + kill_house_free_sale_bar_info = [] if len( + kill_house_free_sale_bar_info_list) == 0 else kill_house_free_sale_bar_info_list + + + else: + now = datetime.datetime.now().date() + date = datetime.datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + date__year=date.year, + date__month=date.month, + date__day=date.day, + trash=False) + buyers = len(kill_house_free_sale_bar_info.values_list('buyer', flat=True).distinct()) + + serializer = KillHouseFreeSaleBarInformationSerializer(kill_house_free_sale_bar_info, many=True).data + + excel_options = [ + 'ردیف', + 'تاریخ', + 'فروشنده', + 'تلفن فروشنده', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'کد قرنطینه', + 'وزن استعلامی', + 'وزن لاشه' + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد فروش', + 'خریدار', + 'وزن کل لاشه', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'فروش به خارج از استان', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if serializer: + for allocation in serializer: + l += 1 + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S') + kill_house = allocation.get('kill_house', {}) + kill_house_operator = kill_house.get('kill_house_operator', {}) + kill_house_user = kill_house_operator.get('user', {}) + buyer = allocation.get('buyer', {}) + + list1 = [ + m, + str(shamsi_date(date)), + kill_house.get('name', ''), + kill_house_user.get('mobile', ''), + buyer.get('fullname', ''), + buyer.get('mobile', ''), + buyer.get('unit_name', ''), + buyer.get('province', ''), + buyer.get('city', ''), + allocation.get('clearance_code', ''), + allocation.get('quarantine_weight_of_carcasses', 0), + allocation.get('real_weight_of_carcasses', 0), + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + total_quarantine_weight = sum( + allocation.get('quarantine_weight_of_carcasses', 0) for allocation in serializer + ) + + total_real_weight = sum( + allocation.get('real_weight_of_carcasses', 0) for allocation in serializer + ) + total_real_weight = sum( + allocation.get('real_weight_of_carcasses', 0) for allocation in serializer + ) + + value_header_list2 = [ + len(kill_house_free_sale_bar_info), + buyers, + total_real_weight, + + ] + + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_quarantine_weight, + total_real_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="فروش به خارج از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def steward_free_sale_out_province_excel(request): + filterset_class = StewardFreeSaleBarInformationFilterSet + filterset_fields = [ + 'steward__user__fullname', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__mobile', + 'buyer__user__fullname', + 'buyer__user__first_name', + 'buyer__user__last_name', + 'buyer__user__mobile', + 'province', + 'city', + 'province' + 'buyer_name' + 'buyer_mobile' + + ] + + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + filters = {'trash': False} + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if role == 'Steward': + steward = Guilds.objects.get(user=user, trash=False) + filters['steward'] = steward + + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + bars = StewardFreeSaleBarInformation.objects.filter(**filters).order_by('-date') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + bars = bars.filter( + build_query(filterset_class, value) + ) + + serializer = StewardFreeSaleBarInformationSerializer(bars, many=True).data + excel_options = [ + 'ردیف', + 'تاریخ', + 'فروشنده', + 'تلفن فروشنده', + 'خریدار', + 'تلفن خریدار', + 'نام واحد', + 'استان', + 'شهر', + 'کد قرنطینه', + 'وزن استعلامی', + 'وزن لاشه' + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + header_list2 = [ + 'تعداد فروش', + 'خریدار', + 'وزن کل لاشه', + + ] + + for col_num, option in enumerate(header_list2, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + excel_description(worksheet, 'A1', f'فروش به خارج از استان مباشرین', size=11, color='red', + row2='D1') + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + + if serializer: + for allocation in serializer: + l += 1 + date = datetime.datetime.strptime(allocation['date'], '%Y-%m-%dT%H:%M:%S') + steward = allocation.get('steward', {}) + steward_user = steward.get('user', {}) + + buyer = allocation.get('buyer', {}) + + list1 = [ + m, + str(shamsi_date(date, in_value=True)), + steward.get('guilds_name', ''), + steward_user.get('mobile', ''), + buyer.get('fullname', ''), + buyer.get('mobile', ''), + buyer.get('unit_name', ''), + buyer.get('province', ''), + buyer.get('city', ''), + allocation.get('clearance_code', ''), + allocation.get('quarantine_weight_of_carcasses', 0), + allocation.get('weight_of_carcasses', 0), + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + buyers = len(set(bars.values_list('buyer', flat=True).distinct())) + + total_quarantine_weight = sum( + allocation.get('quarantine_weight_of_carcasses', 0) for allocation in serializer + ) + + total_real_weight = sum( + allocation.get('weight_of_carcasses', 0) for allocation in serializer + ) + + value_header_list2 = [ + len(bars), + buyers, + bars.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0, + + ] + + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_quarantine_weight, + total_real_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="فروش به خارج از استان مباشرین.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def total_steward_dashboard_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + stewards = Guilds.objects.filter(trash=False, steward=True, active=True).select_related('user').only('user', + 'guilds_name', + 'steward').order_by( + 'id') + + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, allocation_to_steward__date__date__lte=date2) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards1 = list(set(chain(allocation_stewards, free_bar_stewards))) + + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted']) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards1 = list(set(chain(allocation_stewards, free_bar_stewards))) + + serializer = RealGuildsForDashboardSerializer(stewards1, many=True, context={'request': request}).data + + header_list2 = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'ماهیت', + 'شهر', + 'مانده انبار فعلی', + 'تعداد کل بارها', + 'وزن کل بارها', + 'تعداد بار وارد شده به انبار', + 'کل وزن ورودی به انبار', + 'تعداد فروش رفته', + 'کل وزن فروش رفته', + 'تعداد بار درون استان', + 'وزن بار درون استان', + 'تعداد بار لاشه خارج استان', + 'وزن بار لاشه خارج استان', + 'وزن فروش داخل استان', + 'وزن فروش خارج استان', + + ] + create_header(worksheet, header_list2, 1, 12, height=21.8, width=20, border_style='thin') + excel_description(worksheet, 'A2', f'اطلاعات جامع انبار', + size=11, color='red', row2='B4') + if serializer: + l = 13 + m = 1 + + for data in serializer: + steward_type = 'مباشر' if data.get('steward') == True else 'صنف' + list1 = [ + m, + data.get('user', {}).get('fullname', ''), + data.get('user', {}).get('mobile', ''), + f'{steward_type}({data.get("guilds_name", "")})', + data.get("address", {}).get('city', {}).get('name'), + data.get('ware_house_info', {}).get('remain_weight', 0), + data.get('ware_house_info', {}).get('total_bars_count', 0), + data.get('ware_house_info', {}).get('total_bars_weight', 0), + data.get('ware_house_info', {}).get('total_entered_bars_count', 0), + data.get('ware_house_info', {}).get('total_entered_bars_weight', 0), + data.get('ware_house_info', {}).get('total_in_out_province_bars_count', 0), + data.get('ware_house_info', {}).get('total_in_out_province_bars_weight', 0), + data.get('ware_house_info', {}).get('input_bars_count', 0), + data.get('ware_house_info', {}).get('input_bars_weight', 0), + data.get('ware_house_info', {}).get('free_bars_count', 0), + data.get('ware_house_info', {}).get('free_bars_weight', 0), + data.get('ware_house_info', {}).get('in_province_bars_weight', 0), + data.get('ware_house_info', {}).get('out_province_bars_weight', 0), + + ] + + create_value(worksheet, list1, l, 1, border_style='thin', m=m) + m += 1 + l += 1 + header_list2 = [ + 'وزن کل بارها', + 'وزن وارد شده به انبار', + 'وزن توزیع شده داخل استان', + 'وزن توزیع شده خارج استان', + 'مانده انبار', + + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='C00000', border_style='thin') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + stewards_filter = {'trash': False, 'steward': True, 'active': True} + + stewards = Guilds.objects.filter(**stewards_filter).select_related('user').only('user', 'guilds_name', + 'steward').order_by( + 'id') + + products = RolesProducts.objects.filter(guild__in=stewards, trash=False, name='مرغ گرم').first() + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, allocation_to_steward__date__date__lte=date2, + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True, + date__date__gte=date1, date__date__lte=date2, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2, warehouse=True) + segmentations = PosSegmentation.objects.filter(guild__in=stewards, trash=False, warehouse=True, + date__date__gte=date1, date__date__lte=date2) + transactions = ProductsTransactions.objects.filter(product=products, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward__in=stewards) | Q(guild__in=stewards), trash=False, + date__date__gte=date1, date__lte=date2, + warehouse=True) + + + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count').values_list('id', flat=True) + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count').values_list('id', flat=True) + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False, + warehouse=True) + segmentations = PosSegmentation.objects.filter(guild__in=stewards, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=products, transaction__paid=True, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward__in=stewards) | Q(guild__in=stewards), trash=False, + warehouse=True) + + allocations_aggregates = allocations.aggregate( + total_input_bars_count=Count('id', filter=Q(to_steward__isnull=False)), + total_input_bars_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward__isnull=False)), + total_input_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, quota='governmental')), + total_input_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, quota='free')), + total_output_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, receiver_state__in=('pending', 'accepted'))), + total_output_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, + receiver_state__in=('pending', 'accepted'), + quota='governmental')), + total_output_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, + receiver_state__in=('pending', 'accepted'), quota='free')), + total_input_entered_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state='accepted')), + + total_input_entered_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, + receiver_state='accepted', quota='governmental')), + + total_input_entered_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state='accepted', + quota='free')), + + ) + + free_bars_aggregates = free_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses') + ) + + free_sale_bars_aggregates = free_sale_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses'), + total_governmental_weight=Sum('weight_of_carcasses', quota='governmental'), + total_free_weight=Sum('weight_of_carcasses', quota='free'), + + ) + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + + total_in_province_governmental_input_weight = allocations_aggregates[ + 'total_input_entered_governmental_bars_weight'] or 0 + total_in_province_free_input_weight = allocations_aggregates['total_input_entered_free_bars_weight'] or 0 + total_free_buying_input_weight = free_bars_aggregates['total_weight'] or 0 + + total_in_province_governmental_output_weight = allocations_aggregates[ + 'total_output_governmental_bars_weight'] or 0 + total_in_province_free_output_weight = allocations_aggregates['total_output_free_bars_weight'] or 0 + total_governmental_free_sale_weight = free_sale_bars_aggregates['total_governmental_weight'] or 0 + total_free_free_sale_weight = free_sale_bars_aggregates['total_free_weight'] or 0 + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_governmental_input_weight = total_in_province_governmental_input_weight + total_free_input_weight = total_in_province_free_input_weight + total_free_buying_input_weight + total_input_weight = total_governmental_input_weight + total_free_input_weight + + total_governmental_output_weight = total_in_province_governmental_output_weight + total_governmental_free_sale_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_in_province_free_output_weight + total_free_free_sale_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + total_output_weight = total_governmental_output_weight + total_free_output_weight + + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight if ( + ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight) > 0 else 0 + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - archives_free_weight if ( + ( + total_free_input_weight - total_free_output_weight) - archives_free_weight) > 0 else 0 + total_remain_weight = total_governmental_remain_weight + total_free_remain_weight + + input_allocations_weight = allocations_aggregates['total_input_bars_weight'] or 0 + input_entered_allocations_weight = allocations_aggregates['total_input_entered_bars_weight'] or 0 + output_allocations_weight = allocations_aggregates['total_output_bars_weight'] or 0 + free_bars_weight = free_bars_aggregates['total_weight'] or 0 + free_sale_bars_weight = free_sale_bars_aggregates['total_weight'] or 0 + remain_weight = int( + (input_entered_allocations_weight + free_bars_weight) - ( + free_sale_bars_weight + output_allocations_weight + archives_weight)) + + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + shamsi_date1 = shamsi_date(date1) + shamsi_date2 = shamsi_date(date2) + excel_description(worksheet, 'A2', f' اطلاعات جامع انبار از تاریخ {shamsi_date1} تا تاریخ {shamsi_date2}', + size=11, color='red', row2='B4') + + else: + excel_description(worksheet, 'A2', f'اطلاعات جامع انبار', + size=11, color='red', row2='B4') + + result = { + "total_bars_weight": int(input_allocations_weight + free_bars_weight), + "total_entered_bars_weight": int(input_entered_allocations_weight + free_bars_weight), + "in_province_bars_weight": int(output_allocations_weight), + "out_province_bars_weight": int(free_sale_bars_weight), + "remain_weight": remain_weight, + } + + value_header_list = [ + result['total_bars_weight'], + result['total_entered_bars_weight'], + result['in_province_bars_weight'], + result['out_province_bars_weight'], + result['remain_weight'], + + ] + create_value(worksheet, value_header_list, 4, 3, border_style='thin') + + # محاسبه مجموع هر یک از فیلدها + sum_remain_weight = sum(data.get('ware_house_info', {}).get('remain_weight', 0) for data in serializer) + sum_total_bars_count = sum(data.get('ware_house_info', {}).get('total_bars_count', 0) for data in serializer) + sum_total_bars_weight = sum(data.get('ware_house_info', {}).get('total_bars_weight', 0) for data in serializer) + sum_total_entered_bars_count = sum( + data.get('ware_house_info', {}).get('total_entered_bars_count', 0) for data in serializer) + sum_total_entered_bars_weight = sum( + data.get('ware_house_info', {}).get('total_entered_bars_weight', 0) for data in serializer) + sum_total_in_out_province_bars_count = sum( + data.get('ware_house_info', {}).get('total_in_out_province_bars_count', 0) for data in serializer) + sum_total_in_out_province_bars_weight = sum( + data.get('ware_house_info', {}).get('total_in_out_province_bars_weight', 0) for data in serializer) + sum_input_bars_count = sum(data.get('ware_house_info', {}).get('input_bars_count', 0) for data in serializer) + sum_input_bars_weight = sum(data.get('ware_house_info', {}).get('input_bars_weight', 0) for data in serializer) + sum_free_bars_count = sum(data.get('ware_house_info', {}).get('free_bars_count', 0) for data in serializer) + sum_free_bars_weight = sum(data.get('ware_house_info', {}).get('free_bars_weight', 0) for data in serializer) + sum_in_province_bars_weight = sum( + data.get('ware_house_info', {}).get('in_province_bars_weight', 0) for data in serializer) + sum_out_province_bars_weight = sum( + data.get('ware_house_info', {}).get('out_province_bars_weight', 0) for data in serializer) + sum_warehouse_total_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0) for data in serializer) + # ایجاد لیست نهایی برای ردیف مجموع + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + sum_remain_weight, + sum_total_bars_count, + sum_total_bars_weight, + sum_total_entered_bars_count, + sum_total_entered_bars_weight, + sum_total_in_out_province_bars_count, + sum_total_in_out_province_bars_weight, + sum_input_bars_count, + sum_input_bars_weight, + sum_free_bars_count, + sum_free_bars_weight, + sum_in_province_bars_weight, + sum_out_province_bars_weight, + ] + + create_value(worksheet, summary_list, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش جامع انبار مباشرین.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def detail_of_killing_and_warehouse_excel(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + red_font = Font(color="C00000", bold=True) + sheet_list = [ + 'تخصیصات بدون بار', + 'بارهای تخلیه نشده', + 'بار های در انتظار ورود به انبار' + ] + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + for name in sheet_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'تخصیصات بدون بار': + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', + trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', + trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', + trash=False).first().amount + worksheet['H3'] = 'در این قسمت تخصیصات فاقد بار نمایش داده میشود' + merge_range1 = 'H3:K3' + worksheet.merge_cells(merge_range1) + worksheet['H3'].font = Font(color="C00000", bold=True) + worksheet['H3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + province_kill_request = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), + return_to_province=False, + archive_wage=False, + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by( + 'kill_request__recive_date') + + if wage_counting_type == 'carcass': + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن لاشه ملاک تعرفه', + 'جمع کل تعرفه', + ] + else: + header_list = [ + 'تعداد سفارشات', + 'تعداد کل', + 'وزن کل', + 'وزن ملاک تعرفه', + 'جمع کل تعرفه', + ] + for col_num, option in enumerate(header_list, 3): + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[3].height = 20.8 + if wage_counting_type == 'carcass': + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن لاشه ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + else: + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'وزن ملاک تعرفه ', + 'تعرفه (ریال)', + 'تعرفه تخصیص(ریال)', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + create_header_freez(worksheet, excel_options, 1, 6, header_row=7, width=20) + # for col_num, option in enumerate(excel_options, 1): + # col_letter = get_column_letter(col_num) + # cell = worksheet.cell(row=6, column=col_num, value=option) + # cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + # cell.fill = blue_fill + # cell.font = Font(size=10, bold=True, color='D9FFFFFF') + # if len(option) > worksheet.column_dimensions[col_letter].width: + # worksheet.column_dimensions[col_letter].width = len(option) + 3 + # + # # تنظیم ارتفاع سطر + # # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + # worksheet.row_dimensions[6].height = 19 + # worksheet.freeze_panes = worksheet['A7'] + # max_col = worksheet.max_column + # range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + # worksheet.auto_filter.ref = range_str + l = 6 + m = 1 + for province_kill in province_kill_request: + + kill_date_1 = shamsi_date(province_kill.province_request.poultry_request.send_date) + + if province_kill.kill_request.slaughter_house is not None: + kill_place = province_kill.kill_request.slaughter_house.name + else: + kill_place = province_kill.kill_request.kill_house.name + + total_amount = province_kill.total_wage_amount + if wage_counting_type == 'carcass': + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight * 0.75, + province_live_wage_amount, + (province_kill.total_killed_weight * 0.75) * province_live_wage_amount, + + ] + else: + list1 = [ + m, + str(province_kill.province_request.poultry_request.order_code), + province_kill.province_request.poultry_request.poultry.unit_name, + province_kill.province_request.poultry_request.poultry.user.mobile, + province_kill.province_request.poultry_request.poultry.address.city.name, + str(kill_date_1), + kill_place, + province_kill.province_request.poultry_request.hatching.chicken_breed, + province_kill.total_killed_quantity, + province_kill.total_killed_weight, + province_kill.province_request.poultry_request.Index_weight, + province_kill.total_killed_weight, + province_live_wage_amount, + (province_kill.total_killed_weight) * province_live_wage_amount, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + m += 1 + total_weight = \ + province_kill_request.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_killed_quantity = \ + province_kill_request.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_wage_amount = \ + province_kill_request.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + if wage_counting_type == 'carcass': + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight * 0.75, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + value_list = [ + m - 1, + total_killed_quantity, + total_weight, + total_weight, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=4, column=item + 3, value=value_list[item]) + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + if wage_counting_type == 'carcass': + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight * 0.75, + province_live_wage_amount, + (total_weight * 0.75) * province_live_wage_amount, + + ] + else: + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_killed_quantity, + total_weight, + '', + total_weight, + province_live_wage_amount, + (total_weight) * province_live_wage_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بارهای تخلیه نشده': + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state').values( + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date', + 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + ) + filtered_kill_reqs_not_assigment_but_have_code1 = filtered_kill_reqs.filter( + assignment_state_archive='pending') + poultry_request = ( + PoultryRequest.objects.filter(trash=False, + pk__in=filtered_kill_reqs_not_assigment_but_have_code1.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + # worksheet['B1'] = f'بارهای تخلیه نشده با کد قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({shamsi_date(date1)}) تا تاریخ:({shamsi_date(date2)})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment_but_have_code1.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment_but_have_code1.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs_not_assigment_but_have_code1: + for kill in filtered_kill_reqs_not_assigment_but_have_code1: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment_but_have_code1.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_assigment_but_have_code1.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code1), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + kill_house = KillHouse.objects.filter(trash=False).select_related( + 'system_address__province').first() + + if 'date1' in request.GET and request.GET['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() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + else: + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + ware_house_confirmation=False, trash=False, calculate_status=True).order_by( + '-kill_request__recive_date').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', + 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'bar_document_status__title' + ) + + if 'search' in request.GET: + filtered_kill_reqs = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + filtered_kill_reqs = [] if len(filtered_kill_reqs) == 0 else filtered_kill_reqs + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + + ] + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'میانگین وزن ', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + # برای بالای هدر + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + create_header(worksheet, header_list2, 6, 4, height=21.8, color='green') + + create_header(worksheet, header_list, 9, 4, height=21.8) + + header_list2 = [ + 'ردیف', + 'نام محصول', + 'وزن خریدهای دولتی داخل استان(کیلوگرم)', + 'وزن خریدهای آزاد داخل استان(کیلوگرم)', + 'وزن خریدهای خارج استان(کیلوگرم)', + 'کل ورودی به انبار(کیلوگرم)', + 'کل فروش(کیلوگرم)', + 'مانده انبار(کیلوگرم)', + + ] + create_header(worksheet, header_list2, 6, 1, height=21.8, color='FF0000') + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + q = 2 + w = 1 + for product in products: + value_header_list = [ + w, + product.name, + product.province_governmental_carcasses_weight, + product.province_free_carcasses_weight, + product.free_buying_carcasses_weight, + product.total_carcasses_weight, + product.real_allocated_weight, + product.total_remain_weight, + + ] + create_value(worksheet, value_header_list, q, 6) + q += 1 + w += 1 + + kill_house_name = '' + if filtered_kill_reqs.exists(): + kill_house_name = filtered_kill_reqs.first()['killhouse_user__name'] + excel_description(worksheet, 'A1', f'بارهای {kill_house_name} در انتظار ورود به انبار (کشتار داخل استان)', + size=11, color='red', row2='E1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='C3') + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 7, 8, 20) + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + l = 7 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + net_weighte, real_quantity, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 5, 6) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="اطلاعات جامع بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def management_all_poultry_and_warehouse(request): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + sheet_names = ['گزارش جوجه ریزی', 'جوجه ریزی بیش از 60 روز', 'گزارش بارها', 'اطلاعات کشتار روزانه', + 'عملکرد خریداران', 'گزارش سند ها', + 'اطلاعات جامع انبار و توزیع', + 'بارهای بدون مجوز'] + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + for name in sheet_names: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if sheet_name == 'گزارش جوجه ریزی': + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + filtered_poultry_hatch = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q( + date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن روز', + 'سن بایگانی', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + ] + + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', + 'گزارش جوجه ریزی های فعال از تاریخ {0} تا {1}'.format(from_date_1, from_date_2), + color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + poultry_ids = filtered_poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + if poultry_hatching.archive == True: + archive_age = poultry_hatching.chicken_age + else: + archive_age = '-' + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + f'{poultry_hatching.poultry.user.fullname} ({poultry_hatching.poultry.user.mobile})', + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + archive_age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + chain_company, + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'جوجه ریزی بیش از 60 روز': + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + filtered_poultry_hatch = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q( + date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False, chicken_age__gte=60).select_related( + 'poultry', + 'poultry__user').order_by( + '-chicken_age') + + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن روز', + 'سن بایگانی', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + ] + + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', + 'گزارش جوجه ریزی های بزرگ تر از 60 روز از تاریخ {0} تا {1}'.format(from_date_1, + from_date_2), + color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + poultry_ids = filtered_poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + if poultry_hatching.archive == True: + archive_age = poultry_hatching.chicken_age + else: + archive_age = '-' + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + f'{poultry_hatching.poultry.user.fullname} ({poultry_hatching.poultry.user.mobile})', + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + archive_age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + chain_company, + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_name == 'گزارش بارها': + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'province_kill_request__kill_house_price', + 'price', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'province_kill_request__kill_house_price', + 'price', + 'bar_document_status__title' + ) + filtered_kill_reqs = filtered_kill_request + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + 'اختلاف مجوز', + + ] + + from_date_1 = shamsi_date(date1) + + to_date_1 = shamsi_date(date2) + + # worksheet.sheet_view.rightToLeft = True + # worksheet.insert_rows(1) + # cell = worksheet.cell(row=1, column=1) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'حجم بارهای ایجاد شده', + 'وزن بارهای ایجاد شده', + 'میانگین وزن بارهای ایجاد شده', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'حجم بارها', + 'وزن بارها', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + header_list3 = [ + 'درصد بارهای دارای کد قرنطینه', + 'درصد تعداد بارهای احراز شده از قرنطینه', + 'درصد تعداد بارهای تکمیل شده کشتارگاه', + 'درصد وزن نهایی در کشتارگاه نسبت به وزن کل', + 'درصد بارهای فاقد کد قرنطینه', + 'درصد بارهای اختلاف دار در قرنطینه و رصدیار', + 'درصد تعداد بارهای ورودی به انبار', + 'درصد وزن لاشه ها در انبار نسبت به وزن کل', + 'درصد وزن لاشه در انبار نسبت به وزن نهایی در کشتارگاه', + + ] + create_header(worksheet, header_list, 9, 2, height=21.8) + + create_header(worksheet, header_list2, 6, 2, height=21.8, color='green') + + create_header(worksheet, header_list3, 6, 5, height=43, color='orange', text_color='0D0D0D') + create_header_freez(worksheet, excel_options, 1, 8, 9, height=21, len_with=True) + + excel_description(worksheet, 'B1', 'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی', color='red', + row2='D1') + + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + excel_description(worksheet, 'B2', f'استان {name}', color='red', row2='D2') + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + + l = 8 + m = 1 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + if kill['assignment_state_archive'] == 'True' or kill['ware_house_confirmation'] == True: + net_weighte = kill['accepted_real_weight'] + real_quantity = kill['accepted_real_quantity'] + else: + net_weighte = 0 + real_quantity = 0 + net_weighte2, real_quantity2, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = int((weight_loss1 / kill['accepted_real_weight']) * 100) if kill[ + 'accepted_real_weight'] > 0 else 0 + defreent_quarantine = kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else 0 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + round(kill['accepted_real_weight'], 1), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else quarantine_quantity + + ] + if defreent_quarantine < 0: + different_cell = 51 + different_value = 'اختلاف مجوز' + else: + different_cell = None + different_value = None + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=different_cell, + different_value=different_value) + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + + province_kill_request = ProvinceKillRequest.objects.filter( + pk__in=filtered_kill_reqs.values( + 'province_kill_request')).aggregate( + total_quantity_melak=Sum('total_killed_quantity'), + total_weight_melak=Sum('total_killed_weight'), + ) + + accepted_real_quantity_melak = province_kill_request['total_quantity_melak'] or 0 + + accepted_real_wight_melak = province_kill_request['total_weight_melak'] or 0 + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity_melak, + accepted_real_wight_melak, + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 3, 6) + value_header_list2 = [ + f'%{round((has_code * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((has_qarantine * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((len(bar_complete) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_net_weighte) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((len(hasnt_code1) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((difference_bar * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((all_state_ware_house_confirmation * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_net_weighte), 2) if int(all_net_weighte) > 0 else 0}' + ] + create_value(worksheet, value_header_list2, 6, 6) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + elif sheet_name == 'اطلاعات کشتار روزانه': + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + header_list = [ + 'ردیف', + 'تاریخ', + 'حجم درخواست کشتار مرغدار', + 'وزن درخواست کشتار مرغدار', + 'حجم خرید های مستقیم', + 'وزن خرید های مستقیم', + 'حجم خرید های خارج از استان (زنده)', + 'وزن خرید های خارج از استان (زنده)', + 'وزن خرید های خارج از استان (لاشه)', + 'حجم کل تخصیصات (خرید مستقیم/ مرغدار)', + 'وزن کل تخصیصات (خرید مستقیم/ مرغدار)', + 'حجم فروش به خارج استان', + 'وزن فروش به خارج استان', + 'حجم بارها', + 'وزن بارها', + 'لاشه تولیدی امروز با احتساب 25درصد افت کشتار' + ] + + create_header(worksheet, header_list, 1, 3, height=25, width=25, border_style='thin', + color='C00000') + excel_description(worksheet, 'A1', + 'گزارش کشتار روزانه استان از تاریخ {0} تا {1}'.format(from_date_1, from_date_2), + color='red', + row2='E1') + m = 1 + l = 4 + + current_date = date1 + for day in range((date2 - date1).days + 1): + kill_house_free_bar = KillHouseFreeBarInformation.objects.filter( + trash=False, + archive_wage=False, + date__date=current_date + ).only( + 'quantity', + 'live_weight', + 'number_of_carcasses', + 'weight_of_carcasses', + 'send_date', + 'type', + 'out' + ) + kill_house_free_bar_aggregates = kill_house_free_bar.aggregate( + total_quantity_live=Sum('quantity', filter=Q(create_date__date=current_date, buy_type='live')), + total_weight_live=Sum('live_weight', filter=Q(create_date__date=current_date, buy_type='live')), + total_quantity_carcass=Sum('number_of_carcasses', + filter=Q(date__date=current_date, buy_type='carcass')), + total_weight_carcass=Sum('weight_of_carcasses', + filter=Q(date__date=current_date, buy_type='carcass')), + warehouse_total_weight_carcass=Sum('weight_of_carcasses', filter=Q(date__date=current_date)), + + ) + + poultry_request = PoultryRequest.objects.filter( + trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + temporary_trash=False, + temporary_deleted=False, + send_date__date=current_date + ).only( + 'quantity', + 'Index_weight', + 'send_date' + ) + + poultry_request_aggregates = poultry_request.aggregate( + total_quantity=Sum('quantity', + filter=Q(send_date__date=current_date, direct_buying=False, out=False)), + total_weight=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=current_date, direct_buying=False, out=False)), + total_direct_buying_quantity=Sum('quantity', + filter=Q(send_date__date=current_date, direct_buying=True)), + total_direct_buying_weight=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=current_date, direct_buying=True)), + poultry_out_province_quantity=Sum('quantity', filter=Q(out=True, send_date__date=current_date)), + poultry_out_province_weight=Sum(F('quantity') * F('Index_weight'), + filter=Q(out=True, send_date__date=current_date)), + total_killing_ave_weight=Avg('Index_weight', filter=Q(send_date__date=current_date)), + # yesterday + + total_killing_ave_weight_yesterday=Avg('Index_weight', filter=Q(send_date__date=current_date)) + ) + + province_kill_request = ProvinceKillRequest.objects.filter( + trash=False, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date=current_date + ).only( + 'total_killed_quantity', + 'total_killed_weight', + 'kill_request__recive_date' + ) + + province_kill_request_aggregates = province_kill_request.aggregate( + + total_quantity=Sum('total_killed_quantity', filter=Q(kill_request__recive_date__date=current_date)), + total_weight_carcass=Sum('total_killed_weight', + filter=Q(kill_request__recive_date__date=current_date)) * 0.75, + province_kill_request_total_weight=Sum('total_killed_weight', + filter=Q(kill_request__recive_date__date=current_date)), + + ) + + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date=current_date, + temporary_trash=False, + temporary_deleted=False + ).select_related('kill_request').only( + 'ware_house_accepted_real_weight', + 'weight_loss', + 'ware_house_confirmation', + 'kill_request__recive_date' + ) + + kill_house_request_aggregates = kill_house_request.aggregate( + + total_quantity=Sum( + 'accepted_real_quantity', + filter=Q(kill_request__recive_date__date=current_date) + ), + + total_weight=Sum( + 'accepted_real_weight', + filter=Q(kill_request__recive_date__date=current_date) + ) + ) + + province_kill_request_weight = province_kill_request_aggregates[ + 'province_kill_request_total_weight'] or 0 + + bars_live_weight = kill_house_free_bar_aggregates['total_weight_live'] or 0 + + bars_carcasses_weight = kill_house_free_bar_aggregates['total_weight_carcass'] or 0 + + total_loss_weight = int( + ((province_kill_request_weight + bars_live_weight) * 0.75) + bars_carcasses_weight) + + list1 = [ + m, + str(shamsi_date(current_date, in_value=True)), + poultry_request_aggregates.get('total_quantity') or 0, + poultry_request_aggregates.get('total_weight') or 0, + poultry_request_aggregates.get('total_direct_buying_quantity') or 0, + poultry_request_aggregates.get('total_direct_buying_weight') or 0, + + kill_house_free_bar_aggregates.get('total_quantity_live') or 0, + kill_house_free_bar_aggregates.get('total_weight_live') or 0, + kill_house_free_bar_aggregates.get('total_weight_carcass') or 0, + province_kill_request_aggregates.get('total_quantity') or 0, + int(province_kill_request_aggregates.get('province_kill_request_total_weight') or 0), + poultry_request_aggregates.get('poultry_out_province_quantity') or 0, + poultry_request_aggregates.get('poultry_out_province_weight') or 0, + kill_house_request_aggregates.get('total_quantity') or 0, + kill_house_request_aggregates.get('total_weight') or 0, + int(total_loss_weight or 0) + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + current_date += datetime.timedelta(days=1) + city_operators = CityOperator.objects.filter(trash=False) + all_admin_all_violation = 0 + city_operator_name = city_operators.values_list('user__fullname', flat=True).distinct() + + city_operator_all_violation_all = PoultryHatching.objects.filter(trash=False, + violation_reporter__isnull=False, + violation_reporter__in=city_operator_name).count() + row_list = l + 7 + row_city = l + 5 + + len_poultry = 0 + len_all_hatching = 0 + all_hathcing_quantitya_all = 0 + all_province_requests_quantity = 0 + all_province_requests_weight = 0 + len_hatching = 0 + all_hatching_quantity = 0 + all_hatching_lest_over = 0 + all_out_poultry_request_quantity = 0 + all_out_poultry_request_weight = 0 + city_operator_poultry_request_quantity_all = 0 + city_operator_poultry_request_weight_all = 0 + direct_bying_poultry_request_quantity_all = 0 + direct_bying_poultry_request_weight_all = 0 + province_operaor_poultry_request_quantity_all = 0 + province_operaor_poultry_request_weight_all = 0 + row_list2 = l + 2 + worksheet[f'D{row_list2}'] = f'اطلاعات کشتار به تفکیک تعاونی ها از تاریخ {from_date_1} تا {from_date_2}' + worksheet[f'D{row_list2}'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'D{row_list2}'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'D{row_list2}:J{row_list2 + 1}' + worksheet.merge_cells(merge_range1) + for city_operator in city_operators: + poultry_request = PoultryRequest.objects.filter(trash=False, + out_province_request_cancel=False, + province_state='accepted', + poultry__city_operator=city_operator.unit_name) + poultry = Poultry.objects.filter(trash=False, city_operator=city_operator.unit_name) + out_poultry_request = poultry_request.filter(out=True) + city_operator_poultry_request = poultry_request.filter(direct_buying=False, + registrar__role='CityOperator') + province_operaor_poultry_request = poultry_request.filter(~Q(registrar__role='CityOperator'), + direct_buying=False) + direct_bying_poultry_request = poultry_request.filter(direct_buying=True) + + province_requests = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name + , return_to_province=False, + state__in=('accepted', 'pending')) + + province_requests_quantity = \ + province_requests.aggregate( + total=Sum('total_killed_quantity'))[ + 'total'] or 0 + + province_requests_weight = \ + province_requests.aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + + kill_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request__in=province_requests) + all_hatching = PoultryHatching.objects.filter(trash=False, poultry__in=poultry) + all_violation = all_hatching.filter(violation_reporter__isnull=False) + city_operator_all_violation = all_violation.filter( + violation_reporter=city_operator.user.fullname).count() + admin_all_violation = all_violation.filter(~Q(violation_reporter=city_operator.user.fullname)).count() + + hathcing_quantity_all = \ + all_hatching.aggregate( + total=Sum(F('quantity')))[ + 'total'] or 0 + out_poultry_request_quantity_all = \ + out_poultry_request.aggregate( + total=Sum(F('quantity')))[ + 'total'] or 0 + out_poultry_request_weight_all = \ + out_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + hatching = all_hatching.filter(archive=False, allow_hatching='pending') + hatching_quantity = \ + hatching.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + hatching_lest_over = \ + hatching.aggregate( + total=Sum('left_over'))[ + 'total'] or 0 + city_operator_poultry_request_quantity = \ + city_operator_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + city_operator_poultry_request_weight = \ + city_operator_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + direct_bying_poultry_request_quantity = \ + direct_bying_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + direct_bying_poultry_request_weight = \ + direct_bying_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + province_operaor_poultry_request_quantity = \ + province_operaor_poultry_request.aggregate( + total=Sum('quantity'))[ + 'total'] or 0 + province_operaor_poultry_request_weight = \ + province_operaor_poultry_request.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + all_admin_all_violation += admin_all_violation + + len_poultry += len(poultry) + len_all_hatching += len(all_hatching) + all_hathcing_quantitya_all += hathcing_quantity_all + all_province_requests_quantity += province_requests_quantity + all_province_requests_weight += province_requests_weight + len_hatching += len(hatching) + all_hatching_quantity += hatching_quantity + all_hatching_lest_over += hatching_lest_over + all_out_poultry_request_quantity += out_poultry_request_quantity_all + all_out_poultry_request_weight += out_poultry_request_weight_all + province_requests_date = province_requests.filter( + province_request__poultry_request__send_date__date__gte=date1 + , province_request__poultry_request__send_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name + ) + city_operator_poultry_request_quantity_all += city_operator_poultry_request_quantity + city_operator_poultry_request_weight_all += city_operator_poultry_request_weight + direct_bying_poultry_request_quantity_all += direct_bying_poultry_request_quantity + direct_bying_poultry_request_weight_all += direct_bying_poultry_request_weight + province_operaor_poultry_request_quantity_all += province_operaor_poultry_request_quantity + province_operaor_poultry_request_weight_all += province_operaor_poultry_request_weight + + list2 = [ + 'ردیف', + 'ماهیت', + 'خریدار', + 'نام و نام خانوادگی مالک', + 'تلفن مالک', + 'شهر', + 'تعداد سفارش', + 'حجم سفارش', + 'تعداد بار ', + 'حجم بار', + 'وزن بار', + 'وزن لاشه', + ] + + for col_num, option in enumerate(list2, 2): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=row_list, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + if option in ['تعداد سفارش', 'حجم سفارش', 'تعداد بار ', 'حجم بار', 'وزن بار', 'وزن لاشه']: + cell.fill = PatternFill(start_color="FF0000", fill_type="solid") + # worksheet.row_dimensions[row_list].height = 35 + worksheet.column_dimensions[col_letter].width = 17 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + m = 1 + kill_houses1 = province_requests_date.values_list('killhouse_user', flat=True).distinct() + kill_houses = KillHouse.objects.filter(id__in=kill_houses1) + len_province_requests_kill = 0 + all_province_quantity = 0 + len_kill_requests_date = 0 + all_accepted_assignment_real_quantity = 0 + all_accepted_assignment_real_weight = 0 + all_ware_house_accepted_real_weight = 0 + for kill_house in kill_houses: + province_requests_kill = province_requests_date.filter(killhouse_user=kill_house) + + province_quantity = \ + province_requests_kill.aggregate( + total=Sum('main_quantity'))[ + 'total'] or 0 + + kill_requests_date = kill_requests.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + killhouse_user=kill_house, + province_kill_request__in=province_requests_kill) + + accepted_assignment_real_quantity = \ + kill_requests_date.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + accepted_assignment_real_weight = \ + kill_requests_date.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + len_province_requests_kill += len(province_requests_kill) + all_province_quantity += province_quantity + len_kill_requests_date += len(kill_requests_date) + all_accepted_assignment_real_quantity += accepted_assignment_real_quantity + all_accepted_assignment_real_weight += int(accepted_assignment_real_weight) + all_ware_house_accepted_real_weight += int(accepted_assignment_real_weight) * 0.75 + # killer='کشتارگاه' if kill_house.killer == False else 'کشتارکن' + if kill_house.killer == True and kill_house.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + killer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif kill_house.killer == True and kill_house.type == 'public': + killer_type = 'کشتارکن عمومی' + else: + killer_type = 'کشتارگاه' + list1 = [ + m, + killer_type, + kill_house.name, + kill_house.kill_house_operator.user.fullname, + kill_house.kill_house_operator.user.mobile, + kill_house.kill_house_operator.user.city.name, + len(province_requests_kill), + province_quantity, + len(kill_requests_date), + accepted_assignment_real_quantity, + int(accepted_assignment_real_weight), + int(accepted_assignment_real_weight) * 0.75, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row_list + 1, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + row_list += 1 + m += 1 + + else: + row_list += 5 + worksheet[f'F{row_city}'] = f'{city_operator.unit_name}' + worksheet[f'F{row_city}'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'F{row_city}'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'F{row_city}:H{row_city + 1}' + worksheet.merge_cells(merge_range1) + + row_city += len(kill_houses) + 5 + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + len_province_requests_kill, + all_province_quantity, + len_kill_requests_date or 0, + all_accepted_assignment_real_quantity or 0, + all_accepted_assignment_real_weight or 0, + all_ware_house_accepted_real_weight or 0, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=row_city - 2, column=item + 2, value=list2[item]) + value = list2[item] + cell.font = Font(size=10, bold=True, color='FFFFFF') + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'عملکرد خریداران': + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).exclude( + id__in=kill_house_ids).order_by( + 'id') + + serializer = KillHouseForPerformanceDashboardSerializer(kill_houses, many=True, + context={'date1': date1, 'date2': date2, }).data + + excel_options = [ + 'ردیف', + 'ماهیت', + 'کشتارگاه / کشتارکن', + 'مالک', + 'شهر', + 'تعداد بارهای داخل استان', + 'حجم بارهای داخل استان', + 'وزن بارهای داخل استان', + 'تعداد بارهای خارج استان', + 'حجم بارهای خارج استان', + 'وزن بارهای خارج استان', + 'حجم تخصیصات بدون بار', + 'حجم کل بارها', + 'وزن کل بارها', + 'میانگین وزن', + 'حجم وارد شده به انبار', + 'وزن وارد شده به انبار', + 'حجم وارد نشده به انبار', + 'وزن وارد نشده به انبار' + ] + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + create_header(worksheet, excel_options, 1, 2, height=25, width=25, border_style='thin', + color='C00000') + + worksheet['B1'] = f'اطلاعات کشتار زنده کشتارگاه' + + worksheet['E1'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'E1:H1' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 2 + m = 1 + + if serializer: + for data in serializer: + list1 = [ + m, # ردیف + 'کشتارگاه' if data['killer'] else 'کشتارکن', # ماهیت + data['name'], # کشتارگاه / کشتارکن + data['kill_house_operator']['user']['fullname'], # مالک + data['kill_house_operator']['user']['city'], # شهر + data['killing_info']['kill_house_requests_count'], # تعداد بارهای داخل استان + data['killing_info']['kill_house_requests_quantity'], # حجم بارهای داخل استان + data['killing_info']['kill_house_requests_weight'], # وزن بارهای داخل استان + data['killing_info']['kill_house_free_bar_count'], # تعداد بارهای خارج استان + data['killing_info']['kill_house_free_bar_quantity'], # حجم بارهای خارج استان + data['killing_info']['kill_house_free_bar_weight'], # وزن بارهای خارج استان + data['killing_info']['province_kill_requests_quantity'], # حجم تخصیصات بدون بار + data['killing_info']['total_quantity'], # حجم کل بارها + data['killing_info']['total_weight'], # وزن کل بارها + data['killing_info']['total_avg_weight'], # میانگین وزن + data['killing_info']['kill_house_requests_ware_house_true_quantity'], # حجم وارد شده به انبار + data['killing_info']['kill_house_requests_ware_house_true_weight'], # وزن وارد شده به انبار + data['killing_info']['kill_house_requests_ware_house_false_quantity'], # حجم وارد نشده به انبار + data['killing_info']['kill_house_requests_ware_house_false_weight'] # وزن وارد نشده به انبار + ] + m += 1 + + create_value(worksheet, list1, l + 1, 1) + l += 1 + + total_province_kill_requests_count = sum( + data['killing_info']['kill_house_requests_count'] for data in serializer) + total_province_kill_requests_quantity = sum( + data['killing_info']['kill_house_requests_quantity'] for data in serializer) + total_province_kill_requests_weight = sum( + data['killing_info']['kill_house_requests_weight'] for data in serializer) + total_kill_house_requests_count = sum( + data['killing_info']['kill_house_free_bar_count'] for data in serializer) + total_kill_house_requests_quantity = sum( + data['killing_info']['kill_house_free_bar_quantity'] for data in serializer) + total_kill_house_requests_weight = sum( + data['killing_info']['kill_house_free_bar_weight'] for data in serializer) + total_quantity = sum(data['killing_info']['province_kill_requests_quantity'] for data in serializer) + total_kill_house_free_bar_quantity = sum( + data['killing_info']['total_quantity'] for data in serializer) + total_kill_house_free_bar_weight = sum( + data['killing_info']['total_weight'] for data in serializer) + total_avg_weight = sum(data['killing_info']['total_avg_weight'] for data in serializer) / len( + serializer) if serializer else 0 + total_ware_house_true_quantity = sum( + data['killing_info']['kill_house_requests_ware_house_true_quantity'] for data in serializer) + total_ware_house_true_weight = sum( + data['killing_info']['kill_house_requests_ware_house_true_weight'] for data in serializer) + total_ware_house_false_quantity = sum( + data['killing_info']['kill_house_requests_ware_house_false_quantity'] for data in serializer) + total_ware_house_false_weight = sum( + data['killing_info']['kill_house_requests_ware_house_false_weight'] for data in serializer) + + # لیست مجموع مقادیر + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + total_province_kill_requests_count, + total_province_kill_requests_quantity, + total_province_kill_requests_weight, + total_kill_house_requests_count, + total_kill_house_requests_quantity, + total_kill_house_requests_weight, + total_quantity, + total_kill_house_free_bar_quantity, + total_kill_house_free_bar_weight, + total_avg_weight, + total_ware_house_true_quantity, + total_ware_house_true_weight, + total_ware_house_false_quantity, + total_ware_house_false_weight + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 2, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + kill_house_ids = KillHousePercentage.objects.filter(kill_house__type='exclusive', trash=False).values_list( + 'kill_house', flat=True) + kill_houses = KillHouse.objects.filter(out_province=False, active=True, trash=False).exclude( + id__in=kill_house_ids).order_by( + 'id') + + kill_houses = kill_houses.annotate( + allocation_count=Count( + 'kill_house_steward_allocation', + filter=Q(kill_house_steward_allocation__receiver_state__in=['pending', 'accepted']) + ) + ).order_by( + '-allocation_count' + ) + new_serializer = KillHouseForProvinceWareHouseDashboardSerializer(kill_houses, many=True, + context={'request': request}).data + + excel_options = [ + 'ردیف', + 'خریدار', + 'ماهیت', + 'شهر', + 'مانده انبار فعلی', + 'وزن کل فروش (لاشه)', + 'وزن فروش داخل استان (لاشه)', + 'وزن فروش خارج استان (لاشه)' + ] + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + new_l = l + 6 + + create_header(worksheet, excel_options, 1, new_l, height=25, width=25, border_style='thin', + color='C00000') + new_m = 1 + worksheet[f'B{new_l - 1}'] = f'اطلاعات توزیع گوشت مرغ کشتارگاه' + + worksheet[f'E{new_l - 1}'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet[f'B{new_l - 1}'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = f'B{new_l - 1}:D{new_l - 1}' + merge_range2 = f'E{new_l - 1}:H{new_l - 1}' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet[f'B{new_l - 1}'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + if new_serializer: + for data in new_serializer: + list1 = [ + new_m, # ردیف + data['name'], # خریدار + 'کشتارگاه' if data['killer'] else 'کشتارکن', # ماهیت + data['kill_house_operator']['user']['city']['name'], # شهر + data['ware_house_info']['product_remain_weight'], # مانده انبار فعلی + data['ware_house_info']['total_sell'], # وزن کل فروش (لاشه) + data['ware_house_info']['total_kill_house_allocations_weight'], # وزن فروش داخل استان (لاشه) + data['ware_house_info']['total_kill_house_free_sale__bar_carcasses_weight'] + # وزن فروش خارج استان (لاشه) + ] + new_m += 1 + + create_value(worksheet, list1, new_l + 1, 1) + new_l += 1 + + total_inventory = sum(data['ware_house_info']['product_remain_weight'] for data in new_serializer) + total_sales = sum(data['ware_house_info']['total_sell'] for data in new_serializer) + total_in_province = sum( + data['ware_house_info']['total_kill_house_allocations_weight'] for data in new_serializer) + total_out_province = sum( + data['ware_house_info']['total_kill_house_free_sale__bar_carcasses_weight'] for data in + new_serializer) + + list2 = [ + 'مجموع ==>', + '', + '', + '', + total_inventory, + total_sales, + total_in_province, + total_out_province + ] + for item in range(len(list2)): + cell = worksheet.cell(row=new_l + 2, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'گزارش سند ها': + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + kill_house_request = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False) + bar_duc = BarDocumentStatus.objects.filter(trash=False).order_by('id').values_list('title', flat=True) + excel_options = [ + 'ردیف', + 'نام گشتارگاه', + 'تلفن', + 'شهر', + 'تعداد کل بار', + 'بارهای دارای سند', + 'بارهای فاقد سند', + *bar_duc + + ] + + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + excel_description(worksheet, 'B1', + 'گزارش سند ها از تاریخ {0} تا {1}'.format(from_date_1, from_date_2), + color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + l = 5 + m = 1 + total_counts = {title: 0 for title in bar_duc} + + for kill_house in kill_houses: + kill_house_request1 = kill_house_request.filter( + trash=False, + killhouse_user=kill_house, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False + ) + + # محاسبه تعداد کل بارها + bar_count = kill_house_request1.count() + + # محاسبه تعداد بارهای دارای سند و فاقد سند + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True').count() + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + + # محاسبه تعداد هر وضعیت سند + status_counts = {} + for title in bar_duc: + count = kill_house_request1.filter(bar_document_status__title=title).count() + status_counts[title] = count + total_counts[title] += count + + list1 = [ + m, + kill_house.name, + kill_house.kill_house_operator.user.mobile, + kill_house.kill_house_operator.user.city.name, + bar_count, + bar_assigment_true_count, + bar_assigment_pending_count, + *[status_counts.get(title, 0) for title in bar_duc] + ] + + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + bar_count = kill_house_request.count() + + bar_assigment_true_count = kill_house_request.filter(assignment_state_archive='True').count() + bar_assigment_pending_count = kill_house_request.filter(assignment_state_archive='pending').count() + + list2 = [ + 'مجموع', + '', + '', + '', + bar_count, + bar_assigment_true_count, + bar_assigment_pending_count, + *[total_counts[title] for title in bar_duc] + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + elif sheet_name == 'اطلاعات جامع انبار و توزیع': + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id').annotate( + allocation_count=Count( + 'kill_house_steward_allocation', + filter=Q(kill_house_steward_allocation__receiver_state__in=['pending', 'accepted']) + ) + ).order_by( + '-allocation_count' + ) + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + serializer = KillHouseForProvinceWareHouseDashboardSerializer(kill_houses, many=True, + context={'request': request}).data + header_list2 = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'ماهیت', + 'شهر', + 'مانده انبار فعلی', + 'کل وزن ورودی به انبار', + 'کل وزن فروش رفته', + 'حجم تخصیصات بدون ماشین', + 'تعداد بار درون استان', + 'حجم بار درون استان', + 'وزن بار درون استان', + 'تعداد بار زنده خارج استان', + 'حجم بار زنده خارج استان', + 'وزن بار زنده خارج استان', + 'تعداد بار لاشه خارج استان', + 'حجم بار لاشه خارج استان', + 'وزن بار لاشه خارج استان', + 'تعداد کل بارها', + 'حجم کل بارها', + 'وزن کل بارها', + 'تعداد بار وارد شده به انبار', + 'تعداد بار وارد نشده به انبار', + 'حجم بار وارد نشده به انبار', + 'وزن بار وارد نشده به انبار', + 'وزن فروش داخل استان', + 'وزن فروش خارج استان', + + ] + create_header(worksheet, header_list2, 1, 6, height=21.8, width=20, border_style='thin') + l = 7 + if serializer: + + m = 1 + + for data in serializer: + list1 = [ + m, + data.get('name', ''), + data.get('kill_house_operator', {}).get('user', {}).get('mobile', ''), + 'کشتارگاه' if not data.get('killer', False) else 'کشتارکن', + data.get('kill_house_operator', {}).get('user', {}).get('city', {}).get('name', ''), + data.get('ware_house_info', {}).get('product_remain_weight', 0), + data.get('ware_house_info', {}).get('warehouse_total_entered_carcasses_weight', 0), + data.get('ware_house_info', {}).get('total_sell', 0), + data.get('ware_house_info', {}).get('province_kill_requests_quantity', 0), + data.get('ware_house_info', {}).get('total_province_bars', 0), + data.get('ware_house_info', {}).get('total_province_bars_quantity', 0), + data.get('ware_house_info', {}).get('total_province_bars_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_quantity', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_carcasses_bar', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses_weight', 0), + data.get('ware_house_info', {}).get('total_bars', 0), + data.get('ware_house_info', {}).get('warehouse_total_quantity', 0), + data.get('ware_house_info', {}).get('warehouse_total_weight', 0), + int(data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0)), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars', 0), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0), + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_allocations_weight', 0), + data.get('ware_house_info', {}).get('total_kill_house_free_sale__bar_carcasses_weight', 0), + + ] + + create_value(worksheet, list1, l, 1, border_style='thin', m=m) + m += 1 + l += 1 + header_list2 = [ + 'حجم کل بارها', + 'وزن کل بارها', + 'وزن وارد شده به انبار', + 'وزن توزیع شده داخل استان', + 'وزن توزیع شده خارج استان', + 'مانده انبار', + + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='C00000', + border_style='thin') + products = RolesProducts.objects.filter(kill_house__in=kill_houses, trash=False) + product_remain_weight = products.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + shamsi_date1 = shamsi_date(date1) + shamsi_date2 = shamsi_date(date2) + excel_description(worksheet, 'A2', + f' اطلاعات جامع انبار و توزیع کشتارگاه{shamsi_date1} تا تاریخ {shamsi_date2}', + size=11, color='red', row2='B4') + + else: + excel_description(worksheet, 'A2', f'اطلاعات جامع انبار', + size=11, color='red', row2='B4') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter( + Q(date__date__gte=date1, + date__date__lte=date2, + buy_type='carcass') | Q( + create_date__date__gte=date1, create_date__date__lte=date2, buy_type='live'), + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + date__date__gte=date1, + date__date__lte=date2, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, + trash=False, + receiver_state__in=( + 'pending', 'accepted'), + date__date__gte=date1, + date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True) + else: + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses), + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter( + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house__in=kill_houses, + trash=False, + receiver_state__in=( + 'pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True) + total_kill_house_requests_quantity = \ + kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + total_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_weight = \ + kill_house_requests.filter(ware_house_confirmation=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + kill_house_free_bar_informations_live = kill_house_free_bar_informations.filter(buy_type='live') + kill_house_free_bar_informations_carcasses = kill_house_free_bar_informations.filter( + buy_type='carcass') + total_kill_house_free_bar_quantity = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('quantity'))['total'] or 0 + total_kill_house_free_bar_weight = \ + kill_house_free_bar_informations_live.aggregate(total=Sum('live_weight'))['total'] or 0 + total_kill_house_free_bar_carcasses = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations_carcasses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_entered_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_weight = \ + kill_house_free_Sale_bar_informations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + warehouse_total_weight = total_kill_house_requests_weight + total_kill_house_free_bar_weight + total_kill_house_free_bar_carcasses_weight + warehouse_total_entered_carcasses_weight = total_entered_kill_house_requests_carcasses_weight + total_entered_kill_house_free_bar_carcasses_weight + + result = { + "product_remain_weight": int(warehouse_total_entered_carcasses_weight - ( + total_kill_house_allocations_weight + total_kill_house_free_sale__bar_carcasses_weight)), + "warehouse_total_quantity": int( + total_kill_house_requests_quantity + total_kill_house_free_bar_quantity + total_kill_house_free_bar_carcasses), + "warehouse_total_weight": int(warehouse_total_weight), + "warehouse_total_entered_carcasses_weight": int(warehouse_total_entered_carcasses_weight), + "total_kill_house_allocations_weight": int(total_kill_house_allocations_weight), + "total_kill_house_free_sale_bar_carcasses_weight": int( + total_kill_house_free_sale__bar_carcasses_weight), + + } + + value_header_list = [ + result['warehouse_total_quantity'], # حجم کل بارها + result['warehouse_total_weight'], # وزن کل بارها + result['warehouse_total_entered_carcasses_weight'], # وزن وارد شده به انبار + result['total_kill_house_allocations_weight'], # وزن توزیع شده داخل استان + result['total_kill_house_free_sale_bar_carcasses_weight'], + result['product_remain_weight'] # مانده انبار + ] + create_value(worksheet, value_header_list, 4, 3, border_style='thin') + + # محاسبه مجموع هر یک از فیلدها + sum_product_remain_weight = sum( + data.get('ware_house_info', {}).get('product_remain_weight', 0) for data in serializer) + sum_previous_product_remain_weight = sum( + data.get('ware_house_info', {}).get('previous_product_remain_weight', 0) for data in serializer) + sum_province_kill_requests_quantity = sum( + data.get('ware_house_info', {}).get('province_kill_requests_quantity', 0) for data in + serializer) + sum_total_province_bars = sum( + data.get('ware_house_info', {}).get('total_province_bars', 0) for data in serializer) + sum_total_province_bars_quantity = sum( + data.get('ware_house_info', {}).get('total_province_bars_quantity', 0) for data in serializer) + sum_total_province_bars_weight = sum( + data.get('ware_house_info', {}).get('total_province_bars_weight', 0) for data in serializer) + sum_total_kill_house_free_bar = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar', 0) for data in serializer) + sum_total_kill_house_free_live_bar_quantity = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_quantity', 0) for data in + serializer) + sum_total_kill_house_free_live_bar_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_live_bar_weight', 0) for data in + serializer) + sum_total_kill_house_free_carcasses_bar = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_carcasses_bar', 0) for data in + serializer) + sum_total_kill_house_free_bar_carcasses = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses', 0) for data in + serializer) + sum_total_kill_house_free_bar_carcasses_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_bar_carcasses_weight', 0) for data in + serializer) + sum_total_bars = sum(data.get('ware_house_info', {}).get('total_bars', 0) for data in serializer) + sum_warehouse_total_quantity = sum( + data.get('ware_house_info', {}).get('warehouse_total_quantity', 0) for data in serializer) + sum_warehouse_total_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_weight', 0) for data in serializer) + sum_warehouse_total_entered_bars = sum( + int(data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0)) for data in + serializer) + sum_warehouse_total_entered_carcasses_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_carcasses_weight', 0) for data in + serializer) + sum_warehouse_total_not_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars', 0) for data in + serializer) + sum_warehouse_total_not_entered_bars_quantity = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_quantity', 0) for data in + serializer) + sum_warehouse_total_not_entered_bars_weight = sum( + data.get('ware_house_info', {}).get('warehouse_total_not_entered_bars_weight', 0) for data in + serializer) + sum_total_kill_house_allocations_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_allocations_weight', 0) for data in + serializer) + sum_total_kill_house_free_sale__bar_carcasses_weight = sum( + data.get('ware_house_info', {}).get('total_kill_house_free_sale__bar_carcasses_weight', 0) for + data in + serializer) + sum_total_sell = sum( + data.get('ware_house_info', {}).get('total_sell', 0) for data in + serializer) + sum_warehouse_total_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0) for data in + serializer) + + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + sum_product_remain_weight, + sum_warehouse_total_entered_bars, + sum_total_sell, + sum_province_kill_requests_quantity, + sum_total_province_bars, + sum_total_province_bars_quantity, + sum_total_province_bars_weight, + sum_total_kill_house_free_bar, + sum_total_kill_house_free_live_bar_quantity, + sum_total_kill_house_free_live_bar_weight, + sum_total_kill_house_free_carcasses_bar, + sum_total_kill_house_free_bar_carcasses, + sum_total_kill_house_free_bar_carcasses_weight, + sum_total_bars, + sum_warehouse_total_quantity, + sum_warehouse_total_weight, + sum_warehouse_total_entered_bars, + sum_warehouse_total_not_entered_bars, + sum_warehouse_total_not_entered_bars_quantity, + sum_warehouse_total_not_entered_bars_weight, + sum_total_kill_house_allocations_weight, + sum_total_kill_house_free_sale__bar_carcasses_weight + ] + + create_value(worksheet, summary_list, l + 1, 1, color='green') + + new_l = l + 7 + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + stewards = Guilds.objects.filter(trash=False, steward=True).select_related('user').only('user', + 'guilds_name', + 'steward').order_by( + 'id') + + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, + allocation_to_steward__date__date__lte=date2) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards1 = list(set(chain(allocation_stewards, free_bar_stewards))) + + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted']) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards1 = list(set(chain(allocation_stewards, free_bar_stewards))) + + serializer = RealGuildsForDashboardSerializer(stewards1, many=True, context={'request': request}).data + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, + allocation_to_steward__date__date__lte=date2) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True, + date__date__gte=date1, date__date__lte=date2) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2) + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted']) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count').values_list('id', flat=True) + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count').values_list('id', flat=True) + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False) + + header_list2 = [ + 'ردیف', + 'خریدار', + 'تلفن خریدار', + 'ماهیت', + 'شهر', + 'مانده انبار فعلی', + 'تعداد کل بارها', + 'وزن کل بارها', + 'تعداد بار وارد شده به انبار', + 'کل وزن ورودی به انبار', + 'تعداد فروش رفته', + 'کل وزن فروش رفته', + 'تعداد بار درون استان', + 'وزن بار درون استان', + 'تعداد بار لاشه خارج استان', + 'وزن بار لاشه خارج استان', + 'وزن فروش داخل استان', + 'وزن فروش خارج استان', + + ] + create_header(worksheet, header_list2, 1, new_l, height=21.8, width=20, border_style='thin') + + allocations_aggregates = allocations.aggregate( + total_input_bars_count=Count('id', filter=Q(to_steward__isnull=False)), + total_input_bars_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward__isnull=False)), + total_output_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, + receiver_state__in=('pending', 'accepted'))), + total_input_entered_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state='accepted')) + ) + + free_bars_aggregates = free_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses') + ) + + free_sale_bars_aggregates = free_sale_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses'), + + ) + + input_allocations_weight = allocations_aggregates['total_input_bars_weight'] or 0 + input_entered_allocations_weight = allocations_aggregates['total_input_entered_bars_weight'] or 0 + output_allocations_weight = allocations_aggregates['total_output_bars_weight'] or 0 + free_bars_weight = free_bars_aggregates['total_weight'] or 0 + free_sale_bars_weight = free_sale_bars_aggregates['total_weight'] or 0 + remain_weight = int( + (input_entered_allocations_weight + free_bars_weight) - ( + free_sale_bars_weight + output_allocations_weight)) + + if date1: + date1 = datetime.datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(date2), '%Y-%m-%d').date() + shamsi_date1 = shamsi_date(date1) + shamsi_date2 = shamsi_date(date2) + excel_description(worksheet, f'A{new_l - 2}', + f' اطلاعات جامع انبار و توزیع مباشرین از تاریخ {shamsi_date1} تا تاریخ {shamsi_date2}', + size=11, color='red', row2=f'B{new_l - 1}') + + sum_remain_weight = sum(data.get('ware_house_info', {}).get('remain_weight', 0) for data in serializer) + sum_total_bars_count = sum( + data.get('ware_house_info', {}).get('total_bars_count', 0) for data in serializer) + sum_total_bars_weight = sum( + data.get('ware_house_info', {}).get('total_bars_weight', 0) for data in serializer) + sum_total_entered_bars_count = sum( + data.get('ware_house_info', {}).get('total_entered_bars_count', 0) for data in serializer) + sum_total_entered_bars_weight = sum( + data.get('ware_house_info', {}).get('total_entered_bars_weight', 0) for data in serializer) + sum_total_in_out_province_bars_count = sum( + data.get('ware_house_info', {}).get('total_in_out_province_bars_count', 0) for data in serializer) + sum_total_in_out_province_bars_weight = sum( + data.get('ware_house_info', {}).get('total_in_out_province_bars_weight', 0) for data in serializer) + sum_input_bars_count = sum( + data.get('ware_house_info', {}).get('input_bars_count', 0) for data in serializer) + sum_input_bars_weight = sum( + data.get('ware_house_info', {}).get('input_bars_weight', 0) for data in serializer) + sum_free_bars_count = sum(data.get('ware_house_info', {}).get('free_bars_count', 0) for data in serializer) + sum_free_bars_weight = sum( + data.get('ware_house_info', {}).get('free_bars_weight', 0) for data in serializer) + sum_in_province_bars_weight = sum( + data.get('ware_house_info', {}).get('in_province_bars_weight', 0) for data in serializer) + sum_out_province_bars_weight = sum( + data.get('ware_house_info', {}).get('out_province_bars_weight', 0) for data in serializer) + sum_warehouse_total_entered_bars = sum( + data.get('ware_house_info', {}).get('warehouse_total_entered_bars', 0) for data in serializer) + result = { + "total_bars_weight": int(input_allocations_weight + free_bars_weight), + "total_entered_bars_weight": int(input_entered_allocations_weight + free_bars_weight), + "in_province_bars_weight": int(output_allocations_weight), + "out_province_bars_weight": int(free_sale_bars_weight), + "remain_weight": remain_weight, + } + + value_header_list = [ + result['total_bars_weight'], + result['total_entered_bars_weight'], + result['in_province_bars_weight'], + result['out_province_bars_weight'], + result['remain_weight'], + + ] + create_value(worksheet, value_header_list, new_l - 1, 3, border_style='thin') + header_list2 = [ + 'وزن کل بارها', + 'وزن وارد شده به انبار', + 'وزن توزیع شده داخل استان', + 'وزن توزیع شده خارج استان', + 'مانده انبار', + + ] + create_header(worksheet, header_list2, 3, new_l - 2, height=21.8, width=20, color='C00000', + border_style='thin') + if serializer: + m = 1 + for data in serializer: + steward_type = 'مباشر' if data.get('steward') == True else 'صنف' + list1 = [ + m, + data.get('user', {}).get('fullname', ''), + data.get('user', {}).get('mobile', ''), + f'{steward_type}({data.get("guilds_name", "")})', + data.get('user', {}).get('city_name', {}), + data.get('ware_house_info', {}).get('remain_weight', 0), + data.get('ware_house_info', {}).get('total_bars_count', 0), + data.get('ware_house_info', {}).get('total_bars_weight', 0), + data.get('ware_house_info', {}).get('total_entered_bars_count', 0), + data.get('ware_house_info', {}).get('total_entered_bars_weight', 0), + data.get('ware_house_info', {}).get('total_in_out_province_bars_count', 0), + data.get('ware_house_info', {}).get('total_in_out_province_bars_weight', 0), + data.get('ware_house_info', {}).get('input_bars_count', 0), + data.get('ware_house_info', {}).get('input_bars_weight', 0), + data.get('ware_house_info', {}).get('free_bars_count', 0), + data.get('ware_house_info', {}).get('free_bars_weight', 0), + data.get('ware_house_info', {}).get('in_province_bars_weight', 0), + data.get('ware_house_info', {}).get('out_province_bars_weight', 0), + + ] + + create_value(worksheet, list1, new_l + 1, 1, border_style='thin', m=m) + m += 1 + new_l += 1 + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + sum_remain_weight, + sum_total_bars_count, + sum_total_bars_weight, + sum_total_entered_bars_count, + sum_total_entered_bars_weight, + sum_total_in_out_province_bars_count, + sum_total_in_out_province_bars_weight, + sum_input_bars_count, + sum_input_bars_weight, + sum_free_bars_count, + sum_free_bars_weight, + sum_in_province_bars_weight, + sum_out_province_bars_weight, + ] + + create_value(worksheet, summary_list, new_l + 1, 1, color='green') + + + else: + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + temporary_trash=False, + temporary_deleted=False, + clearance_code__isnull=False + ).values_list('clearance_code', flat=True).distinct() + + kill_house_free_sale = PoultryRequest.objects.filter(trash=False, quarantine_code__isnull=False, out=True) \ + .values_list('quarantine_code', flat=True).distinct() + + result = list(kill_house_request) + list(kill_house_free_sale) + + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar/?province={base_url_for_sms_report}' + f'&date1={date1}&date2={date2}', + json=result, + headers={'Content-Type': 'application/json'} + ) + + header_list = [ + 'تعداد مرغداران', + 'تعداد کشتارگاه ها', + 'حجم کشتار', + + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', + color='C00000') + + excel_options = [ + 'ردیف', + 'نوع بار', + 'تاریخ کشتار', + 'مرغدار', + 'شناسه یکتا مرغدار', + 'شماره مجوز جوجه ریزی', + 'شماره موبایل مرغدار', + 'شهر مرغدار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد قرنطینه', + 'وضعیت بار', + 'کشتارگاه', + 'شناسه یکتا کشتارگاه', + 'استان', + 'شهر', + 'حجم کشتار', + 'سن کشتار', + + ] + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + unique_poultry_out_false = set() + unique_slaughterhouses_out_false = set() + total_slaughter_out_false = 0 + excel_description(worksheet, 'A1', f'بارهای دارای مغایرت', color='red', + row2='B1') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='C3') + for data in response.json(): + if data['Out'] == False: + state = 'داخل استان' + else: + state = 'خارج استان' + vet_farm_mobile = '' + vet_farm_name = '' + vet_farm = VetFarm.objects.filter(trash=False, + poultry__breeding_unique_id=data['hatching']['poultry'][ + 'PartIdCode']).first() + if vet_farm: + vet_farm_mobile = vet_farm.vet.user.mobile + vet_farm_name = vet_farm.vet.user.fullname + unique_poultry_out_false.add(data['hatching']['poultry']['UnitName']) + unique_slaughterhouses_out_false.add(data['DesUnitName']) + total_slaughter_out_false += data['GoodAmount'] + date_str = str(data['Date']).split('T')[0] # جدا کردن بخش تاریخ + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + list1 = [ + m, + state, + str(shamsi_date(date, in_value=True)), + data['hatching']['poultry']['UnitName'], + data['hatching']['poultry']['PartIdCode'], + data['hatching']['RequestCode'], + data['hatching']['poultry']['Mobile'], + data['hatching']['poultry']['City'], + vet_farm_name, + vet_farm_mobile, + data['TrackingCode'], + data['TrackingStatusDescription'], + data['DesUnitName'], + data['DesPartIdCode'], + data['Province'], + data['City'], + data['GoodAmount'], + data['Age'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + value_header_list = [ + len(unique_poultry_out_false), + len(unique_slaughterhouses_out_false), + total_slaughter_out_false + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + quantity = sum( + data['GoodAmount'] for data in response.json() if data['Out'] == False) or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + + ] + + create_value(worksheet, list2, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response1 = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response1[ + 'Content-Disposition'] = f'attachment; filename="پایش کلی اطلاعات.xlsx"'.encode( + 'utf-8') + response1.write(output.getvalue()) + return response1 + + +def market_requests_excel(request): + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'poultry_request__chicken_breed', + 'poultry_request__order_code', + 'poultry_request__poultry__address__city__name', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__user__fullname', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + now = datetime.datetime.now().date() + role = request.GET.get('role') + filter = { + 'trash': False, + 'market': True, + 'recive_date__date': now, + } + excel_name = 'سفارشات دریافتی' + excel_options = [ + "ردیف", + "فارم", + "مرغدار", + "تلفن مرغدار", + "شهر", + "ماهیت خریدار", + "خریدار", + "تلفن خریدار", + "آدرس خریدار", + "نژاد", + "سن (روز)", + "تعداد قطعه", + "تاریخ کشتار", + "میانگین وزنی (کیلوگرم)", + "وزن تقریبی (کیلوگرم)", + "مبلغ هر کیلو (ریال)", + "حداکثر مهلت تسویه", + "وضعیت", + + ] + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + filter['kill_house'] = kill_house + excel_name = 'خریدهای ثبت شده' + excel_options = [ + "ردیف", + "فارم", + "مرغدار", + "تلفن مرغدار", + "شهر", + "نژاد", + "سن (روز)", + "تعداد قطعه", + "تاریخ کشتار", + "میانگین وزنی (کیلوگرم)", + "وزن تقریبی (کیلوگرم)", + "مبلغ هر کیلو (ریال)", + "حداکثر مهلت تسویه", + "وضعیت", + + ] + + elif role in ('CityJahad', 'CityOperator', 'CityCommerce', 'CityVet', 'CitySupervisor', 'CityPoultry'): + filter['poultry__address__city'] = user.city + state_type = request.GET.get('type') + + if state_type and state_type != 'all': + filter['market_state'] = state_type + + kill_requests = KillRequest.objects.filter(**filter).select_related('poultry_hatching', 'poultry').only( + 'poultry_hatching', 'poultry').order_by( + Case( + When(market_state='pending', then=Value(0)), + default=Value(1) + ), + '-create_date' + ) + + if 'search' in request.GET: + kill_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=kill_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=kill_requests) + kill_requests_list = ps.filter() + kill_requests = [] if len( + kill_requests_list) == 0 else kill_requests_list + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد قطعه', + "وزن تقریبی (کیلوگرم)", + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', excel_name, color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + all_wight = 0 + serializer = KillRequestForDirectBuyingSerializer(kill_requests, many=True).data + if serializer: + for data in serializer: + all_wight += int(data['Index_weight'] * data['kill_capacity']) + state = '-' + if data['market_state'] == "pending" and data['market_code_status'] == True and data[ + 'market_final_accept'] == True \ + and data.get('input_market_code'): + state = 'در انتظار ورود کد احراز' + elif data['market_final_accept'] == False: + state = 'در انتظار تایید خریدار' + elif data['market_state'] == "pending": + state = 'در انتظار تایید استان' + elif data['market_state'] == "accepted": + state = 'تایید شده' + elif data['market_state'] == "rejected": + state = 'رد شده' + elif data['market_state'] == "deleted": + state = 'حذف شده' + + if type(data['recive_date']) is str: + try: + # فرمت با کسری ثانیه + str_date = datetime.datetime.strptime(str(data['recive_date']), "%Y-%m-%dT%H:%M:%S.%f").date() + except: + try: + # فرمت بدون کسری ثانیه + str_date = datetime.datetime.strptime(str(data['recive_date']), "%Y-%m-%dT%H:%M:%S").date() + except: + try: + # فقط تاریخ + str_date = datetime.datetime.strptime(str(data['recive_date']), '%Y-%m-%d').date() + except: + # اگر هیچکدام کار نکرد، مقدار پیشفرض قرار دهید + str_date = None + date = shamsi_date(str_date, in_value=True) if str_date else '-' + elif data['recive_date'] is None: + date = '-' + else: + date = shamsi_date(data['recive_date'], in_value=True) + + if type(data['payment_deadline_date']) is str: + try: + # فرمت با کسری ثانیه + str_date = datetime.datetime.strptime(str(data['payment_deadline_date']), + "%Y-%m-%dT%H:%M:%S.%f").date() + except: + try: + # فرمت بدون کسری ثانیه + str_date = datetime.datetime.strptime(str(data['payment_deadline_date']), + "%Y-%m-%dT%H:%M:%S").date() + except: + try: + # فقط تاریخ + str_date = datetime.datetime.strptime(str(data['payment_deadline_date']), '%Y-%m-%d').date() + except: + # اگر هیچکدام کار نکرد، مقدار پیشفرض قرار دهید + str_date = None + payment_deadline_date = shamsi_date(str_date, in_value=True) if str_date else '-' + elif data['payment_deadline_date'] is None: + payment_deadline_date = '-' + else: + payment_deadline_date = shamsi_date(data['payment_deadline_date'], in_value=True) + if role == 'KillHouse': + + list1 = [ + m, + str(data['poultry']['unit_name']), + data['poultry']['fullname'], + data['poultry']['mobile'], + data['poultry']['city'], + data['chicken_breed'], + data['poultry_request']['killing_age'], + data['kill_capacity'], + str(date), + str(data['Index_weight']), + int(data['Index_weight'] * data['kill_capacity']), + data['amount'], + str(payment_deadline_date), + state + ] + else: + killer = 'کشتارکن' if data['kill_house']['killer'] == True else 'کشتارگاه' + list1 = [ + m, + data['poultry']['unit_name'], + data['poultry']['fullname'], + data['poultry']['mobile'], + data['poultry']['city'], + data['chicken_breed'], + killer, + data['kill_house']['name'], + data['kill_house']['mobile'], + data['kill_house']['city'], + data['poultry_request']['killing_age'], + data['kill_capacity'], + str(date), + str(data['Index_weight']), + int(data['Index_weight'] * data['kill_capacity']), + data['amount'], + str(payment_deadline_date), + state + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + kill_capacity = sum( + item['kill_capacity'] for item in serializer) + + value_header_list = [ + kill_capacity, + all_wight, + + ] + create_value(worksheet, value_header_list, 3, 5) + if role == 'KillHouse': + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + kill_capacity, + '', + '', + all_wight, + '', + '', + '', + + ] + else: + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + kill_capacity, + '', + '', + all_wight, + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="{excel_name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def get_more_than_one_role(request): + users = SystemUserProfile.objects.filter(trash=False).annotate(role_count=Count('role')) \ + .filter(role_count__gt=1) + + excel_options = [ + 'ردیف', + 'نام و نام خانوادگی کاربر', + 'موبایل کاربر', + 'نقش', + 'شهرستان', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 1, 2, 20, width=30) + + l = 2 + for user in users: + role_list = [role.name for role in user.role.all()] + list1 = [ + m, + user.fullname, + user.mobile, + str(role_list), + user.city.name if user.city else '-' + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin') + m += 1 + l += 1 + province = users.first().province.name + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کاربران چند نقشی استان {province} .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def return_province_request_excel(request): + serializer_class = ReturnProvinceKillRequestSerializer + filterset_class = ReturnProvinceKillRequestFilterSet + filterset_fields = [ + 'province_request__poultry_request__order_code', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__address__city__name', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + if role == 'KillHouse': + filters['killhouse_user__kill_house_operator__user'] = user + if date1: + filters['kill_request__recive_date__date__gte'] = date1 + filters['kill_request__recive_date__date__lte'] = date2 + + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), **filters).order_by('id') + + if 'search' in request.GET: + return_province_kill_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=return_province_kill_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=return_province_kill_requests) + return_province_kill_requests_list = ps.filter() + return_province_kill_requests = [] if len( + return_province_kill_requests_list) == 0 else return_province_kill_requests_list + + serializer = serializer_class(return_province_kill_requests, many=True).data + + header_list2 = [ + 'ردیف', + 'کدسفارش', + 'نوع درخواست', + 'نام فارم', + 'نام مرغدار', + 'شهر مرغدار', + 'تاریخ کشتار', + 'تعداد درخواست', + 'تاریخ ثبت تخصیص', + 'نام کشتارگاه', + 'شهر کشتارگاه', + 'قیمت مرغدار', + 'قیمت کشتارگاه', + 'تعداد تخصیص', + 'وضعیت تایید', + 'وضعیت تخصیص ماشین', + 'مانده قابل تخصیص', + 'برگشت دهنده', + ] + create_header(worksheet, header_list2, 1, 12, height=21.8, width=20, border_style='thin') + excel_description(worksheet, 'A2', f'تخصیصات برگشت داده شده', + size=11, color='red', row2='B4') + if serializer: + l = 13 + m = 1 + + for item in serializer: + state = "" + if item.get('state') == "pending": + state = "در انتظار تایید" + elif item.get('state') == "accepted": + state = "تایید شده" + elif item.get('state') == "rejected": + state = "رد شده" + + request_type = "" + if item.get('market'): + request_type = "پنل معاملات" + elif item.get('direct_buying'): + request_type = "خرید مستقیم" + elif item.get('warehouse'): + request_type = "انبار" + else: + request_type = "اتحادیه" + + poultry_info = "" + if item.get('poultry_fullname') and item.get('poultry_mobile'): + poultry_info = f"{item.get('poultry_fullname')} ({item.get('poultry_mobile')})" + else: + poultry_info = item.get('poultry_fullname', '-') + returner_info = "" + if item.get('returner'): + returner_fullname = item.get('returner', {}).get('fullname', '') + returner_mobile = item.get('returner', {}).get('mobile', '') + modify_date = str(shamsi_date((convert_str_to_date(item.get('modify_date'))), in_value=True)) + returner_info = f"{returner_fullname} ({returner_mobile}) {modify_date}" + else: + returner_info = "سیستم" + + list1 = [ + m, + item.get('order_code') or "-", + request_type, + item.get('poultry_unit_name') or "-", + poultry_info, + item.get('poultry_city') or "-", + str(shamsi_date(convert_str_to_date(item.get('killing_date')), in_value=True)), + item.get('poultry_request_quantity'), + str(shamsi_date(convert_str_to_date(item.get('create_date')), in_value=True)), + item.get('killhouse_user', {}).get('name') or "-", + item.get('killhouse_user', {}).get('city') or "-", + int(float(item.get('poultry_amount') or 0)), + item.get('kill_house_price'), + item.get('quantity'), + state, + "دارد" if item.get('first_car_allocated_quantity', 0) > 0 else "ندارد", + (item.get('quantity', 0) - item.get('total_killed_quantity', 0)), + returner_info + ] + + create_value(worksheet, list1, l, 1, border_style='thin', m=m) + m += 1 + l += 1 + header_list2 = [ + "تعداد کل تخصیصات", + "تعداد تخصیصات بازگشتی کاربر", + "تعداد تخصیصات بازگشتی سیستم", + "حجم کل تخصیصات", + "حجم تخصیصات بازگشتی کاربر", + "حجم تخصیصات بازگشتی سیستم", + "وزن کل تخصیصات", + "وزن بازگشتی کاربر", + "وزن بازگشتی سیستم", + "تعداد کل بارها", + "تعداد بارهای عدم وصول", + "تعداد بارهای بازگشتی سیستمی", + "حجم کل بارها", + "حجم بارهای عدم وصول", + "حجم بارهای بازگشتی سیستمی", + "وزن کل بارها", + "وزن بارهای عدم وصول", + "وزن بارهای بازگشتی سیستمی", + "وزن خریدهای بازگشتی با کارمزد", + "کارمزد خریدهای بازگشتی" + ] + create_header(worksheet, header_list2, 3, 3, height=21.8, width=20, color='C00000', border_style='thin') + + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + + province_kill_request_filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + + kill_house_request_filters = {} + if date1: + province_kill_request_filters['kill_request__recive_date__date__gte'] = date1 + province_kill_request_filters['kill_request__recive_date__date__lte'] = date2 + kill_house_request_filters['kill_request__recive_date__date__gte'] = date1 + kill_house_request_filters['kill_request__recive_date__date__lte'] = date2 + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + province_kill_request_filters['killhouse_user'] = kill_house + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + else: + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True, non_receipt_state__in=('pending', 'accepted')) | Q( + trash=True, return_trash=True), + **kill_house_request_filters) + + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), + **province_kill_request_filters).order_by('id') + + return_province_kill_requests_aggregates = return_province_kill_requests.aggregate( + total_count=Count('id'), + total_operator_return_count=Count('id', filter=Q(trash=False, return_to_province=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('total_killed_quantity'), + total_operator_return_quantity=Sum('main_quantity', filter=Q(trash=False, return_to_province=True)), + total_system_return_quantity=Sum('total_killed_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('total_killed_weight'), + total_operator_return_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight'), + filter=Q(trash=False, return_to_province=True)), + total_system_return_weight=Sum('total_killed_weight', filter=Q(trash=True, return_trash=True)), + + ) + return_kill_house_requests_aggregates = return_kill_house_requests.aggregate( + total_count=Count('id'), + total_non_receipt_count=Count('id', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_count=Count('id', filter=Q(trash=True, return_trash=True)), + total_quantity=Sum('accepted_real_quantity'), + total_non_receipt_quantity=Sum('accepted_real_quantity', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_quantity=Sum('accepted_real_quantity', filter=Q(trash=True, return_trash=True)), + total_weight=Sum('accepted_real_weight'), + total_non_receipt_weight=Sum('accepted_real_weight', filter=Q(non_receipt=True, main_non_receipt=True)), + total_system_return_weight=Sum('accepted_real_weight', filter=Q(trash=True, return_trash=True)), + ) + province_kill_request_total_operator_return_quantity = return_province_kill_requests_aggregates[ + 'total_operator_return_quantity'] or 0 + province_kill_request_total_system_return_quantity = return_province_kill_requests_aggregates[ + 'total_system_return_quantity'] or 0 + province_kill_request_total_quantity = province_kill_request_total_operator_return_quantity + province_kill_request_total_system_return_quantity + province_kill_request_total_operator_return_weight = return_province_kill_requests_aggregates[ + 'total_operator_return_weight'] or 0 + province_kill_request_total_system_return_weight = return_province_kill_requests_aggregates[ + 'total_system_return_weight'] or 0 + province_kill_request_total_weight = province_kill_request_total_operator_return_weight + province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight = return_kill_house_requests_aggregates[ + 'total_system_return_weight'] or 0 + total_return_weight_with_wage = province_kill_request_total_system_return_weight + kill_house_request_total_system_return_weight + result = { + "province_kill_request_total_count": return_province_kill_requests_aggregates['total_count'] or 0, + "province_kill_request_total_operator_return_count": return_province_kill_requests_aggregates[ + 'total_operator_return_count'] or 0, + "province_kill_request_total_system_return_count": return_province_kill_requests_aggregates[ + 'total_system_return_count'] or 0, + "province_kill_request_total_quantity": province_kill_request_total_quantity, + "province_kill_request_total_operator_return_quantity": province_kill_request_total_operator_return_quantity, + "province_kill_request_total_system_return_quantity": province_kill_request_total_system_return_quantity, + "province_kill_request_total_weight": province_kill_request_total_weight, + "province_kill_request_total_operator_return_weight": province_kill_request_total_operator_return_weight, + "province_kill_request_total_system_return_weight": province_kill_request_total_system_return_weight, + "kill_house_request_total_count": return_kill_house_requests_aggregates['total_count'] or 0, + "kill_house_request_total_non_receipt_count": return_kill_house_requests_aggregates[ + 'total_non_receipt_count'] or 0, + "kill_house_request_total_system_return_count": return_kill_house_requests_aggregates[ + 'total_system_return_count'] or 0, + "kill_house_request_total_quantity": return_kill_house_requests_aggregates['total_quantity'] or 0, + "kill_house_request_total_non_receipt_quantity": return_kill_house_requests_aggregates[ + 'total_non_receipt_quantity'] or 0, + "kill_house_request_total_system_return_quantity": return_kill_house_requests_aggregates[ + 'total_system_return_quantity'] or 0, + "kill_house_request_total_weight": return_kill_house_requests_aggregates['total_weight'] or 0, + "kill_house_request_total_non_receipt_weight": return_kill_house_requests_aggregates[ + 'total_non_receipt_weight'] or 0, + "kill_house_request_total_system_return_weight": kill_house_request_total_system_return_weight, + "total_return_weight_with_wage": total_return_weight_with_wage, + "total_return_wage": total_return_weight_with_wage * province_live_wage_type_amount, + } + value_header_list = [ + result.get('province_kill_request_total_count') or 0, + result.get('province_kill_request_total_operator_return_count') or 0, + result.get('province_kill_request_total_system_return_count') or 0, + result.get('province_kill_request_total_quantity') or 0, + result.get('province_kill_request_total_operator_return_quantity') or 0, + result.get('province_kill_request_total_system_return_quantity') or 0, + result.get('province_kill_request_total_weight') or 0, + result.get('province_kill_request_total_operator_return_weight') or 0, + result.get('province_kill_request_total_system_return_weight') or 0, + result.get('kill_house_request_total_count') or 0, + result.get('kill_house_request_total_non_receipt_count') or 0, + result.get('kill_house_request_total_system_return_count') or 0, + result.get('kill_house_request_total_quantity') or 0, + result.get('kill_house_request_total_non_receipt_quantity') or 0, + result.get('kill_house_request_total_system_return_quantity') or 0, + result.get('kill_house_request_total_weight') or 0, + result.get('kill_house_request_total_non_receipt_weight') or 0, + result.get('kill_house_request_total_system_return_weight') or 0, + result.get('total_return_weight_with_wage') or 0, + result.get('total_return_wage') or 0, + + ] + create_value(worksheet, value_header_list, 4, 3, border_style='thin') + + summary_list = [ + 'جمع کل==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + + create_value(worksheet, summary_list, l + 1, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="تخصیصات برگشت داده شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def guilds_without_allocation_excel(request): + guilds = Guilds.objects.filter(trash=False, active=True).order_by('id') + + guilds_with_allocation = StewardAllocation.objects.filter( + trash=False + ).values_list('to_steward_id', 'to_guilds_id') + + allocated_guild_ids = set() + for to_steward_id, to_guilds_id in guilds_with_allocation: + if to_steward_id: + allocated_guild_ids.add(to_steward_id) + if to_guilds_id: + allocated_guild_ids.add(to_guilds_id) + + pos_machines_with_paid_transactions = POSTransactions.objects.filter( + trash=False, + paid=True, + pos_machine__isnull=False + ).values_list('pos_machine_id', flat=True).distinct() + + guilds_with_paid_pos = POSMachine.objects.filter( + id__in=pos_machines_with_paid_transactions, + guild__isnull=False + ).values_list('guild_id', flat=True).distinct() + + guilds_to_keep = allocated_guild_ids.union(set(guilds_with_paid_pos)) + + guilds_without_allocation = guilds.exclude(id__in=guilds_to_keep) + + total_guilds_count = guilds.count() + guilds_without_allocation_count = guilds_without_allocation.count() + guilds_with_allocation_count = total_guilds_count - guilds_without_allocation_count + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment_CELL + + header_list = [ + 'تعداد کل صنف‌ها', + 'تعداد صنف‌های دارای توزیع', + 'تعداد صنف‌های بدون توزیع', + ] + create_header(worksheet, header_list, 4, 2, 21, 22) + + excel_description(worksheet, 'A1', f'گزارش صنف‌های بدون توزیع', + size=12, color='red', row2='C1') + + value_header_list = [ + total_guilds_count, + guilds_with_allocation_count, + guilds_without_allocation_count, + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'نام صنف', + 'کد صنف', + 'شماره مجوز', + 'نام مالک', + 'موبایل', + 'شهر', + 'استان', + 'نوع فعالیت', + 'حوزه فعالیت', + 'مباشر', + 'وضعیت پز', + 'وضعیت فعال', + 'تاریخ ثبت', + ] + + create_header_freez(worksheet, excel_options, 1, 6, 7, 22, width=22) + + l = 7 + m = 1 + for guild in guilds_without_allocation: + steward_status = '✅' if guild.steward else '❌' + has_pos_status = '✅' if guild.has_pos else '❌' + active_status = 'فعال' if guild.active else 'غیرفعال' + + if guild.create_date: + create_date_shamsi = str(shamsi_date(guild.create_date.date(), in_value=True)) + else: + create_date_shamsi = '-' + + list1 = [ + m, + guild.guilds_name if guild.guilds_name else '-', + guild.guilds_id if guild.guilds_id else '-', + guild.license_number if guild.license_number else '-', + guild.user.fullname if guild.user else '-', + guild.user.mobile if guild.user else '-', + guild.user.city.name if guild.user.city else '-', + guild.user.province.name if guild.user.province else '-', + guild.type_activity if guild.type_activity else '-', + guild.area_activity if guild.area_activity else '-', + steward_status, + has_pos_status, + active_status, + create_date_shamsi, + ] + + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=22) + m += 1 + l += 1 + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="صنف‌های بدون توزیع.xlsx"'.encode('utf-8') + response.write(output.getvalue()) + return response \ No newline at end of file diff --git a/panel/ProvinceOperator/helpers.py b/panel/ProvinceOperator/helpers.py new file mode 100644 index 0000000..7cc889d --- /dev/null +++ b/panel/ProvinceOperator/helpers.py @@ -0,0 +1,284 @@ +from django.db.models import Sum, Q +from django.http import HttpResponse + +from LiveStock.models import LiveStockAllocations, Rancher, LiveStockProduct, Cooperative, LiveStockRolseProduct, \ + CooperativeProductsShare +from panel.convert_date import convert_to_miladi +from panel.models import StewardAllocation, StewardFreeBarInformation, StewardFreeSaleBarInformation, \ + PosAllocationTransactions, PosMachineTransactions, PosSegmentation, ProductsTransactions, RolesProducts, \ + WarehouseArchive + + +def guild_steward_free_buying_product_warehousing(product): + guild_steward_free_buying_bars = StewardFreeBarInformation.objects.filter( + Q(guild=product.guild) | Q(steward=product.guild), trash=False,warehouse=True) + product.free_buying_carcasses_quantity = \ + guild_steward_free_buying_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + product.free_buying_carcasses_weight = \ + guild_steward_free_buying_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + product.save() + product.guild.total_out_province_buying_bars_weight = product.free_buying_carcasses_weight + product.guild.save() + + +def guild_steward_free_sale_product_warehousing(product): + guild_steward_free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + Q(guild=product.guild) | Q(steward=product.guild), trash=False,warehouse=True) + + product.out_province_allocated_quantity = guild_steward_free_sale_bars.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + product.out_province_allocated_weight = guild_steward_free_sale_bars.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + out_province_governmental_allocated_weight = guild_steward_free_sale_bars.filter(quota='governmental').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + out_province_free_allocated_weight = guild_steward_free_sale_bars.filter(quota='free').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + product.save() + product.guild.total_selling_out_province_governmental_weight=out_province_governmental_allocated_weight + product.guild.total_selling_out_province_free_weight = out_province_free_allocated_weight + product.guild.save() + + +def guild_steward_allocations_product_warehousing(product): + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=product.guild) | Q(to_guilds=product.guild) | Q(steward=product.guild) | Q(to_steward=product.guild), + trash=False, calculate_status=True,warehouse=True,steward_warehouse=True) + + guild_steward_allocated = guild_steward_allocations.filter(Q(guilds=product.guild) | Q(steward=product.guild)) + guild_steward_allocated_from = guild_steward_allocations.filter( + Q(to_guilds=product.guild) | Q(to_steward=product.guild)) + + governmental_guild_steward_allocated_from = guild_steward_allocated_from.filter(quota='governmental') + free_guild_steward_allocated_from = guild_steward_allocated_from.filter(quota='free') + + product.province_allocated_quantity = \ + guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_number_of_carcasses'))[ + 'total'] or 0 + product.province_allocated_weight = \ + guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted')).aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + in_province_governmental_allocated_weight = \ + guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted'),quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + in_province_free_allocated_weight = \ + guild_steward_allocated.filter(receiver_state__in=('pending', 'accepted'),quota='free').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + product.receive_governmental_carcasses_quantity = \ + governmental_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + product.receive_governmental_carcasses_weight = \ + governmental_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + product.receive_free_carcasses_quantity = \ + free_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + product.receive_free_carcasses_weight = \ + free_guild_steward_allocated_from.filter(receiver_state='accepted').aggregate( + total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + + product.save() + product.guild.total_in_province_governmental_bars_weight = product.receive_governmental_carcasses_weight + product.guild.total_in_province_free_bars_weight = product.receive_free_carcasses_weight + product.guild.total_selling_in_province_governmental_weight = in_province_governmental_allocated_weight + product.guild.total_selling_in_province_free_weight = in_province_free_allocated_weight + product.guild.save() + + +def allocation_calculate_price(allocation): + transactions = PosAllocationTransactions.objects.filter(allocation=allocation, trash=False, paid=True) + allocation.total_amount_paid = transactions.aggregate(total=Sum('price'))['total'] or 0 + allocation.save() + + +def pos_allocation_weight_for_product(product): + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False,warehouse=True) + product.pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + product.save() + pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + pos_governmental_allocated_weight = transactions.filter(price_approved=True).aggregate(total=Sum('cur_weight'))['total'] or 0 + pos_free_allocated_weight = transactions.filter(price_approved=False).aggregate(total=Sum('cur_weight'))['total'] or 0 + if product.kill_house: + product.kill_house.pos_allocated_weight=int(pos_allocated_weight/1000) + product.kill_house.pos_governmental_allocated_weight=int(pos_governmental_allocated_weight/1000) + product.kill_house.pos_free_allocated_weight=int(pos_free_allocated_weight/1000) + product.kill_house.save() + else: + product.guild.pos_allocated_weight=int(pos_allocated_weight/1000) + product.guild.pos_governmental_allocated_weight=int(pos_governmental_allocated_weight/1000) + product.guild.pos_free_allocated_weight=int(pos_free_allocated_weight/1000) + product.guild.save() + + + +def guild_steward_product_segmentation(product): + if product.kill_house: + segmentations = PosSegmentation.objects.filter(kill_house=product.kill_house, trash=False,warehouse=True) + else: + + segmentations = PosSegmentation.objects.filter(guild=product.guild, trash=False,warehouse=True) + product.segmentation_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.save() + if product.kill_house: + product.kill_house.total_segmentation_governmental_weight = segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.kill_house.total_segmentation_free_weight = segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.kill_house.save() + else: + product.guild.total_segmentation_governmental_weight = segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.guild.total_segmentation_free_weight = segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + product.guild.save() + + + +def guild_steward_archive_warehousing(guild): + product = RolesProducts.objects.filter(guild=guild, trash=False, name='مرغ گرم').first() + + archives = WarehouseArchive.objects.filter(Q(steward=guild)|Q(guild=guild),trash=False,warehouse=True) + + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + product.ware_house_archive_weight = archives_weight + product.save() + guild.ware_house_archive_governmental_weight = archives_governmental_weight + guild.ware_house_archive_free_weight = archives_free_weight + guild.save() + + + +def cooperative_warehousing(product): + transactions = ProductsTransactions.objects.filter(live_stack_products=product, transaction__paid=True, trash=False) + output_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + product.total_allocated_weight = output_weight + product.save() + + +def rancher_warehousing(transaction): + # todo:دامدار با کد ملی چند تا بر گپمیرگرده باید بر اساس شناسه گله بشه + rancher = Rancher.objects.filter(national_id=transaction.natcode).order_by('herd_code').first() + if rancher: + transactions = ProductsTransactions.objects.filter(transaction=transaction, transaction__paid=True, trash=False) + output_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + rancher.total_weight = output_weight + rancher.save() + + +def update_role_product(request): + products=LiveStockProduct.objects.filter(trash=False).exclude(name__in=('جو','سویا','ذرت','سبوس')) + cooperative=Cooperative.objects.filter(trash=False) + for c in cooperative: + for p in products: + live=LiveStockRolseProduct( + parent_product=p, + cooperative=c, + ) + live.save() + return HttpResponse('ok') + + +def update_cooperative_share(request): + products=LiveStockProduct.objects.filter(trash=False).exclude(name__in=('جو','سویا','ذرت','سبوس')) + cooperative=Cooperative.objects.filter(trash=False) + for c in cooperative: + for p in products: + live=CooperativeProductsShare( + product=p, + cooperative=c, + ) + live.save() + return HttpResponse('ok') + + +def calculate_bad_transactions(): + transactions = PosMachineTransactions.objects.filter(trash=False, paid=False, live_stock=True, result='تراکنش موفق', + state=0) + for transaction in transactions: + product_transaction = ProductsTransactions.objects.filter(transaction=transaction, + trash=False, + live_stack_products__isnull=False).first() + if product_transaction: + cooperative_warehousing(product_transaction.live_stack_products) + rancher_warehousing(transaction) + transaction.paid = True + transaction.save() + + + + +def _normalize_fa_ar(text): + """نرمالایز کردن متن فارسی/عربی""" + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + +def parse_yes_no(val): + """تبدیل مقدار به boolean""" + if isinstance(val, bool): + return val + if isinstance(val, str): + return False if val == 'خیر' else True + return bool(val) + +def persian_date_to_datetime(persian_date_str): + """تبدیل تاریخ فارسی به datetime""" + if not persian_date_str: + return None + try: + persian_numbers = '۰۱۲۳۴۵۶۷۸۹' + english_numbers = '0123456789' + translation_table = str.maketrans(persian_numbers, english_numbers) + english_date = persian_date_str.translate(translation_table) + parts = english_date.split('/') + if len(parts) != 3: + return None + year = int(parts[0]) + month = int(parts[1]) + day = int(parts[2]) + return convert_to_miladi(year=year, month=month, day=day) + except: + return None \ No newline at end of file diff --git a/panel/ProvinceOperator/serializers.py b/panel/ProvinceOperator/serializers.py new file mode 100644 index 0000000..0e29d08 --- /dev/null +++ b/panel/ProvinceOperator/serializers.py @@ -0,0 +1,6380 @@ +from datetime import datetime +import json + +from django.db.models import Q, Sum, F, Case, When, FloatField, Count +from jdatetime import timedelta +from rest_framework import serializers +import django_filters +from rest_framework_recursive.fields import RecursiveField + +from LiveStock.Cooperative.serializers import CooperativeForSharesSerializer +from LiveStock.models import LiveStockRolseProduct, Cooperative, CooperativeProductsShare +from authentication.models import SystemUserProfile, ExternalTransaction +from authentication.serializer.serializer import SystemUserProfileSerializer, BankCardSerializer, \ + SystemUserProfileForAutoAllocationSerializer, SystemUserProfileForGuildSerializer, \ + SystemUserProfileForInspectionSerializer, SystemUserProfileForFactorSerializer, \ + SystemUserProfileForPoultryLocSerializer, SystemUserProfileForPoultryScienceSerializer, \ + SystemUserProfileForPoultryScienceWithoutRoleSerializer +from authentication.serializers import UserProfileSerializer, SystemAddressSerializer +from deposit_id import wage_counting_type, out_selling_ignore, new_out_selling_count_wage, \ + new_out_selling_count_wage_date, before_out_buying_count_wage_amount +from deposit_percent import wage_percent, carcases_sell +from general_urls import base_url_for_sms_report +from panel.CityOperator.serializers import CityOperatorForSubSectorTransactionsSerializer +from panel.KillHouse.helpers import get_finance_info, get_difference_carcasses_weight, get_new_wage_for_free_buying +from panel.KillHouse.serializers import VetSerializer, ProvinceKillRequestSerializer, \ + KillHouseAssignmentInformationSerializer, KillHouseSerializer, KillHouseDailyQuotaSerializer, \ + ProvinceKillRequestForAutoAllocationSerializer, KillHouseWareHouseSerializer, KillHouseForProvinceSerializer, \ + KillHouseRequestForColdHouseAllocationsSerializer, KillHouseFreeBarInformationSerializer, \ + KillHouseForKillHouseVetKillHouseSerializer, KillHouseForKillingInformationDiscrepancyReportSerializer, \ + KillHouseForAutoAllocationSerializer, KillHouseForKillHouseGuildRelationSerializer, \ + KillHouseForKillHouseStewardRelationSerializer, KillHouseOperatorForAutoAllocationsSerializer, \ + PosKillHouseForKillingInformationDiscrepancyReportSerializer, KillHouseForCommonlyUsedSerializer, \ + KillHouseForReturnBuyingSerializer +from panel.ProvinceOperator.services.pos_transfer_service import POSTransferService +from panel.models import ( + Pricing, + ProvinceCheckOperatorRequest, + ProvinceCheckInformation, + ProvinceFactorToKillHouse, + KillHouseFactorToProvince, + ProvinceCheckKillHouseFactor, + DepositAllocation, + PovinceInspector, + PriceAnalysis, + WareHouseFactor, + ProvinceOperator, ProvinceRequestAction, ProvincePercentLeftOver, InspectorOperator, ShareOfAllocation, + PaymentDeadLine, MonthlyProfitPercentage, ProvinceFactorToKillHouseForPoultry, KillHouseFactorToPoultry, + Wallet, Itransaction, Debt, Deposit, Penalty, FinancialDocument, FinancialTransaction, Admin, + ProvinceImportKillHouseOutFactors, VetSupervisor, Jahad, ProvincialGovernment, VetCheckAllocations, HourLimit, + SmsLicense, PoultryRequest, PoultryAllowCityProvince, ProvinceAllowKillHouseRegisterCar, + ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultryChooseKillHouseTotal, ProvinceAllowPoultrySellFree, + ProvinceAllowPoultrySellFreeTotal, ProvinceCheckOperatorOutRequest, + ProvinceAutoAllocation, KillHouseAssignmentInformation, AutoAcceptProvinceKillRequest, + AutoMakeKillHouseRequest, CityJahad, Guilds, Steward, KillHousePercentageOfLosses, StewardAllocation, + ProvinceAllowKillHouseChooseStewardGuilds, StewardWareHouse, GuildsWareHouse, Commerce, CityCommerce, + HatchingLossesPermission, KillHouse, WagePayment, ProvinceAllowKillHouseDirectBuyingTotal, + ProvinceAllowKillHouseDirectBuying, ProvinceAllowKillHouseRegisterGuilds, ProvinceAllowKillHouseRegisterGuildsTotal, + CityVet, KillHouseHourLimit, AutomaticStewardAllocation, FreeSaleWithinprovince, Observatory, ProvinceSupervisor, + Car, Product, PosVersion, PosItem, GuildRoom, PosCompany, POSId, POSMachine, AdditionalProducts, POSTransactions, + StewardFreeBarInformation, TypeActivity, AreaActivity, EvacuationPermit, SellForFreezing, LiveStockSupport, + ColdHouse, ColdHouseAllocations, OperationLimitation, ApprovedPrice, Announcements, ChickenAgeRange, TimeRange, + CitySupervisor, JahadInspector, SystemWallet, SuperAdmin, PaymentGatewayPercentage, WageType, PercentageOfWageType, + ShareType, TotalWageInformation, ProvinceKillRequest, SlaughterHouseTransaction, ChainCompanyTransaction, + ChainAllocation, KillHouseFreeBarInformation, KillHouseRequest, ChainCompany, InternalTransaction, + TotalPaymentGatewayPercentage, StewardFreeSaleBarInformation, CityLivestock, ImprovingLivestock, Reports, + ReportsUsers, UserReports, ReportSubmissionTime, MovingText, MovingTextDashboardStatus, MovingTextRole, + MovingTextWithRole, NewProduct, AdminX, Supporter, ZarinPalAccounts, PoultryExport, PoultryOutProvinceRequest, + Dispenser, VetFarmAggregatePermission, KillHouseBarLimitation, CityPoultry, KillHouseStewardGuildRelation, + OutOfProvinceSellingCarcassesPermission, OutProvinceCarcassesBuyer, KillHouseFreeSaleBarInformation, + ProductPricingType, KillHousePricePermission, BaseOutProvinceCarcassesBuyer, RolesProducts, + AutomaticDirectBuyingPermission, PosMachineTransactions, BroadcastPrice, OutProvinceSaleLimitation, + PosAllocationTransactions, ParentCompany, POSDeviceSession, PosDeviceVersion, SubSectorTransactions, + SubSectorPercentageOfWageType, PosSegmentation, Vet, CityGuild, DistributionUserLevel, BarDifferenceRequest, + OtherProducts, ProductsTransactions, PriceConfirmation, CompanyBeneficiaryAccount, ProteinGuild, CommonlyUsed, + PercentageDropLimitation, UploadImageLimitation, ApkInfo, DirectBuyingVerification, FinePermission, + ShowMarketRequest, IndexWeightCategory, PoultryScience, PoultryScienceReport, AllowRegisterCodeForGuilds, + GuildsGeneralConfigs, StewardAppLogin, StewardRequest, RestrictionCarcassDistribution, + AllowRegisterCodeForKillHouseFreeSaleBarInformation, AllowRegisterCodeForStewardFreeSaleBarInformation, + LimitationForDirectPurchaseAndBarInformation, WarehouseArchive, SmsRecipient, MarketDailyLimitation, + HatchingArchivePercent, Representative, POSAccessLevel, DispenserInformation +) +from panel.poultry.helpers import market_daily_limitation_info +from panel.poultry.serializers import PoultryRequestSerializer, PoultrySerializer, \ + PoultryRequestForAutoAllocationSerializer, ChainAllocationSerializer, ChainCompanySerializer, \ + PoultryForPoultryRequestLetterSerializer, OutProvincePoultryRequestBuyerSerializer, \ + PoultryRequestForOutRequestTransactionsSerializer, PoultryDetailForPoultryScienceSerializer, \ + PoultryHatchingForPredictionSerializer, PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer + + +# سریالایزر مربوط به اپراتور شهرستان +class ProvinceOperatorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ProvinceOperator + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + ) + + +class ProvinceOperatorForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ProvinceOperator + fields = ['address', 'user_bank_info', 'identity_documents', 'phone'] + + +class AdminForAllUserSerializer(serializers.ModelSerializer): + class Meta: + model = Admin + fields = ['address', 'identity_documents', 'active'] + + +# سریالایزر مربوط به اپراتور شهرستان +class AdminSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + + class Meta: + model = Admin + exclude = ( + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'created_by', + 'modified_by', + ) + + +class ProvinceCheckOperatorOutRequestSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + + class Meta: + model = ProvinceCheckOperatorOutRequest + fields = '__all__' + + +# سریالایزر مربوط به تایید یا رد درخواست تایید شده شهرستان +class ProvinceCheckOperatorRequestSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + + class Meta: + model = ProvinceCheckOperatorRequest + fields = '__all__' + + +class AdditionalProductsSerializer(serializers.ModelSerializer): + class Meta: + model = AdditionalProducts + exclude = ( + 'create_date', + 'modify_date', + 'created_by', + 'modified_by', + ) + + +class ProductSerializer(serializers.ModelSerializer): + product_price = serializers.SerializerMethodField('get_product_price') + product_weight = serializers.SerializerMethodField('get_product_weight') + product_sale_weight = serializers.SerializerMethodField('get_product_sale_weight') + product_remain_weight = serializers.SerializerMethodField('get_product_remain_weight') + product_extra_sale_weight = serializers.SerializerMethodField('get_product_extra_sale_weight') + parent_key = serializers.SerializerMethodField('get_parent_product') + + class Meta: + model = Product + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'guild', + 'steward', + 'kill_house', + 'created_by', + 'modified_by', + ) + # fields = '__all__' + + def get_product_price(self, obj): + try: + price_type = ProductPricingType.objects.filter(trash=False).first() + if price_type and price_type.province == False and obj.name == 'مرغ گرم': + if obj.kill_house is not None: + price = obj.kill_house.kill_house_operator.user.city.product_price / 1000 if obj.kill_house.kill_house_operator.user.city.product_price > 0 else 0 + elif obj.guild is not None: + price = obj.guild.user.city.product_price / 1000 if obj.guild.user.city.product_price > 0 else 0 + + else: + price = obj.steward.guild.user.city.product_price / 1000 if obj.steward.guild.user.city.product_price > 0 else 0 + + + else: + price = obj.price / 1000 if obj.price > 0 else 0 + except: + + price = obj.price / 1000 if obj.price > 0 else 0 + return price + + def get_product_weight(self, obj): + weight = obj.weight * 1000 if obj.weight > 0 else 0 + return weight + + def get_product_sale_weight(self, obj): + sale_weight = obj.sale_weight * 1000 if obj.sale_weight > 0 else 0 + return sale_weight + + def get_product_remain_weight(self, obj): + remain_weight = obj.remain_weight * 1000 if obj.remain_weight > 0 else 0 + return remain_weight + + def get_product_extra_sale_weight(self, obj): + extra_sale_weight = obj.extra_sale_weight * 1000 if obj.extra_sale_weight > 0 else 0 + return extra_sale_weight + + def get_parent_product(self, obj): + parent = AdditionalProducts.objects.filter(name=obj.name, trash=False) + parent_key = parent.first().key if parent else None + return parent_key + + +class ProvinceRequestActionSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceRequestAction + fields = '__all__' + + +class SmsLicenseSerializer(serializers.ModelSerializer): + class Meta: + model = SmsLicense + fields = '__all__' + + +# سریالایزر مربوط به تایید یا رد اطلاعات بار وارد شده کشتارگاه +class ProvinceCheckInformationSerializer(serializers.ModelSerializer): + kill_house_assignment = KillHouseAssignmentInformationSerializer(read_only=True) + + class Meta: + model = ProvinceCheckInformation + fields = '__all__' + + +# سریالایزر مربوط به قیمت گذاری +class ProvincePercentLeftOverSerializer(serializers.ModelSerializer): + class Meta: + model = ProvincePercentLeftOver + fields = '__all__' + + +# سریالایزر مربوط به قیمت گذاری +class PricingSerializer(serializers.ModelSerializer): + operator = SystemUserProfileSerializer(read_only=True) + + class Meta: + model = Pricing + fields = '__all__' + + +class ProvinceFactorToKillHouseForPoultrySerializer(serializers.ModelSerializer): + province_check_info = ProvinceCheckInformationSerializer(read_only=True) + bank = BankCardSerializer(read_only=True) + + class Meta: + model = ProvinceFactorToKillHouseForPoultry + fields = '__all__' + + +class ProvinceFactorToKillHousePdfSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceFactorToKillHouse + fields = '__all__' + + +# سریالایزر مربوط به فاکتور استان برای کشتارگاه +class ProvinceFactorToKillHouseSerializer(serializers.ModelSerializer): + province_check_info = ProvinceCheckInformationSerializer(read_only=True) + # province_check_req = ProvinceCheckOperatorRequestSerializer(read_only=True) + bank = BankCardSerializer(read_only=True) + kill_house_factor_to_province = serializers.SerializerMethodField('get_kill_house_factor') + province_factor_to_kill_house = serializers.SerializerMethodField('get_province_factor') + poultry_request = serializers.SerializerMethodField('get_poultry_request') + + class Meta: + model = ProvinceFactorToKillHouse + fields = '__all__' + + def get_poultry_request(self, instance): + poultry_request_dict = None + poultry_request = PoultryRequest.objects.filter( + key=instance.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.province_request.poultry_request.key) + if poultry_request.count() > 0: + poultry_request = poultry_request.last() + + poultry_request_dict = { + "poultry_request_id": poultry_request.id, + "poultry_name": poultry_request.poultry.unit_name, + "send_date": poultry_request.send_date, + "chicken_breed": poultry_request.chicken_breed, + "poultry_user_name": poultry_request.poultry.user.fullname, + "poultry_user_mobile": poultry_request.poultry.user.mobile, + + } + return poultry_request_dict + + def get_kill_house_factor(self, instance): + + factors = KillHouseFactorToProvince.objects.filter(province_factor=instance) + + factor_dict = None + if factors.count() > 0: + factors = factors.last() + factor_dict = { + "factor_key": factors.key, + "payment_code": factors.payment_code, + "factor_state": factors.state, + + } + return factor_dict + + def get_province_factor(self, instance): + factor_dict = None + + user = SystemUserProfile.objects.filter(role__name='ProvinceFinancial', + province=instance.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.system_address.province) + if user.count() > 0: + user = user.last() + province_operator = ProvinceOperator.objects.filter(user=user) + if province_operator.count() > 0: + province_operator = province_operator.last() + if province_operator.user_bank_info != None: + factor_dict = { + "card": province_operator.user_bank_info.card, + "shaba": province_operator.user_bank_info.shaba, + "name_of_bank_user": province_operator.user_bank_info.name_of_bank_user, + "bank_name": province_operator.user_bank_info.bank_name, + + } + assingment = KillHouseAssignmentInformation.objects.get( + key=instance.province_check_info.kill_house_assignment.key) + if assingment.kill_house_request.kill_request.slaughter_house != None: + + kill_place = assingment.kill_house_request.kill_request.slaughter_house.name + else: + kill_place = assingment.kill_house_request.kill_request.kill_house.name + factor_dict.update(({ + "factor_create_date": instance.create_date, + "total_factor_amount": instance.total_price, + "real_amount_factor": instance.total_weight * instance.factor_fee, + "poultry_share": instance.shares['poultry_share'], + "province_share": instance.shares['province_share'], + "kill_place": kill_place, + "real_quantity": assingment.real_quantity, + "bar_quantity": assingment.kill_house_request.quantity, + "net_weight": assingment.net_weight, + })) + + return factor_dict + + +class ProvinceImportKillHouseOutFactorsSerializer(serializers.ModelSerializer): + kill_house_factor = ProvinceFactorToKillHouseSerializer(read_only=True) + kill_house_factor_poultry = ProvinceFactorToKillHouseForPoultrySerializer(read_only=True) + province_check = ProvinceCheckOperatorRequestSerializer(read_only=True) + + class Meta: + model = ProvinceImportKillHouseOutFactors + fields = '__all__' + + +class KillHouseFactorToPoultrySerializer(serializers.ModelSerializer): + province_factor = ProvinceFactorToKillHouseForPoultrySerializer(read_only=True) + + class Meta: + model = KillHouseFactorToPoultry + fields = '__all__' + + +# سریالایزر مربوط به فاکتور کشتارگاه برای استان +class KillHouseFactorToProvinceSerializer(serializers.ModelSerializer): + province_factor = ProvinceFactorToKillHouseSerializer(read_only=True) + + class Meta: + model = KillHouseFactorToProvince + fields = '__all__' + + +# سریالایزر مربوط به بررسی فاکتور کشتارگاه توسط استان +class ProvinceCheckKillHouseFactorSerializer(serializers.ModelSerializer): + kill_house_factor = KillHouseFactorToProvinceSerializer(read_only=True) + + class Meta: + model = ProvinceCheckKillHouseFactor + fields = '__all__' + + +# سریالایزر مربوط به تخصیصات مالی +class DepositAllocationSerializer(serializers.ModelSerializer): + poultry = PoultryRequestSerializer(read_only=True) + + class Meta: + model = DepositAllocation + fields = '__all__' + + +# سریالایزر مربوط به بازرس استان +class InspectorOperatorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = InspectorOperator + fields = '__all__' + + +class InspectorOperatorForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = InspectorOperator + fields = ['address', 'identity_documents', 'active'] + + +# سریالایزر مربوط به بازرس استان +class PovinceInspectorSerializer(serializers.ModelSerializer): + class Meta: + model = PovinceInspector + fields = '__all__' + + +class VetSupervisorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + vet = VetSerializer(read_only=True) + + class Meta: + model = VetSupervisor + fields = '__all__' + + +class CityVetSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = CityVet + fields = '__all__' + + +class CommerceSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Commerce + fields = '__all__' + + +class CityCommerceSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = CityCommerce + fields = '__all__' + + +class ProvinceSupervisorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = ProvinceSupervisor + fields = '__all__' + + +class CitySupervisorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = CitySupervisor + fields = '__all__' + + +class SuperAdminSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = SuperAdmin + fields = '__all__' + + +class JahadInspectorSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = JahadInspector + fields = '__all__' + + +class VetSupervisorForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + vet = VetSerializer(read_only=True) + + class Meta: + model = VetSupervisor + fields = ['address', 'vet'] + + +class VetCheckAllocationsSerializer(serializers.ModelSerializer): + vet = VetSerializer(read_only=True) + province_kill_request = ProvinceKillRequestSerializer(read_only=True) + + class Meta: + model = VetCheckAllocations + fields = '__all__' + + +# سریالایزر مربوط به آنالیز قیمت +class PriceAnalysisorSerializer(serializers.ModelSerializer): + class Meta: + model = PriceAnalysis + fields = '__all__' + + +class ShareOfAllocationSerializer(serializers.ModelSerializer): + class Meta: + model = ShareOfAllocation + fields = '__all__' + + +class PaymentDeadLineSerializer(serializers.ModelSerializer): + class Meta: + model = PaymentDeadLine + fields = '__all__' + + +class MonthlyProfitPercentageSerializer(serializers.ModelSerializer): + class Meta: + model = MonthlyProfitPercentage + fields = '__all__' + + +# سریالایزر مربوط به ثبت در خواست مرغ منجمد +class WareHouseFactorSerializer(serializers.ModelSerializer): + first_operator = UserProfileSerializer(read_only=True) + second_operator = UserProfileSerializer(read_only=True) + + class Meta: + model = WareHouseFactor + fields = '__all__' + # extra_kwargs = ['customer', 'national_code', 'date', 'mobile', 'product_type', 'weight', 'fee', 'wage','considerations','' ] + extra_kwargs = {"considerations": {"required": False, "allow_null": True}, + "Complications": {"required": False, "allow_null": True}, + "tax": {"required": False, "allow_null": True}, + "discount": {"required": False, "allow_null": True}, + "name_of_bank_user": {"required": False, "allow_null": True}, + "card": {"required": False, "allow_null": True}, + "shaba": {"required": False, "allow_null": True}, + "account": {"required": False, "allow_null": True} + } + + +class walletSerializer(serializers.ModelSerializer): + class Meta: + model = Wallet + fields = '__all__' + + +class ItransactionSerializer(serializers.ModelSerializer): + wallet = walletSerializer(read_only=True) + + class Meta: + model = Itransaction + fields = '__all__' + + +class DebtSerializer(serializers.ModelSerializer): + class Meta: + model = Debt + fields = '__all__' + + +class PenaltySerializer(serializers.ModelSerializer): + class Meta: + model = Penalty + fields = '__all__' + + +class DepositSerializer(serializers.ModelSerializer): + class Meta: + model = Deposit + fields = '__all__' + + +# class IwalletSerializer(serializers.ModelSerializer): +# class Meta: +# model = Iwallet +# fields = '__all__' + + +class FinancialDocumentSerializer(serializers.ModelSerializer): + class Meta: + model = FinancialDocument + fields = '__all__' + + +# class ItransactionFilter(django_filters.FilterSet): +# class Meta: +# model = Itransaction +# fields = ['wallet',] + +class FinancialTransactionSerializer(serializers.ModelSerializer): + itransaction = ItransactionSerializer(read_only=True) + + class Meta: + model = FinancialTransaction + fields = '__all__' + + +class CarSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = Car + fields = '__all__' + + +class JahadForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = Jahad + fields = ['address', 'user_bank_info', 'identity_documents', 'active'] + + +class CityJahadForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = CityJahad + fields = ['address', 'user_bank_info', 'identity_documents', 'active'] + + +class CityPoultrySerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = CityPoultry + fields = '__all__' + + +# سریالازر مربوط به جهاد +class JahadSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = Jahad + fields = '__all__' + + +class PosCompanySerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + + class Meta: + model = PosCompany + fields = '__all__' + + +# سریالازر مربوط به استانداری +class ProvincialGovernmentSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ProvincialGovernment + fields = '__all__' + + +class ProvincialGovernmentForAllUserSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ProvincialGovernment + fields = ['address', 'user_bank_info', 'identity_documents', 'active'] + + +class HourLimitSerializer(serializers.ModelSerializer): + class Meta: + model = HourLimit + fields = '__all__' + + +class KillHouseHourLimitSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouseHourLimit + fields = '__all__' + + +class PoultryAllowCityProvinceSerializer(serializers.ModelSerializer): + poultry = PoultrySerializer(read_only=True) + + class Meta: + model = PoultryAllowCityProvince + fields = '__all__' + + +class ProvinceAllowKillHouseRegisterCarSerializer(serializers.ModelSerializer): + kill_house = KillHouseSerializer(read_only=True) + + class Meta: + model = ProvinceAllowKillHouseRegisterCar + fields = '__all__' + + +class ProvinceAllowPoultryChooseKillHouseSerializer(serializers.ModelSerializer): + Poultry = PoultrySerializer(read_only=True) + + class Meta: + model = ProvinceAllowPoultryChooseKillHouse + fields = '__all__' + + +class ProvinceAllowPoultryChooseKillHouseTotalSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceAllowPoultryChooseKillHouseTotal + fields = '__all__' + + +class ProvinceAllowPoultrySellFreeSerializer(serializers.ModelSerializer): + Poultry = PoultrySerializer(read_only=True) + + class Meta: + model = ProvinceAllowPoultrySellFree + fields = '__all__' + + +class ProvinceAllowPoultrySellFreeTotalSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceAllowPoultrySellFreeTotal + fields = '__all__' + + +class FreeSaleWithinprovinceSerializer(serializers.ModelSerializer): + class Meta: + model = FreeSaleWithinprovince + fields = ['key', 'allow', 'weight', 'percent', 'type'] + + +class ProvinceAutoAllocationSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + daily_quota = KillHouseDailyQuotaSerializer(read_only=True) + province_kill_request = ProvinceKillRequestSerializer(read_only=True) + + class Meta: + model = ProvinceAutoAllocation + fields = '__all__' + + +class StewardForGuildsSerializer(serializers.ModelSerializer): + class Meta: + model = Steward + fields = ['key'] + + +class GeneralGuildsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user'] + + +class GeneralGuildsForInspectionsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user', 'type_activity', 'area_activity'] + + +class GuildsForKillHousePercentageSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['user', 'guilds_name', 'allocation_limit', 'address'] + + +class GuildsForStewardAutoAllocationSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['user', 'guilds_name', 'steward', 'allocation_limit', 'address', 'license_number', + 'type_activity', 'area_activity', 'guilds_id', 'create_date'] + + +class TotalGuildsForPosSerializer(serializers.ModelSerializer): + class Meta: + model = Guilds + fields = ['key'] + + +class GuildInfoForPosSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + products = serializers.SerializerMethodField('get_products') + + class Meta: + model = Guilds + fields = ['user', 'phone', 'key', 'guilds_id', 'license_number', 'guilds_name', 'type_activity', + 'area_activity', + 'products', 'address', 'condition', 'description_condition'] + + def get_products(self, obj): + # pos = Product.objects.filter(guild=obj,trash=False) + products = Product.objects.filter( + Q(general=False, guild=obj) | Q(general=True, guild__isnull=True), + trash=False) + serializer = ProductSerializer(products, many=True) + return serializer.data + + +class POSDeviceSessionForCompaniesSerializer(serializers.ModelSerializer): + class Meta: + model = POSDeviceSession + fields = ['key', 'name', 'serial', 'password', 'session_create_date', 'session_last_seen_date'] + + +class POSMachineForGuildsSerializer(serializers.ModelSerializer): + pos_company = serializers.SerializerMethodField('get_pos_company') + pos_sessions = serializers.SerializerMethodField('get_pos_sessions') + pos_status = serializers.SerializerMethodField('get_pos_status_method') + + class Meta: + model = POSMachine + fields = ['pos_id', 'key', 'receiver_number', 'receiver_number', 'terminal_number', 'pos_company', 'Lat', + 'active', 'Long', 'pos_sessions', 'pos_status', 'serial', 'password'] + + def get_pos_company(self, obj): + pos_company = PosCompany.objects.get(key=obj.pos_company.key, trash=False) + return pos_company.name + + def get_pos_sessions(self, obj): + pos_sessions = POSDeviceSession.objects.filter(pos=obj, trash=False) + serializer = POSDeviceSessionForCompaniesSerializer(pos_sessions, many=True) + return serializer.data + + def get_pos_status_method(self, obj): + if not self.get_pos_sessions(obj): + return False + now = datetime.now().date() - timedelta(days=4) + pos_sessions = POSDeviceSession.objects.filter(pos=obj, trash=False) + active_sessions = pos_sessions.filter(session_last_seen_date__gt=now) + active_count = active_sessions.count() + return active_count > 0 + + +class GuildsForInspectionSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + guild_pos = serializers.SerializerMethodField('get_guild_pos') + number_of_pos = serializers.SerializerMethodField('get_number_of_pos') + ware_house_info = serializers.SerializerMethodField('get_ware_house_quantity') + + class Meta: + model = Guilds + fields = ['user', 'key', 'guilds_id', 'license_number', 'guilds_name', 'type_activity', 'area_activity', + 'guild_pos', 'number_of_pos', 'ware_house_info'] + + def get_guild_pos(self, obj): + pos = POSMachine.objects.filter(guild=obj, trash=False) + serializer = POSMachineForGuildsSerializer(pos, many=True) + return serializer.data + + def get_number_of_pos(self, obj): + pos = POSMachine.objects.filter(guild=obj, trash=False) + return len(pos) + + def get_ware_house_quantity(self, obj): + try: + ware_house = GuildsWareHouse.objects.get(guilds=obj, trash=False) + return { + "quantity": ware_house.remain_total_number_of_carcasses, + "weight": ware_house.remain_total_weight_of_carcasses + } + except: + return { + "quantity": 0, + "weight": 0 + } + + +class GuildsForCompaniesSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + guild_pos = serializers.SerializerMethodField('get_guild_pos') + number_of_pos = serializers.SerializerMethodField('get_number_of_pos') + + class Meta: + model = Guilds + fields = ['user', 'key', 'guilds_id', 'license_number', 'guilds_name', 'type_activity', 'area_activity', + 'guild_pos', 'number_of_pos', 'condition', 'description_condition', 'province_accept_state'] + + def get_guild_pos(self, obj): + pos = POSMachine.objects.filter(guild=obj, pos_company__name=self.context.get('company'), trash=False) + serializer = POSMachineForGuildsSerializer(pos, many=True) + return serializer.data + + def get_number_of_pos(self, obj): + pos = POSMachine.objects.filter(guild=obj, trash=False) + return len(pos) + + +class TypeActivitySerializer(serializers.ModelSerializer): + class Meta: + model = TypeActivity + fields = ['key', 'title'] + + +class AreaActivitySerializer(serializers.ModelSerializer): + class Meta: + model = AreaActivity + fields = ['key', 'title'] + + +class GuildsForDispenserAllocationsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + allocation_limit = serializers.SerializerMethodField('get_allocation_limit') + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user', 'license_number', 'type_activity', 'area_activity', 'guilds_id', + 'allocation_limit'] + + def get_allocation_limit(self, obj): + guild = self.context.get('guild') + if guild: + relation = KillHouseStewardGuildRelation.objects.filter(guild=guild, steward=guild).first() + if relation: + return { + "allocation_limit": relation.allocation_limit, + "allocation_type": relation.allocation_type + } + return None + + +class GuildsForBroadcastManagementSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward'] + + +class PosGuildsForBroadcastManagementSerializer(serializers.ModelSerializer): + # user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'type_activity', 'area_activity', 'guilds_id', 'steward'] + + +class GuildsForStewardMenueSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user'] + + +class GuildsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + guild_area_activity = AreaActivitySerializer(read_only=True) + guild_type_activity = TypeActivitySerializer(read_only=True) + kill_house = serializers.SerializerMethodField('get_kill_house') + # kill_house = KillHouseForAutoAllocationSerializer(many=True,read_only=True) + steward_kill_house = serializers.SerializerMethodField('get_steward_kill_house') + # steward_kill_house = KillHouseForAutoAllocationSerializer(many=True,read_only=True) + stewards = GuildsForDispenserAllocationsSerializer(many=True, read_only=True) + + get_pos_status = serializers.SerializerMethodField('get_pos_status_method') + product_info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Guilds + fields = '__all__' + + def get_kill_house(self, obj): + kill_houses = KillHouse.objects.filter( + pk__in=KillHouseStewardGuildRelation.objects.filter(guild=obj).values_list('kill_house', flat=True)) + serializer = KillHouseForKillHouseGuildRelationSerializer(kill_houses, many=True, context={'guild': obj}) + return serializer.data + + def get_steward_kill_house(self, obj): + kill_houses = KillHouse.objects.filter( + pk__in=KillHouseStewardGuildRelation.objects.filter(guild=obj).values_list('kill_house', flat=True)) + serializer = KillHouseForKillHouseStewardRelationSerializer(kill_houses, many=True, context={'guild': obj}) + return serializer.data + + def get_pos_status_method(self, obj): + has_pos = POSMachine.objects.filter(guild=obj).exists() + if not has_pos: + return { + "len_active_sessions": 0, + "has_pons": False, + "has_active_pons": False, + } + pos_device_ids = POSMachine.objects.filter(guild=obj).values_list('id', flat=True) + now = datetime.now().date() - timedelta(days=4) + sessions = POSDeviceSession.objects.filter(trash=False, pos__id__in=pos_device_ids) + active_sessions = sessions.filter(session_last_seen_date__gt=now) + active_count = active_sessions.count() + return { + "len_active_sessions": active_count, + "has_pons": has_pos, + "has_active_pons": active_count > 0, + } + + def get_info(self, obj): + products = RolesProducts.objects.filter(guild=obj, trash=False).first() + return RolesProductsSerializer(products).data + + +class DistributionUserLevelSerializer(serializers.ModelSerializer): + class Meta: + model = DistributionUserLevel + fields = ['key', 'fa_title', 'en_title'] + + +class RealGuildsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'user', 'guilds_name', 'type_activity', 'area_activity', + ] + + +class RealGuildsForDashboardSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + ware_house_info = serializers.SerializerMethodField('get_ware_house_info') + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'user', 'guilds_name', 'steward', 'ware_house_info', 'address'] + + def get_ware_house_info(self, obj): + + date1 = self.context.get('request').GET.get('date1') + date2 = self.context.get('request').GET.get('date2') + product = RolesProducts.objects.filter(guild=obj, trash=False, name='مرغ گرم').first() + + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocations = StewardAllocation.objects.filter( + Q(steward=obj) | Q(to_steward=obj), + trash=False, calculate_status=True, to_cold_house__isnull=True, + date__date__gte=date1, date__date__lte=date2, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, steward=obj, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, steward=obj, + warehouse=True) + segmentations = PosSegmentation.objects.filter(guild=obj, trash=False, warehouse=True, + date__date__gte=date1, date__date__lte=date2) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward=obj) | Q(guild=obj), trash=False, + date__date__gte=date1, date__lte=date2, + warehouse=True) + + + else: + allocations = StewardAllocation.objects.filter( + Q(steward=obj) | Q(to_steward=obj), + trash=False, calculate_status=True, to_cold_house__isnull=True, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(trash=False, steward=obj, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(trash=False, steward=obj, warehouse=True) + segmentations = PosSegmentation.objects.filter(guild=obj, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward=obj) | Q(guild=obj), trash=False, warehouse=True) + + allocations_aggregates = allocations.aggregate( + total_input_bars_count=Count('id', filter=Q(to_steward=obj)), + total_output_bars_count=Count('id', filter=Q(steward=obj)), + total_input_bars_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward=obj)), + total_input_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward=obj, quota='governmental')), + total_input_free_bars_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward=obj, quota='free')), + total_output_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward=obj, receiver_state__in=('pending', 'accepted'))), + total_output_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward=obj, receiver_state__in=('pending', 'accepted'), + quota='governmental')), + total_output_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward=obj, receiver_state__in=('pending', 'accepted'), + quota='free')), + total_input_entered_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward=obj, receiver_state='accepted')), + + total_input_entered_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward=obj, receiver_state='accepted', + quota='governmental')), + total_input_entered_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward=obj, receiver_state='accepted', quota='free')), + total_input_entered_bars_count=Count('id', filter=Q(to_steward=obj, receiver_state='accepted')) + + ) + + free_bars_aggregates = free_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses') + ) + + free_sale_bars_aggregates = free_sale_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses'), + total_governmental_weight=Sum('weight_of_carcasses', filter=Q(quota='governmental')), + total_free_weight=Sum('weight_of_carcasses', filter=Q(quota='free')), + + ) + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + + input_allocations_count = allocations_aggregates['total_input_bars_count'] or 0 + input_allocations_weight = allocations_aggregates['total_input_bars_weight'] or 0 + input_governmental_allocations_weight = allocations_aggregates['total_input_governmental_bars_weight'] or 0 + input_free_allocations_weight = allocations_aggregates['total_input_free_bars_weight'] or 0 + input_entered_allocations_weight = allocations_aggregates['total_input_entered_bars_weight'] or 0 + input_entered_governmental_allocations_weight = allocations_aggregates[ + 'total_input_entered_governmental_bars_weight'] or 0 + input_entered_free_allocations_weight = allocations_aggregates['total_input_entered_free_bars_weight'] or 0 + input_entered_allocations_count = allocations_aggregates['total_input_entered_bars_count'] or 0 + output_allocations_weight = allocations_aggregates['total_output_bars_weight'] or 0 + output_governmental_allocations_weight = allocations_aggregates['total_output_governmental_bars_weight'] or 0 + output_free_allocations_weight = allocations_aggregates['total_output_free_bars_weight'] or 0 + output_allocations_count = allocations_aggregates['total_output_bars_count'] or 0 + free_bars_weight = free_bars_aggregates['total_weight'] or 0 + free_bars_count = free_bars_aggregates['total_count'] or 0 + free_sale_bars_weight = free_sale_bars_aggregates['total_weight'] or 0 + free_sale_governmental_bars_weight = free_sale_bars_aggregates['total_governmental_weight'] or 0 + free_sale_free_bars_weight = free_sale_bars_aggregates['total_free_weight'] or 0 + free_sale_bars_count = free_sale_bars_aggregates['total_count'] or 0 + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + remain_weight = int( + (input_entered_allocations_weight + free_bars_weight) - (free_sale_bars_weight + output_allocations_weight)) + + total_input_governmental_weight = input_entered_governmental_allocations_weight + total_input_free_weight = input_entered_free_allocations_weight + free_bars_weight + total_input_weight = total_input_governmental_weight + total_input_free_weight + total_output_governmental_weight = output_governmental_allocations_weight + free_sale_governmental_bars_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_output_free_weight = output_free_allocations_weight + free_sale_free_bars_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + total_output_weight = total_output_governmental_weight + total_output_free_weight + total_remain_weight = total_input_weight - total_output_weight + total_remain_governmental_weight = ( + total_input_governmental_weight - total_output_governmental_weight) - archives_governmental_weight if ( + ( + total_input_governmental_weight - total_output_governmental_weight) - archives_governmental_weight) > 0 else 0 + total_remain_free_weight = (total_input_free_weight - total_output_free_weight) - archives_free_weight if ( + ( + total_input_free_weight - total_output_free_weight) - archives_free_weight) > 0 else 0 + last_total_remain_free_weight = (( + total_input_free_weight - total_output_free_weight) - archives_free_weight) * -1 if ( + ( + total_input_free_weight - total_output_free_weight) - archives_free_weight) < 0 else 0 + last_total_remain_governmental_weight = ( + ( + total_input_governmental_weight - total_output_governmental_weight) - archives_governmental_weight) * -1 if ( + ( + total_input_governmental_weight - total_output_governmental_weight) - archives_governmental_weight) < 0 else 0 + last_total_remain_weight = last_total_remain_governmental_weight + last_total_remain_free_weight + + result = { + "total_bars_weight": int(input_allocations_weight + free_bars_weight), + "total_bars_count": free_bars_count + input_allocations_count, + "input_bars_weight": int(input_allocations_weight), + "input_governmental_allocations_weight": int(input_governmental_allocations_weight), + "input_free_allocations_weight": int(input_free_allocations_weight), + "input_bars_count": input_allocations_count, + "total_entered_bars_weight": int(input_entered_allocations_weight + free_bars_weight), + "input_entered_governmental_allocations_weight": int(input_entered_governmental_allocations_weight), + "input_entered_free_allocations_weight": int(input_entered_free_allocations_weight), + "total_entered_bars_count": input_entered_allocations_count + free_bars_count, + "in_province_bars_count": output_allocations_count, + "in_province_bars_weight": int(output_allocations_weight), + "in_province_governmental_bars_weight": int(output_governmental_allocations_weight), + "in_province_free_bars_weight": int(output_free_allocations_weight), + "out_province_bars_count": free_sale_bars_count, + "out_province_bars_weight": int(free_sale_bars_weight), + "out_province_governmental_bars_weight": int(free_sale_governmental_bars_weight), + "out_province_free_bars_weight": int(free_sale_free_bars_weight), + "total_in_out_province_bars_weight": int(free_sale_bars_weight) + int(output_allocations_weight), + "total_in_out_province_bars_count": output_allocations_count + free_sale_bars_count, + "free_bars_weight": free_bars_weight, + "free_bars_count": free_bars_count, + "remain_weight": remain_weight, + "segmentations_weight": segmentations_weight, + "segmentations_governmental_weight": segmentations_governmental_weight, + "segmentations_free_weight": segmentations_free_weight, + "total_input_weight": total_input_weight, + "total_input_governmental_weight": total_input_governmental_weight, + "total_input_free_weight": total_input_free_weight, + "total_output_weight": total_output_weight, + "total_output_governmental_weight": total_output_governmental_weight, + "total_output_free_weight": total_output_free_weight, + "total_remain_weight": total_remain_weight, + "total_remain_governmental_weight": total_remain_governmental_weight, + "total_remain_free_weight": total_remain_free_weight, + "last_total_remain_free_weight": last_total_remain_free_weight, + "last_total_remain_governmental_weight": last_total_remain_governmental_weight, + "last_total_remain_weight": last_total_remain_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "archives_weight": archives_weight, + "archives_governmental_weight": archives_governmental_weight, + "archives_free_weight": archives_free_weight, + } + + return result + + +class PosGuildsSerializer(serializers.ModelSerializer): + shop_name = serializers.CharField(source='guilds_name', read_only=True) + fullname = serializers.CharField(source='user.fullname', read_only=True) + mobile = serializers.CharField(source='user.mobile', read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'shop_name', 'fullname', 'mobile', 'steward'] + + +class ColdHouseForStewardSerializer(serializers.ModelSerializer): + steward = GuildsForStewardMenueSerializer(read_only=True) + + class Meta: + model = ColdHouse + fields = ['key', 'kill_house', 'steward', 'total_input_weight', 'total_allocated_weight', + 'total_remain_weight', 'name', 'province', 'city', 'address', 'capacity', 'active', 'broadcast', + 'relocate'] + + +class GuildsForTotalColdHouseSerializer(serializers.ModelSerializer): + cold_houses_info = serializers.SerializerMethodField('get_cold_houses_info') + fullname = serializers.CharField(source='user.fullname', read_only=True) + mobile = serializers.CharField(source='user.mobile', read_only=True) + province = serializers.CharField(source='user.province.name', read_only=True) + city = serializers.CharField(source='user.city.name', read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'fullname', 'mobile', 'province', 'city', 'cold_houses_info'] + + def get_cold_houses_info(self, obj): + cold_houses = ColdHouse.objects.filter(steward=obj, trash=False) + + total_input_weight = cold_houses.aggregate(total=Sum('total_input_weight'))[ + 'total'] or 0 + total_allocated_weight = cold_houses.aggregate(total=Sum('total_allocated_weight'))[ + 'total'] or 0 + total_remain_weight = cold_houses.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + + return { + "total_cold_houses": len(cold_houses), + "total_input_weight": total_input_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + +class StewardColdHousesSerializer(serializers.ModelSerializer): + cold_houses = serializers.SerializerMethodField('get_cold_houses') + + class Meta: + model = Guilds + fields = ['key', 'cold_houses'] + + def get_cold_houses(self, obj): + cold_houses = ColdHouse.objects.filter(steward=obj, trash=False) + serializer = ColdHouseForStewardSerializer(cold_houses, many=True) + return serializer.data + + +class GuildsForColdHouseSerializer(serializers.ModelSerializer): + fullname = serializers.CharField(source='user.fullname', read_only=True) + mobile = serializers.CharField(source='user.mobile', read_only=True) + province = serializers.CharField(source='user.province.name', read_only=True) + city = serializers.CharField(source='user.city.name', read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'fullname', 'mobile', 'province', 'city'] + + +class GuildsForDistributionManagementSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + city = serializers.CharField(source='address.city.name', read_only=True) + general_infos = serializers.SerializerMethodField('get_general_infos') + kill_house = serializers.SerializerMethodField('get_kill_house') + steward_kill_house = serializers.SerializerMethodField('get_steward_kill_house') + stewards = serializers.SerializerMethodField('get_stewards') + user_level = DistributionUserLevelSerializer(read_only=True, many=True) + transactions = serializers.SerializerMethodField('get_transactions') + + class Meta: + model = Guilds + fields = ['key', 'user', 'city', 'guilds_name', 'type_activity', 'area_activity', 'steward', 'general_infos', + 'kill_house', 'steward_kill_house', 'stewards', 'user_level', 'transactions'] + + def get_kill_house(self, obj): + kill_houses = KillHouse.objects.filter( + pk__in=KillHouseStewardGuildRelation.objects.filter(guild=obj).values_list('kill_house', flat=True)) + serializer = KillHouseForKillHouseGuildRelationSerializer(kill_houses, many=True, context={'guild': obj}) + return serializer.data + + def get_steward_kill_house(self, obj): + kill_houses = KillHouse.objects.filter( + pk__in=KillHouseStewardGuildRelation.objects.filter(guild=obj).values_list('kill_house', flat=True)) + serializer = KillHouseForKillHouseStewardRelationSerializer(kill_houses, many=True, context={'guild': obj}) + return serializer.data + + def get_stewards(self, obj): + stewards = Guilds.objects.filter( + pk__in=KillHouseStewardGuildRelation.objects.filter(guild=obj).values_list('steward', flat=True)) + serializer = GuildsForDispenserAllocationsSerializer(stewards, many=True, context={'guild': obj}) + return serializer.data + + def get_general_infos(self, obj): + + steward_guild_relations = KillHouseStewardGuildRelation.objects.filter(Q(guild=obj) | Q(steward=obj), + trash=False) + + if obj.steward == False: + input_total_allocation_limit = \ + steward_guild_relations.filter(Q(kill_house__isnull=False) | Q(steward__isnull=False), + guild=obj).aggregate(total=Sum('allocation_limit'))['total'] or 0 + output_total_allocation_limit = 0 + else: + input_total_allocation_limit = \ + steward_guild_relations.filter(kill_house__isnull=False, steward=obj).aggregate( + total=Sum('allocation_limit'))['total'] or 0 + output_total_allocation_limit = \ + steward_guild_relations.filter(steward=obj, guild__isnull=False).aggregate( + total=Sum('allocation_limit'))['total'] or 0 + + type_object = self.context.get('type_object') + role_object = self.context.get('role_object') + type = self.context.get('type') + if type_object == 'KillHouse': + if type == 'guild': + relation = steward_guild_relations.filter(guild=obj, kill_house=role_object).first() + else: + relation = steward_guild_relations.filter(steward=obj, kill_house=role_object).first() + else: + relation = steward_guild_relations.filter(guild=obj, steward=role_object).first() + + return { + "self_input_total_allocation_limit": relation.allocation_limit if relation else None, + "self_total_allocation_type": relation.allocation_type if relation else None, + "input_total_allocation_limit": input_total_allocation_limit, + "output_total_allocation_limit": output_total_allocation_limit + } + + def get_transactions(self, obj): + transactions = PosAllocationTransactions.objects.filter(pos__guild=obj, trash=False) + return len(transactions) + + +class TestGuildsSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(many=True, required=False) + + guilds_steward = serializers.SerializerMethodField('get_steward') + stewarrd_info = serializers.SerializerMethodField('get_stewarrd_info') + kill_house_info = serializers.SerializerMethodField('get_kill_house_info') + + class Meta: + model = Guilds + fields = '__all__' + + def get_steward(self, obj): + steward = Steward.objects.filter(guilds=obj, guilds__steward=True).last() + if steward: + serializer = StewardForGuildsSerializer(steward) + return serializer.data + return None + + def get_stewarrd_info(self, obj): + if obj.centers_allocation != None and len(obj.centers_allocation) != 0: + import uuid + key = obj.centers_allocation[0]['value'] + steward = Steward.objects.filter(key=uuid.UUID(key), guilds__steward=True).last() + if steward: + return steward.guilds.guilds_name + return None + + def get_kill_house_info(self, obj): + kill_house_list = [] + if obj.kill_house_centers_allocation != None: + for kill_house in obj.kill_house_centers_allocation: + kill_house = KillHouse.objects.get(key=kill_house['value'], trash=False) + kill_house_list.append({ + "name": kill_house.name, + "killer": kill_house.killer, + "mobile": kill_house.kill_house_operator.user.mobile + }) + + return kill_house_list + + +class GuildsWareHouseSerializer(serializers.ModelSerializer): + guilds = GuildsSerializer(read_only=True) + + class Meta: + model = GuildsWareHouse + fields = '__all__' + + +class StewardForDispenserAllocationsSerializer(serializers.ModelSerializer): + guilds = GuildsForDispenserAllocationsSerializer(read_only=True) + + class Meta: + model = Steward + fields = ['key', 'guilds'] + + +class StewardSerializer(serializers.ModelSerializer): + guilds = GuildsSerializer(read_only=True) + product_info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Steward + fields = '__all__' + + def get_info(self, obj): + products = RolesProducts.objects.filter(guild=obj.guilds, trash=False).first() + return RolesProductsSerializer(products).data + + +class ProductForStewardFreeBarInformationSerializer(serializers.ModelSerializer): + class Meta: + model = Product + fields = ['key', 'name'] + + +class StewardFreeBarInformationSerializer(serializers.ModelSerializer): + steward = GuildsForStewardAutoAllocationSerializer(read_only=True) + guild = GuildsForStewardAutoAllocationSerializer(read_only=True) + product = ProductForStewardFreeBarInformationSerializer(read_only=True) + + class Meta: + model = StewardFreeBarInformation + fields = '__all__' + + +class PosStewardFreeBarInformationSerializer(serializers.ModelSerializer): + buyer = serializers.SerializerMethodField('get_buyer') + + class Meta: + model = StewardFreeBarInformation + fields = ['key', 'buyer', 'kill_house_name', 'kill_house_mobile', 'province', 'city', 'date', + 'number_of_carcasses', 'weight_of_carcasses', 'bar_image'] + + def get_buyer(self, obj): + buyer = obj.guild if obj.guild else obj.steward + type = 'guild' if obj.guild else 'steward' + return { + "fullname": buyer.user.fullname, + "mobile": buyer.user.mobile, + "shop": buyer.guilds_name, + "type": type, + + } + + +class OutProvinceCarcassesBuyerForStewardSerializer(serializers.ModelSerializer): + steward = GeneralGuildsForInspectionsSerializer(read_only=True) + + class Meta: + model = OutProvinceCarcassesBuyer + fields = ['key', 'fullname', 'first_name', 'last_name', 'mobile', 'unit_name', 'city', 'province', 'active', + 'steward'] + + +class StewardFreeSaleBarInformationSerializer(serializers.ModelSerializer): + buyer = OutProvinceCarcassesBuyerForStewardSerializer(read_only=True) + guild = RealGuildsSerializer(read_only=True) + steward = RealGuildsSerializer(read_only=True) + + class Meta: + model = StewardFreeSaleBarInformation + fields = '__all__' + + +class StewardForStewardAutoAllocationSerializer(serializers.ModelSerializer): + guilds = GuildsForStewardAutoAllocationSerializer(read_only=True) + + class Meta: + model = Steward + fields = ['guilds'] + + +class StewardWareHouseSerializer(serializers.ModelSerializer): + steward = StewardSerializer(read_only=True) + + class Meta: + model = StewardWareHouse + fields = '__all__' + + +class StewardWareHouseForDailyBroadCastOInDetailsSerializer(serializers.ModelSerializer): + informations = serializers.SerializerMethodField('get_informations') + + class Meta: + model = Steward + fields = ['informations', 'key'] + + def get_informations(self, obj): + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, steward=obj, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + return { + "buyers": obj.guilds.guilds_name, + "city": obj.guilds.address.city.name, + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": 0, + "total_pre_cold_weight": 0, + "total_number_of_free_carcasses": total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + "total_free_weight_of_carcasses": total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "final_total_number_of_carcasses": final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + "final_total_weight_of_carcasses": final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + "total_allocated_quantity": total_allocated_quantity if total_allocated_quantity != None else 0, + "total_allocated_weight": total_allocated_weight if total_allocated_weight != None else 0, + "total_accepted_allocated_quantity": total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + "total_accepted_allocated_weight": total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + "total_remain_quantity": total_remain_quantity if total_remain_quantity != None else 0, + "total_remain_weight": total_remain_weight if total_remain_weight != None else 0, + "number_of_guild": number_of_guild, + } + + +class AutomaticStewardAllocationSerializer(serializers.ModelSerializer): + steward = StewardForStewardAutoAllocationSerializer(read_only=True) + + # guilds = GuildsSerializer(read_only=True) + class Meta: + model = StewardAllocation + fields = ['key', 'steward', 'number_of_carcasses', 'real_number_of_carcasses', 'weight_of_carcasses', + 'real_weight_of_carcasses', 'final_registration', 'registration_code', 'system_registration_code', + 'logged_registration_code', + 'state', 'date'] + + +class DispenserForAllocationsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Dispenser + exclude = ('created_by', 'modified_by', 'user_bank_info', 'wallet', 'address', 'create_date', + 'modify_date') + + +class DispenserSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + guild = GuildsForStewardAutoAllocationSerializer(read_only=True) + kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + allocations_info = serializers.SerializerMethodField('get_allocations_info') + + class Meta: + model = Dispenser + exclude = ('created_by', 'modified_by', 'user_bank_info', 'wallet', 'address', 'create_date', + 'modify_date') + + def get_allocations_info(self, obj): + today = datetime.now().date() + allocations = StewardAllocation.objects.filter(dispenser=obj, trash=False) + today_allocations = allocations.filter(date__date=today) + total_quantity = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + total_weight = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + today_quantity = today_allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + today_weight = today_allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + return { + "number_of_allocations": len(allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + "number_of_today_allocations": len(today_allocations), + "total_today_quantity": today_quantity, + "total_today_weight": today_weight, + } + + +class NewDispenserSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = Dispenser + fields = ['key', 'user', 'in_use'] + + +class NewDispenserSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + + class Meta: + model = Dispenser + fields = ['key', 'user', 'in_use'] + + +class DispenserAllocationSerializer(serializers.ModelSerializer): + steward = StewardForDispenserAllocationsSerializer(read_only=True) + guilds = GuildsForDispenserAllocationsSerializer(read_only=True) + dispenser = DispenserForAllocationsSerializer(read_only=True) + seller = serializers.SerializerMethodField('get_seller_info') + index_weight = serializers.SerializerMethodField('get_index_weight') + + class Meta: + model = StewardAllocation + fields = '__all__' + + def get_seller_info(self, obj): + seller_name = None + seller_mobile = None + seller_role = None + if obj.steward != None: + seller_name = obj.steward.guilds.user.fullname + seller_mobile = obj.steward.guilds.user.mobile + seller_role = 'Steward' + else: + seller_name = obj.guilds.user.fullname + seller_mobile = obj.guilds.user.mobile + seller_role = 'Guilds' + + return { + "seller_name": seller_name, + "seller_mobile": seller_mobile, + "seller_role": seller_role + } + + def get_index_weight(self, obj): + + index_weight = round((obj.real_weight_of_carcasses / obj.real_number_of_carcasses), + 2) if obj.real_number_of_carcasses > 0 else 0 + + return index_weight + + +class DispenserInformationSerializer(serializers.ModelSerializer): + class Meta: + model = DispenserInformation + fields = '__all__' + + +class ChildNewProductSerializer(serializers.ModelSerializer): + class Meta: + model = NewProduct + fields = ['key', 'name'] + + +class NewProductSerializer(serializers.ModelSerializer): + child = ChildNewProductSerializer(many=True, read_only=True) + parent = ChildNewProductSerializer(read_only=True) + + class Meta: + model = NewProduct + fields = ['key', 'name', 'parent', 'child'] + + +class PosNewProductSerializer(serializers.ModelSerializer): + class Meta: + model = NewProduct + fields = ['key', 'name', 'sale_type', 'sale_type_package_weight', 'approved_price_status', 'approved_price', + 'sale_limitation_status', 'selling_more_than_inventory', 'image'] + + +class RolesProductsSerializer(serializers.ModelSerializer): + # parent_product = NewProductSerializer(read_only=True) + # kill_house = KillHouseForAutoAllocationSerializer (read_only=True) + # guild = GuildsForStewardMenueSerializer (read_only=True) + + class Meta: + model = RolesProducts + fields = '__all__' + + +class RolesProductsForInspectionSerializer(serializers.ModelSerializer): + class Meta: + model = RolesProducts + fields = ['name', 'total_carcasses_weight', 'real_allocated_weight', + 'total_remain_weight'] + + +class PosRolesProductsSerializer(serializers.ModelSerializer): + parent_product = PosNewProductSerializer(read_only=True) + price = serializers.SerializerMethodField('get_price') + + class Meta: + model = RolesProducts + fields = ['key', 'parent_product', 'name', 'total_carcasses_weight', 'real_allocated_weight', + 'total_remain_weight', 'approved_price_status', 'price', 'segmentation_weight', + 'pos_allocated_weight'] + + def get_price(self, obj): + broad_price = BroadcastPrice.objects.get(trash=False) + price = obj.approved_price if broad_price.active == True else obj.free_price + return price + + +class PosOtherProductsSerializer(serializers.ModelSerializer): + class Meta: + model = OtherProducts + fields = ['key', 'name', 'unit', 'image', 'price', 'active'] + + +class CombinedPosProductSerializer(serializers.ModelSerializer): + price = serializers.SerializerMethodField('get_price') + product_type = serializers.CharField() + + def get_price(self, obj): + if isinstance(obj, RolesProducts): + broad_price = BroadcastPrice.objects.filter(trash=False).first() + # if broad_price and broad_price.active: + # if obj.kill_house: + # if obj.approved_price > 0: + # if obj.approved_price > obj.free_price and obj.free_price > 0: + # return obj.free_price + # else: + # return obj.approved_price + # + # else: + # return obj.free_price + # + # else: + # + # if obj.guild.steward: + # if broad_price.steward_price > 0: + # if broad_price.steward_price > obj.free_price and obj.free_price > 0: + # return obj.free_price + # else: + # return broad_price.steward_price + # else: + # return obj.free_price + # else: + # if broad_price.guild_price > 0: + # if broad_price.guild_price > obj.free_price and obj.free_price > 0: + # return obj.free_price + # else: + # return broad_price.guild_price + # else: + # return obj.free_price + if broad_price and broad_price.active: + if obj.kill_house: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + + else: + return obj.free_price + + else: + + if obj.guild.steward: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + else: + return obj.free_price + else: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + else: + return obj.free_price + + return obj.free_price + elif isinstance(obj, OtherProducts): + return obj.price + elif isinstance(obj, LiveStockRolseProduct): + pos_id = self.context.get('validation_device') + + main_product = obj.parent_product + pos = POSMachine.objects.get(pos_id=pos_id) + share = CooperativeProductsShare.objects.get(product=main_product, cooperative=pos.cooperative, trash=False) + + return share.price + share.shipping_price + share.cooperative_price + share.company_price + share.cooperative.first_sub_cooperative_price + share.cooperative.second_sub_cooperative_price + return None + + def to_representation(self, instance): + if isinstance(instance, RolesProducts): + + data = { + "key": instance.key, + "parent_product": instance.parent_product.key, + "product_type": "roles_product", + "name": instance.name, + "image": instance.parent_product.image, + "price": self.get_price(instance), + "price_approved": instance.approved_price_status, + "selling_more": instance.parent_product.selling_more_than_inventory, + "unit": 'kg', + "total_carcasses_weight": instance.total_carcasses_weight, + "real_allocated_weight": instance.real_allocated_weight, + "total_remain_weight": instance.total_remain_weight, + "segmentation_weight": instance.segmentation_weight, + "pos_allocated_weight": instance.pos_allocated_weight, + "active": True, + "targetunit": "g", + + } + return data + + elif isinstance(instance, OtherProducts): + data = { + "key": instance.key, + "parent_product": None, + "product_type": "other_product", + "name": instance.name, + "image": instance.image, + "price": instance.price, + "price_approved": False, + "selling_more": True, + "unit": instance.unit, + "total_carcasses_weight": 0, + "real_allocated_weight": 0, + "total_remain_weight": 0, + "segmentation_weight": 0, + "pos_allocated_weight": 0, + "active": instance.active, + "targetunit": "g", + + } + return data + elif isinstance(instance, LiveStockRolseProduct): + data = { + "key": instance.key, + "parent_product": instance.parent_product.key, + "product_type": "stock_product", + "name": instance.parent_product.name, + "image": instance.parent_product.image, + "price": self.get_price(instance), + "price_approved": True, + "selling_more": False, + "unit": 'kg', + "total_carcasses_weight": instance.total_weight, + "real_allocated_weight": instance.total_allocated_weight, + "total_remain_weight": instance.total_remain_weight, + "segmentation_weight": 0, + "pos_allocated_weight": 0, + "active": True, + "targetunit": "kg", + + } + return data + return super().to_representation(instance) +class NewCombinedPosProductSerializer(serializers.ModelSerializer): + price = serializers.SerializerMethodField('get_price') + product_type = serializers.CharField() + + def get_price(self, obj): + if isinstance(obj, RolesProducts): + broad_price = BroadcastPrice.objects.filter(trash=False).first() + if broad_price and broad_price.active: + if obj.kill_house: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + + else: + return obj.free_price + + else: + + if obj.guild.steward: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + else: + return obj.free_price + else: + if broad_price.guild_price > 0: + if broad_price.guild_price > obj.free_price and obj.free_price > 0: + return obj.free_price + else: + return broad_price.guild_price + else: + return obj.free_price + + return obj.free_price + elif isinstance(obj, OtherProducts): + return obj.price + elif isinstance(obj, LiveStockRolseProduct): + pos_id = self.context.get('validation_device') + + main_product = obj.parent_product + pos = POSMachine.objects.get(pos_id=pos_id) + share = CooperativeProductsShare.objects.get(product=main_product, cooperative=pos.cooperative, trash=False) + + return share.price + share.shipping_price + share.cooperative_price + share.company_price + share.cooperative.first_sub_cooperative_price + share.cooperative.second_sub_cooperative_price + return None + + def to_representation(self, instance): + if isinstance(instance, RolesProducts): + + data = { + "key": instance.key, + "parent_product": instance.parent_product.key, + "product_type": "roles_product", + "name": instance.name, + "image": instance.parent_product.image, + "price": self.get_price(instance), + "price_approved": instance.approved_price_status, + "selling_more": instance.parent_product.selling_more_than_inventory, + "unit": 'kg', + "total_carcasses_weight": instance.total_carcasses_weight, + "real_allocated_weight": instance.real_allocated_weight, + "total_remain_weight": instance.total_remain_weight, + "segmentation_weight": instance.segmentation_weight, + "pos_allocated_weight": instance.pos_allocated_weight, + "active": True, + "targetunit": "g", + + } + return data + + elif isinstance(instance, OtherProducts): + data = { + "key": instance.key, + "parent_product": None, + "product_type": "other_product", + "name": instance.name, + "image": instance.image, + "price": instance.price, + "price_approved": False, + "selling_more": True, + "unit": instance.unit, + "total_carcasses_weight": 0, + "real_allocated_weight": 0, + "total_remain_weight": 0, + "segmentation_weight": 0, + "pos_allocated_weight": 0, + "active": instance.active, + "targetunit": "g", + + } + return data + elif isinstance(instance, LiveStockRolseProduct): + data = { + "key": instance.key, + "parent_product": instance.parent_product.key, + "product_type": "stock_product", + "name": instance.parent_product.name, + "image": instance.parent_product.image, + "price": self.get_price(instance), + "price_approved": True, + "selling_more": False, + "unit": 'kg', + "total_carcasses_weight": instance.total_weight, + "real_allocated_weight": instance.total_allocated_weight, + "total_remain_weight": instance.total_remain_weight, + "segmentation_weight": 0, + "pos_allocated_weight": 0, + "active": True, + "targetunit": "kg", + + } + return data + return super().to_representation(instance) + + +class RolesProductsForStewardAllocationsSerializer(serializers.ModelSerializer): + # parent_product = NewProductSerializer(read_only=True) + # kill_house = KillHouseForAutoAllocationSerializer (read_only=True) + # guild = GuildsForStewardMenueSerializer (read_only=True) + + class Meta: + model = RolesProducts + fields = ['name', 'weight_average'] + + +class LiveStockSupportForColdHouseSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = LiveStockSupport + fields = ['key', 'user'] + + +class ColdHouseSerializer(serializers.ModelSerializer): + kill_house = KillHouseForProvinceSerializer(read_only=True) + steward = GuildsForStewardMenueSerializer(read_only=True) + + class Meta: + model = ColdHouse + fields = ['key', 'kill_house', 'steward', 'total_input_weight', 'total_allocated_weight', + 'total_remain_weight', 'name', 'province', 'city', 'address', 'active', 'broadcast', 'relocate', + 'capacity'] + + +class StewardAllocationSerializer(serializers.ModelSerializer): + # steward = StewardSerializer(read_only=True) + product = RolesProductsForStewardAllocationsSerializer(read_only=True) + kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + to_kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + steward = GuildsSerializer(read_only=True) + to_steward = GuildsSerializer(read_only=True) + # ware_house = KillHouseWareHouseSerializer(read_only=True) + guilds = GuildsSerializer(read_only=True) + to_guilds = GuildsSerializer(read_only=True) + to_cold_house = ColdHouseSerializer(read_only=True) + other_cold_house = ColdHouseSerializer(read_only=True) + # seller = serializers.SerializerMethodField('get_seller_info') + index_weight = serializers.SerializerMethodField('get_index_weight') + date_timestamp = serializers.SerializerMethodField('get_date_timestamp') + new_state = serializers.SerializerMethodField('get_new_state') + new_receiver_state = serializers.SerializerMethodField('get_new_receiver_state') + new_allocation_state = serializers.SerializerMethodField('get_new_allocation_state') + + class Meta: + model = StewardAllocation + fields = '__all__' + + # def get_seller_info(self, obj): + # seller_name = None + # seller_mobile = None + # seller_role = None + # if obj.ware_house != None: + # seller_name = obj.ware_house.kill_house.kill_house_operator.user.fullname + # seller_mobile = obj.ware_house.kill_house.kill_house_operator.user.mobile + # seller_role = 'KillHouse' + # else: + # seller_name = obj.steward_ware_house.steward.guilds.user.fullname + # seller_mobile = obj.steward_ware_house.steward.guilds.user.mobile + # seller_role = 'Steward' + # + # return { + # "seller_name": seller_name, + # "seller_mobile": seller_mobile, + # "seller_role": seller_role + # } + + def get_index_weight(self, obj): + + index_weight = round((obj.real_weight_of_carcasses / obj.real_number_of_carcasses), + 2) if obj.real_number_of_carcasses > 0 else 0 + + return index_weight + + def get_date_timestamp(self, obj): + ts = datetime.timestamp(obj.date) + return int(ts) + + def get_new_state(self, obj): + state = None + if obj.state == 'pending': + state = 0 + elif obj.state == 'accepted': + state = 1 + else: + state = -1 + return state + + def get_new_receiver_state(self, obj): + state = None + if obj.receiver_state == 'pending': + state = 0 + elif obj.receiver_state == 'accepted': + state = 1 + else: + state = -1 + return state + + def get_new_allocation_state(self, obj): + state = None + if obj.allocation_state == 'pending': + state = 0 + elif obj.allocation_state == 'accepted': + state = 1 + else: + state = -1 + return state + + +class InProvinceAllocationSerializer(serializers.ModelSerializer): + product = RolesProductsForStewardAllocationsSerializer(read_only=True) + kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + to_kill_house = KillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + steward = RealGuildsSerializer(read_only=True) + to_steward = RealGuildsSerializer(read_only=True) + guilds = RealGuildsSerializer(read_only=True) + to_guilds = RealGuildsSerializer(read_only=True) + steward_pos_status = serializers.SerializerMethodField() + guild_pos_status = serializers.SerializerMethodField() + + class Meta: + model = StewardAllocation + exclude = ('created_by', 'modified_by', 'dispenser', 'car', 'to_cold_house', 'steward_ware_house', 'ware_house', + 'create_date', + 'modify_date', 'temporary_deleted', 'temporary_trash', 'calculate_status', + 'steward_temp_key', 'role') + + def get_steward_pos_status(self, obj): + steward = getattr(obj, 'steward', None) + if not steward: + return 'ندارد' + has_paid_pos = POSTransactions.objects.filter( + paid=True, + pos_machine__guild=steward + ).exists() + return 'دارد' if has_paid_pos else 'ندارد' + + def get_guild_pos_status(self, obj): + steward = getattr(obj, 'steward', None) + to_guilds = getattr(obj, 'to_guilds', None) + if not steward or not to_guilds: + return 'ندارد' + has_paid_pos = POSTransactions.objects.filter( + paid=True, + pos_machine__guild=to_guilds + ).exists() + return 'دارد' if has_paid_pos else 'ندارد' + + +class PosStewardAllocationSerializer(serializers.ModelSerializer): + # kill_house = PosKillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + # to_kill_house = PosKillHouseForKillingInformationDiscrepancyReportSerializer(required=False) + # steward = PosGuildsForBroadcastManagementSerializer(read_only=True) + # to_steward = PosGuildsForBroadcastManagementSerializer(read_only=True) + # guilds = PosGuildsForBroadcastManagementSerializer(read_only=True) + # to_guilds = PosGuildsForBroadcastManagementSerializer(read_only= + allocation_from = serializers.SerializerMethodField('get_allocation_from') + allocation_to = serializers.SerializerMethodField('get_allocation_to') + + class Meta: + model = StewardAllocation + fields = ['key', 'allocation_from', 'allocation_to', 'real_number_of_carcasses', 'real_weight_of_carcasses', + 'receiver_real_number_of_carcasses', 'receiver_real_weight_of_carcasses', 'sell_type', + 'allocation_type', 'system_registration_code', 'logged_registration_code', 'receiver_state', 'date', + 'amount', 'total_amount', 'total_amount_paid', 'total_amount_remain', 'active_expire_date_time', + 'production_date', 'quota', 'approved_price_status'] + + def get_allocation_from(self, obj): + if obj.kill_house: + + return { + "key": obj.kill_house.key, + "name": obj.kill_house.name, + "type_activity": "KillHouse", + } + elif obj.steward: + return { + "key": obj.steward.key, + "name": obj.steward.guilds_name, + "type_activity": "Steward", + } + + else: + return { + "key": obj.guilds.key, + "name": obj.guilds.guilds_name, + "type_activity": "Guild", + } + + def get_allocation_to(self, obj): + if obj.to_kill_house: + + return { + "key": obj.to_kill_house.key, + "name": obj.to_kill_house.name, + "type_activity": "KillHouse", + } + elif obj.to_steward: + return { + "key": obj.to_steward.key, + "name": obj.to_steward.guilds_name, + "type_activity": "Steward", + } + + else: + return { + "key": obj.to_guilds.key, + "name": obj.to_guilds.guilds_name, + "type_activity": "Guild", + } + + +class AutoAcceptProvinceKillRequestSerializer(serializers.ModelSerializer): + class Meta: + model = AutoAcceptProvinceKillRequest + fields = ['allow'] + + +class AutoMakeKillHouseRequestSerializer(serializers.ModelSerializer): + class Meta: + model = AutoMakeKillHouseRequest + fields = ['allow'] + + +class NewProvinceAutoAllocationSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestForAutoAllocationSerializer(read_only=True) + province_kill_request = ProvinceKillRequestForAutoAllocationSerializer(read_only=True) + + class Meta: + model = ProvinceAutoAllocation + fields = ['key', 'create_date', 'poultry_request', 'province_kill_request'] + + +class KillHousePercentageOfLossesSerializer(serializers.ModelSerializer): + class Meta: + model = KillHousePercentageOfLosses + fields = '__all__' + + +class ProvinceAllowKillHouseChooseStewardGuildsSerializer(serializers.ModelSerializer): + kill_house = KillHouseForProvinceSerializer(read_only=True) + + class Meta: + model = ProvinceAllowKillHouseChooseStewardGuilds + fields = ['key', 'kill_house', 'steward', 'guilds'] + + +class HatchingLossesPermissionSerializer(serializers.ModelSerializer): + class Meta: + model = HatchingLossesPermission + fields = ['key', 'percent', 'allow'] + + +class WagePaymentSerializer(serializers.ModelSerializer): + class Meta: + model = WagePayment + fields = '__all__' + + +class ProvinceAllowKillHouseDirectBuyingTotalSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceAllowKillHouseDirectBuyingTotal + fields = ['key', 'allow'] + + +class ProvinceAllowKillHouseDirectBuyingSerializer(serializers.ModelSerializer): + kill_house = KillHouseForProvinceSerializer(read_only=True) + + class Meta: + model = ProvinceAllowKillHouseDirectBuying + fields = ['key', 'allow', 'kill_house', 'export_status'] + + +class ProvinceAllowKillHouseRegisterGuildsTotalSerializer(serializers.ModelSerializer): + class Meta: + model = ProvinceAllowKillHouseRegisterGuildsTotal + fields = ['key', 'allow'] + + +class ProvinceAllowKillHouseRegisterGuildsSerializer(serializers.ModelSerializer): + kill_house = KillHouseForProvinceSerializer(read_only=True) + + class Meta: + model = ProvinceAllowKillHouseRegisterGuilds + fields = ['key', 'allow', 'kill_house'] + + +class ObservatorySerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Observatory + fields = '__all__' + + +class PosVersiontSerializer(serializers.ModelSerializer): + class Meta: + model = PosVersion + fields = '__all__' + + +class PosItemSerializer(serializers.ModelSerializer): + class Meta: + model = PosItem + fields = '__all__' + + +class POSIdSerializer(serializers.ModelSerializer): + class Meta: + model = POSId + fields = '__all__' + + +class GuildRoomSerializer(serializers.ModelSerializer): + class Meta: + model = GuildRoom + fields = '__all__' + + +class POSMachineForInspectionSerializer(serializers.ModelSerializer): + guild_info = serializers.SerializerMethodField('get_guild_info') + ware_house_info = serializers.SerializerMethodField('get_ware_house_info') + + class Meta: + model = POSMachine + exclude = ('created_by', 'modified_by', 'user', 'pos_company', 'kill_house', 'guild', 'steward', 'create_date', + 'modify_date', 'trash') + + def get_guild_info(self, obj): + + return { + "fullname": obj.user.fullname, + "mobile": obj.user.mobile, + "city": obj.user.city.name, + "province": obj.user.province.name, + "guild_name": obj.guild.guilds_name, + } + + def get_ware_house_info(self, obj): + try: + ware_house = GuildsWareHouse.objects.get(guilds=obj.guild, trash=False) + return { + "quantity": ware_house.remain_total_number_of_carcasses, + "weight": ware_house.remain_total_weight_of_carcasses + } + except: + return { + "quantity": 0, + "weight": 0 + } + + +class PosDeviceVersionSerializer(serializers.ModelSerializer): + class Meta: + model = PosDeviceVersion + fields = '__all__' + + +class POSMachineSerializer(serializers.ModelSerializer): + class Meta: + model = POSMachine + fields = '__all__' + + +class NewPOSMachineSerializer(serializers.ModelSerializer): + owner = serializers.SerializerMethodField('get_owner') + company_name = serializers.CharField(source='pos_company.name', read_only=True) + + class Meta: + model = POSMachine + fields = '__all__' + + def get_owner(self, obj): + result = None + if obj.kill_house: + result = { + "type": "KillHouse", + "unit_name": obj.kill_house.name, + "fullname": obj.kill_house.kill_house_operator.user.fullname, + "mobile": obj.kill_house.kill_house_operator.user.mobile, + "license_number": '-', + "steward": '-', + } + + + elif obj.steward: + result = { + "type": "Steward", + "unit_name": obj.guild.guilds_name, + "fullname": obj.guild.user.fullname, + "mobile": obj.guild.user.mobile, + "license_number": obj.guild.license_number, + "steward": obj.guild.steward, + } + + + + + elif obj.guild: + result = { + "type": "Guilds", + "unit_name": obj.guild.guilds_name, + "fullname": obj.guild.user.fullname, + "mobile": obj.guild.user.mobile, + "license_number": obj.guild.license_number, + "steward": obj.guild.steward, + } + + else: + pass + return result + + +class POSMachineForLiveStockSerializer(serializers.ModelSerializer): + company_name = serializers.SerializerMethodField('get_company_name') + + class Meta: + model = POSMachine + fields = ['company_name', 'pos_id'] + + def get_company_name(self, obj): + return obj.pos_company.name + + +class POSDeviceSessionSerializer(serializers.ModelSerializer): + class Meta: + model = POSDeviceSession + fields = '__all__' + + +class POSMachineForInspectionsSerializer(serializers.ModelSerializer): + guild = GeneralGuildsForInspectionsSerializer(read_only=True) + products = serializers.SerializerMethodField('get_products') + transactions = serializers.SerializerMethodField('get_transactions') + + class Meta: + model = POSMachine + fields = ['key', 'pos_id', 'guild', 'products', 'transactions', 'create_date'] + + def get_products(self, obj): + products = RolesProducts.objects.filter(guild=obj.guild, trash=False).order_by('id') + serializer = RolesProductsForInspectionSerializer(products, many=True) + return serializer.data + + def get_transactions(self, obj): + transactions = PosMachineTransactions.objects.filter(pos=obj, paid=True, trash=False) + return len(transactions) + + +class POSMachineForTransactionInspectionsSerializer(serializers.ModelSerializer): + guild = GeneralGuildsForInspectionsSerializer(read_only=True) + + class Meta: + model = POSMachine + fields = ['key', 'pos_id', 'guild'] + + +class POSMachineForLiveStockTransactionsSerializer(serializers.ModelSerializer): + cooperative = CooperativeForSharesSerializer(read_only=True) + + class Meta: + model = POSMachine + fields = ['key', 'pos_id', 'cooperative'] + + +class POSDeviceSessionForInspectionSerializer(serializers.ModelSerializer): + pos = POSMachineForInspectionsSerializer(read_only=True) + + class Meta: + model = POSDeviceSession + fields = ['key', 'name', 'pos', 'version', 'session_last_seen_date', 'lng', 'lot'] + + +class POSMachineForServerSerializer(serializers.ModelSerializer): + class Meta: + model = POSMachine + fields = ['pos_id'] + + +class POSTransactionsSerializer(serializers.ModelSerializer): + class Meta: + model = POSTransactions + fields = '__all__' + + +class EvacuationPermitSerializer(serializers.ModelSerializer): + class Meta: + model = EvacuationPermit + fields = '__all__' + + +class SellForFreezingSerializer(serializers.ModelSerializer): + class Meta: + model = SellForFreezing + fields = ['permission'] + + +class LiveStockSupportSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = LiveStockSupport + fields = '__all__' + + +class ColdHouseForRplesSerializer(serializers.ModelSerializer): + sumation_status = serializers.SerializerMethodField('get_sumation_status') + + class Meta: + model = ColdHouse + fields = ['sumation_status', 'total_quantity', 'total_weight', 'name', 'key'] + + def get_sumation_status(self, obj): + allocations = ColdHouseAllocations.objects.filter(state='accepted', cold_house=obj, trash=False).order_by('id') + accepted_quantitys = allocations.aggregate(total=Sum('accepted_quantity'))['total'] or 0 + accepted_weights = allocations.aggregate(total=Sum('accepted_weight'))['total'] or 0 + obj.total_quantity = accepted_quantitys + obj.total_weight = accepted_weights + obj.save() + return "1" + + +class ColdHouseAllocationsSerializer(serializers.ModelSerializer): + cold_house = ColdHouseSerializer(read_only=True) + kill_house_request = KillHouseRequestForColdHouseAllocationsSerializer(read_only=True) + + class Meta: + model = ColdHouseAllocations + fields = '__all__' + + +class OperationLimitationSerializer(serializers.ModelSerializer): + class Meta: + model = OperationLimitation + exclude = ('id', 'key', 'create_date', 'modify_date', 'trash', 'created_by', 'modified_by') + + +class ApprovedPriceSerializer(serializers.ModelSerializer): + class Meta: + model = ApprovedPrice + exclude = ('id', 'key', 'create_date', 'modify_date', 'trash', 'created_by', 'modified_by') + + +class AnnouncementsSerializer(serializers.ModelSerializer): + class Meta: + model = Announcements + exclude = ('id', 'create_date', 'modify_date', 'trash', 'created_by', 'modified_by') + + +class PaymentGatewayPercentageSerializer(serializers.ModelSerializer): + class Meta: + model = PaymentGatewayPercentage + exclude = ('id', 'create_date', 'key', 'modify_date', 'trash', 'created_by', 'modified_by') + + +class TotalPaymentGatewayPercentageSerializer(serializers.ModelSerializer): + class Meta: + model = TotalPaymentGatewayPercentage + exclude = ('id', 'create_date', 'key', 'modify_date', 'trash', 'created_by', 'modified_by') + + +class ChickenAgeRangeSerializer(serializers.ModelSerializer): + class Meta: + model = ChickenAgeRange + fields = ['active', 'maximum', 'minimum'] + + +class TimeRangeSerializer(serializers.ModelSerializer): + class Meta: + model = TimeRange + exclude = ( + 'id', + 'key', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date', + ) + + +class SystemWalletSerializer(serializers.ModelSerializer): + sumation_status = serializers.SerializerMethodField('get_sumation_status') + + class Meta: + model = SystemWallet + exclude = ( + 'id', + 'key', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date' + ) + + def get_sumation_status(self, obj): + status = 0 + if obj.kill_house != None: + transactions = ExternalTransaction.objects.filter(transaction_type='wallet', + kill_house_user=obj.kill_house.kill_house_operator.user, + status='completed', + trash=False).order_by( + 'id') + deposit_transactions = transactions.filter(type='deposit') + withdraw_transactions = transactions.filter(type='withdraw') + deposit = deposit_transactions.aggregate(total=Sum('amount'))['total'] or 0 + withdraw = withdraw_transactions.aggregate(total=Sum('amount'))['total'] or 0 + total = deposit - withdraw if (deposit - withdraw) > 0 else 0 + + obj.balance = total + obj.save() + status = 1 + return status + + +class ShareTypeSerializer(serializers.ModelSerializer): + class Meta: + model = ShareType + exclude = ( + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date', + ) + + +class PercentageForWageTypeSerializer(serializers.ModelSerializer): + name = serializers.SerializerMethodField('get_share_name') + + class Meta: + model = PercentageOfWageType + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date', + 'wage_type' + ) + + def get_share_name(self, obj): + return obj.share_type.name + + +class WageTypeForPoultryOutProvinceRequestSerializer(serializers.ModelSerializer): + class Meta: + model = WageType + exclude = ( + 'id', + 'name', + 'en_name', + 'amount', + 'key', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date' + ) + + +class WageTypeSerializer(serializers.ModelSerializer): + percentages = serializers.SerializerMethodField('get_percentages') + + class Meta: + model = WageType + exclude = ( + 'id', + 'trash', + 'created_by', + 'modified_by', + 'create_date', + 'modify_date' + ) + + def get_percentages(self, obj): + percentages = PercentageOfWageType.objects.filter(wage_type=obj, trash=False).order_by('id') + serializer = PercentageForWageTypeSerializer(percentages, many=True) + return serializer.data + + +class PercentageOfWageTypeSerializer(serializers.ModelSerializer): + wage_type = WageTypeSerializer(read_only=True) + + class Meta: + model = PercentageOfWageType + fields = '__all__' + + +class SubSectorPercentageOfWageTypeSerializer(serializers.ModelSerializer): + percentage_of_wage_type = PercentageOfWageTypeSerializer(read_only=True) + + class Meta: + model = SubSectorPercentageOfWageType + fields = '__all__' + + +class InternalTransactionSerializer(serializers.ModelSerializer): + kill_house = KillHouseForKillHouseVetKillHouseSerializer(read_only=True) + parent_kill_house = KillHouseForKillHouseVetKillHouseSerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + poultry_request = PoultryRequestForAutoAllocationSerializer(read_only=True, many=True) + poultry = PoultryForPoultryRequestLetterSerializer(read_only=True) + out_province_poultry_request_buyer = OutProvincePoultryRequestBuyerSerializer(read_only=True) + payer_info = serializers.SerializerMethodField('get_payer_info') + transaction_amount = serializers.SerializerMethodField('get_total_wage_pay') + union_info = serializers.SerializerMethodField('get_union_info') + + class Meta: + model = InternalTransaction + fields = '__all__' + + def get_payer_info(self, obj): + fullname = None + mobile = None + if obj.kill_house != None: + fullname = obj.kill_house.kill_house_operator.user.fullname + mobile = obj.kill_house.kill_house_operator.user.mobile + elif obj.out_province_poultry_request_buyer != None: + fullname = obj.out_province_poultry_request_buyer.user.fullname + mobile = obj.out_province_poultry_request_buyer.user.mobile + elif obj.chain_company != None: + fullname = obj.chain_company.user.fullname + mobile = obj.chain_company.user.mobile + + else: + fullname = obj.user.fullname + mobile = obj.user.mobile + + return { + "fullname": fullname, + "mobile": mobile + } + + def get_total_wage_pay(self, obj): + role = self.context.get('request').GET['role'] + + # if role == 'ProvinceOperator': + # amout = obj.union_share + # elif role == 'Company': + # amout = obj.company_share + # elif role == 'Guilds': + # amout = obj.guilds_share + # elif role == 'SuperAdmin': + # amout = obj.amount - obj.other_share + # else: + # amout = obj.amount + + return obj.amount + + def get_union_info(self, obj): + user = SystemUserProfile.objects.filter(role__name='ProvinceOperator', trash=False).first() + serializer = SystemUserProfileForFactorSerializer(user) + return serializer.data + + +class PoultryOutRequestInternalTransactionSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestForOutRequestTransactionsSerializer(read_only=True, many=True) + poultry = PoultryForPoultryRequestLetterSerializer(read_only=True) + out_province_poultry_request_buyer = OutProvincePoultryRequestBuyerSerializer(read_only=True) + payer_info = serializers.SerializerMethodField('get_payer_info') + + class Meta: + model = InternalTransaction + fields = '__all__' + + def get_payer_info(self, obj): + fullname = None + mobile = None + if obj.kill_house != None: + fullname = obj.kill_house.kill_house_operator.user.fullname + mobile = obj.kill_house.kill_house_operator.user.mobile + elif obj.out_province_poultry_request_buyer != None: + fullname = obj.out_province_poultry_request_buyer.user.fullname + mobile = obj.out_province_poultry_request_buyer.user.mobile + elif obj.chain_company != None: + fullname = obj.chain_company.user.fullname + mobile = obj.chain_company.user.mobile + + else: + fullname = obj.user.fullname + mobile = obj.user.mobile + + return { + "fullname": fullname, + "mobile": mobile + } + + +# class TotalWageInformationSerializer(serializers.ModelSerializer): +# wage_info = serializers.SerializerMethodField('get_wage_info') +# +# class Meta: +# model = TotalWageInformation +# fields = ['key', 'wage_info'] +# +# def get_wage_info(self, obj): +# +# total_weight = 0 +# total_wage = 0 +# total_paid_wage = 0 +# total_unpaid_wage = 0 +# union_total_weight = 0 +# union_total_wage = 0 +# union_total_paid_wage = 0 +# union_total_unpaid_wage = 0 +# union_province_kill_request_total_wage = 0 +# union_poultry_request_out_total_wage = 0 +# freezing_union_province_kill_request_total_wage = 0 +# union_kill_house_free_live_bar_total_wage = 0 +# union_kill_house_free_carcases_bar_total_wage = 0 +# union_chain_allocation_total_wage = 0 +# union_province_kill_request_total_weight = 0 +# union_poultry_request_out_total_weight = 0 +# freezing_union_province_kill_request_total_weight = 0 +# union_kill_house_free_live_bar_total_weight = 0 +# union_kill_house_free_carcases_bar_total_weight = 0 +# union_chain_allocation_total_weight = 0 +# +# company_total_weight = 0 +# company_total_wage = 0 +# company_total_paid_wage = 0 +# company_total_unpaid_wage = 0 +# company_province_kill_request_total_wage = 0 +# freezing_company_province_kill_request_total_wage = 0 +# company_kill_house_free_live_bar_total_wage = 0 +# company_kill_house_free_carcases_bar_total_wage = 0 +# company_chain_allocation_total_wage = 0 +# company_province_kill_request_total_weight = 0 +# freezing_company_province_kill_request_total_weight = 0 +# company_kill_house_free_live_bar_total_weight = 0 +# company_kill_house_free_carcases_bar_total_weight = 0 +# company_chain_allocation_total_weight = 0 +# company_poultry_request_out_total_wage = 0 +# company_poultry_request_out_total_weight = 0 +# +# guilds_total_weight = 0 +# guilds_total_wage = 0 +# guilds_total_paid_wage = 0 +# guilds_total_unpaid_wage = 0 +# guilds_province_kill_request_total_wage = 0 +# freezing_guilds_province_kill_request_total_wage = 0 +# guilds_kill_house_free_live_bar_total_wage = 0 +# guilds_kill_house_free_carcases_bar_total_wage = 0 +# guilds_chain_allocation_total_wage = 0 +# guilds_province_kill_request_total_weight = 0 +# freezing_guilds_province_kill_request_total_weight = 0 +# guilds_kill_house_free_live_bar_total_weight = 0 +# guilds_kill_house_free_carcases_bar_total_weight = 0 +# guilds_chain_allocation_total_weight = 0 +# guilds_poultry_request_out_total_wage = 0 +# guilds_poultry_request_out_total_weight = 0 +# province_kill_request_total_wage = 0 +# province_kill_request_total_weight = 0 +# poultry_request_out_total_wage = 0 +# poultry_request_out_total_weight = 0 +# freezing_province_kill_requests_total_wage = 0 +# freezing_province_kill_requests_total_weight = 0 +# chain_total_wage = 0 +# chain_total_weight = 0 +# free_bars_live_total_wage = 0 +# free_bars_live_total_weight = 0 +# free_bars_carcases_total_wage = 0 +# free_bars_carcases_total_weight = 0 +# role = self.context.get('request').GET['role'] +# user = SystemUserProfile.objects.get(user=self.context.get('request').user) +# if role == 'KillHouse': +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() +# province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, +# state__in=('pending', 'accepted'), trash=False, +# return_to_province=False, +# first_car_allocated_quantity=0, +# archive_wage=False, +# ) +# freezing_province_kill_requests = province_kill_requests.filter( +# province_request__poultry_request__freezing=True) +# +# kill_house_requests = KillHouseRequest.objects.filter( +# Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( +# Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( +# Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, +# trash=False +# ) +# freezing_kill_house_requests = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=True) +# +# # kill_house_requests = KillHouseRequest.objects.filter( +# # killer=kill_house, archive_wage=False,killer__isnull=False, +# # trash=False +# # ).exclude( +# # province_kill_request__in=province_kill_requests +# # ) +# +# free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, +# trash=False) +# free_bars_live = free_bars.filter(buy_type='live', trash=False) +# free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) +# province_kill_requests_total_wage = \ +# province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_wage_amount'))[ +# 'total'] or 0 +# freezing_province_kill_request_total_wage = \ +# freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 +# +# total_wage += province_kill_requests_total_wage + freezing_province_kill_request_total_wage +# province_kill_requests_total_weight = \ +# province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_province_kill_request_total_weight = \ +# freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 +# total_weight += province_kill_requests_total_weight + freezing_province_kill_request_total_weight +# kill_house_reqest_total_wage = \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ +# 'total'] or 0 +# freezing_kill_house_reqest_total_wage = \ +# freezing_kill_house_requests.aggregate( +# total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ +# 'total'] or 0 +# total_wage += kill_house_reqest_total_wage + freezing_kill_house_reqest_total_wage +# +# kill_house_reqest_total_weight = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# freezing_kill_house_reqest_total_weight = \ +# freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# total_weight += kill_house_reqest_total_weight + freezing_kill_house_reqest_total_weight +# +# free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ +# 'total'] or 0 +# total_wage += free_bars_live_total_wage +# free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# total_weight += free_bars_live_total_weight +# free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ +# 'total'] or 0 +# total_wage += free_bars_carcases_total_wage +# free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# total_weight += free_bars_carcases_total_weight +# +# slaughter_transactions = InternalTransaction.objects.filter( +# Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', +# trash=False) +# +# total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ +# 'total'] or 0 +# +# return { +# "total_weight": total_weight, +# "total_wage": total_wage, +# "total_paid_wage": total_paid_wage, +# "total_unpaid_wage": total_wage - total_paid_wage, +# "province_kill_requests_total_wage": province_kill_requests_total_wage + kill_house_reqest_total_wage, +# "province_kill_requests_total_weight": province_kill_requests_total_weight + kill_house_reqest_total_weight, +# "freezing_province_kill_requests_total_wage": freezing_province_kill_request_total_wage + freezing_kill_house_reqest_total_wage, +# "freezing_province_kill_requests_total_weight": freezing_province_kill_request_total_weight + freezing_kill_house_reqest_total_weight, +# "free_bars_live_total_wage": free_bars_live_total_wage, +# "free_bars_live_total_weight": free_bars_live_total_weight, +# "free_bars_carcases_total_wage": free_bars_carcases_total_wage, +# "free_bars_carcases_total_weight": free_bars_carcases_total_weight, +# } +# elif role == 'ChainCompany': +# chain_company = ChainCompany.objects.get(user=user, trash=False) +# chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, state='accepted', +# trash=False) +# chain_allocations_total_wage = chain_allocations.aggregate(total=Sum('total_wage_amount'))[ +# 'total'] or 0 +# total_wage += chain_allocations_total_wage +# chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# total_weight += chain_allocations_total_weight +# +# chain_company_transactions = InternalTransaction.objects.filter(chain_company=chain_company, +# status='completed', trash=False) +# total_paid_wage += chain_company_transactions.aggregate(total=Sum('amount'))[ +# 'total'] or 0 +# +# return { +# "total_weight": total_weight, +# "total_wage": total_wage, +# "chain_allocations_total_wage": chain_allocations_total_wage, +# "chain_allocations_total_weight": chain_allocations_total_weight, +# "total_paid_wage": total_paid_wage, +# "total_unpaid_wage": total_wage - total_paid_wage +# } +# +# else: +# +# if role == 'ProvinceOperator': +# type = 'union_share' +# share_type = 'union_share' +# out_poultry_requests = PoultryRequest.objects.filter(out=True, trash=False, wage_pay=True, +# union_share__gt=0) +# poultry_request_out_total_weight = \ +# out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# poultry_request_out_total_wage = out_poultry_requests.aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('union_share_percent') / 100)))[ +# 'total'] or 0 +# province_kill_requests = ProvinceKillRequest.objects.filter( +# state__in=('pending', 'accepted'), trash=False, +# first_car_allocated_quantity=0, +# return_to_province=False, archive_wage=False, union_share__gt=0) +# freezing_province_kill_requests = province_kill_requests.filter( +# province_request__poultry_request__freezing=True) +# kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, +# province_kill_request__union_share__gt=0) +# freezing_kill_house_requests = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=True) +# +# chain_allocations = ChainAllocation.objects.filter(union_share__gt=0, state='accepted', trash=False) +# free_bars = KillHouseFreeBarInformation.objects.filter(union_share__gt=0, archive_wage=False, +# trash=False) +# +# province_kill_requests_total_weight = \ +# province_kill_requests.aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_weight = \ +# freezing_province_kill_requests.aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# province_kill_requests_total_weight += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_weight += \ +# freezing_kill_house_requests.aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + poultry_request_out_total_weight +# +# province_kill_requests_total_wage = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('union_share'))[ +# 'total'] or 0 +# province_kill_requests_total_wage += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__union_share_percent') / 100)))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_wage = \ +# freezing_province_kill_requests.aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_wage += \ +# freezing_kill_house_requests.aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__union_share_percent') / 100)))[ +# 'total'] or 0 +# total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + poultry_request_out_total_wage +# +# free_bars_live = free_bars.filter(buy_type='live', trash=False) +# free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) +# +# chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += chain_allocations_total_wage +# chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# total_weight += chain_allocations_total_weight +# free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_live_total_wage +# free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# total_weight += free_bars_live_total_weight +# free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_carcases_total_wage +# free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# total_weight += free_bars_carcases_total_weight +# slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', +# union_share__gt=0, +# trash=False) +# +# total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', +# status='completed', union_share__gt=0, +# trash=False) +# total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# +# +# +# elif role == 'Guilds': +# type = 'guilds_share' +# share_type = 'guilds_share' +# out_poultry_requests = PoultryRequest.objects.filter(out=True, trash=False, wage_pay=True, +# guilds_share__gt=0) +# poultry_request_out_total_weight = \ +# out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# poultry_request_out_total_wage = out_poultry_requests.aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('guilds_share_percent') / 100)))[ +# 'total'] or 0 +# province_kill_requests = ProvinceKillRequest.objects.filter( +# state__in=('pending', 'accepted'), trash=False, +# first_car_allocated_quantity=0, +# +# return_to_province=False, archive_wage=False, guilds_share__gt=0) +# freezing_province_kill_requests = province_kill_requests.filter( +# province_request__poultry_request__freezing=True) +# +# kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, +# province_kill_request__guilds_share__gt=0) +# freezing_kill_house_requests = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=True) +# +# chain_allocations = ChainAllocation.objects.filter(guilds_share__gt=0, state='accepted', trash=False) +# free_bars = KillHouseFreeBarInformation.objects.filter(guilds_share__gt=0, archive_wage=False, +# trash=False) +# +# province_kill_requests_total_weight = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_weight = \ +# freezing_province_kill_requests.aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# province_kill_requests_total_weight += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_weight += \ +# freezing_kill_house_requests.aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + poultry_request_out_total_weight +# +# province_kill_requests_total_wage = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('union_share'))[ +# 'total'] or 0 +# province_kill_requests_total_wage += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__guilds_share_percent') / 100)))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_wage = \ +# freezing_province_kill_requests.aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_wage += \ +# freezing_kill_house_requests.aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__guilds_share_percent') / 100)))[ +# 'total'] or 0 +# total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + poultry_request_out_total_wage +# +# free_bars_live = free_bars.filter(buy_type='live', trash=False) +# free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) +# +# chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += chain_allocations_total_wage +# chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# total_weight += chain_allocations_total_weight +# free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_live_total_wage +# free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# total_weight += free_bars_live_total_weight +# free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_carcases_total_wage +# free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# total_weight += free_bars_carcases_total_weight +# slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', +# guilds_share__gt=0, +# trash=False) +# +# total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', +# status='completed', guilds_share__gt=0, +# trash=False) +# total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# +# +# elif role == 'Company': +# type = 'company_share' +# share_type = 'company_share' +# out_poultry_requests = PoultryRequest.objects.filter(out=True, trash=False, wage_pay=True, +# company_share__gt=0) +# poultry_request_out_total_weight = \ +# out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# poultry_request_out_total_wage = out_poultry_requests.aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('company_share_percent') / 100)))[ +# 'total'] or 0 +# province_kill_requests = ProvinceKillRequest.objects.filter( +# state__in=('pending', 'accepted'), trash=False, +# first_car_allocated_quantity=0, +# return_to_province=False, archive_wage=False, company_share__gt=0) +# freezing_province_kill_requests = province_kill_requests.filter( +# province_request__poultry_request__freezing=True) +# +# kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False, +# province_kill_request__company_share__gt=0) +# freezing_kill_house_requests = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=True) +# +# chain_allocations = ChainAllocation.objects.filter(company_share__gt=0, state='accepted', trash=False) +# free_bars = KillHouseFreeBarInformation.objects.filter(company_share__gt=0, archive_wage=False, +# trash=False) +# +# province_kill_requests_total_weight = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_weight = \ +# freezing_province_kill_requests.aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# province_kill_requests_total_weight += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_weight += \ +# freezing_kill_house_requests.aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + poultry_request_out_total_weight +# +# province_kill_requests_total_wage = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('union_share'))[ +# 'total'] or 0 +# province_kill_requests_total_wage += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__company_share_percent') / 100)))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_wage = \ +# freezing_province_kill_requests.aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_wage += \ +# freezing_kill_house_requests.aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__company_share_percent') / 100)))[ +# 'total'] or 0 +# total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + poultry_request_out_total_wage +# +# free_bars_live = free_bars.filter(buy_type='live', trash=False) +# free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) +# +# chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += chain_allocations_total_wage +# chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# total_weight += chain_allocations_total_weight +# free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_live_total_wage +# free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# total_weight += free_bars_live_total_weight +# free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_carcases_total_wage +# free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# total_weight += free_bars_carcases_total_weight +# slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', +# company_share__gt=0, +# trash=False) +# +# total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', +# status='completed', company_share__gt=0, +# trash=False) +# total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# +# +# else: +# type = 'total_wage_amount' +# share_type = 'amount' +# out_poultry_requests = PoultryRequest.objects.filter(out=True, trash=False, wage_pay=True) +# poultry_request_out_total_weight = \ +# out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# poultry_request_out_total_wage = out_poultry_requests.aggregate( +# total=Sum( +# (F('quantity') * F('Index_weight')) * F('wage')))[ +# 'total'] or 0 +# province_kill_requests = ProvinceKillRequest.objects.filter( +# state__in=('pending', 'accepted'), trash=False, archive_wage=False, +# first_car_allocated_quantity=0, +# return_to_province=False) +# freezing_province_kill_requests = province_kill_requests.filter( +# province_request__poultry_request__freezing=True) +# +# kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False) +# freezing_kill_house_requests = kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=True) +# +# chain_allocations = ChainAllocation.objects.filter(trash=False, state='accepted') +# free_bars = KillHouseFreeBarInformation.objects.filter(archive_wage=False, trash=False) +# total_slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', +# status='completed', +# trash=False) +# total_chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', +# status='completed', trash=False) +# +# province_kill_requests_total_weight = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_weight = \ +# freezing_province_kill_requests.aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# province_kill_requests_total_weight += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_weight += \ +# freezing_kill_house_requests.aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + poultry_request_out_total_weight +# +# province_kill_requests_total_wage = \ +# province_kill_requests.filter( +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('union_share'))[ +# 'total'] or 0 +# province_kill_requests_total_wage += \ +# kill_house_requests.filter( +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ +# 'total'] or 0 +# +# freezing_province_kill_requests_total_wage = \ +# freezing_province_kill_requests.aggregate(total=Sum(type))[ +# 'total'] or 0 +# freezing_province_kill_requests_total_wage += \ +# freezing_kill_house_requests.aggregate( +# total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ +# 'total'] or 0 +# total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + poultry_request_out_total_wage +# +# free_bars_live = free_bars.filter(buy_type='live', trash=False) +# free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False) +# +# chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += chain_allocations_total_wage +# chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# total_weight += chain_allocations_total_weight +# free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_live_total_wage +# free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# total_weight += free_bars_live_total_weight +# free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ +# 'total'] or 0 +# total_wage += free_bars_carcases_total_wage +# free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# total_weight += free_bars_carcases_total_weight +# slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', +# trash=False) +# +# total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', +# status='completed', +# trash=False) +# total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ +# 'total'] or 0 +# +# union_poultry_request_out_total_weight = \ +# out_poultry_requests.filter(union_share__gt=0).aggregate(total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# union_poultry_request_out_total_wage = out_poultry_requests.aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('union_share_percent') / 100)))[ +# 'total'] or 0 +# +# union_province_kill_request_total_weight = \ +# province_kill_requests.filter(union_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_union_province_kill_request_total_weight = \ +# freezing_province_kill_requests.filter(union_share__gt=0).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# union_province_kill_request_total_weight += \ +# kill_house_requests.filter(province_kill_request__union_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_union_province_kill_request_total_weight += \ +# freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# union_province_kill_request_total_wage = \ +# province_kill_requests.filter(union_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('union_share'))[ +# 'total'] or 0 +# union_province_kill_request_total_wage += \ +# kill_house_requests.filter(province_kill_request__union_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__union_share_percent') / 100)))[ +# 'total'] or 0 +# +# freezing_union_province_kill_request_total_wage = \ +# freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# freezing_union_province_kill_request_total_wage += \ +# freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__union_share_percent') / 100)))[ +# 'total'] or 0 +# union_chain_allocation_total_weight = \ +# chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# union_chain_allocation_total_wage = \ +# chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# union_kill_house_free_live_bar_total_weight = \ +# free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# union_kill_house_free_live_bar_total_wage = \ +# free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# +# union_kill_house_free_carcases_bar_total_weight = \ +# free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# union_kill_house_free_carcases_bar_total_wage = \ +# free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# union_total_paid_wage += \ +# total_slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# union_total_paid_wage += \ +# total_chain_company_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# union_total_weight = union_province_kill_request_total_weight + freezing_union_province_kill_request_total_weight + union_chain_allocation_total_weight + union_kill_house_free_live_bar_total_weight + union_kill_house_free_carcases_bar_total_weight + union_poultry_request_out_total_weight +# union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_chain_allocation_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage +# union_total_unpaid_wage = union_total_wage - ( +# union_total_paid_wage + union_poultry_request_out_total_wage) +# +# company_poultry_request_out_total_weight = \ +# out_poultry_requests.filter(company_share__gt=0).aggregate( +# total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# company_poultry_request_out_total_wage = out_poultry_requests.filter(company_share__gt=0).aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('company_share_percent') / 100)))[ +# 'total'] or 0 +# +# company_province_kill_request_total_weight = \ +# province_kill_requests.filter(company_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# company_province_kill_request_total_weight += \ +# kill_house_requests.filter(province_kill_request__company_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# freezing_company_province_kill_request_total_weight = \ +# freezing_province_kill_requests.filter(company_share__gt=0).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_company_province_kill_request_total_weight += \ +# freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# company_province_kill_request_total_wage = \ +# province_kill_requests.filter(company_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('company_share'))[ +# 'total'] or 0 +# company_province_kill_request_total_wage += \ +# kill_house_requests.filter(province_kill_request__company_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__company_share_percent') / 100)))[ +# 'total'] or 0 +# freezing_company_province_kill_request_total_wage = \ +# freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# freezing_company_province_kill_request_total_wage += \ +# freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__company_share_percent') / 100)))[ +# 'total'] or 0 +# company_chain_allocation_total_weight = \ +# chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# company_chain_allocation_total_wage = \ +# chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# company_kill_house_free_live_bar_total_weight = \ +# free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# company_kill_house_free_live_bar_total_wage = \ +# free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# +# company_kill_house_free_carcases_bar_total_weight = \ +# free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate( +# total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# company_kill_house_free_carcases_bar_total_wage = \ +# free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# company_total_paid_wage += \ +# total_slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# company_total_paid_wage += \ +# total_chain_company_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ +# 'total'] or 0 +# company_total_weight = company_province_kill_request_total_weight + freezing_company_province_kill_request_total_weight + company_chain_allocation_total_weight + company_kill_house_free_live_bar_total_weight + company_kill_house_free_carcases_bar_total_weight + company_poultry_request_out_total_weight +# company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_chain_allocation_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage +# company_total_unpaid_wage = company_total_wage - (company_total_paid_wage + company_poultry_request_out_total_wage) +# +# +# guilds_poultry_request_out_total_weight = \ +# out_poultry_requests.filter(guilds_share__gt=0).aggregate( +# total=Sum(F('quantity') * F('Index_weight')))[ +# 'total'] or 0 +# guilds_poultry_request_out_total_wage = out_poultry_requests.filter(guilds_share__gt=0).aggregate( +# total=Sum( +# ((F('quantity') * F('Index_weight')) * F('wage')) * ( +# F('guilds_share_percent') / 100)))[ +# 'total'] or 0 +# +# +# guilds_province_kill_request_total_weight = \ +# province_kill_requests.filter(guilds_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# guilds_province_kill_request_total_weight += \ +# kill_house_requests.filter(province_kill_request__guilds_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# +# freezing_guilds_province_kill_request_total_weight = \ +# freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate( +# total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# freezing_guilds_province_kill_request_total_weight += \ +# freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate( +# total=Sum('accepted_real_weight'))[ +# 'total'] or 0 +# guilds_province_kill_request_total_wage = \ +# province_kill_requests.filter(guilds_share__gt=0, +# province_request__poultry_request__freezing=False).aggregate( +# total=Sum('guilds_share'))[ +# 'total'] or 0 +# guilds_province_kill_request_total_wage += \ +# kill_house_requests.filter(province_kill_request__guilds_share__gt=0, +# province_kill_request__province_request__poultry_request__freezing=False).aggregate( +# total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__guilds_share_percent') / 100)))[ +# 'total'] or 0 +# freezing_guilds_province_kill_request_total_wage = \ +# freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# freezing_guilds_province_kill_request_total_wage += \ +# freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( +# F('accepted_real_weight') * F('province_kill_request__wage') * ( +# F('province_kill_request__guilds_share_percent') / 100)))[ +# 'total'] or 0 +# guilds_chain_allocation_total_weight = \ +# chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('weight'))[ +# 'total'] or 0 +# guilds_chain_allocation_total_wage = \ +# chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# guilds_kill_house_free_live_bar_total_weight = \ +# free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('live_weight'))[ +# 'total'] or 0 +# guilds_kill_house_free_live_bar_total_wage = \ +# free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# +# guilds_kill_house_free_carcases_bar_total_weight = \ +# free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate( +# total=Sum('weight_of_carcasses'))[ +# 'total'] or 0 +# guilds_kill_house_free_carcases_bar_total_wage = \ +# free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# guilds_total_paid_wage += \ +# total_slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# guilds_total_paid_wage += \ +# total_chain_company_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ +# 'total'] or 0 +# guilds_total_weight = guilds_province_kill_request_total_weight + freezing_guilds_province_kill_request_total_weight + guilds_chain_allocation_total_weight + guilds_kill_house_free_live_bar_total_weight + guilds_kill_house_free_carcases_bar_total_weight + guilds_poultry_request_out_total_weight +# guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_chain_allocation_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage +# guilds_total_unpaid_wage = guilds_total_wage - (guilds_total_paid_wage + guilds_poultry_request_out_total_wage) +# +# if role == 'SuperAdmin': +# return { +# "total_weight": total_weight, +# "total_wage": total_wage, +# "total_paid_wage": total_paid_wage, +# "total_unpaid_wage": total_wage - total_paid_wage, +# "province_kill_requests_total_wage": province_kill_requests_total_wage, +# "province_kill_requests_total_weight": province_kill_requests_total_weight, +# "freezing_province_kill_requests_total_wage": freezing_province_kill_requests_total_wage, +# "freezing_province_kill_requests_total_weight": freezing_province_kill_requests_total_weight, +# "chain_allocations_total_wage": chain_allocations_total_wage, +# "chain_allocations_total_weight": chain_allocations_total_weight, +# "free_bars_live_total_wage": free_bars_live_total_wage, +# "free_bars_live_total_weight": free_bars_live_total_weight, +# "free_bars_carcases_total_wage": free_bars_carcases_total_wage, +# "free_bars_carcases_total_weight": free_bars_carcases_total_weight, +# "poultry_request_out_total_wage" :poultry_request_out_total_wage, +# "poultry_request_out_total_weight" :poultry_request_out_total_weight, +# "shares": { +# "union_total_weight": union_total_weight, +# "union_total_wage": union_total_wage, +# "union_total_paid_wage": union_total_paid_wage, +# "union_total_unpaid_wage": union_total_unpaid_wage, +# "union_province_kill_request_total_wage": union_province_kill_request_total_wage, +# "union_kill_house_free_live_bar_total_wage": union_kill_house_free_live_bar_total_wage, +# "union_kill_house_free_carcases_bar_total_wage": union_kill_house_free_carcases_bar_total_wage, +# "union_chain_allocation_total_wage": union_chain_allocation_total_wage, +# "union_province_kill_request_total_weight": union_province_kill_request_total_weight, +# "union_kill_house_free_live_bar_total_weight": union_kill_house_free_live_bar_total_weight, +# "union_kill_house_free_carcases_bar_total_weight": union_kill_house_free_carcases_bar_total_weight, +# "union_chain_allocation_total_weight": union_chain_allocation_total_weight, +# "freezing_union_province_kill_request_total_wage": freezing_union_province_kill_request_total_wage, +# "freezing_union_province_kill_request_total_weight": freezing_union_province_kill_request_total_weight, +# "union_poultry_request_out_total_wage":union_poultry_request_out_total_wage, +# "union_poultry_request_out_total_weight":union_poultry_request_out_total_weight, +# +# "company_total_weight": company_total_weight, +# "company_total_wage": company_total_wage, +# "company_total_paid_wage": company_total_paid_wage, +# "company_total_unpaid_wage": company_total_unpaid_wage, +# "company_province_kill_request_total_wage": company_province_kill_request_total_wage, +# "company_kill_house_free_live_bar_total_wage": company_kill_house_free_live_bar_total_wage, +# "company_kill_house_free_carcases_bar_total_wage": company_kill_house_free_carcases_bar_total_wage, +# "company_chain_allocation_total_wage": company_chain_allocation_total_wage, +# "company_province_kill_request_total_weight": company_province_kill_request_total_weight, +# "company_kill_house_free_live_bar_total_weight": company_kill_house_free_live_bar_total_weight, +# "company_kill_house_free_carcases_bar_total_weight": company_kill_house_free_carcases_bar_total_weight, +# "company_chain_allocation_total_weight": company_chain_allocation_total_weight, +# "freezing_company_province_kill_request_total_wage": freezing_company_province_kill_request_total_wage, +# "freezing_company_province_kill_request_total_weight": freezing_company_province_kill_request_total_weight, +# "company_poultry_request_out_total_wage":company_poultry_request_out_total_wage, +# "company_poultry_request_out_total_weight":company_poultry_request_out_total_weight, +# +# "guilds_total_weight": guilds_total_weight, +# "guilds_total_wage": guilds_total_wage, +# "guilds_total_paid_wage": guilds_total_paid_wage, +# "guilds_total_unpaid_wage": guilds_total_unpaid_wage, +# "guilds_province_kill_request_total_wage": guilds_province_kill_request_total_wage, +# "guilds_kill_house_free_live_bar_total_wage": guilds_kill_house_free_live_bar_total_wage, +# "guilds_kill_house_free_carcases_bar_total_wage": guilds_kill_house_free_carcases_bar_total_wage, +# "guilds_chain_allocation_total_wage": guilds_chain_allocation_total_wage, +# "guilds_province_kill_request_total_weight": guilds_province_kill_request_total_weight, +# "guilds_kill_house_free_live_bar_total_weight": guilds_kill_house_free_live_bar_total_weight, +# "guilds_kill_house_free_carcases_bar_total_weight": guilds_kill_house_free_carcases_bar_total_weight, +# "guilds_chain_allocation_total_weight": guilds_chain_allocation_total_weight, +# "freezing_guilds_province_kill_request_total_wage": freezing_guilds_province_kill_request_total_wage, +# "freezing_guilds_province_kill_request_total_weight": freezing_guilds_province_kill_request_total_weight, +# "guilds_poultry_request_out_total_wage" :guilds_poultry_request_out_total_wage, +# "guilds_poultry_request_out_total_weight" :guilds_poultry_request_out_total_weight, +# } +# } +# +# return { +# "total_weight": total_weight, +# "total_wage": total_wage, +# "total_paid_wage": total_paid_wage, +# "total_unpaid_wage": total_wage - total_paid_wage, +# "province_kill_requests_total_wage": province_kill_requests_total_wage, +# "province_kill_requests_total_weight": province_kill_requests_total_weight, +# "freezing_province_kill_requests_total_wage": freezing_province_kill_requests_total_wage, +# "freezing_province_kill_requests_total_weight": freezing_province_kill_requests_total_weight, +# "chain_allocations_total_wage": chain_allocations_total_wage, +# "chain_allocations_total_weight": chain_allocations_total_weight, +# "free_bars_live_total_wage": free_bars_live_total_wage, +# "free_bars_live_total_weight": free_bars_live_total_weight, +# "free_bars_carcases_total_wage": free_bars_carcases_total_wage, +# "free_bars_carcases_total_weight": free_bars_carcases_total_weight, +# "poultry_request_out_total_wage": poultry_request_out_total_wage, +# "poultry_request_out_total_weight": poultry_request_out_total_weight, +# } + + +class TotalWageInformationSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = TotalWageInformation + fields = ['key', 'wage_info'] + + def get_wage_info(self, obj): + before_total_out_live_buying_province_carcasses_weight = 0 + after_total_out_live_buying_province_carcasses_weight = 0 + before_new_out_selling = 0 + after_new_out_selling = 0 + company_before_total_out_live_buying_province_carcasses_price = 0 + before_total_out_live_buying_province_carcasses_price = 0 + company_before_total_out_live_buying_province_carcasses_weight = 0 + extra_company_amount = 0 + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + shares_list = [] + total_unpaid_wage = 0 + union_total_weight = 0 + union_total_wage = 0 + union_total_paid_wage = 0 + union_total_unpaid_wage = 0 + union_province_kill_request_total_wage = 0 + freezing_union_province_kill_request_total_wage = 0 + union_kill_house_free_live_bar_total_wage = 0 + union_kill_house_free_carcases_bar_total_wage = 0 + union_chain_allocation_total_wage = 0 + union_province_kill_request_total_weight = 0 + freezing_union_province_kill_request_total_weight = 0 + union_kill_house_free_live_bar_total_weight = 0 + union_kill_house_free_carcases_bar_total_weight = 0 + union_chain_allocation_total_weight = 0 + + company_total_weight = 0 + company_total_wage = 0 + company_total_paid_wage = 0 + company_total_unpaid_wage = 0 + company_province_kill_request_total_wage = 0 + freezing_company_province_kill_request_total_wage = 0 + company_kill_house_free_live_bar_total_wage = 0 + company_kill_house_free_carcases_bar_total_wage = 0 + company_chain_allocation_total_wage = 0 + company_province_kill_request_total_weight = 0 + freezing_company_province_kill_request_total_weight = 0 + company_kill_house_free_live_bar_total_weight = 0 + company_kill_house_free_carcases_bar_total_weight = 0 + company_chain_allocation_total_weight = 0 + + guilds_total_weight = 0 + guilds_total_wage = 0 + guilds_total_paid_wage = 0 + guilds_total_unpaid_wage = 0 + guilds_province_kill_request_total_wage = 0 + freezing_guilds_province_kill_request_total_wage = 0 + guilds_kill_house_free_live_bar_total_wage = 0 + guilds_kill_house_free_carcases_bar_total_wage = 0 + guilds_chain_allocation_total_wage = 0 + guilds_province_kill_request_total_weight = 0 + freezing_guilds_province_kill_request_total_weight = 0 + guilds_kill_house_free_live_bar_total_weight = 0 + guilds_kill_house_free_carcases_bar_total_weight = 0 + guilds_chain_allocation_total_weight = 0 + + other_total_weight = 0 + other_total_wage = 0 + other_total_paid_wage = 0 + other_total_unpaid_wage = 0 + other_province_kill_request_total_wage = 0 + freezing_other_province_kill_request_total_wage = 0 + other_kill_house_free_live_bar_total_wage = 0 + other_kill_house_free_carcases_bar_total_wage = 0 + other_chain_allocation_total_wage = 0 + other_province_kill_request_total_weight = 0 + freezing_other_province_kill_request_total_weight = 0 + other_kill_house_free_live_bar_total_weight = 0 + other_kill_house_free_carcases_bar_total_weight = 0 + other_chain_allocation_total_weight = 0 + + province_kill_request_total_wage = 0 + province_kill_request_total_weight = 0 + freezing_province_kill_requests_total_wage = 0 + freezing_province_kill_requests_total_weight = 0 + chain_total_wage = 0 + chain_total_weight = 0 + free_bars_live_total_wage = 0 + free_bars_live_total_weight = 0 + free_bars_carcases_total_wage = 0 + free_bars_carcases_total_weight = 0 + real_free_sale_wage = 0 + union_real_free_sale_wage = 0 + company_real_free_sale_wage = 0 + guilds_real_free_sale_wage = 0 + other_real_free_sale_wage = 0 + total_check_wage = 0 + union_wage_percent = 0 + company_wage_percent = 0 + guilds_wage_percent = 0 + other_wage_percent = 0 + date1 = None + date2 = None + role = None + if self.context: + role = self.context.get('request').GET.get('role') + if self.context.get('request').GET.get('date1'): + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_province_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + if role == 'KillHouse': + try: + user = SystemUserProfile.objects.get(user=self.context.get('request').user) + except: + user = SystemUserProfile.objects.get(key=self.context.get('request').GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if date1: + finance_info = get_finance_info(kill_house, date1, date2) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), date__date__gte=date1, + date__date__lte=date2, status='completed', + trash=False) + + else: + finance_info = get_finance_info(kill_house) + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "wage_counting_type": wage_counting_type, + "total_wage": finance_info['total_price'], + "total_paid_wage": total_paid_wage, + "off": kill_house.off, + "total_unpaid_wage": finance_info['total_price'] - (total_paid_wage + kill_house.off), + "province_kill_requests_total_wage": finance_info['total_pure_province_carcasses_price'], + "province_kill_requests_total_weight": finance_info['total_pure_province_carcasses_weight'], + "free_bars_live_total_wage": finance_info['total_out_live_buying_province_carcasses_price'], + "free_bars_live_total_weight": finance_info['total_out_live_buying_province_carcasses_weight'], + "free_bars_carcases_total_wage": finance_info['total_out_carcasses_buying_province_carcasses_price'], + "free_bars_carcases_total_weight": finance_info['total_out_carcasses_buying_province_carcasses_weight'], + "free_bars_out_province_carcases_total_wage": finance_info[ + 'total_out_selling_province_carcasses_price'], + "free_bars_out_province_carcases_total_weight": finance_info[ + 'total_out_selling_province_carcasses_weight'], + "total_province_live_weight": finance_info['total_province_live_weight'], + "total_province_carcasses_weight": finance_info['total_province_carcasses_weight'], + "province_live_wage_amount": province_live_wage_amount, + "free_buying_live_weight_amount": free_buying_live_weight_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_amount, + "finance_info": finance_info, + "return_total_province_live_weight": finance_info['return_total_province_live_weight'], + "total_return_pure_province_carcasses_price": finance_info[ + 'total_return_pure_province_carcasses_price'], + } + + elif role == 'ChainCompany': + try: + user = SystemUserProfile.objects.get(user=self.context.get('request').user) + except: + user = SystemUserProfile.objects.get(key=self.context.get('request').GET['key']) + chain_company = ChainCompany.objects.get(user=user, trash=False) + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, state='accepted', + trash=False) + chain_allocations_total_wage = chain_allocations.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += chain_allocations_total_wage + chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_weight += chain_allocations_total_weight + + chain_company_transactions = InternalTransaction.objects.filter(chain_company=chain_company, + status='completed', trash=False) + total_paid_wage += chain_company_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return { + "total_weight": total_weight, + "total_wage": total_wage, + "chain_allocations_total_wage": chain_allocations_total_wage, + "chain_allocations_total_weight": chain_allocations_total_weight, + "total_paid_wage": total_paid_wage, + "total_unpaid_wage": total_wage - total_paid_wage + } + + + + + else: + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + if date1: + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0).order_by( + 'id') + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, + trash=True, return_trash=True, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + kill_request__recive_date__date__gte=date1, kill_request__recive_date__date__lte=date2, + trash=False, calculate_status=True + ) + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + kill_request__recive_date__date__gte=date1, kill_request__recive_date__date__lte=date2, + trash=True, return_trash=True, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + create_date__date__gte=date1, + create_date__date__lte=date2, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, calculate_status=True, date__date__gte=date1, date__date__lte=date2, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__in=kill_houses, status='completed', date__date__gte=date1, date__date__lte=date2, + trash=False) + poultry_transactions = InternalTransaction.objects.filter( + poultry__isnull=False, status='completed', date__date__gte=date1, date__date__lte=date2, + trash=False) + + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, send_date__date__gte=date1, + send_date__date__lte=date2, + wage_pay=True, has_wage=True, + temporary_deleted=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + create_date__date__gte=date1, + create_date__date__lte=date2, + state='accepted') + else: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by( + 'id') + return_province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, + trash=True, return_trash=True, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + return_kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=True, return_trash=True, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, calculate_status=True, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__in=kill_houses, status='completed', + trash=False) + poultry_transactions = InternalTransaction.objects.filter( + poultry__isnull=False, status='completed', + trash=False) + + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + + out_province_poultry_request_weight = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + union_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + company_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('company_share'))[ + 'total'] or 0 + guilds_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + other_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + off = kill_houses.aggregate(total=Sum('off'))[ + 'total'] or 0 + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_paid_wage += poultry_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + # total_out_selling_province_carcasses_weight = \ + # kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + # total_out_selling_province_quarantine_carcasses_weight = \ + # kill_house_free_sale_bar_info.aggregate(total=Sum('quarantine_weight_of_carcasses'))['total'] or 0 + + # sum_quarantine_carcasses_weight = \ + # kill_house_free_sale_bar_info.filter(quarantine_weight_of_carcasses__gt=0).aggregate( + # total_weight=Sum( + # Case( + # When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + # then=F('real_weight_of_carcasses')), + # default=F('quarantine_weight_of_carcasses'), + # output_field=FloatField() + # ) + # ) + # ) + # total_out_selling_province_quarantine_carcasses_weight = sum_quarantine_carcasses_weight[ + # 'total_weight'] or 0 + + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + difference_requests_weight = \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + return_total_province_live_weight = \ + return_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + return_total_province_live_weight += \ + return_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + final_date = '2025-05-28' + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__lte=final_date).aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + new_total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.filter(date__date__gt=final_date, + quarantine_weight_of_carcasses__gt=0).aggregate( + total_weight=Sum( + Case( + When(real_weight_of_carcasses__lt=F('quarantine_weight_of_carcasses'), + then=F('real_weight_of_carcasses')), + default=F('quarantine_weight_of_carcasses'), + output_field=FloatField() + ) + ) + ) + new_out_selling = new_total_out_selling_province_carcasses_weight['total_weight'] or 0 + + total_out_selling_province_carcasses_weight += new_out_selling + + if wage_counting_type == 'live': + total_province_carcasses_weight = total_province_live_weight + + total_pure_province_carcasses_weight = total_province_carcasses_weight + else: + return_total_province_live_weight = int(return_total_province_live_weight * 0.75) + total_province_carcasses_weight = total_province_live_weight * 0.75 + difference_requests_weight = difference_requests_weight * 0.75 + + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + if date1: + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses, date1, date2) + else: + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + real_total_out_live_buying_province_carcasses_weight = total_out_live_buying_province_carcasses_weight + if new_out_selling_count_wage: + if out_selling_ignore: + before_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__lt=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + after_total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(create_date__date__gte=new_out_selling_count_wage_date, + buy_type='live').aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + get_new_wage = get_new_wage_for_free_buying(kill_house_free_sale_bar_info) + + before_new_out_selling = get_new_wage['before_new_out_selling'] + after_new_out_selling = get_new_wage['after_new_out_selling'] + max_amount = before_total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= before_new_out_selling: + before_total_out_live_buying_province_carcasses_weight -= max_amount + else: + before_total_out_live_buying_province_carcasses_weight -= before_new_out_selling + + if after_total_out_live_buying_province_carcasses_weight > after_new_out_selling: + extra_company_amount = int(after_new_out_selling * extra_company_amount) + after_total_out_live_buying_province_carcasses_weight -= after_new_out_selling + + else: + extra_company_amount = int( + after_total_out_live_buying_province_carcasses_weight * extra_company_amount) + + after_total_out_live_buying_province_carcasses_weight = 0 + + total_out_live_buying_province_carcasses_weight = before_total_out_live_buying_province_carcasses_weight + after_total_out_live_buying_province_carcasses_weight + company_before_total_out_live_buying_province_carcasses_weight = before_total_out_live_buying_province_carcasses_weight + + else: + if out_selling_ignore: + max_amount = total_out_live_buying_province_carcasses_weight * 0.80 + if max_amount <= new_out_selling: + total_out_live_buying_province_carcasses_weight -= max_amount + else: + total_out_live_buying_province_carcasses_weight -= new_out_selling + + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_amount + difference_requests_price = difference_requests_weight * province_live_wage_amount + total_return_pure_province_carcasses_price = return_total_province_live_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_amount + + if new_out_selling_count_wage: + total_out_live_buying_province_carcasses_price = int( + (before_total_out_live_buying_province_carcasses_weight * before_out_buying_count_wage_amount) + ( + after_total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount)) + + before_total_out_live_buying_province_carcasses_price = before_total_out_live_buying_province_carcasses_weight * before_out_buying_count_wage_amount + else: + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount + + # total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + out_province_poultry_request_wage + extra_company_amount + total_return_pure_province_carcasses_price + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + return_union_province_kill_request_wage = total_return_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + union_out_province_poultry_request_wage + return_union_province_kill_request_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_paid_wage += poultry_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + shares_list.append({ + "name": "اتحادیه", + "out_province_poultry_request_wage": union_out_province_poultry_request_wage, + "province_kill_request_wage": union_province_kill_request_wage, + "return_province_kill_request_wage": return_union_province_kill_request_wage, + "free_buying_live_wage": union_free_buying_live_wage, + "free_buying_carcasses_wage": union_free_buying_carcasses_wage, + "free_sell_carcasses_wage": union_free_sell_carcasses_wage, + "total_wage": union_total_wage, + "total_paid_wage": union_total_paid_wage, + "total_unpaid_wage": union_total_unpaid_wage, + + }) + + guilds_difference_requests_price = difference_requests_price * guilds_province_kill_request_percent + other_difference_requests_price = difference_requests_price * other_province_kill_request_percent + guild_return_province_kill_request_wage = total_return_pure_province_carcasses_price * guilds_province_kill_request_percent + other_return_province_kill_request_wage = total_return_pure_province_carcasses_price * other_province_kill_request_percent + + company_province_kill_request_wage = ( + total_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guilds_difference_requests_price + other_difference_requests_price) + return_company_province_kill_request_wage = ( + total_return_pure_province_carcasses_price * company_province_kill_request_percent) + ( + guild_return_province_kill_request_wage + other_return_province_kill_request_wage) + company_free_buying_live_wage = (( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * company_free_buying_live_percent) + before_total_out_live_buying_province_carcasses_price + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + company_out_province_poultry_request_wage + return_company_province_kill_request_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + company_total_paid_wage += poultry_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + # company_total_pure_paid_wage = company_total_paid_wage - (company_total_paid_wage * 0.08)) + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + shares_list.append({ + "name": "شرکت", + "out_province_poultry_request_wage": company_out_province_poultry_request_wage, + "province_kill_request_wage": company_province_kill_request_wage, + "return_province_kill_request_wage": return_company_province_kill_request_wage, + "free_buying_live_wage": company_free_buying_live_wage, + "free_buying_carcasses_wage": company_free_buying_carcasses_wage, + "free_sell_carcasses_wage": company_free_sell_carcasses_wage, + "total_wage": company_total_wage, + "total_paid_wage": company_total_paid_wage, + "total_unpaid_wage": company_total_unpaid_wage, + + }) + + guilds_province_kill_request_wage = ( + total_pure_province_carcasses_price * guilds_province_kill_request_percent) - guilds_difference_requests_price + # return_guilds_province_kill_request_wage = total_return_pure_province_carcasses_price * guilds_province_kill_request_percent + guilds_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_out_province_poultry_request_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_paid_wage += poultry_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + shares_list.append({ + "name": "صنف پروتئین", + "out_province_poultry_request_wage": guilds_out_province_poultry_request_wage, + "province_kill_request_wage": guilds_province_kill_request_wage, + "return_province_kill_request_wage": 0, + "free_buying_live_wage": guilds_free_buying_live_wage, + "free_buying_carcasses_wage": guilds_free_buying_carcasses_wage, + "free_sell_carcasses_wage": guilds_free_sell_carcasses_wage, + "total_wage": guilds_total_wage, + "total_paid_wage": guilds_total_paid_wage, + "total_unpaid_wage": guilds_total_unpaid_wage, + + }) + + other_province_kill_request_wage = ( + total_pure_province_carcasses_price * other_province_kill_request_percent) - other_difference_requests_price + # return_other_province_kill_request_wage = total_return_pure_province_carcasses_price * other_province_kill_request_percent + other_free_buying_live_wage = ( + total_out_live_buying_province_carcasses_price - before_total_out_live_buying_province_carcasses_price) * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_out_province_poultry_request_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_paid_wage += poultry_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + + shares_list.append({ + "name": "دامپزشک", + "out_province_poultry_request_wage": other_out_province_poultry_request_wage, + "province_kill_request_wage": other_province_kill_request_wage, + "return_province_kill_request_wage": 0, + "free_buying_live_wage": other_free_buying_live_wage, + "free_buying_carcasses_wage": other_free_buying_carcasses_wage, + "free_sell_carcasses_wage": other_free_sell_carcasses_wage, + "total_wage": other_total_wage, + "total_paid_wage": other_total_paid_wage, + "total_unpaid_wage": other_total_unpaid_wage, + + }) + + return { + "wage_counting_type": wage_counting_type, + "total_wage": total_price, + "total_paid_wage": total_paid_wage, + "off": off, + "total_unpaid_wage": total_price - (total_paid_wage + off), + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "out_province_poultry_request_wage": out_province_poultry_request_wage, + "province_kill_requests_total_wage": total_pure_province_carcasses_price, + "province_kill_requests_total_weight": total_pure_province_carcasses_weight, + "free_bars_live_total_wage": total_out_live_buying_province_carcasses_price, + "free_bars_live_total_weight": real_total_out_live_buying_province_carcasses_weight, + "free_bars_carcases_total_wage": total_out_carcasses_buying_province_carcasses_price, + "free_bars_carcases_total_weight": total_out_carcasses_buying_province_carcasses_weight, + "free_bars_out_province_carcases_total_wage": total_out_selling_province_carcasses_price, + "free_bars_out_province_carcases_total_weight": total_out_selling_province_carcasses_weight, + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "province_live_wage_amount": province_live_wage_amount, + "free_buying_live_weight_amount": free_buying_live_weight_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_amount, + "out_province_poultry_request_wage_amount": out_province_poultry_request_wage_amount, + "extra_company_amount": extra_company_amount, + "shares": shares_list, + "return_total_province_live_weight": return_total_province_live_weight, + "total_return_pure_province_carcasses_price": total_return_pure_province_carcasses_price, + } + + +class ParentCompanyTotalWageInformationSerializer(serializers.ModelSerializer): + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = TotalWageInformation + fields = ['key', 'wage_info'] + + def get_wage_info(self, obj): + shares_list = [] + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_buying_live_weight_amount = total_wage_type.filter(en_name='live-buy', trash=False).first().amount + free_buying_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-buy', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_province_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, + archive_wage=False, calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( + kill_house__in=kill_houses, + archive_wage=False, calculate_status=True, + trash=False) + + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__in=kill_houses, status='completed', + trash=False) + + poultry_transactions = InternalTransaction.objects.filter( + poultry__isnull=False, status='completed', + trash=False) + + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False) + + out_province_poultry_request_weight = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + union_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + company_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('company_share'))[ + 'total'] or 0 + guilds_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + other_out_province_poultry_request_wage = poultry_requests.aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + off = kill_houses.aggregate(total=Sum('off'))[ + 'total'] or 0 + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + total_paid_wage += poultry_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + if wage_counting_type == 'live': + total_province_carcasses_weight = total_province_live_weight + total_pure_province_carcasses_weight = total_province_carcasses_weight + else: + + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_amount + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + out_province_poultry_request_wage + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter(wage_type__en_name='province-kill-request', + share_type__en_name='union').first().percent / 100 + company_province_kill_request_percent = percentages_wage_type.filter(wage_type__en_name='province-kill-request', + share_type__en_name='company').first().percent / 100 + guilds_province_kill_request_percent = percentages_wage_type.filter(wage_type__en_name='province-kill-request', + share_type__en_name='guilds').first().percent / 100 + other_province_kill_request_percent = percentages_wage_type.filter(wage_type__en_name='province-kill-request', + share_type__en_name='other').first().percent / 100 + + union_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='union').first().percent / 100 + union_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='union').first().percent / 100 + company_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='company').first().percent / 100 + company_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='company').first().percent / 100 + guilds_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='guilds').first().percent / 100 + guilds_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='guilds').first().percent / 100 + other_free_buying_live_percent = percentages_wage_type.filter(wage_type__en_name='live-buy', + share_type__en_name='other').first().percent / 100 + other_free_buying_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-buy', + share_type__en_name='other').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + company_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='company').first().percent / 100 + guilds_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='guilds').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_buying_live_wage = total_out_live_buying_province_carcasses_price * union_free_buying_live_percent + union_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * union_free_buying_carcasses_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + union_total_wage = union_province_kill_request_wage + union_free_buying_live_wage + union_free_buying_carcasses_wage + union_free_sell_carcasses_wage + union_out_province_poultry_request_wage + union_total_paid_wage = slaughter_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_paid_wage += poultry_transactions.aggregate(total=Sum('union_share'))['total'] or 0 + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + shares_list.append({ + "name": "اتحادیه", + "out_province_poultry_request_wage": union_out_province_poultry_request_wage, + "province_kill_request_wage": union_province_kill_request_wage, + "free_buying_live_wage": union_free_buying_live_wage, + "free_buying_carcasses_wage": union_free_buying_carcasses_wage, + "free_sell_carcasses_wage": union_free_sell_carcasses_wage, + "total_wage": union_total_wage, + "total_paid_wage": union_total_paid_wage, + "total_unpaid_wage": union_total_unpaid_wage, + + }) + + company_province_kill_request_wage = total_pure_province_carcasses_price * company_province_kill_request_percent + company_free_buying_live_wage = total_out_live_buying_province_carcasses_price * company_free_buying_live_percent + company_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * company_free_buying_carcasses_percent + company_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * company_free_sell_carcasses_percent + company_total_wage = company_province_kill_request_wage + company_free_buying_live_wage + company_free_buying_carcasses_wage + company_free_sell_carcasses_wage + company_out_province_poultry_request_wage + company_total_paid_wage = slaughter_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + company_total_paid_wage += poultry_transactions.aggregate(total=Sum('company_share'))['total'] or 0 + # company_total_pure_paid_wage = company_total_paid_wage - (company_total_paid_wage * 0.08)) + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + shares_list.append({ + "name": "شرکت", + "out_province_poultry_request_wage": company_out_province_poultry_request_wage, + "province_kill_request_wage": company_province_kill_request_wage, + "free_buying_live_wage": company_free_buying_live_wage, + "free_buying_carcasses_wage": company_free_buying_carcasses_wage, + "free_sell_carcasses_wage": company_free_sell_carcasses_wage, + "total_wage": company_total_wage, + "total_paid_wage": company_total_paid_wage, + "total_unpaid_wage": company_total_unpaid_wage, + + }) + + guilds_province_kill_request_wage = total_pure_province_carcasses_price * guilds_province_kill_request_percent + guilds_free_buying_live_wage = total_out_live_buying_province_carcasses_price * guilds_free_buying_live_percent + guilds_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * guilds_free_buying_carcasses_percent + guilds_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * guilds_free_sell_carcasses_percent + guilds_total_wage = guilds_province_kill_request_wage + guilds_free_buying_live_wage + guilds_free_buying_carcasses_wage + guilds_free_sell_carcasses_wage + guilds_out_province_poultry_request_wage + guilds_total_paid_wage = slaughter_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_paid_wage += poultry_transactions.aggregate(total=Sum('guilds_share'))['total'] or 0 + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + shares_list.append({ + "name": "صنف پروتئین", + "out_province_poultry_request_wage": guilds_out_province_poultry_request_wage, + "province_kill_request_wage": guilds_province_kill_request_wage, + "free_buying_live_wage": guilds_free_buying_live_wage, + "free_buying_carcasses_wage": guilds_free_buying_carcasses_wage, + "free_sell_carcasses_wage": guilds_free_sell_carcasses_wage, + "total_wage": guilds_total_wage, + "total_paid_wage": guilds_total_paid_wage, + "total_unpaid_wage": guilds_total_unpaid_wage, + + }) + + other_province_kill_request_wage = total_pure_province_carcasses_price * other_province_kill_request_percent + other_free_buying_live_wage = total_out_live_buying_province_carcasses_price * other_free_buying_live_percent + other_free_buying_carcasses_wage = total_out_carcasses_buying_province_carcasses_price * other_free_buying_carcasses_percent + other_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * other_free_sell_carcasses_percent + other_total_wage = other_province_kill_request_wage + other_free_buying_live_wage + other_free_buying_carcasses_wage + other_free_sell_carcasses_wage + other_out_province_poultry_request_wage + other_total_paid_wage = slaughter_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_paid_wage += poultry_transactions.aggregate(total=Sum('other_share'))['total'] or 0 + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + + shares_list.append({ + "name": "دامپزشک", + "out_province_poultry_request_wage": other_out_province_poultry_request_wage, + "province_kill_request_wage": other_province_kill_request_wage, + "free_buying_live_wage": other_free_buying_live_wage, + "free_buying_carcasses_wage": other_free_buying_carcasses_wage, + "free_sell_carcasses_wage": other_free_sell_carcasses_wage, + "total_wage": other_total_wage, + "total_paid_wage": other_total_paid_wage, + "total_unpaid_wage": other_total_unpaid_wage, + + }) + + return { + "wage_counting_type": wage_counting_type, + "total_wage": total_price, + "total_paid_wage": total_paid_wage, + "off": off, + "total_unpaid_wage": total_price - (total_paid_wage + off), + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "out_province_poultry_request_wage": out_province_poultry_request_wage, + "province_kill_requests_total_wage": total_pure_province_carcasses_price, + "province_kill_requests_total_weight": total_pure_province_carcasses_weight, + "free_bars_live_total_wage": total_out_live_buying_province_carcasses_price, + "free_bars_live_total_weight": total_out_live_buying_province_carcasses_weight, + "free_bars_carcases_total_wage": total_out_carcasses_buying_province_carcasses_price, + "free_bars_carcases_total_weight": total_out_carcasses_buying_province_carcasses_weight, + "free_bars_out_province_carcases_total_wage": total_out_selling_province_carcasses_price, + "free_bars_out_province_carcases_total_weight": total_out_selling_province_carcasses_weight, + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "province_live_wage_amount": province_live_wage_amount, + "free_buying_live_weight_amount": free_buying_live_weight_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_amount, + "out_province_poultry_request_wage_amount": out_province_poultry_request_wage_amount, + "shares": shares_list, + } + + +class CityLivestockSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = CityLivestock + fields = ['address', 'user_bank_info', 'identity_documents', 'active'] + + +class ImprovingLivestockSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = ImprovingLivestock + fields = '__all__' + + +class ReportSubmissionTimeSerializer(serializers.ModelSerializer): + class Meta: + model = ReportSubmissionTime + fields = '__all__' + + +class ReportsSerializer(serializers.ModelSerializer): + class Meta: + model = Reports + fields = ['title', 'key', 'description'] + + +class UserReportsForReportsUsersSerializer(serializers.ModelSerializer): + report = ReportsSerializer(read_only=True) + + class Meta: + model = UserReports + fields = ['report', 'active', 'key'] + + +class ReportsUsersSerializer(serializers.ModelSerializer): + user_reports = serializers.SerializerMethodField('get_user_reports') + + class Meta: + model = ReportsUsers + fields = '__all__' + + def get_user_reports(self, obj): + user_reports = UserReports.objects.filter(user=obj).order_by('id') + serializer = UserReportsForReportsUsersSerializer(user_reports, many=True) + return serializer.data + + +class UserReportsSerializer(serializers.ModelSerializer): + class Meta: + model = UserReports + fields = '__all__' + + +class MovingTextDashboardStatusSerializer(serializers.ModelSerializer): + class Meta: + model = MovingTextDashboardStatus + fields = ['active'] + + +class MovingTextRoleSerializer(serializers.ModelSerializer): + class Meta: + model = MovingTextRole + fields = '__all__' + + +class MovingTextRoleForMovingTextWithRoleSerializer(serializers.ModelSerializer): + class Meta: + model = MovingTextRole + fields = ['role'] + + +class MovingTextWithRoleForMovingTextSerializer(serializers.ModelSerializer): + role = serializers.SerializerMethodField('get_role') + + class Meta: + model = MovingTextWithRole + fields = ['key', 'active', 'role'] + + def get_role(self, obj): + return obj.role.role + + +class MovingTextSerializer(serializers.ModelSerializer): + roles = serializers.SerializerMethodField('get_roles') + + class Meta: + model = MovingText + fields = ['key', 'id', 'moving_text', 'active', 'roles'] + + def get_roles(self, obj): + moving_text_with_roles = MovingTextWithRole.objects.filter(moving_text=obj).order_by('id') + serializer = MovingTextWithRoleForMovingTextSerializer(moving_text_with_roles, many=True) + return serializer.data + + +class MovingTextWithRoleSerializer(serializers.ModelSerializer): + moving_text = MovingTextSerializer(read_only=True) + role = MovingTextRoleSerializer(read_only=True) + + class Meta: + model = MovingTextWithRole + fields = '__all__' + + +class MovingTextForDashboardSerializer(serializers.ModelSerializer): + class Meta: + model = MovingText + fields = ['moving_text'] + + +class AdminXSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = AdminX + fields = '__all__' + + +class SupporterSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Supporter + fields = '__all__' + + +class ZarinPalAccountsSerializer(serializers.ModelSerializer): + class Meta: + model = ZarinPalAccounts + fields = ['key', 'name', 'account', 'en_name'] + + +class PoultryExportSerializer(serializers.ModelSerializer): + class Meta: + model = PoultryExport + fields = ['key', 'allow', 'limitation_status', 'limitation'] + + +class PoultryOutProvinceRequestSerializer(serializers.ModelSerializer): + class Meta: + model = PoultryOutProvinceRequest + fields = ['key', 'allow', 'limitation_status', 'limitation'] + + +class VetFarmAggregatePermissionSerializer(serializers.ModelSerializer): + class Meta: + model = VetFarmAggregatePermission + fields = ['key', 'allow', 'limitation'] + + +class KillHouseBarLimitationSerializer(serializers.ModelSerializer): + class Meta: + model = KillHouseBarLimitation + fields = ['key', 'allow', 'limitation'] + + +class ProductPricingTypeSerializer(serializers.ModelSerializer): + class Meta: + model = ProductPricingType + fields = ['key', 'province'] + + +class OutOfProvinceSellingCarcassesPermissionSerializer(serializers.ModelSerializer): + class Meta: + model = OutOfProvinceSellingCarcassesPermission + fields = ['key', 'active', 'type', 'percent'] + + +class KillHouseDistributionManagementStewardGuildSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + distribution_info = serializers.SerializerMethodField('get_distribution_info') + + class Meta: + model = KillHouse + fields = ['key', 'name', 'kill_house_operator', 'distribution_info'] + + def get_distribution_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter( + return_to_province=False, state__in=('pending', 'accepted'), first_car_allocated_quantity=0, + trash=False).order_by( + 'kill_request__recive_date') + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=obj, killer__isnull=True) | Q(killer=obj), trash=False).order_by( + 'kill_request__recive_date') + total_weight = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + total_weight += province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + dates = kill_house_requests.values_list('kill_request__recive_date__date').distinct() + province_kill_requests_dates = province_kill_requests.values_list('kill_request__recive_date__date').distinct() + kill_house_relations = KillHouseStewardGuildRelation.objects.filter(kill_house=obj, trash=False) + stewards = len(kill_house_relations.filter(steward__isnull=False)) + guilds = len(kill_house_relations.filter(guild__isnull=False)) + total_daily_weight = kill_house_relations.aggregate(total=Sum('allocation_limit'))['total'] or 0 + optional_daily_weight = \ + kill_house_relations.filter(allocation_type='optional').aggregate(total=Sum('allocation_limit'))[ + 'total'] or 0 + force_daily_weight = \ + kill_house_relations.filter(allocation_type='force').aggregate(total=Sum('allocation_limit'))['total'] or 0 + + return { + "stewards": stewards, + "guilds": guilds, + "total_daily_weight": total_daily_weight, + "optional_daily_weight": optional_daily_weight, + "force_daily_weight": force_daily_weight, + "kill_house_requests": len(kill_house_requests), + "total_weight": total_weight * 0.75 if total_weight > 0 else 0, + "days": len(set(dates)) + len(set(province_kill_requests_dates)), + "ave_total_daily_weight": round(total_weight / (len(set(dates)) + len(set(province_kill_requests_dates))), + 2) if (len(set(dates)) + len(set(province_kill_requests_dates))) > 0 else 0, + } + + +class StewardDistributionManagementGuildSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForAutoAllocationsSerializer(read_only=True) + distribution_info = serializers.SerializerMethodField('get_distribution_info') + + class Meta: + model = Guilds + fields = ['key', 'name', 'kill_house_operator', 'distribution_info'] + + def get_distribution_info(self, obj): + allocations = StewardAllocation.objects.filter(guilds=obj, kill_house__isnull=False, trash=False).order_by('id') + total_weight = allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + dates = allocations.values_list('date__date').distinct() + steward_relations = KillHouseStewardGuildRelation.objects.filter(steward=obj, trash=False) + guilds = len(steward_relations.filter(guild__isnull=False)) + total_daily_weight = steward_relations.aggregate(total=Sum('allocation_limit'))['total'] or 0 + optional_daily_weight = steward_relations.aggregate(total=Sum('allocation_limit'))['total'] or 0 + force_daily_weight = steward_relations.aggregate(total=Sum('allocation_limit'))['total'] or 0 + + return { + "guilds": guilds, + "total_daily_weight": total_daily_weight, + "optional_daily_weight": optional_daily_weight, + "force_daily_weight": force_daily_weight, + "kill_house_requests": len(allocations), + "total_weight": total_weight, + "days": len(set(dates)), + "ave_total_daily_weight": round(total_weight / len(set(dates)), 2) if len(set(dates)) > 0 else 0, + } + + +class BaseOutProvinceCarcassesBuyerSerializer(serializers.ModelSerializer): + class Meta: + model = BaseOutProvinceCarcassesBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + +class BaseOutProvinceCarcassesBuyerFordispensersSerializer(serializers.ModelSerializer): + kill_houses = serializers.SerializerMethodField('get_kill_houses') + requests_info = serializers.SerializerMethodField('get_requests_info') + + class Meta: + model = BaseOutProvinceCarcassesBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + def get_kill_houses(self, obj): + kill_houses = OutProvinceCarcassesBuyer.objects.filter(trash=False, buyer=obj) + kill_houses = kill_houses.values_list('Kill_house__name', flat=True).distinct() if kill_houses else [] + return kill_houses + + def get_requests_info(self, obj): + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer__buyer=obj) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + return { + "number_of_requests": len(free_sales), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + + +class OutProvinceCarcassesBuyerrSerializer(serializers.ModelSerializer): + type_activity = TypeActivitySerializer(read_only=True) + Kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + steward = GeneralGuildsSerializer(read_only=True) + + class Meta: + model = OutProvinceCarcassesBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + +class OutProvinceCarcassesBuyerForChoosingBuyerSerializer(serializers.ModelSerializer): + class Meta: + model = OutProvinceCarcassesBuyer + fields = ['key', 'fullname', 'mobile', 'unit_name', 'city', 'province'] + + +class OutProvinceCarcassesBuyerForBuyerRequestSerializer(serializers.ModelSerializer): + # type_activity = TypeActivitySerializer(read_only=True) + Kill_house = KillHouseForAutoAllocationSerializer(read_only=True) + # steward = GeneralGuildsSerializer(read_only=True) + buyer = BaseOutProvinceCarcassesBuyerSerializer(read_only=True) + requests_info = serializers.SerializerMethodField('get_requests_info') + + class Meta: + model = OutProvinceCarcassesBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + def get_requests_info(self, obj): + role = self.context.get('request').GET['role'] + total_quantity = 0 + total_weight = 0 + total_weight = 0 + if role == 'KillHouse': + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False, buyer=obj) + else: + free_sales = StewardFreeSaleBarInformation.objects.filter(trash=False, buyer=obj) + + total_quantity = free_sales.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + total_weight = free_sales.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + return { + "number_of_requests": len(free_sales), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + + +class KillHousePricePermissionSerializer(serializers.ModelSerializer): + class Meta: + model = KillHousePricePermission + fields = ['allow'] + + +class AutomaticDirectBuyingPermissionSerializer(serializers.ModelSerializer): + class Meta: + model = AutomaticDirectBuyingPermission + fields = '__all__' + + +class ProductsTransactionsSerializer(serializers.ModelSerializer): + class Meta: + model = ProductsTransactions + fields = '__all__' + + +class NewPosMachineTransactionsSerializer(serializers.ModelSerializer): + products = serializers.SerializerMethodField('get_products') + + class Meta: + model = PosMachineTransactions + fields = '__all__' + + def get_products(self, obj): + transactions = ProductsTransactions.objects.filter(transaction=obj, trash=False) + serializer = ProductsTransactionsSerializer(transactions, many=True) + return serializer.data + + +class PosMachineTransactionsForLiveStockSerializer(serializers.ModelSerializer): + products = serializers.SerializerMethodField('get_products') + shares = serializers.SerializerMethodField('get_shares') + pos = POSMachineForLiveStockTransactionsSerializer(read_only=True) + + class Meta: + model = PosMachineTransactions + fields = '__all__' + + def get_products(self, obj): + transactions = ProductsTransactions.objects.filter(transaction=obj, trash=False) + serializer = ProductsTransactionsSerializer(transactions, many=True) + return serializer.data + + def get_shares(self, obj): + product_transaction = ProductsTransactions.objects.get( + trash=False, + live_stack_products__isnull=False, + transaction=obj + ) + + total_union_price = 0 + total_company_price = 0 + + additional_data = json.loads(obj.additional) + for share in additional_data.get('shares', []): + share_price = int(share.get('price', 0)) + if share.get('name') == 'union': + total_union_price = share_price * product_transaction.cur_weight + else: + total_company_price = share_price * product_transaction.cur_weight + total_cooperative_price = additional_data.get('cooperative_price', 0) + cur_heavy = additional_data.get('cur_heavy', 0) + cur_light = additional_data.get('cur_light', 0) + weight = product_transaction.cur_weight + + dict_result = { + 'totalCooperativePrice': total_cooperative_price, + 'totalUnionPrice': total_union_price, + 'totalCompanyPrice': total_company_price, + 'curHeavy': cur_heavy, + 'curLight': cur_light, + 'curWeight': weight, + } + return dict_result + + +class PosMachineTransactionsSerializer(serializers.ModelSerializer): + class Meta: + model = PosMachineTransactions + fields = '__all__' + + +class PosMachineTransactionsForInspectionSerializer(serializers.ModelSerializer): + pos = POSMachineForTransactionInspectionsSerializer(read_only=True) + product = RolesProductsForInspectionSerializer(read_only=True) + + class Meta: + model = PosMachineTransactions + fields = '__all__' + + +class PosAllocationTransactionsSerializer(serializers.ModelSerializer): + class Meta: + model = PosAllocationTransactions + fields = '__all__' + + # cart = serializers.CharField(allow_null=True, allow_blank=True, required=False) + # refnum = serializers.CharField(allow_null=True, allow_blank=True, required=False) + # terminal = serializers.CharField(allow_null=True, allow_blank=True,required=False) + # additional = serializers.CharField(allow_null=True, allow_blank=True,required=False) + + +class BroadcastPriceSerializer(serializers.ModelSerializer): + class Meta: + model = BroadcastPrice + fields = ['active', 'kill_house_price', 'steward_price', 'guild_price'] + + +class OutProvinceSaleLimitationSerializer(serializers.ModelSerializer): + class Meta: + model = OutProvinceSaleLimitation + fields = ['active', 'kill_house', 'steward', 'guild'] + + +class ParentCompanySerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = ParentCompany + fields = '__all__' + + +class CityGuildSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = CityGuild + fields = '__all__' + + +class CityGuildForSubSectorSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = CityGuild + fields = ['key', 'user', 'wage_info'] + + def get_wage_info(self, obj): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + if self.context.get('request').GET.get('date1'): + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + transactions = PosMachineTransactions.objects.filter(paid=True, pos__guild__user__city=obj.user.city, + trash=False, date__date__gte=date1, + date__date__lte=date2) + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__user__city=obj.user.city, + calculate_status=True, temporary_trash=False, + temporary_deleted=False, receiver_state='accepted', + date__date__gte=date1, date__date__lte=date2) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild=obj, date__date__gte=date1, + date__date__lte=date2) + else: + transactions = PosMachineTransactions.objects.filter(paid=True, pos__guild__user__city=obj.user.city, + trash=False) + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__user__city=obj.user.city, + calculate_status=True, temporary_trash=False, + temporary_deleted=False, receiver_state='accepted') + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild=obj) + allocations_weight = allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + transactions_weight = transactions.aggregate(total=Sum('weight'))[ + 'total'] or 0 + transactions_weight = transactions_weight / 1000 if transactions_weight > 0 else 0 + total_wage = transactions_weight * (province_live_wage_amount * other_province_kill_request_percent) + + sub_transactions_amount = sub_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + remain_wage = total_wage - sub_transactions_amount + + result = { + "buy_weight": allocations_weight, + "sell_weight": transactions_weight, + "total_wage": total_wage, + "guild_deposit": sub_transactions_amount, + "remain_wage": remain_wage + } + return result + + +class CityGuildForSubsectorTransactionSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = CityGuild + fields = ['key', 'user'] + + +class VetForSubSectorTransactionsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['key', 'user'] + + +class SubSectorTransactionsSerializer(serializers.ModelSerializer): + city_operator = CityOperatorForSubSectorTransactionsSerializer(read_only=True) + vet = VetForSubSectorTransactionsSerializer(read_only=True) + city_guild = CityGuildForSubsectorTransactionSerializer(read_only=True) + + class Meta: + model = SubSectorTransactions + fields = '__all__' + + +class PosSegmentationSerializer(serializers.ModelSerializer): + buyer = serializers.SerializerMethodField('get_buyer') + + class Meta: + model = PosSegmentation + fields = ['key', 'buyer', 'date', 'weight', 'production_date', 'distribution_type', 'amount', 'total_amount', + 'sale_type', 'quota'] + + # def get_buyer(self, obj): + # buyer = obj.guild + # type = 'guild' + # return { + # "fullname": buyer.user.fullname, + # "mobile": buyer.user.mobile, + # "shop": buyer.guilds_name, + # "type": type, + # + # } + def get_buyer(self, obj): + buyer = obj.guild if obj.guild else obj.kill_house + type = 'guild' if obj.guild else 'kill_house' + return { + "fullname": buyer.user.fullname if obj.guild else buyer.kill_house_operator.user.fullname, + "mobile": buyer.user.mobile if obj.guild else buyer.kill_house_operator.user.mobile, + "shop": buyer.guilds_name if obj.guild else buyer.name, + "type": type, + + } + + +class AppSegmentationSerializer(serializers.ModelSerializer): + buyer = serializers.SerializerMethodField('get_buyer') + to_guild = GuildsForBroadcastManagementSerializer(read_only=True) + + class Meta: + model = PosSegmentation + fields = ['key', 'buyer', 'date', 'weight', 'to_guild', 'sale_type', 'quota', 'production_date', 'amount', + 'total_amount'] + + def get_buyer(self, obj): + buyer = obj.guild if obj.guild else obj.kill_house + type = 'guild' if obj.guild else 'kill_house' + return { + "fullname": buyer.user.fullname if obj.guild else buyer.kill_house_operator.user.fullname, + "mobile": buyer.user.mobile if obj.guild else buyer.kill_house_operator.user.mobile, + "shop": buyer.guilds_name if obj.guild else buyer.name, + "type": type, + + } + + +class GuildsPosMachineForTransactionsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + transaction = serializers.SerializerMethodField() + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user', 'transaction'] + + def get_transaction(self, obj): + request = self.context.get('request') + date1, date2 = self._get_dates_from_request(request) + + pos_data = self._get_pos_transaction_data(obj, date1, date2) + allocation_data = self._get_allocation_data(obj, date1, date2) + product_data = self._get_product_data(obj, allocation_data) + + return { + **pos_data, + **product_data, + } + + def _get_dates_from_request(self, request): + date1_str = request.GET.get('date1') + date2_str = request.GET.get('date2') + + date1 = datetime.strptime(date1_str, '%Y-%m-%d').date() if date1_str else None + date2 = datetime.strptime(date2_str, '%Y-%m-%d').date() if date2_str else None + + return date1, date2 + + def _get_pos_transaction_data(self, guild, date1, date2): + pos_transactions = PosMachineTransactions.objects.filter( + trash=False, pos__guild=guild, paid=True + ) + + if date1 and date2: + pos_transactions = pos_transactions.filter( + date__date__gte=date1, date__date__lte=date2 + ) + + len_pos = pos_transactions.count() + total_price = pos_transactions.aggregate(total=Sum('price'))['total'] or 0 + real_allocated_weight = pos_transactions.aggregate(total=Sum('weight'))['total'] or 0 + if real_allocated_weight > 0: + real_allocated_weight = round(real_allocated_weight / 1000, 1) + + return { + "len_transaction": len_pos, + "total_price": total_price, + "real_allocated_weight": real_allocated_weight, + } + + def _get_allocation_data(self, guild, date1, date2): + allocations = StewardAllocation.objects.filter( + (Q(to_steward=guild) | Q(steward=guild)), + trash=False, calculate_status=True, + receiver_state__in=('pending', 'accepted') + ).order_by('id') + + free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + (Q(guild=guild) | Q(steward=guild)), trash=False + ) + + if date1 and date2: + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + free_sale_bars = free_sale_bars.filter(date__date__gte=date1, date__date__lte=date2) + + return { + "allocations": allocations, + "free_sale_bars": free_sale_bars, + } + + def _get_product_data(self, guild, allocation_data): + allocations = allocation_data["allocations"] + free_sale_bars = allocation_data["free_sale_bars"] + + product = RolesProducts.objects.filter(trash=False, guild=guild).first() + + if product: + recive_allocation = allocations.filter(to_steward=guild, receiver_state__in=('pending', 'accepted')) + + real_weight_of_carcasses = recive_allocation.aggregate( + total=Sum('real_weight_of_carcasses') + )['total'] or 0 + + weight_free_sale_bars = free_sale_bars.aggregate( + total=Sum('weight_of_carcasses') + )['total'] or 0 + + product_total_carcasses_weight = real_weight_of_carcasses + weight_free_sale_bars + + return { + "product": product.name, + "total_carcasses_weight": product_total_carcasses_weight, + "total_remain_weight": product.total_remain_weight, + } + else: + return { + "product": '-', + "total_carcasses_weight": 0, + "total_remain_weight": 0, + "real_allocated_weight": 0, + } + + +class CooperativeForAllocationsReportSerializer(serializers.ModelSerializer): + user = SystemUserProfileForInspectionSerializer(read_only=True) + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Cooperative + fields = ['key', 'user', 'name', 'info'] + + def get_info(self, obj): + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + "sheep_concentrate": "کنسانتره گوسفندی", + "high_cow_concentrate": "کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate": "کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate": "کنسانتره گوساله پرواری", + } + name = products[self.context.get('request').GET.get('name')] + cooperative_roles = LiveStockRolseProduct.objects.get(cooperative=obj, parent_product__name=name) + product_transactions = ProductsTransactions.objects.filter(live_stack_products=cooperative_roles, + transaction__paid=True) + transactions = PosMachineTransactions.objects.filter( + pk__in=product_transactions.values_list('transaction', flat=True), trash=False) + transactions_amount = product_transactions.aggregate( + total=Sum('total_price') + )['total'] or 0 + + total_transactions_weight = product_transactions.aggregate( + total=Sum('cur_weight') + )['total'] or 0 + + total_weight = cooperative_roles.total_weight + total_receipt_weight = cooperative_roles.total_receipt_weight + total_allocated_weight = cooperative_roles.total_allocated_weight + total_remain_weight = cooperative_roles.total_remain_weight + return { + "total_transactions_price": transactions_amount, + "total_transactions_weight": total_transactions_weight, + "transactions": len(transactions), + "total_weight": total_weight, + "total_receipt_weight": total_receipt_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + +class PriceConfirmationSerializer(serializers.ModelSerializer): + class Meta: + model = PriceConfirmation + fields = ['key', 'poultry_status'] + + +class CityGuildForSubSectorSerializerForExcel(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = CityGuild + fields = ['key', 'user', 'wage_info'] + + def get_wage_info(self, obj): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + if self.context.get('request').GET['date1']: + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + transactions = PosMachineTransactions.objects.filter(paid=True, pos__guild__user__city=obj.user.city, + trash=False, date__date__gte=date1, + date__date__lte=date2) + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__user__city=obj.user.city, + calculate_status=True, temporary_trash=False, + temporary_deleted=False, receiver_state='accepted', + date__date__gte=date1, date__date__lte=date2) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild=obj, date__date__gte=date1, + date__date__lte=date2) + else: + transactions = PosMachineTransactions.objects.filter(paid=True, pos__guild__user__city=obj.user.city, + trash=False) + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__user__city=obj.user.city, + calculate_status=True, temporary_trash=False, + temporary_deleted=False, receiver_state='accepted') + + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild=obj) + + allocations_weight = allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + transactions_weight = transactions.aggregate(total=Sum('weight'))[ + 'total'] or 0 + transactions_weight = transactions_weight / 1000 if transactions_weight > 0 else 0 + total_wage = transactions_weight * (province_live_wage_amount * other_province_kill_request_percent) + + sub_transactions_amount = sub_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + remain_wage = total_wage - sub_transactions_amount + + result = { + "buy_weight": allocations_weight, + "sell_weight": transactions_weight, + "total_wage": total_wage, + "guild_deposit": sub_transactions_amount, + "remain_wage": remain_wage + } + return result + + +class ProductsTransactionsSerializerForExcel(serializers.ModelSerializer): + class Meta: + model = ProductsTransactions + fields = ['name', 'cur_weight', 'cur_weight'] + + +class PosMachineTransactionsForLiveStockSerializerForExcel(serializers.ModelSerializer): + products = serializers.SerializerMethodField('get_products') + pos = POSMachineForLiveStockTransactionsSerializer(read_only=True) + + class Meta: + model = PosMachineTransactions + fields = ['fullname', 'additional', 'date', 'natcode', 'mobile', 'pos', 'result', 'products', 'price'] + + def get_products(self, obj): + transactions = ProductsTransactions.objects.filter(transaction=obj, trash=False) + serializer = ProductsTransactionsSerializerForExcel(transactions, many=True) + return serializer.data + + +class CompanyBeneficiaryAccountSerializer(serializers.ModelSerializer): + class Meta: + model = CompanyBeneficiaryAccount + fields = ['key', 'name', 'shaba', 'percent', 'in_province', 'out_province'] + + +class POSMachineForCompanySerializer(serializers.ModelSerializer): + pos_company = serializers.SerializerMethodField('get_pos_company') + user_info = serializers.SerializerMethodField('get_user_info') + + class Meta: + model = POSMachine + fields = ['pos_id', 'key', 'receiver_number', 'receiver_number', 'terminal_number', 'Lat', + 'active', 'Long', 'serial', 'password', 'user_info', 'pos_company'] + + def get_pos_company(self, obj): + pos_company = PosCompany.objects.get(key=obj.pos_company.key, trash=False) + return pos_company.name + + def get_user_info(self, obj): + if obj.kill_house: + dict_info = { + 'name': obj.kill_house.name, + 'mobile': obj.kill_house.kill_house_operator.user.mobile, + 'fullname': obj.kill_house.kill_house_operator.user.fullname, + 'national_code': obj.kill_house.kill_house_operator.user.national_code, + 'type': 'کشتارگاه', + } + elif obj.guild: + dict_info = { + 'name': obj.guild.guilds_name, + 'mobile': obj.guild.user.mobile, + 'fullname': obj.guild.user.fullname, + 'national_code': obj.guild.user.national_code, + 'type': 'صنف', + } + else: + dict_info = { + 'name': obj.cooperative.name, + 'mobile': obj.cooperative.user.mobile, + 'fullname': obj.cooperative.user.fullname, + 'national_code': obj.cooperative.user.national_code, + 'type': 'سامانه دام', + } + return dict_info + + +class POSDeviceSessionForCompanySerializer(serializers.ModelSerializer): + pos = POSMachineForCompanySerializer(read_only=True) + + class Meta: + model = POSDeviceSession + fields = ['key', 'name', 'serial', 'password', 'session_create_date', 'session_last_seen_date', 'pos'] + + +class ProteinGuildSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ProteinGuild + fields = ['key', 'user', 'address', 'user_bank_info'] + + +class PosCompanyForPosVersionSerializer(serializers.ModelSerializer): + class Meta: + model = PosCompany + fields = ['id', 'active', 'name', 'en_name', 'trash', 'key'] + + +class PosDeviceVersionForOneCompanySerializer(serializers.ModelSerializer): + company = PosCompanyForPosVersionSerializer(read_only=True) + + class Meta: + model = PosDeviceVersion + fields = ["key", "trash", "name", "id", "code", "description", "enable", "remove", "company"] + + +class CommonlyUsedSerializer(serializers.ModelSerializer): + kill_house = KillHouseForCommonlyUsedSerializer(read_only=True) + guild = GuildsForBroadcastManagementSerializer(read_only=True) + steward = GuildsForBroadcastManagementSerializer(read_only=True) + exclusive = serializers.SerializerMethodField('get_exclusive') + + class Meta: + model = CommonlyUsed + fields = ["key", "kill_house", "guild", "steward", "exclusive"] + + def get_exclusive(self, obj): + if obj.kill_house: + kill_house = obj.kill_house + + guild_ids = list(kill_house.guild_kill_houses.values_list('id', flat=True)) + steward_ids = list(kill_house.steward_kill_houses.values_list('id', flat=True)) + + combined_ids = guild_ids + steward_ids + else: + steward = obj.steward + guild_ids = list(steward.guild_stewards.all().values_list('id', flat=True)) + combined_ids = guild_ids + + guilds_exist = Guilds.objects.filter( + id__in=combined_ids, + trash=False, + active=True + ).exists() + + return guilds_exist + + +class GetAllGuildsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryLocSerializer(read_only=True) + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user'] + + +class GuildsForGeneralConfigsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryLocSerializer(read_only=True) + + class Meta: + model = Guilds + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'trash', + 'created_by', + 'modified_by', + 'address', + 'user_bank_info', + 'wallet', + 'guild_area_activity', + 'guild_type_activity', + 'cars', + 'kill_house', + 'steward_kill_house', + 'stewards', + 'user_level', + + ) + + +class PercentageDropLimitationSerializer(serializers.ModelSerializer): + class Meta: + model = PercentageDropLimitation + fields = ['key', 'kill_house_limit_percent_down', 'kill_house_limit_percent_up'] + + +class UploadImageLimitationSerializer(serializers.ModelSerializer): + class Meta: + model = UploadImageLimitation + fields = ['key', 'kill_house_allocation', 'kill_house_free_sale', 'steward_allocation', 'steward_free_sale'] + + +class ApkInfoSerializer(serializers.ModelSerializer): + class Meta: + model = ApkInfo + fields = ['key', 'info', 'download_link'] + + +class DirectBuyingVerificationSerializer(serializers.ModelSerializer): + class Meta: + model = DirectBuyingVerification + fields = ['key', 'poultry_code_mandatory', 'payment_deadline', 'payment_deadline_days'] + + +class FinePermissionSerializer(serializers.ModelSerializer): + class Meta: + model = FinePermission + fields = ['key', 'name', 'start_time', 'end_time', 'fine_coefficient', 'fine'] + + +class ShowMarketRequestSerializer(serializers.ModelSerializer): + class Meta: + model = ShowMarketRequest + fields = ['key', 'allow', 'start_time', 'end_time'] + + +class IndexWeightCategorySerializer(serializers.ModelSerializer): + class Meta: + model = IndexWeightCategory + fields = ['key', 'name', 'min_value', 'max_value'] + + +class GuildsGeneralConfigsSerializer(serializers.ModelSerializer): + class Meta: + model = GuildsGeneralConfigs + fields = '__all__' + + +class PoultryScienceSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryScienceWithoutRoleSerializer(read_only=True) + poultry = PoultryDetailForPoultryScienceSerializer(read_only=True, many=True) + + class Meta: + model = PoultryScience + fields = '__all__' + + +class PoultryScienceForReportSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryScienceWithoutRoleSerializer(read_only=True) + + class Meta: + model = PoultryScience + fields = '__all__' + + +class PoultryScienceReportSerializer(serializers.ModelSerializer): + poultry_science = PoultryScienceForReportSerializer(read_only=True) + hatching = PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer(read_only=True) + user = SystemUserProfileForPoultryScienceWithoutRoleSerializer(read_only=True) + + class Meta: + model = PoultryScienceReport + fields = '__all__' + + +class AllowRegisterCodeForGuildsSerializer(serializers.ModelSerializer): + class Meta: + model = AllowRegisterCodeForGuilds + fields = '__all__' + + +class StewardAppLoginSerializer(serializers.ModelSerializer): + class Meta: + model = StewardAppLogin + fields = '__all__' + + +class StewardRequestSerializer(serializers.ModelSerializer): + class Meta: + model = StewardRequest + fields = '__all__' + + +class RestrictionCarcassDistributionSerializer(serializers.ModelSerializer): + class Meta: + model = RestrictionCarcassDistribution + fields = '__all__' + + +class AllowRegisterCodeForKillHouseFreeSaleBarInformationSerializer(serializers.ModelSerializer): + class Meta: + model = AllowRegisterCodeForKillHouseFreeSaleBarInformation + fields = '__all__' + + +class AllowRegisterCodeForStewardFreeSaleBarInformationSerializer(serializers.ModelSerializer): + class Meta: + model = AllowRegisterCodeForStewardFreeSaleBarInformation + fields = '__all__' + + +class LimitationForDirectPurchaseAndBarInformationSerializer(serializers.ModelSerializer): + class Meta: + model = LimitationForDirectPurchaseAndBarInformation + fields = '__all__' + + +class GuildsPosMachineForTransactionsNewSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + transaction = serializers.SerializerMethodField() + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'user', 'transaction', 'guilds_id', 'license_number', 'type_activity', + 'area_activity'] + + def get_transaction(self, obj): + request = self.context.get('request') + date1, date2 = self._get_dates_from_request(request) + + pos_data = self._get_pos_transaction_data(obj, date1, date2) + allocation_data = self._get_allocation_data(obj, date1, date2) + product_data = self._get_product_data(obj, allocation_data) + + return { + **pos_data, + **product_data, + } + + def _get_dates_from_request(self, request): + date1_str = request.GET.get('date1') + date2_str = request.GET.get('date2') + + date1 = datetime.strptime(date1_str, '%Y-%m-%d').date() if date1_str else None + date2 = datetime.strptime(date2_str, '%Y-%m-%d').date() if date2_str else None + + return date1, date2 + + def _get_pos_transaction_data(self, guild, date1, date2): + pos_transactions = PosMachineTransactions.objects.filter( + trash=False, pos__guild=guild, paid=True + ) + pos_segmentation = PosSegmentation.objects.filter(trash=False, guild=guild) + + if date1 and date2: + pos_transactions = pos_transactions.filter( + date__date__gte=date1, date__date__lte=date2 + ) + pos_segmentation = pos_segmentation.filter( + date__date__gte=date1, date__date__lte=date2 + ) + + len_pos = pos_transactions.count() + total_price = pos_transactions.aggregate(total=Sum('price'))['total'] or 0 + real_allocated_weight = pos_transactions.aggregate(total=Sum('weight'))['total'] or 0 + if real_allocated_weight > 0: + real_allocated_weight = round(real_allocated_weight / 1000, 1) + pos_segmentation_weight = pos_segmentation.aggregate(total=Sum('weight'))['total'] or 0 + if pos_segmentation_weight > 0: + pos_segmentation_weight = round(pos_segmentation_weight / 1000, 1) + return { + "len_transaction": len_pos, + "total_price": total_price, + "real_allocated_weight": real_allocated_weight + pos_segmentation_weight, + } + + def _get_allocation_data(self, guild, date1, date2): + allocations = StewardAllocation.objects.filter( + to_guilds=guild, + trash=False, calculate_status=True, + receiver_state__in=('pending', 'accepted') + ).order_by('id') + + # allocations = StewardAllocation.objects.filter( + # (Q(to_steward=guild) | Q(to_guilds=guild)), + # trash=False, calculate_status=True, + # receiver_state__in=('pending', 'accepted') + # ).order_by('id') + + # free_sale_bars = StewardFreeSaleBarInformation.objects.filter( + # (Q(guild=guild) | Q(steward=guild)), trash=False + # ) + + if date1 and date2: + allocations = allocations.filter(date__date__gte=date1, date__date__lte=date2) + # free_sale_bars = free_sale_bars.filter(date__date__gte=date1, date__date__lte=date2) + + return { + "allocations": allocations, + # "free_sale_bars": free_sale_bars, + } + + def _get_product_data(self, guild, allocation_data): + allocations = allocation_data["allocations"] + # free_sale_bars = allocation_data["free_sale_bars"] + + product = RolesProducts.objects.filter(trash=False, guild=guild).first() + + if product: + recive_allocation = allocations + + real_weight_of_carcasses = recive_allocation.aggregate( + total=Sum('real_weight_of_carcasses') + )['total'] or 0 + + # weight_free_sale_bars = free_sale_bars.aggregate( + # total=Sum('weight_of_carcasses') + # )['total'] or 0 + + # product_total_carcasses_weight = real_weight_of_carcasses + weight_free_sale_bars + product_total_carcasses_weight = real_weight_of_carcasses + + return { + "product": product.name, + "total_carcasses_weight": product_total_carcasses_weight, + "total_remain_weight": product.total_remain_weight, + } + else: + return { + "product": '-', + "total_carcasses_weight": 0, + "total_remain_weight": 0, + "real_allocated_weight": 0, + } + + +# class GuildsPosMachineForTransactionsNewSerializer(serializers.ModelSerializer): +# # user = SystemUserProfileForAutoAllocationSerializer(read_only=True) +# fullname = serializers.CharField(source='user.fullname', read_only=True) +# mobile = serializers.CharField(source='user.mobile', read_only=True) +# city = serializers.CharField(source='user.city.name', read_only=True) +# transaction = serializers.SerializerMethodField() +# +# class Meta: +# model = Guilds +# fields = ['key', 'guilds_name', 'fullname','mobile','city','guilds_id','license_number','type_activity','area_activity','transaction'] +# +# def get_transaction(self, obj): +# # Read precomputed map passed by the view +# precomputed = self.context.get('precomputed_transactions', {}) +# # obj.id is the guild id +# data = precomputed.get(obj.id) +# if not data: +# return { +# "len_transaction": 0, +# "total_price": 0, +# "real_allocated_weight": 0, +# "product": '-', +# "total_carcasses_weight": 0, +# "total_remain_weight": 0, +# } +# return data + + +class WarehouseArchiveSerializer(serializers.ModelSerializer): + kill_house = KillHouseForReturnBuyingSerializer(read_only=True) + steward = GuildsForStewardMenueSerializer(read_only=True) + guild = GuildsForStewardMenueSerializer(read_only=True) + + class Meta: + model = WarehouseArchive + fields = '__all__' + + +class SmsRecipientSerializer(serializers.ModelSerializer): + class Meta: + model = SmsRecipient + fields = ['id', 'phone_number', 'name', 'is_active', 'create_date', 'modify_date'] + read_only_fields = ['id', 'create_date', 'modify_date'] + + +class TotalStewardRemainWeightSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'info'] + + def get_info(self, obj): + product = RolesProducts.objects.filter(guild=obj, trash=False, name='مرغ گرم').first() + archives = WarehouseArchive.objects.filter(Q(steward=obj) | Q(guild=obj), trash=False) + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=obj) | Q(to_guilds=obj) | Q(steward=obj) | Q(to_steward=obj), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True + ) + output_steward_allocations = guild_steward_allocations.filter(Q(guilds=obj) | Q(steward=obj)) + input_steward_allocations = guild_steward_allocations.filter(Q(to_guilds=obj) | Q(to_steward=obj)) + + steward_free_bar_informations = StewardFreeBarInformation.objects.filter( + steward=obj, trash=False, temporary_trash=False, temporary_deleted=False, warehouse=True + ) + steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( + steward=obj, trash=False, temporary_trash=False, temporary_deleted=False, warehouse=True + ) + segmentations = PosSegmentation.objects.filter(guild=obj, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + + days_set = set() + days_set.update(input_steward_allocations.values_list('date__date', flat=True)) + days_set.update(output_steward_allocations.values_list('production_date__date', flat=True)) + days_set.update(steward_free_bar_informations.values_list('date__date', flat=True)) + days_set.update(steward_free_Sale_bar_informations.values_list('production_date__date', flat=True)) + days_set.update(segmentations.values_list('production_date__date', flat=True)) + days_set.update(transactions.values_list('transaction__date__date', flat=True)) + days_set.update(archives.values_list('date__date', flat=True)) + days_set = {day for day in days_set if day is not None} + + days = sorted(days_set) + today = datetime.now().date() + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + date_list = [two_days_ago, yesterday, two_days_ago] + + governmental_list = [] + free_list = [] + final_dict = {} + + for day in days: + input_steward_allocations_info = input_steward_allocations.aggregate( + total_input_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', + quota='governmental', date__date=day)), + total_input_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', quota='free', + date__date=day)) + ) + output_steward_allocations_info = output_steward_allocations.aggregate( + total_output_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental', + production_date__date=day)), + total_output_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)) + ) + steward_free_bar_info = steward_free_bar_informations.aggregate( + total_free_bar_weight=Sum('weight_of_carcasses', filter=Q(date__date=day)), + ) + steward_free_Sale_bar_info = steward_free_Sale_bar_informations.aggregate( + total_free_Sale_bar_governmental_weight=Sum('weight_of_carcasses', + filter=Q(quota='governmental', production_date__date=day)), + total_free_Sale_bar_free_weight=Sum('weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)) + ) + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental', production_date__date=day)), + segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), + ) + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True, transaction__date__date=day)), + pos_free_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=False, transaction__date__date=day)), + ) + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental', date__date=day)), + archives_free_weight=Sum('weight', + filter=Q(quota='free', date__date=day)), + ) + + total_input_steward_allocations_governmental_weight = input_steward_allocations_info[ + 'total_input_allocations_governmental_weight'] or 0 + total_input_steward_allocations_free_weight = input_steward_allocations_info[ + 'total_input_allocations_free_weight'] or 0 + total_steward_free_buying_bars_weight = steward_free_bar_info['total_free_bar_weight'] or 0 + total_output_steward_allocations_governmental_weight = output_steward_allocations_info[ + 'total_output_allocations_governmental_weight'] or 0 + total_output_steward_allocations_free_weight = output_steward_allocations_info[ + 'total_output_allocations_free_weight'] or 0 + total_steward_free_sale_bars_governmental_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_governmental_weight'] or 0 + total_steward_free_sale_bars_free_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_governmental_input = total_input_steward_allocations_governmental_weight + total_free_input = total_input_steward_allocations_free_weight + total_steward_free_buying_bars_weight + total_governmental_output = total_output_steward_allocations_governmental_weight + total_steward_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output = total_output_steward_allocations_free_weight + total_steward_free_sale_bars_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + + governmental_amount = ( + total_governmental_input - total_governmental_output) - archives_governmental_weight + free_amount = (total_free_input - total_free_output) - archives_free_weight + + governmental_data = { + 'day': day, + 'amount': governmental_amount, + } + free_data = { + 'day': day, + 'amount': free_amount, + } + + if day not in date_list: + + if governmental_amount > 0: + governmental_list.append(governmental_data) + if free_amount > 0: + free_list.append(free_data) + + final_dict['governmental'] = governmental_list + final_dict['free'] = free_list + + return (final_dict) + + +# class TotalStewardRemainWeightSerializer(serializers.ModelSerializer): +# info = serializers.SerializerMethodField() +# +# class Meta: +# model = Guilds +# fields = [ +# 'id', +# 'guilds_name', +# 'user', +# 'steward', +# 'total_remain_warehouse_weight', +# 'info', +# ] +# +# def get_info(self, obj): +# precomputed = self.context.get('precomputed_data', {}) +# data = precomputed.get(obj.id, {}) +# +# governmental = data.get('governmental', []) +# free = data.get('free', []) +# +# return { +# 'governmental': [ +# {'day': item['day'], 'amount': float(item['amount'])} for item in governmental +# ], +# 'free': [ +# {'day': item['day'], 'amount': float(item['amount'])} for item in free +# ], +# } + + +class TotalGuildStewardWarehouseArchiveDashboardSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = Guilds + fields = ['key', 'guilds_name', 'info'] + + def get_info(self, obj): + date1 = self.context.get('date1') + date2 = self.context.get('date2') + owner_type = self.context.get('owner_type') + if date1: + if owner_type == 'steward': + archives = WarehouseArchive.objects.filter(trash=False, steward=obj, create_date__date__gte=date1, + create_date__date__lte=date2) + else: + archives = WarehouseArchive.objects.filter(trash=False, guild=obj, create_date__date__gte=date1, + create_date__date__lte=date2) + + else: + if owner_type == 'steward': + archives = WarehouseArchive.objects.filter(trash=False, steward=obj) + else: + archives = WarehouseArchive.objects.filter(trash=False, guild=obj) + + archives_info = archives.aggregate( + total_count=Count('id'), + total_governmental_count=Count('id', filter=Q(quota='governmental')), + total_free_count=Count('id', filter=Q(quota='free')), + total_weight=Sum('weight'), + total_governmental_weight=Sum('weight', filter=Q(quota='governmental')), + total_free_weight=Sum('weight', filter=Q(quota='free')), + ) + + total_count = archives_info['total_count'] or 0 + total_governmental_count = archives_info['total_governmental_count'] or 0 + total_free_count = archives_info['total_free_count'] or 0 + total_weight = archives_info['total_weight'] or 0 + total_governmental_weight = archives_info['total_governmental_weight'] or 0 + total_free_weight = archives_info['total_free_weight'] or 0 + + result = { + 'total_count': total_count, + 'total_governmental_count': total_governmental_count, + 'total_free_count': total_free_count, + 'total_weight': total_weight, + 'total_governmental_weight': total_governmental_weight, + 'total_free_weight': total_free_weight, + } + return result + + +class MarketDailyLimitationSerializer(serializers.ModelSerializer): + market = serializers.SerializerMethodField('get_market') + + class Meta: + model = MarketDailyLimitation + fields = ['key', 'active', 'quantity', 'register_role', 'register_fullname', 'register_mobile', 'market'] + + def get_market(self, obj): + return market_daily_limitation_info() + + +class HatchingArchivePercentSerializer(serializers.ModelSerializer): + class Meta: + model = HatchingArchivePercent + fields = ['key', 'active', 'percent'] + + +class POSMachineTransferSerializer(serializers.Serializer): + recipient_type = serializers.ChoiceField( + choices=['owner', 'current_user', 'representative'] + ) + recipient_key = serializers.CharField() + + def validate(self, data): + recipient_type = data['recipient_type'] + key = data['recipient_key'] + + if recipient_type in ['owner', 'current_user']: + data['recipient'] = SystemUserProfile.objects.get(key=key, trash=False) + + elif recipient_type == 'representative': + data['recipient'] = Representative.objects.get(key=key, trash=False) + + return data + + def save(self, **kwargs): + pos = self.context['pos'] + user = self.context['request'].user + + return POSTransferService.transfer( + pos=pos, + recipient_type=self.validated_data['recipient_type'], + recipient=self.validated_data['recipient'], + performed_by=user + ) + + +class POSAccessLevelSerializer(serializers.ModelSerializer): + class Meta: + model = POSAccessLevel + fields = '__all__' + + +class POSMachineReadSerializer(serializers.ModelSerializer): + access_levels = POSAccessLevelSerializer(many=True, read_only=True) + + class Meta: + model = POSMachine + fields = '__all__' + + +class StewardForRepresentativeSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Steward + fields = ['key', 'user', 'city'] + + +class RepresentativeSerializer(serializers.ModelSerializer): + kill_house = KillHouseForReturnBuyingSerializer(read_only=True) + steward = StewardForRepresentativeSerializer(read_only=True) + + class Meta: + model = Representative + fields = '__all__' + + +class UserPOSMachineSerializer(serializers.ModelSerializer): + owner = SystemUserProfileForGuildSerializer(read_only=True) + current_user = SystemUserProfileForGuildSerializer(read_only=True) + current_representative = RepresentativeSerializer(read_only=True) + access_levels = POSAccessLevelSerializer(many=True, read_only=True) + + class Meta: + model = POSMachine + fields = '__all__' diff --git a/panel/ProvinceOperator/services/__init__.py b/panel/ProvinceOperator/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/ProvinceOperator/services/pos_transfer_service.py b/panel/ProvinceOperator/services/pos_transfer_service.py new file mode 100644 index 0000000..d92cf50 --- /dev/null +++ b/panel/ProvinceOperator/services/pos_transfer_service.py @@ -0,0 +1,71 @@ +import secrets + +from panel.models import POSAuditLog, POSAccessLevel, POSMachine +from django.db import transaction + + +def make_unique_id(): + while True: + random_number = ''.join(str(secrets.randbelow(10)) for _ in range(6)) + if not POSMachine.objects.filter(pos_unique_id=random_number).exists(): + return random_number + + +class POSTransferService: + ACTION_MAP = { + 'owner': 'CHANGE_OWNER', + 'current_user': 'CHANGE_CURRENT_USER', + 'representative': 'CHANGE_REPRESENTATIVE', + } + + @staticmethod + @transaction.atomic + def transfer(pos, recipient_type, recipient, performed_by): + old_state = { + "owner": pos.owner_id, + "current_user": pos.current_user_id, + "current_representative": pos.current_representative_id, + } + + pos.current_user = None + pos.current_representative = None + + if recipient_type == 'owner': + pos.owner = recipient + pos.current_user = None + pos.current_representative = None + if not pos.pos_unique_id: + pos.pos_unique_id = make_unique_id() + elif recipient_type == 'current_user': + pos.current_user = recipient + pos.current_representative = None + + elif recipient_type == 'representative': + pos.current_representative = recipient + pos.current_user = None + + pos.save() + + if recipient_type == 'owner': + POSAccessLevel.objects.filter(pos=pos).delete() + user_roles = recipient.role.all() + for role in user_roles: + if role.name in ['KillHouse', 'Steward', 'Guilds']: + POSAccessLevel.objects.create( + pos=pos, + name=role.name + ) + + POSAuditLog.objects.create( + pos=pos, + action=POSTransferService.ACTION_MAP[recipient_type], + performed=performed_by, + old_value=old_state, + new_value={ + "recipient_type": recipient_type, + "recipient_id": recipient.id + }, + description="انتقال دستگاه پوز" + ) + + return pos diff --git a/panel/ProvinceOperator/views.py b/panel/ProvinceOperator/views.py new file mode 100644 index 0000000..9486a31 --- /dev/null +++ b/panel/ProvinceOperator/views.py @@ -0,0 +1,27737 @@ +import json +import logging +import math +# import time +import threading +import traceback +from collections import defaultdict +from io import BytesIO +from itertools import chain +import difflib + +import openpyxl +from django.db import transaction +from django.db.models import Count +from django.db.models import Sum, F, Q, Prefetch +from django.db.models.functions import Cast +from django.http import QueryDict +from django.shortcuts import get_object_or_404 +from django.utils.timezone import now +from num2fawords import words +from rest_framework.generics import GenericAPIView +from rest_framework.pagination import PageNumberPagination +from rest_framework.views import APIView + +from GateWay import PaymentGateway, PaymentGatewayZarinPal +from LiveStock.helpers import build_query +from LiveStock.models import LiveStockRolseProduct, Cooperative +from RasadyaarBale.models import User_Bale +from RasadyaarBale.views import send_transaction +from authentication.arvan_image.arvan_storage import upload_object, upload_object_resize +from authentication.helper.helper import register_user +from authentication.sahandsms.sms import price_reminder +from authentication.sms_management import province_kill_request_reject_sms, allow_poultry_city_province_sms, \ + allow_poultry_city_for_poultry_sms, \ + allow_poultry_province_for_poultry_sms, steward_allocation_sms, transaction_sms_threading, \ + transaction_sms_threading_for_company, transaction_sms_threading_appreciation, province_out_request_transaction_sms, \ + send_sms_for_final_approval_out_province_threading, confirmation_of_the_need_for_slaughterhouse_sms_threading, \ + confirm_price_poultry_request_direct_buying_sms, \ + operator_out_poultry_request_sms, transaction_sms_threading_in_province, send_sms_for_guild, send_sms_for_sale_bar, \ + send_sms_for_sale_bar_for_steward +from bot_eata import bot_eitaa_for_each_province_kill_request, bot_eitaa_out_province_live_bar, transaction_for_eata +from deposit_id import sha_deposit_id, arta_deposit_id, ar_deposit_id, ha_deposit_id, ma_deposit_id, guilds_deposit_id, \ + wage_counting_type +from general_urls import base_pos_id, base_url_for_sms_report +from panel.KillHouse.helpers import kill_house_cold_house_allocations_product_warehousing, \ + kill_house_allocations_product_warehousing, get_finance_info, kill_house_cold_house_allocations, \ + get_difference_carcasses_weight, get_kill_house_percent, cold_house_warehousing, kill_house_archive_warehousing +from panel.ProvinceOperator.helpers import guild_steward_allocations_product_warehousing, \ + guild_steward_free_buying_product_warehousing, guild_steward_free_sale_product_warehousing, \ + allocation_calculate_price, pos_allocation_weight_for_product, guild_steward_product_segmentation, \ + cooperative_warehousing, rancher_warehousing, guild_steward_archive_warehousing, _normalize_fa_ar +from panel.ProvinceOperator.serializers import ( + PricingSerializer, + ProvinceCheckOperatorRequestSerializer, + ProvinceCheckInformationSerializer, + ProvinceFactorToKillHouseSerializer, + KillHouseFactorToProvinceSerializer, + ProvinceCheckKillHouseFactorSerializer, + DepositAllocationSerializer, + PovinceInspectorSerializer, + PriceAnalysisorSerializer, + WareHouseFactorSerializer, + ProvinceOperatorSerializer, ProvinceRequestActionSerializer, ProvincePercentLeftOverSerializer, + InspectorOperatorSerializer, ShareOfAllocationSerializer, + PaymentDeadLineSerializer, MonthlyProfitPercentageSerializer, ProvinceFactorToKillHouseForPoultrySerializer, + KillHouseFactorToPoultrySerializer, + walletSerializer, + ItransactionSerializer, + DebtSerializer, + PenaltySerializer, + DepositSerializer, + # IwalletSerializer, + FinancialDocumentSerializer, + FinancialTransactionSerializer, AdminSerializer, ProvinceImportKillHouseOutFactorsSerializer, + VetSupervisorSerializer, JahadSerializer, ProvincialGovernmentSerializer, VetCheckAllocationsSerializer, + HourLimitSerializer, SmsLicenseSerializer, PoultryAllowCityProvinceSerializer, + ProvinceAllowKillHouseRegisterCarSerializer, ProvinceAllowPoultryChooseKillHouseSerializer, + ProvinceAllowPoultryChooseKillHouseTotalSerializer, ProvinceAllowPoultrySellFreeSerializer, + ProvinceAllowPoultrySellFreeTotalSerializer, ProvinceCheckOperatorOutRequestSerializer, + ProvinceAutoAllocationSerializer, AutoAcceptProvinceKillRequestSerializer, AutoMakeKillHouseRequestSerializer, + CityJahadForAllUserSerializer, GuildsSerializer, StewardSerializer, KillHousePercentageOfLossesSerializer, + StewardAllocationSerializer, ProvinceAllowKillHouseChooseStewardGuildsSerializer, StewardWareHouseSerializer, + GuildsWareHouseSerializer, CommerceSerializer, CityCommerceSerializer, HatchingLossesPermissionSerializer, + GuildsForKillHousePercentageSerializer, WagePaymentSerializer, ProvinceAllowKillHouseDirectBuyingSerializer, + ProvinceAllowKillHouseDirectBuyingTotalSerializer, ProvinceAllowKillHouseRegisterGuildsSerializer, + ProvinceAllowKillHouseRegisterGuildsTotalSerializer, CityVetSerializer, KillHouseHourLimitSerializer, + AutomaticStewardAllocationSerializer, FreeSaleWithinprovinceSerializer, ObservatorySerializer, + ProvinceSupervisorSerializer, CarSerializer, ProductSerializer, PosItemSerializer, PosVersiontSerializer, + GuildRoomSerializer, PosCompanySerializer, POSIdSerializer, POSMachineSerializer, GuildsForCompaniesSerializer, + AdditionalProductsSerializer, GuildsForInspectionSerializer, POSTransactionsSerializer, + POSMachineForServerSerializer, TotalGuildsForPosSerializer, GuildInfoForPosSerializer, + StewardFreeBarInformationSerializer, StewardWareHouseForDailyBroadCastOInDetailsSerializer, TypeActivitySerializer, + AreaActivitySerializer, POSMachineForInspectionSerializer, EvacuationPermitSerializer, SellForFreezingSerializer, + LiveStockSupportSerializer, ColdHouseSerializer, ColdHouseAllocationsSerializer, OperationLimitationSerializer, + ApprovedPriceSerializer, AnnouncementsSerializer, ChickenAgeRangeSerializer, + TimeRangeSerializer, CitySupervisorSerializer, JahadInspectorSerializer, SystemWalletSerializer, + SuperAdminSerializer, PaymentGatewayPercentageSerializer, WageTypeSerializer, PercentageOfWageTypeSerializer, + ShareTypeSerializer, TotalWageInformationSerializer, InternalTransactionSerializer, + TotalPaymentGatewayPercentageSerializer, WageTypeForPoultryOutProvinceRequestSerializer, + StewardFreeSaleBarInformationSerializer, CityLivestockSerializer, ImprovingLivestockSerializer, ReportsSerializer, + ReportsUsersSerializer, UserReportsSerializer, ReportSubmissionTimeSerializer, MovingTextSerializer, + MovingTextForDashboardSerializer, MovingTextDashboardStatusSerializer, MovingTextWithRoleSerializer, + NewProductSerializer, AdminXSerializer, SupporterSerializer, ZarinPalAccountsSerializer, PoultryExportSerializer, + PoultryOutProvinceRequestSerializer, DispenserSerializer, DispenserAllocationSerializer, GeneralGuildsSerializer, + TestGuildsSerializer, VetFarmAggregatePermissionSerializer, + KillHouseBarLimitationSerializer, CityPoultrySerializer, KillHouseDistributionManagementStewardGuildSerializer, + GuildsForDistributionManagementSerializer, StewardDistributionManagementGuildSerializer, + OutOfProvinceSellingCarcassesPermissionSerializer, OutProvinceCarcassesBuyerrSerializer, + OutProvinceCarcassesBuyerForBuyerRequestSerializer, ProductPricingTypeSerializer, + PoultryOutRequestInternalTransactionSerializer, KillHousePricePermissionSerializer, + BaseOutProvinceCarcassesBuyerSerializer, OutProvinceCarcassesBuyerForChoosingBuyerSerializer, + BaseOutProvinceCarcassesBuyerFordispensersSerializer, RolesProductsSerializer, + GuildsForBroadcastManagementSerializer, AutomaticDirectBuyingPermissionSerializer, PosRolesProductsSerializer, + PosGuildsForBroadcastManagementSerializer, PosStewardAllocationSerializer, PosMachineTransactionsSerializer, + BroadcastPriceSerializer, PosGuildsSerializer, OutProvinceSaleLimitationSerializer, + PosAllocationTransactionsSerializer, ParentCompanySerializer, ParentCompanyTotalWageInformationSerializer, + GuildsForColdHouseSerializer, GuildsForTotalColdHouseSerializer, StewardColdHousesSerializer, + POSDeviceSessionSerializer, PosDeviceVersionSerializer, SubSectorTransactionsSerializer, + SubSectorPercentageOfWageTypeSerializer, PosStewardFreeBarInformationSerializer, PosSegmentationSerializer, + POSDeviceSessionForInspectionSerializer, CityGuildSerializer, + CityGuildForSubSectorSerializer, CityGuildForSubsectorTransactionSerializer, + PosMachineTransactionsForInspectionSerializer, GuildsPosMachineForTransactionsSerializer, RealGuildsSerializer, + PosOtherProductsSerializer, CombinedPosProductSerializer, NewPosMachineTransactionsSerializer, + PosMachineTransactionsForLiveStockSerializer, CooperativeForAllocationsReportSerializer, + PriceConfirmationSerializer, + POSMachineForLiveStockSerializer, CompanyBeneficiaryAccountSerializer, POSDeviceSessionForCompanySerializer, + ProteinGuildSerializer, PosCompanyForPosVersionSerializer, + PosDeviceVersionForOneCompanySerializer, CommonlyUsedSerializer, InProvinceAllocationSerializer, + GetAllGuildsSerializer, RealGuildsForDashboardSerializer, PercentageDropLimitationSerializer, + UploadImageLimitationSerializer, ApkInfoSerializer, AppSegmentationSerializer, DirectBuyingVerificationSerializer, + FinePermissionSerializer, ShowMarketRequestSerializer, IndexWeightCategorySerializer, PoultryScienceSerializer, + PoultryScienceReportSerializer, AllowRegisterCodeForGuildsSerializer, GuildsGeneralConfigsSerializer, + GuildsForGeneralConfigsSerializer, StewardAppLoginSerializer, StewardRequestSerializer, + RestrictionCarcassDistributionSerializer, AllowRegisterCodeForKillHouseFreeSaleBarInformationSerializer, + AllowRegisterCodeForStewardFreeSaleBarInformationSerializer, LimitationForDirectPurchaseAndBarInformationSerializer, + GuildsPosMachineForTransactionsNewSerializer, WarehouseArchiveSerializer, SmsRecipientSerializer, + NewPOSMachineSerializer, TotalStewardRemainWeightSerializer, TotalGuildStewardWarehouseArchiveDashboardSerializer, + MarketDailyLimitationSerializer, HatchingArchivePercentSerializer, POSMachineReadSerializer, + POSMachineTransferSerializer, UserPOSMachineSerializer, DispenserInformationSerializer, NewDispenserSerializer, + RepresentativeSerializer, NewCombinedPosProductSerializer) +from panel.ProvinceOperator.services.pos_transfer_service import POSTransferService +from panel.ReportingPanel.views import get_gid +from panel.admin import PROJECT_API_KEY +from panel.poultry.helpers import poultry_prediction, create_update_chicken_commission_prices +from panel.validate_headers import get_client_ip, PosDeviceValidator + +# test +from ticket.helper import send_image_to_server, send_image_to_server_for_poultry_science + +logger = logging.getLogger(__name__) + + +def update_out_province_hatching(poultry_hatching): + poultry_requests = PoultryRequest.objects.filter(trash=False, hatching=poultry_hatching, state_process='accepted', + province_state='accepted', out_province_request_cancel=False, + wage_pay=True) + total_killed_quantity = poultry_requests.aggregate(total=Sum('quantity'))['total'] or 0 + total_killed_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))['total'] or 0 + + poultry_hatching.out_province_killed_quantity = total_killed_quantity + poultry_hatching.out_province_killed_weight = total_killed_weight + poultry_hatching.save() + + +def update_steward_allocations_on_role_change(system_profile, guilds, is_steward_now): + if not guilds: + return + + allocations = StewardAllocation.objects.filter( + Q(guilds=guilds) | Q(to_guilds=guilds) | Q(steward=guilds) | Q(to_steward=guilds), + trash=False + ) + + for allocation in allocations: + + is_sender = (allocation.guilds == guilds) or (allocation.steward == guilds) + is_receiver = (allocation.to_guilds == guilds) or (allocation.to_steward == guilds) + + if is_steward_now: + if is_sender: + + if allocation.guilds == guilds: + allocation.steward = guilds + allocation.guilds = None + + if is_receiver: + + if allocation.to_guilds == guilds: + allocation.to_steward = guilds + allocation.to_guilds = None + + else: + + if is_sender: + + if allocation.steward == guilds: + allocation.guilds = guilds + allocation.steward = None + + if is_receiver: + + if allocation.to_steward == guilds: + allocation.to_guilds = guilds + allocation.to_steward = None + + if allocation.to_cold_house or allocation.other_cold_house: + + pass + elif allocation.to_steward: + if allocation.steward: + allocation.type = 'steward_steward' + elif allocation.kill_house: + allocation.type = 'killhouse_steward' + elif allocation.to_guilds: + if allocation.steward: + allocation.type = 'steward_guild' + elif allocation.kill_house: + allocation.type = 'killhouse_guild' + + allocation.save() + + product = RolesProducts.objects.filter(trash=False, guild=guilds).first() + guild_steward_allocations_product_warehousing(product) + + +from panel.KillHouse.serializers import ( + KillHouseADDCARSerializer, + KillRequestSerializer, TotalKillHouseRemainWeightViewSetSerializer, + TotalKillHouseWarehouseArchiveDashboardSerializer +) + +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from authentication.models import UserProfile, User, UserMessage, BankCard, Province, SystemAddress, ExternalTransaction + +from panel.helper import UNION_NUMBER, COMPANY_NUMBER, GUILD_NUMBER +from province_orderid import sha_order_id, test_order_id, ha_order_id, ar_order_id, ma_order_id + +ARTA_URL_REGISTER = "https://userbackend.rasadyar.com/api/register/" + +from rest_framework.response import Response +from django.contrib.auth.models import Group + +from panel.models import ( + CityOperatorCheckRequest, + PoultryRequest, + Pricing, + KillHouse, + KillHouseRequest, + KillRequest, + ProvinceCheckOperatorRequest, + ProvinceCheckInformation, + KillHouseAssignmentInformation, + ProvinceFactorToKillHouse, + KillHouseFactorToProvince, + KillHouseCheckRequest, + ProvinceCheckKillHouseFactor, + DepositAllocation, + PovinceInspector, + PriceAnalysis, + WareHouseFactor, + ProvinceKillRequest, + ProvinceOperator, + ProvinceRequestAction, + PoultryRequestAuction, + ProvincePercentLeftOver, + KillHouseADDCAR, + KillHouseDriver, InspectorOperator, ShareOfAllocation, KillHouseOperator, Vet, KillHouseVet, PoultryHatching, + VetFarm, KillHouseRequestActionWinner, PaymentDeadLine, MonthlyProfitPercentage, + ProvinceFactorToKillHouseForPoultry, KillHouseFactorToPoultry, Poultry, + Wallet, + Itransaction, + Debt, + Penalty, + Deposit, CityOperator, FinancialDocument, FinancialTransaction, Admin, KillHouseComplaint, + ProvinceImportKillHouseOutFactors, VetSupervisor, Jahad, ProvincialGovernment, VetCheckAllocations, HourLimit, + SmsLicense, KillRequestFactorPayment, KillRequestFactor, PoultryAllowCityProvince, + ProvinceAllowKillHouseRegisterCar, ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultryChooseKillHouseTotal, + ProvinceAllowPoultrySellFree, ProvinceAllowPoultrySellFreeTotal, ProvinceCheckOperatorOutRequest, + KillHousePercentage, KillHouseDailyQuota, ProvinceAutoAllocation, AutoAcceptProvinceKillRequest, + AutoMakeKillHouseRequest, CityJahad, Guilds, Steward, KillHousePercentageOfLosses, StewardAllocation, + KillHouseWareHouse, ProvinceAllowKillHouseChooseStewardGuilds, StewardWareHouse, GuildsWareHouse, Commerce, + CityCommerce, HatchingLossesPermission, WagePayment, ProvinceAllowKillHouseDirectBuying, + ProvinceAllowKillHouseDirectBuyingTotal, ProvinceAllowKillHouseRegisterGuilds, + ProvinceAllowKillHouseRegisterGuildsTotal, CityVet, KillHouseHourLimit, AutomaticStewardAllocation, + FreeSaleWithinprovince, Observatory, ProvinceSupervisor, Car, Product, PosVersion, PosItem, GuildRoom, PosCompany, + POSId, POSMachine, AdditionalProducts, POSTransactions, StewardFreeBarInformation, TypeActivity, AreaActivity, + EvacuationPermit, SellForFreezing, LiveStockSupport, ColdHouse, ColdHouseAllocations, OperationLimitation, + ApprovedPrice, Announcements, ChickenAgeRange, TimeRange, CitySupervisor, JahadInspector, SystemWallet, SuperAdmin, + PaymentGatewayPercentage, SlaughterHouseTransaction, WageType, PercentageOfWageType, ShareType, + TotalWageInformation, InternalTransaction, ChainCompany, ChainAllocation, + TotalPaymentGatewayPercentage, StewardFreeSaleBarInformation, CityLivestock, + ImprovingLivestock, OutProvincePoultryRequestBuyer, Reports, ReportsUsers, UserReports, + ReportSubmissionTime, MovingText, MovingTextDashboardStatus, MovingTextWithRole, MovingTextRole, NewProduct, AdminX, + Supporter, ZarinPalAccounts, PoultryExport, PoultryOutProvinceRequest, Dispenser, VetFarmAggregatePermission, + KillHouseBarLimitation, CityPoultry, KillHouseStewardGuildRelation, + OutOfProvinceSellingCarcassesPermission, OutProvinceCarcassesBuyer, ProductPricingType, KillHousePricePermission, + BaseOutProvinceCarcassesBuyer, RolesProducts, AutomaticDirectBuyingPermission, PosMachineTransactions, + BroadcastPrice, OutProvinceSaleLimitation, PosAllocationTransactions, ParentCompany, POSDeviceSession, + PosDeviceVersion, SubSectorTransactions, SubSectorPercentageOfWageType, PosSegmentation, CityGuild, + BarDifferenceRequest, OtherProducts, ProductsTransactions, PriceConfirmation, + CompanyBeneficiaryAccount, ProteinGuild, CommonlyUsed, PercentageDropLimitation, UploadImageLimitation, ApkInfo, + DirectBuyingVerification, FinePermission, ShowMarketRequest, IndexWeightCategory, PoultryScience, + PoultryScienceReport, AllowRegisterCodeForGuilds, AllowRegisterCodeForStewardAllocation, GuildsGeneralConfigs, + StewardAppLogin, StewardRequest, RestrictionCarcassDistribution, + AllowRegisterCodeForKillHouseFreeSaleBarInformation, AllowRegisterCodeForStewardFreeSaleBarInformation, + KillHouseFreeBarInformation, KillHouseFreeSaleBarInformation, LimitationForDirectPurchaseAndBarInformation, + WarehouseArchive, SmsRecipient, MarketDailyLimitation, HatchingArchivePercent, Representative, DispenserInformation + +) +from authentication.models import City +from url_filter.integrations.drf import DjangoFilterBackend +from panel.filterset import (PoultryFilterSet, ProvinceOperatorFilterSet, KillHouseFilterSet, + VetFilterSet, CityOperatorFilterSet, KillHouseOperatorFilterSet, KillHouseDriverFilterSet, + InspectorOperatorFilterSet, GuildsFilterSet, WagePaymentFilterSet, + InternalTransactionFilterSet, ReportsUsersFilterSet, DispenserFilterSet, + DispenserAllocationFilterSet, TestGuildsFilterSet, OutProvinceCarcassesBuyerFilterSet, + BaseOutProvinceCarcassesBuyerFilterSet, StewardAllocationFilterSet, + ColdHouseAllocationsFilterSet, ColdHouseFilterSet, SubSectorTransactionsFilterSet, + StewardFreeBarInformationFilterSet, PosSegmentationFilterSet, CooperativeFilterSet, + PosMachineTransactionsFilterSet, GuildsForPostationFilterSet, + POSDeviceSessionForCompanyFilterSet, CommonlyUsedFilterSet, + StewardFreeSaleBarInformationFilterSet, StewardAllocationDashboardFilterSet, + PoultryScienceFilterSet, PoultryScienceReportFilterSet, GuildsForGeneralConfigsFilterSet, + WarehouseArchiveFilterSet, POSMachineFilterSet, GuildsForArchiveFilterSet, + DispenserInformationFilterSet, RepresentativeFilterSet) +from authentication.models import SystemUserProfile +from panel.KillHouse.serializers import ( + KillHouseSerializer, +) +from panel.poultry.serializers import PoultryRequestSerializer, PoultrySerializer, GetAllPoultrySerializer, \ + GetAllPoultryForPoultryScienceSerializer, PoultryDetailForPoultryScienceSerializer, \ + PoultryHatchingForBazrasiSerializer, PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer +from rest_framework.decorators import api_view, permission_classes, action +from django.views.decorators.csrf import csrf_exempt +from rest_framework.permissions import AllowAny +from rest_framework import viewsets +from rest_framework import status +# from datetime import datetime +# import datetime +from datetime import datetime, timedelta, timezone +# from backports.datetime_fromisoformat import MonkeyPatch +# import pandas as pd +import jdatetime +from datetime import date +import pytz +import string +import random +import requests + +ARTA_URL_CHANGE_MOBILE_NUMBER = "https://userbackend.rasadyar.com/change_mobile_number/" +ARTA_URL_REMOVE_USER_ROLE = "https://userbackend.rasadyar.com/api/remove_user_role/" + +ARVAN_Kill_house_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +ARVAN_poultry_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +ARVAN_deposit_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +ARVAN_Kill_house_Factor_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +# arta_shaba_id='IR200120020000009055694184' +# ha_shaba_id='IR540160000000000318967648' +# ma_shaba_id='IR580160000000000656171877' +# guilds_shaba_id='IR200120020000009055694184' + +# ARVAN_Kill_house_URL = 'https://kill-house-gallery.s3.ir-thr-at1.arvanstorage.ir/' +# ARVAN_poultry_URL = 'https://poultry-gallery.s3.ir-thr-at1.arvanstorage.ir/' +# ARVAN_deposit_URL = 'https://deposit-gallery.s3.ir-thr-at1.arvanstorage.ir/' +# ARVAN_Kill_house_Factor_URL = 'https://kill-house-factor-gallery.s3.ir-thr-at1.arvanstorage.ir/' + +utc = pytz.UTC + + +# MonkeyPatch.patch_fromisoformat() + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +class EvacuationPermitViewSet(viewsets.ModelViewSet): + queryset = EvacuationPermit.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = EvacuationPermitSerializer + + def list(self, request, *args, **kwargs): + evacuation_permit = EvacuationPermit.objects.all().first() + serializer = self.serializer_class(evacuation_permit) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + evacuation_permit = EvacuationPermit.objects.all().first() + serializer = self.serializer_class(evacuation_permit) + serializer.update(instance=evacuation_permit, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class SellForFreezingViewSet(viewsets.ModelViewSet): + queryset = SellForFreezing.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SellForFreezingSerializer + + def list(self, request, *args, **kwargs): + sell_for_freezing = SellForFreezing.objects.all().first() + serializer = self.serializer_class(sell_for_freezing) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + sell_for_freezing = SellForFreezing.objects.all().first() + serializer = self.serializer_class(sell_for_freezing) + serializer.update(instance=sell_for_freezing, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProductViewSet(viewsets.ModelViewSet): + queryset = Product.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProductSerializer + + +class CarViewSet(viewsets.ModelViewSet): + queryset = Car.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CarSerializer + + # def create(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # role = request.data['role'] + # request.data.pop('role') + # kill_house = None + # guild = None + # if 'kill_house_key' in request.data.keys(): + # if request.data['kill_house_key'] != None: + # kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + # request.data.pop('kill_house_key') + # elif 'guild_key' in request.data.keys(): + # if request.data['guild_key'] != None: + # kill_house = Guilds.objects.get(key=request.data['guild_key']) + # request.data.pop('guild_key') + # if role == 'KillHouse': + # kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + # kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + # elif role == 'Guilds': + # guild = Guilds.objects.get(user=user,trash=False) + # person = SystemUserProfile.objects.get(user=request.user) + # group = Group.objects.get(name__exact="Driver") + # city = City.objects.get(name=request.data['city_name']) + # province = Province.objects.get(key=user.province.key) + # request.data.pop('city_name') + # if Car.objects.filter(pelak=request.data['pelak'], trash=False).exists(): + # return Response({"result": "این ماشین قبلا ثبت شده!"}, status=status.HTTP_403_FORBIDDEN) + # system_profile = SystemUserProfile.objects.filter(mobile=request.data['driver_mobile'], trash=False) + # if system_profile.count() > 0: + # system_profile = system_profile.last() + # if group not in system_profile.role.all(): + # system_profile.role.add(group) + # + # else: + # + # password = "00100" + # data = { + # "username": request.data['driver_mobile'], + # "password": password, + # "api_key": PROJECT_API_KEY + # } + # req = requests.post( + # url=ARTA_URL_REGISTER, + # data=data, + # verify=False + # ) + # if req.status_code == 200: + # user = User(username=request.data['driver_mobile'], first_name=request.data['first_name'], + # last_name=request.data['last_name']) + # user.save() + # base_id = SystemUserProfile.objects.all() + # if base_id.count() > 0: + # base_id = int(base_id.last().base_order) + 1 + # else: + # base_id = 1000 + # system_profile = SystemUserProfile( + # mobile=request.data['driver_mobile'], + # first_name=request.data['first_name'], + # last_name=request.data['last_name'], + # fullname=request.data['first_name'] + " " + request.data['last_name'], + # user=user, + # base_order=base_id, + # password=password, + # city=city, + # province=province + # ) + # system_profile.save() + # system_profile.role.add(group) + # + # + # else: + # return Response({"result": "در ثبت کاربر مشکلی پیش آمده است!"}, status=status.HTTP_403_FORBIDDEN) + # + # wallet = Wallet() + # wallet.save() + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # full_name = request.data['first_name'] + " " + request.data['last_name'] + # request.data.pop('first_name') + # request.data.pop('last_name') + # car = serializer.create(validated_data=request.data) + # car.user = system_profile + # car.wallet = wallet + # car.registrar = { + # "role": role, + # "full_name": person.fullname, + # "mobile": person.mobile, + # "date": str(car.create_date) + # } + # car.driver_name = full_name + # car.save() + # if kill_house != None: + # if KillHouseADDCAR.objects.filter(kill_house__in=kill_house, driver=kill_house_driver, + # trash=False).exists(): + # return Response({"result": "این ماشین قبلا برای کشتارگاه ثبت شده!"}, + # status=status.HTTP_403_FORBIDDEN) + # else: + # add_car = KillHouseADDCAR( + # kill_house=kill_house.last(), + # driver=kill_house_driver + # ) + # add_car.save() + # else: + # kill_houses = KillHouse.objects.filter(kill_house_operator__user__province=user.province, trash=False) + # for kill_house in kill_houses: + # add_car = KillHouseADDCAR( + # kill_house=kill_house, + # driver=kill_house_driver + # ) + # add_car.save() + # + # return Response({"result": "ماشین با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + # return Response(serializer.errors) + + +class HatchingLossesPermissionViewSet(viewsets.ModelViewSet): + queryset = HatchingLossesPermission.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = HatchingLossesPermissionSerializer + + def list(self, request, *args, **kwargs): + hatching_losses = HatchingLossesPermission.objects.all().last() + if not hatching_losses: + hatching_losses = HatchingLossesPermission() + hatching_losses.save() + serializer = self.serializer_class(hatching_losses) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + hatching_losses = HatchingLossesPermission.objects.get(key=request.data['permission_key'], trash=False) + request.data.pop('permission_key') + serializer = self.serializer_class(hatching_losses) + serializer.update(instance=hatching_losses, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# def auto_steward_allocation(kill_house_key, quantity, weight, date): +# kill_house = KillHouse.objects.get(key=kill_house_key, trash=False) +# stewards = Steward.objects.filter(guilds__steward=True, trash=False).order_by('id') +# stewards_list = [] +# allocatated_quantity = 0 +# kill_house_total_quantity = 0 +# for steward in stewards: +# if steward.centers_allocation != None: +# for center_allocation in steward.centers_allocation: +# if str(kill_house.key) == center_allocation['value']: +# kill_house_total_quantity += steward.allocation_limit +# stewards_list.append(steward) +# if len(stewards_list) > 0: +# for steward_list in stewards_list: +# allocatated_quantity = (steward_list.allocation_limit / kill_house_total_quantity) * quantity +# auto_allocation = StewardAllocation( +# kill_house=kill_house, +# steward=steward_list, +# number_of_carcasses=allocatated_quantity, +# real_number_of_carcasses=allocatated_quantity, +# weight_of_carcasses=int(allocatated_quantity * weight), +# real_weight_of_carcasses=int(allocatated_quantity * weight), +# type='auto', +# date=date +# ) +# auto_allocation.save() + + +class ProvinceCheckDirectBuyingViewSet(viewsets.ModelViewSet): + queryset = KillRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillRequestSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = None + kill_request = KillRequest.objects.get(key=request.data['kill_request_key']) + if kill_request.trash: + return Response({"result": "به علت بدهی درخواست شما حذف گردید!"}, status=status.HTTP_403_FORBIDDEN) + free_sale_in_province = False if kill_request.free_direct_buying == False else True + + request.data.pop('kill_request_key') + state = request.data['state'] + request.data.pop('state') + if 'role' in request.data.keys(): + role = request.data['role'] + if state == 'accepted': + kill_request.kill_capacity = int(request.data['quantity']) + kill_request.remain_quantity = int(request.data['quantity']) + + request.data.pop('quantity') + poultry_requests = PoultryRequest.objects.filter(poultry__user=kill_request.poultry.user, + trash=False).order_by( + 'create_date') + # hatching = PoultryHatching.objects.filter(poultry=kill_request.poultry, state='pending', archive=False, + # allow_hatching='pending', trash=False).order_by( + # 'left_over').last() + + hatching = kill_request.poultry_hatching + + free_sale_with_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_with_province.allow == True: + if ('out' in request.data.keys() and request.data['out'] == True) or ( + 'free_sale_in_province' in request.data.keys() and request.data[ + 'free_sale_in_province'] == True): + poultry_requests_for_free_sale = PoultryRequest.objects.filter( + Q(direct_buying=True) | Q(out=True, wage_pay=True) | Q(free_sale_in_province=True), + state_process='accepted', province_state='accepted', trash=False, hatching=hatching) + poultry_requests_for_free_sale_sum = \ + poultry_requests_for_free_sale.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + if poultry_requests_for_free_sale_sum + request.data[ + 'quantity'] > hatching.total_free_commitment_quantity: + return Response({"result": "مجموع حجم کشتار آزاد از حجم کل تعهد آزاد بیشتر است "}, + status=status.HTTP_403_FORBIDDEN) + poultry = Poultry.objects.get(key=kill_request.poultry.key, trash=False) + vet_farm = VetFarm.objects.filter(trash=False, poultry=poultry).first() + last_poultry_request = PoultryRequest.objects.all() + if last_poultry_request.count() > 0: + general_order_code = last_poultry_request.last().general_order_code + 1 + else: + general_order_code = 1 + + if poultry_requests.count() > 0: + order_code = poultry_requests.last().order_code + 1 + else: + order_code = int(str(poultry.user.base_order) + '0001') + city_operator = CityOperator.objects.filter(unit_name=poultry.city_operator, trash=False).last() + if not city_operator: + city_operator = CityOperator.objects.filter(unit_name='اتحادیه استان (فاقد تعاونی)', trash=False).last() + if hatching.left_over < kill_request.kill_capacity: + return Response({"result": "تعداد جوجه در سالن کمتر از تعداد درخواستی است"}, + status=status.HTTP_403_FORBIDDEN) + if kill_request.kill_house.max_kill_limit and kill_request.kill_house.total_kill_capacity > 0: + + if kill_request.kill_house.max_kill_limit and kill_request.kill_house.total_kill_capacity > 0: + total_province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + return_to_province=False, + archive_wage=False, + state__in=('pending', 'accepted'), + killhouse_user=kill_request.kill_house, + kill_request__recive_date__date=kill_request.recive_date.date()) + total_province_kill_requests_quantity = \ + total_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + if kill_request.kill_house.total_kill_capacity < total_province_kill_requests_quantity + kill_request.kill_capacity: + return Response({"result": "تعداد وارد شده از مانده سهمیه کشتار روزانه کشتارگاه بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + kill_request.save() + poultry_request = PoultryRequest( + hatching=hatching, + order_code=order_code, + general_order_code=general_order_code, + city_operator=city_operator, + poultry=poultry, + previous_quantity=kill_request.kill_capacity, + remain_quantity=kill_request.kill_capacity, + quantity=kill_request.kill_capacity, + first_quantity=kill_request.kill_capacity, + chicken_breed=hatching.chicken_breed, + Index_weight=kill_request.Index_weight, + state_process='accepted', + province_state='accepted', + direct_buying=True, + amount=kill_request.amount, + free_sale_in_province=free_sale_in_province, + send_date=kill_request.recive_date + ) + poultry_request.save() + kill_request.poultry_request = poultry_request + poultry_prediction(poultry_request.poultry) + + if kill_request.export_status == True: + poultry_request.export = True + + poultry_request.state = { + "city_operator": city_operator.user.fullname, + "city_state": poultry_request.state_process, + "city_operator_mobile": city_operator.user.mobile, + "province_operator": "", + "province_state": "" + } + poultry_request.registrar = { + "role": role, + "fullname": user.fullname, + "date": str(poultry_request.create_date) + } + poultry_request.killing_age = (poultry_request.send_date.date() - hatching.date.date()).days + 1 + + poultry_request.save() + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=True, + province_state='accept', + allow_hatching=True + + ) + city_operator_check_request.save() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + wage_type = WageType.objects.filter(en_name='province-kill-request', trash=False).first() + wage = wage_type.amount if wage_type.status == True else 0 + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + province_killrequest = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + kill_request=kill_request, + province_request=check, + quantity=kill_request.kill_capacity, + total_killed_quantity=kill_request.kill_capacity, + total_killed_weight=int(kill_request.kill_capacity * poultry_request.Index_weight), + main_quantity=kill_request.kill_capacity, + wage=wage, + direct_buying=True, + total_wage_amount=wage * int(kill_request.kill_capacity * poultry_request.Index_weight), + ) + province_killrequest.save() + # fine = FinePermission.objects.filter(trash=False).first() + # time_for_fine = datetime.now().time().replace(second=0, microsecond=0) + # if fine.direct_buying: + # if fine.direct_buying_start_time < time_for_fine < fine.direct_buying_end_time: + # province_killrequest.direct_buying_fine = True + # province_killrequest.direct_buying_fine_amount = ( + # fine.direct_buying_fine_coefficient - 1) * province_killrequest.total_wage_amount if fine.direct_buying_fine_coefficient > 1 else province_killrequest.total_wage_amount + # province_killrequest.direct_buying_fine_coefficient = fine.direct_buying_fine_coefficient + create_update_chicken_commission_prices() + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + province_killrequest.union_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.union_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'company': + province_killrequest.company_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.company_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'guilds': + province_killrequest.guilds_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.guilds_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'city': + province_killrequest.city_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.city_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'other': + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + + elif percentage_wage_type.share_type.en_name == 'wallet': + province_killrequest.wallet_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.wallet_share_percent = percentage_wage_type.percent + + else: + province_killrequest.other_share = int( + (percentage_wage_type.percent / 100) * province_killrequest.total_wage_amount) + province_killrequest.other_share_percent = percentage_wage_type.percent + province_killrequest.save() + + tomorrow = datetime.now().date() + timedelta(days=1) + if not KillHouseWareHouse.objects.filter(kill_house=kill_request.kill_house, date__date=tomorrow).exists(): + ware_house_date = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=1, + minute=12, second=20) + kill_house_ware_house = KillHouseWareHouse( + kill_house=kill_request.kill_house, + date=ware_house_date + ) + kill_house_ware_house.save() + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_killrequest, + state='accepted' + ) + + kill_house_check.save() + province_killrequest.state = 'accepted' + if kill_request.payment_deadline: + province_killrequest.payment_deadline = True + province_killrequest.payment_deadline_date = kill_request.payment_deadline_date + province_killrequest.save() + check.quantity = 0 + check.save() + + if poultry_request.export == True: + hatching.export_killed_weight += int(kill_request.kill_capacity * poultry_request.Index_weight) + hatching.export_killed_quantity += kill_request.kill_capacity + + + elif poultry_request.free_sale_in_province == True: + hatching.free_killed_quantity += int(kill_request.kill_capacity * poultry_request.Index_weight) + hatching.free_quantity += kill_request.kill_capacity + + else: + hatching.governmental_killed_quantity += int(kill_request.kill_capacity * poultry_request.Index_weight) + hatching.governmental_quantity += kill_request.kill_capacity + hatching.killed_quantity += kill_request.kill_capacity + hatching.save() + poultry_request.remain_quantity = 0 + poultry_request.direct_buying_kill_place = kill_request.kill_house.name + poultry_request.direct_buying_buyer_info = { + "buyer_fullname": kill_request.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": kill_request.kill_house.kill_house_operator.user.mobile, + } + poultry_request.save() + if kill_request.export_status == True: + kill_request.export_state = 'accepted' + kill_request.direct_buying_message = request.data['direct_buying_message'] + + else: + kill_request.direct_buying_state = 'accepted' + + kill_request.accept_reject_date = datetime.now() + + kill_request.save() + # kill_house_key = kill_request.kill_house.key + # quantity = province_killrequest.main_quantity + # weight = poultry_request.Index_weight + # date = province_killrequest.create_date + # automatic_allocation = threading.Thread(target=auto_steward_allocation, + # args=( + # kill_house_key, quantity, weight, date)) + # automatic_allocation.start() + bot_eitaa_for_each_province_kill_request(province_killrequest, vet_farm) + poultry_fullname = poultry.unit_name + poultry_mobile = poultry.user.mobile if not kill_request.direct_buying_intermediary_mobile else kill_request.direct_buying_intermediary_mobile + quantity = kill_request.kill_capacity + chicken_breed = kill_request.chicken_breed + request_kill_house = kill_request.kill_house.name + date_str = kill_request.recive_date + # clean_date_str = date_str.split('T')[0] + ' ' + date_str.split('T')[1].split('.')[0] + # send_date = datetime.strptime(str(clean_date_str), '%Y-%m-%d %H:%M:%S').date() + if isinstance(date_str, str): + clean_date_str = date_str.split('.')[0] + clean_date_str = clean_date_str.replace('T', ' ') + clean_date_str = clean_date_str.replace('Z', '') + + send_date = datetime.strptime(clean_date_str, '%Y-%m-%d %H:%M:%S').date() + + elif isinstance(date_str, datetime): + send_date = date_str.date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + code = "-" + send_date = separate.join(date_list) + confirm_price_poultry_request = threading.Thread( + target=confirm_price_poultry_request_direct_buying_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + send_date, + kill_request.free_direct_buying, + kill_request.amount, request_kill_house, + code)) + confirm_price_poultry_request.start() + + else: + if kill_request.export_status == True: + kill_request.export_state = 'rejected' + else: + kill_request.direct_buying_state = 'rejected' + kill_request.direct_buying_message = request.data['direct_buying_message'] + kill_request.province_state = 'rejected' + kill_request.accept_reject_date = datetime.now() + kill_request.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_200_OK) + + +# ویوست مربوط یه اپراتور استان +class ProvinceOperatorViewSet(viewsets.ModelViewSet): + queryset = ProvinceOperator.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceOperatorSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + operator = user.province_operator_user.all() + + # send to serializer + serializer = self.serializer_class(operator[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + operator = ProvinceOperator.objects.get(key=request.data['operator_key'], trash=False) + request.data.pop('operator_key') + serializer = self.serializer_class(operator) + serializer.update(instance=operator, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به جهاد +class JahadViewSet(viewsets.ModelViewSet): + queryset = Jahad.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = JahadSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + jahad = user.jahad_user.all() + + # send to serializer + serializer = self.serializer_class(jahad[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSIdViewSet(viewsets.ModelViewSet): + queryset = POSId.objects.all() + permission_classes = [AllowAny] + serializer_class = POSIdSerializer + + +class PosCompanyViewSet(viewsets.ModelViewSet): + queryset = PosCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PosCompanySerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + pos_company = user.pos_company_user.all() + + # send to serializer + serializer = self.serializer_class(pos_company[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CommerceViewSet(viewsets.ModelViewSet): + queryset = Commerce.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CommerceSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + commerce = user.commerce_user.all() + + # send to serializer + serializer = self.serializer_class(commerce[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceSupervisorViewSet(viewsets.ModelViewSet): + queryset = ProvinceSupervisor.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceSupervisorSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + province_supervisor = user.province_supervisor_user.all() + + # send to serializer + serializer = self.serializer_class(province_supervisor[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CitySupervisorViewSet(viewsets.ModelViewSet): + queryset = CitySupervisor.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CitySupervisorSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + city_supervisor = user.city_supervisor_user.all() + + # send to serializer + serializer = self.serializer_class(city_supervisor[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class SuperAdminViewSet(viewsets.ModelViewSet): + queryset = SuperAdmin.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SuperAdminSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + super_admin = user.super_admin_user.all() + + # send to serializer + serializer = self.serializer_class(super_admin[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class JahadInspectorViewSet(viewsets.ModelViewSet): + queryset = JahadInspector.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = JahadInspectorSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + jahad_inspector = user.jahad_inspector_user.all() + + # send to serializer + serializer = self.serializer_class(jahad_inspector[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityCommerceViewSet(viewsets.ModelViewSet): + queryset = CityCommerce.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityCommerceSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + city_commerce = user.city_commerce_user.all() + + # send to serializer + serializer = self.serializer_class(city_commerce[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityJahadViewSet(viewsets.ModelViewSet): + queryset = CityJahad.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityJahadForAllUserSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + jahad = user.city_jahad_user.all() + + # send to serializer + serializer = self.serializer_class(jahad[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityPoultryViewSet(viewsets.ModelViewSet): + queryset = CityPoultry.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityPoultrySerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + city_poultry = SystemUserProfile.objects.get(user=request.user, trash=False).city_poultry_user.first() + + serializer = self.serializer_class(city_poultry) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DispenserDashboardViewSet(viewsets.ModelViewSet): + queryset = Dispenser.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DispenserSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + dispensers = Dispenser.objects.filter(kill_house=kill_house, trash=False).order_by('id') + elif request.GET['role'] in ['Guilds', 'Steward']: + guild = Guilds.objects.get(user=user, trash=False) + dispensers = Dispenser.objects.filter(guild=guild, trash=False).order_by('id') + else: + dispensers = Dispenser.objects.filter(trash=False).order_by('id') + + today = datetime.now().date() + allocations = StewardAllocation.objects.filter(dispenser__in=dispensers, trash=False) + today_allocations = allocations.filter(date__date=today) + total_quantity = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + total_weight = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + today_quantity = today_allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + today_weight = today_allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + allocation_info = { + "number_of_dispensers": len(dispensers), + "number_of_allocations": len(allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + "number_of_today_allocations": len(today_allocations), + "total_today_quantity": today_quantity, + "total_today_weight": today_weight, + } + return Response(allocation_info, status=status.HTTP_200_OK) + + +class DispenserViewSet(viewsets.ModelViewSet): + queryset = Dispenser.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = NewDispenserSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = DispenserFilterSet + filterset_fields = [ + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'guild__user__mobile', + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'pelak', + + ] + + def retrieve(self, request, pk=None, *args, **kwargs): + + if 'profile' in request.GET: + dispenser = SystemUserProfile.objects.get(user=request.user, trash=False).dispenser_user.first() + + serializer = self.serializer_class(dispenser) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + with transaction.atomic(): + kill_house = None + steward = None + birthday_str = None + user = SystemUserProfile.objects.get(user=request.user, trash=False) + group = Group.objects.get(name__exact="Dispenser") + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + first_name = request.data.get('firstName') + last_name = request.data.get('lastName') + father_name = request.data.get('fatherName') + gender = request.data.get('gender') + identity_no = request.data.get('identityNo') + birth_date = request.data.get('birthDate') + city_name = request.data.get('city') + is_alive = request.data.get('isLive') + mobile = request.data.get('mobile') + national_code = request.data.get('nationalCode') + role = request.data['role'] + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + + if birth_date: + try: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + except: + pass + + if not city: + return Response({"result": "شهر مورد نظر یافت نشد!"}, status=status.HTTP_403_FORBIDDEN) + + province = Province.objects.get(key=city.province.key) + + if role == 'ProvinceOperator': + if 'kill_house_key' in request.data.keys(): + kill_house = KillHouse.objects.filter(trash=False, key=request.data['kill_house_key']).first() + request.data.pop('kill_house_key') + else: + steward = Steward.objects.get(key=request.data['steward_key'], trash=False) + request.data.pop('steward_key') + + else: + if role == "KillHouse": + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user).first() + else: + steward = Steward.objects.get(user=user, trash=False) + + password = "2025" + data = { + "username": mobile, + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + system_user = User(username=mobile, first_name=first_name, + last_name=last_name) + system_user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + " " + last_name, + user=system_user, + base_order=base_id, + password=password, + national_code=identity_no, + national_id=national_code, + gender=national_code, + is_alive=is_alive, + father_name=father_name, + birthday=birthday_str, + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + system_profile.role.add(group) + wallet = Wallet() + wallet.save() + request.data.pop('role') + request.data.pop('firstName') + request.data.pop('lastName') + request.data.pop('fatherName') + request.data.pop('gender') + request.data.pop('identityNo') + request.data.pop('birthDate') + request.data.pop('city') + request.data.pop('mobile') + request.data.pop('nationalCode') + request.data.pop('isLive') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + dispenser = serializer.create(validated_data=request.data) + dispenser.user = system_profile + dispenser.wallet = wallet + dispenser.registrar = user.fullname + dispenser_info = DispenserInformation(dispenser=dispenser) + if kill_house is not None: + dispenser_info.kill_house = kill_house + else: + dispenser_info.steward = steward + + dispenser_info.fullname = system_profile.fullname + dispenser_info.national_id = system_profile.national_code + dispenser_info.first_name = system_profile.first_name + dispenser_info.last_name = system_profile.last_name + dispenser_info.mobile = system_profile.mobile + dispenser_info.city = system_profile.city.name + dispenser_info.province = system_profile.province.name + dispenser_info.save() + dispenser.in_use = True + dispenser.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + with transaction.atomic(): + dispenser_key = request.data.pop('key') + mobile = request.data.pop('mobile') + dispenser = Dispenser.objects.get(key=dispenser_key, trash=False) + dispenser_info = DispenserInformation.objects.filter(key=dispenser_key, active=True, trash=False).first() + system_user_profile = SystemUserProfile.objects.get(key=dispenser.user.key, trash=False) + if mobile: + first_mobile_number = system_user_profile.mobile + second_mobile_number = mobile + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + if dispenser_info: + dispenser_info.mobile = second_mobile_number + dispenser_info.save() + serializer = self.serializer_class(dispenser) + serializer.update(instance=dispenser, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + dispenser_list = [] + dispensers = Dispenser.objects.filter(trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=dispensers + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=dispensers) + dispenser_list = ps.filter() + dispensers = [] if len(dispenser_list) == 0 else dispenser_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(dispensers) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(dispensers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DispenserInformationViewSet(viewsets.ModelViewSet): + queryset = DispenserInformation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DispenserInformationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = DispenserInformationFilterSet + filterset_fields = [ + 'dispenser__user__first_name', + 'dispenser__user__last_name', + 'dispenser__user__fullname', + 'dispenser__user__mobile', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'steward__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'first_name', + 'last_name', + 'fullname', + 'mobile', + 'city', + 'province', + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + role = request.GET.get('role') + dispenser_type = request.GET.get('type') + + dispenser_filter = { + 'trash': False + } + role_filters = { + 'KillHouse': 'kill_house__kill_house_operator__user', + 'Steward': 'steward__user', + } + type_filter = { + 'KillHouse': 'kill_house__isnull', + 'Steward': 'steward__isnull', + } + filter_key = role_filters.get(role) + type_key = type_filter.get(dispenser_type) + if filter_key: + dispenser_filter[filter_key] = user + if type_key: + dispenser_filter[type_key] = False + dispenser_list = [] + + dispensers = DispenserInformation.objects.filter(**dispenser_filter).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=dispensers + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=dispensers) + dispenser_list = ps.filter() + dispensers = [] if len(dispenser_list) == 0 else dispenser_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(dispensers) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(dispensers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + dispenser_info_key = request.data['key'] + dispenser_info = DispenserInformation.objects.get(key=dispenser_info_key, trash=False) + serializer = self.serializer_class(dispenser_info) + serializer.update(instance=dispenser_info, validated_data=request.data) + if 'active' in request.data.keys(): + active = request.data['active'] + if not active: + dispenser_info.dispenser.in_use = False + dispenser_info.dispenser.save() + return Response(serializer.data, status=status.HTTP_200_OK) + +class RepresentativeViewSet(viewsets.ModelViewSet): + queryset = Representative.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = RepresentativeSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = RepresentativeFilterSet + filterset_fields = [ + 'first_name', + 'last_name', + 'mobile', + 'city', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'steward__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname' + ] + + def create(self, request, *args, **kwargs): + with transaction.atomic(): + kill_house = None + steward = None + owner_type = request.data.pop('owner_type', None) + owner_key = request.data.pop('owner_key', None) + role = request.data.pop('role', None) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + elif role == 'Steward': + steward = Steward.objects.get(user=user, trash=False) + + else: + if owner_type == 'KillHouse': + kill_house = KillHouse.objects.get(key=owner_key, trash=False) + else: + steward = Steward.objects.get(key=owner_key, trash=False) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + representative = serializer.create(validated_data=request.data) + + if kill_house is not None: + representative.kill_house = kill_house + else: + representative.steward = steward + representative.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + representative = Representative.objects.get(key=request.data['key'], trash=False) + serializer = self.serializer_class(representative) + serializer.update(instance=representative, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user) + role = request.GET.get('role') + representative_type = request.GET.get('type') + + representative_filter = { + 'trash': False + } + role_filters = { + 'KillHouse': 'kill_house__kill_house_operator__user', + 'Steward': 'steward__user', + } + type_filter = { + 'KillHouse': 'kill_house__isnull', + 'Steward': 'steward__isnull', + } + filter_key = role_filters.get(role) + type_key = type_filter.get(representative_type) + if filter_key: + representative_filter[filter_key] = user + if type_key: + representative_filter[type_key] = False + + representative_list = [] + representatives = Representative.objects.filter(**representative_filter).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=representatives + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=representatives) + representative_list = ps.filter() + representatives = [] if len(representative_list) == 0 else representative_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(representatives) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(representatives, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockSupportViewSet(viewsets.ModelViewSet): + queryset = LiveStockSupport.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = LiveStockSupportSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + support = user.live_stock_support_user.all() + + # send to serializer + serializer = self.serializer_class(support[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به استانداری +class ProvincialGovernmentViewSet(viewsets.ModelViewSet): + queryset = ProvincialGovernment.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvincialGovernmentSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + government = user.government_user.all() + + # send to serializer + serializer = self.serializer_class(government[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def products_for_guild(guild): + additional_products = AdditionalProducts.objects.filter(trash=False).exclude(name='سایر محصولات').order_by('id') + if additional_products: + for additional_product in additional_products: + show = True if additional_product.name == 'مرغ گرم' else False + product = Product( + name=additional_product.name, + image=additional_product.image, + unit_of_measurement=additional_product.unit_of_measurement, + priority=additional_product.priority, + guild=guild, + selling_free_price=additional_product.selling_free_price, + selling_approved_price=additional_product.selling_approved_price, + selling_more_than_inventory=additional_product.selling_more_than_inventory, + selling_other_products=additional_product.selling_other_products, + price=additional_product.price, + show=show, + ) + product.save() + + +class TotalGuildsForPosViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [AllowAny] + serializer_class = TotalGuildsForPosSerializer + + def list(self, request, *args, **kwargs): + if 'total' in request.GET: + guilds = Guilds.objects.filter(trash=False).order_by('id') + serializer = TotalGuildsForPosSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + guilds = Guilds.objects.get(key=request.GET['guild-key']) + serializer = GuildInfoForPosSerializer(guilds) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TypeActivityViewSet(viewsets.ModelViewSet): + queryset = TypeActivity.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TypeActivitySerializer + + +class AreaActivityViewSet(viewsets.ModelViewSet): + queryset = AreaActivity.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AreaActivitySerializer + + +def persian_to_gregorian_datetime(jdate_str): + y, m, d = map(int, jdate_str.split('/')) + g_date = jdatetime.date(y, m, d).togregorian() + return datetime( + g_date.year, g_date.month, g_date.day, + 15, 48, 8, 0, + tzinfo=timezone(timedelta(hours=3, minutes=30)) + ) + + +class GuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsSerializer + + # pagination_class = CustomPagination + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + guilds = user.guilds_user.all() + + serializer = self.serializer_class(guilds[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + father_name = request.data['father_name'] + gender = request.data['gender'] + is_alive = request.data['is_alive'] + user_login = SystemUserProfile.objects.get(trash=False, user=request.user) + allow_register_code = AllowRegisterCodeForGuilds.objects.filter(trash=False, active=True).first() + # if request.data['role'] not in ('ProvinceOperator', 'SuperAdmin', 'AdminX'): + # return Response({"result": "مجاز به ثبت واحد صنفی نمی باشید!"}, status=status.HTTP_403_FORBIDDEN) + + group = Group.objects.get(name__exact="Guilds") + steward_role = Group.objects.get(name__exact="Steward") + city = City.objects.get(key=request.data['city']) + request.data.pop('city') + province = city.province + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if Guilds.objects.filter(user=system_profile, trash=False).exists(): + return Response({"result": "این صنف قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "00100" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province, + father_name=father_name, + gender=gender, + is_alive=is_alive + + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + address = SystemAddress(city=city, province=province, address=request.data['address'], + postal_code=request.data['postal_code']) + address.save() + system_profile.role.add(group) + wallet = Wallet() + wallet.save() + role = request.data['role'] + type_activity_name = request.data['type_activity_name'] + type_activity = TypeActivity.objects.filter(title__icontains=type_activity_name, trash=False).first() + if not type_activity: + type_activity = TypeActivity.objects.filter(trash=False).first() + + area_activity = AreaActivity.objects.filter(trash=False).first() + request.data.pop('role') + request.data.pop('type_activity_name') + request.data.pop('mobile') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('postal_code') + request.data.pop('type_activity') + request.data.pop('area_activity') + request.data.pop('father_name') + request.data.pop('is_alive') + request.data.pop('gender') + + # license_number = data.get("license_number"), + # license_type = data.get("license_type"), + # license_status = data.get("license_status"), + # license_issue_date = license_issue_date, + # license_expire_date = license_expire_date, + # company_name = data.get("company_name"), + # company_identifier = data.get("company_identifier"), + # is_foreign_national = parse_bool(data.get("is_foreign_national")), + # has_partner = parse_bool(data.get("has_partner")), + # has_inquiry = parse_bool(data.get("has_inquiry")), + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + guilds = serializer.create(validated_data=request.data) + guilds.user = system_profile + guilds.registerar_fullname = user_login.fullname + guilds.registerar_mobile = user_login.mobile + guilds.registerar_role = role + guilds.address = address + guilds.wallet = wallet + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.province_accept_state = 'pending' + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.license_issue_date = persian_to_gregorian_datetime(request.data['license_issue_date']) + guilds.license_expire_date = persian_to_gregorian_datetime(request.data['license_expire_date']) + guilds.save() + if allow_register_code: + number = random.randint(10000, 99000) + guilds.register_code = number + guilds.active_register_code = True + guilds.register_date_register_code = datetime.now() + if allow_register_code.has_time: + guilds.expire_time_register_code = datetime.now() + timedelta(minutes=int(allow_register_code.time)) + guilds.save() + try: + send_sms_for_guild(guilds) + except: + pass + + parent_product = NewProduct.objects.all().first() + # approved_type = True if parent_product.approved_price_status == True else False + # approved_price = parent_product.approved_price + + price = BroadcastPrice.objects.filter(trash=False).first() + + approved_price = price.steward_price if guilds.steward else price.guild_price + approved_type = price.active if approved_price > 0 else False + + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + + # if guilds.steward == True: + # steward = Steward( + # guilds=guilds + # ) + # steward.save() + # system_profile.role.add(steward_role) + + if role == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).order_by( + 'id').first() + guilds.kill_house_centers_allocation = [ + {"label": kill_house.name, "value": str(kill_house.key)}] + guilds.province_accept_state = 'pending' + guilds.kill_house_register = True + + guilds.save() + + if guilds.steward == True: + guilds.steward_kill_house.add(kill_house) + + else: + guilds.kill_house.add(kill_house) + + # if guilds.steward == True: + # steward.centers_allocation = [ + # {"label": kill_house.name, "value": str(kill_house.key)}] + # steward.allocation_limit = guilds.allocation_limit + # steward.province_accept_state = 'pending' + # steward.kill_house_register = True + # steward.save() + elif role == 'Guilds': + user = SystemUserProfile.objects.get(user=request.user) + steward = Steward.objects.get(guilds__user=user, trash=False) + + guilds.centers_allocation = [ + {"label": steward.guilds.user.fullname, "value": str(steward.key)}] + guilds.province_accept_state = 'pending' + guilds.steward_register = True + guilds.save() + + elif role == 'PosCompany': + guilds.province_accept_state = 'pending' + guilds.pos_company_register = True + guilds.save() + + # guild_products = threading.Thread(target=products_for_guild, + # args=(guilds,)) + # + # guild_products.start() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + guilds = Guilds.objects.get(key=request.data['guilds_key'], trash=False) + system_user_profile = SystemUserProfile.objects.get(key=guilds.user.key, trash=False) + address = SystemAddress.objects.get(key=guilds.address.key, trash=False) + if 'KillHouseList' in request.data.keys(): + kill_houses = KillHouse.objects.filter(key__in=request.data['KillHouseList']).order_by('id') + guilds.kill_house.set(kill_houses) + KillHouseStewardGuildRelation.objects.filter(guild=guilds, kill_house__isnull=False).delete() + + relations = [ + KillHouseStewardGuildRelation(guild=guilds, kill_house=kill_house) + for kill_house in kill_houses + ] + + KillHouseStewardGuildRelation.objects.bulk_create(relations) + # guilds.guild_kill_houses.clear() + # guilds.guild_kill_houses.add(*kill_houses) + if 'StewardList' in request.data.keys(): + stewards = Guilds.objects.filter(key__in=request.data['StewardList']).order_by('id') + guilds.stewards.set(stewards) + request.data.pop('StewardList') + + if 'StewardKillHouseList' in request.data.keys(): + kill_houses = KillHouse.objects.filter(key__in=request.data['StewardKillHouseList']).order_by('id') + guilds.steward_kill_house.set(kill_houses) + request.data.pop('StewardKillHouseList') + + if 'type_activity' in request.data.keys(): + type_activity = TypeActivity.objects.get(title=request.data['type_activity']) + area_activity = AreaActivity.objects.get(title=request.data['area_activity']) + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.save() + request.data.pop('type_activity') + request.data.pop('area_activity') + + if 'first_name' in request.data.keys(): + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.national_id = request.data['national_id'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + request.data.pop('mobile') + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + city = City.objects.get(name=request.data['city']) + province = Province.objects.get(key=city.province.key) + address.city = city + address.province = province + address.address = request.data['address'] + address.postal_code = request.data['postal_code'] + address.save() + request.data.pop('guilds_key') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('city') + if 'active' in request.data: + role = request.data['role'] + activation_role = guilds.role_activation + if request.data['active']: + if activation_role: + if (activation_role == 'AdminX' and role != 'AdminX') or \ + (activation_role == 'SuperAdmin' and role not in ('AdminX', 'SuperAdmin')): + return Response( + {"result": "شما دسترسی ویرایش صنف را ندارید!"}, + status=status.HTTP_403_FORBIDDEN + ) + guilds.role_activation = role + guilds.save() + + request.data.pop('guilds_key') + request.data.pop('role') + serializer = self.serializer_class(guilds) + serializer.update(instance=guilds, validated_data=request.data) + return Response({"result": "با موفقیت ویرایش شد"}, status=status.HTTP_200_OK) + + guilds.is_registered = False + guilds.logged_register_code = None + guilds.register_code = None + guilds.save() + serializer = self.serializer_class(guilds) + serializer.update(instance=guilds, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + if 'psp_pos' in request.GET: + base_queryset = ( + Guilds.objects.filter(trash=False, active=True, has_inquiry=True) + .select_related('user', 'address__city') + .values( + 'key', + 'guilds_name', + 'guilds_id', + 'license_number', + 'type_activity', + 'area_activity', + 'steward', + 'user__fullname', + 'user__mobile', + 'address__city__name', + ) + ) + + raw_data = base_queryset.order_by('steward') + guilds_data = [ + { + "key": g["key"], + "guilds_name": g["guilds_name"], + "steward": g["steward"], + "guilds_id": g["guilds_id"], + "license_number": g["license_number"], + "type_activity": g["type_activity"], + "area_activity": g["area_activity"], + "user": { + "fullname": g["user__fullname"], + "mobile": g["user__mobile"], + "city": g["address__city__name"], + } + } + for g in raw_data + ] + + return Response(guilds_data, status=status.HTTP_200_OK) + + if 'commonly_used' in request.GET: + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + commonly_used = CommonlyUsed.objects.filter(kill_house=kill_house, trash=False).values_list('guild', + flat=True) + else: + steward = Guilds.objects.get(user=user, steward=True, active=True, trash=False) + commonly_used = CommonlyUsed.objects.filter(steward=steward, trash=False).values_list('guild', + flat=True) + guilds = Guilds.objects.filter(trash=False, active=True).order_by('-steward').exclude(id__in=commonly_used) + serializer = GuildsForBroadcastManagementSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if 'dispenser' in request.GET: + guilds = Guilds.objects.filter(steward=True, trash=False) + serializer = GeneralGuildsSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + if 'type' in request.GET: + guilds = [] + kill_house_percentage = KillHousePercentage.objects.get(key=request.GET["percentage_key"], + trash=False) + guilds_list = Guilds.objects.filter(kill_house_centers_allocation__isnull=False, trash=False) + if guilds_list: + for guild in guilds_list: + if len(guild.kill_house_centers_allocation) == 0 or guild.kill_house_centers_allocation == None: + continue + if guild.kill_house_centers_allocation[0]['value'] == str( + kill_house_percentage.kill_house.key): + guilds.append(guild) + serializer = GuildsForKillHousePercentageSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'steward_sub_guilds' in request.GET: + guilds_list = [] + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + steward = Steward.objects.get(guilds__user=user, active=True, trash=False) + steward_ware_house = StewardWareHouse.objects.filter(steward=steward, date__date=date, trash=False).first() + guilds = Guilds.objects.filter(trash=False, steward=False).order_by('id') + for guild in guilds: + if guild.centers_allocation != None: + for center_allocation in guild.centers_allocation: + if str(steward.key) == center_allocation['value']: + if not StewardAllocation.objects.filter(date__date=date, + guilds=guild, + steward_ware_house=steward_ware_house).exists(): + guilds_list.append(guild) + guilds = guilds_list + elif 'other_guilds_for_steward' in request.GET: + guilds_list = [] + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + steward = Steward.objects.get(guilds__user=user, active=True, trash=False) + steward_ware_house = StewardWareHouse.objects.filter(steward=steward, date__date=date, trash=False).first() + guilds = Guilds.objects.filter(trash=False, steward=False).order_by('id') + for guild in guilds: + if guild.centers_allocation == None: + guilds_list.append(guild) + else: + + for center_allocation in guild.centers_allocation: + if str(steward.key) != center_allocation['value']: + if not StewardAllocation.objects.filter(date__date=date, + guilds=guild, + steward_ware_house=steward_ware_house).exists(): + guilds_list.append(guild) + guilds = guilds_list + + elif 'role' in request.GET: + + if request.GET['role'] == 'CityCommerce': + guilds = Guilds.objects.filter(trash=False, address__city=user.city).order_by('id') + + + elif request.GET['role'] == 'ProvinceOperator': + guilds = Guilds.objects.filter(trash=False, steward=False, address__province=user.province).order_by( + 'id') + + elif request.GET['role'] == 'Steward': + is_free = request.GET.get('free') == 'true' + all = request.GET.get('all') == 'true' + steward = Guilds.objects.select_related('user').get(user=user, active=True, trash=False) + base_queryset = ( + Guilds.objects.filter(trash=False, active=True) + .select_related('user', 'address__city') + .values( + 'key', + 'guilds_name', + 'steward', + 'user__fullname', + 'user__mobile', + 'address__city__name', + ) + ) + if not all: + if is_free: + raw_data = base_queryset.filter(trash=False, active=True).exclude(id=steward.id).order_by( + 'steward') + else: + raw_data = base_queryset.filter( + stewards=steward, + trash=False, + province_accept_state__in=('pending', 'accepted'), + steward=False, + active=True + ).order_by('id') + else: + raw_data = base_queryset.order_by('steward') + guilds_data = [ + { + "key": g["key"], + "guilds_name": g["guilds_name"], + "steward": g["steward"], + "user": { + "fullname": g["user__fullname"], + "mobile": g["user__mobile"], + "city": g["address__city__name"], + } + } + for g in raw_data + ] + + return Response(guilds_data, status=status.HTTP_200_OK) + + + # elif request.GET['role'] == 'PosCompany': + # + # # steward = Guilds.objects.select_related('user').get(user=user, trash=False) + # base_queryset = ( + # Guilds.objects + # .select_related('user', 'address__city') + # .values( + # 'key', + # 'guilds_name', + # 'guilds_id', + # 'type_activity', + # 'area_activity', + # 'steward', + # 'user__fullname', + # 'user__mobile', + # 'address__city__name', + # ) + # ) + # + # raw_data = base_queryset.order_by('steward') + # guilds_data = [ + # { + # "key": g["key"], + # "guilds_name": g["guilds_name"], + # "steward": g["steward"], + # "guilds_id": g["guilds_id"], + # "type_activity": g["type_activity"], + # "area_activity": g["area_activity"], + # "user": { + # "fullname": g["user__fullname"], + # "mobile": g["user__mobile"], + # "city": g["address__city__name"], + # } + # } + # for g in raw_data + # ] + # + # return Response(guilds_data, status=status.HTTP_200_OK) + + else: + guilds_list = [] + guilds = Guilds.objects.filter(steward=False, active=True, trash=False).order_by('id') + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + for guild in guilds: + if guild.kill_house_centers_allocation != None: + for kill_house_center_allocation in guild.kill_house_centers_allocation: + if request.GET['kill_house_key'] == kill_house_center_allocation['value']: + if not StewardAllocation.objects.filter(date__year=date.year, + date__month=date.month, + date__day=date.day, guilds=guild, + ware_house__kill_house=kill_house).exists(): + guilds_list.append(guild) + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + all = request.GET.get('all') == 'true' + if all: + base_queryset = ( + Guilds.objects + .filter(trash=False, active=True).select_related('user', 'address__city') + .values( + 'key', + 'guilds_name', + 'steward', + 'user__fullname', + 'user__mobile', + 'address__city__name', + ) + ) + raw_data = base_queryset.order_by('steward') + guilds_data = [ + { + "key": g["key"], + "guilds_name": g["guilds_name"], + "steward": g["steward"], + "user": { + "fullname": g["user__fullname"], + "mobile": g["user__mobile"], + "city": g["address__city__name"], + } + } + for g in raw_data + ] + + return Response(guilds_data, status=status.HTTP_200_OK) + # if 'free' in request.GET: + if request.GET['free'] == 'true': + guild_kill_ids = set(kill_house.guild_kill_houses.values_list('id', flat=True)) + steward_kill_ids = set(kill_house.steward_kill_houses.values_list('id', flat=True)) + all_exclude_ids = guild_kill_ids | steward_kill_ids + + guilds = Guilds.objects.filter( + trash=False, + active=True + ).exclude(id__in=all_exclude_ids).select_related('user__city') \ + .only('key', 'guilds_name', 'type_activity', 'area_activity', 'guilds_id', 'steward', + 'user') \ + .order_by('steward') + else: + guilds = Guilds.objects.filter( + Q(id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) | Q( + id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True)), + active=True, trash=False).order_by( + 'steward') + serializer = GuildsForBroadcastManagementSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + # + # counter = 0 + # for guild in guilds: + # if guild.kill_house_centers_allocation != None: + # if len(guild.kill_house_centers_allocation) == 0: + # continue + # for kill_house_center_allocation in guild.kill_house_centers_allocation: + # if str(kill_house.key) != kill_house_center_allocation['value']: + # counter += 1 + # if guild not in guilds_list and counter == len(guild.kill_house_centers_allocation): + # guilds_list.append(guild) + # else: + # guilds_list.append(guild) + + guilds = guilds_list + + serializer = GuildsSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class RealGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = RealGuildsSerializer + + def create(self, request, *args, **kwargs): + allocation_limit = None + allocation_type = None + owner_key = None + role_type = None + group = Group.objects.get(name__exact="Guilds") + role = request.data['role'] + type_activity = TypeActivity.objects.get(title=request.data['type_activity']) + area_activity = AreaActivity.objects.get(title=request.data['area_activity']) + register = register_user(group, request.data['city'], request.data['mobile'], request.data['first_name'], + request.data['last_name'], request.data['national_id'], request.data['postal_code'], + request.data['address']) + if 'allocation_limit' in request.data.keys(): + allocation_limit = request.data['allocation_limit'] + allocation_type = request.data['allocation_type'] + request.data.pop('allocation_limit') + request.data.pop('allocation_type') + + if 'owner_key' in request.data.keys(): + owner_key = request.data['owner_key'] + request.data.pop('owner_key') + + if 'role_type' in request.data.keys(): + role_type = request.data['role_type'] + request.data.pop('role_type') + + if not register: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است"}, status=status.HTTP_403_FORBIDDEN) + request.data.pop('city') + request.data.pop('role') + request.data.pop('mobile') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('postal_code') + request.data.pop('type_activity') + request.data.pop('area_activity') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + guilds = serializer.create(validated_data=request.data) + guilds.user = register["system_profile"] + guilds.address = register["address"] + guilds.wallet = register["wallet"] + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.save() + parent_product = NewProduct.objects.all().first() + approved_type = True if parent_product.approved_price_status == True else False + approved_price = parent_product.approved_price + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + if role == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).order_by( + 'id').first() + guilds.province_accept_state = 'pending' + guilds.kill_house_register = True + + guilds.save() + + if guilds.steward == True: + guilds.steward_kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(steward=guilds, kill_house=kill_house, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + + + + + else: + guilds.kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(guild=guilds, kill_house=kill_house, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + + + elif role == 'Steward': + user = SystemUserProfile.objects.get(user=request.user) + steward = Steward.objects.get(guilds__user=user, trash=False) + guilds.stewards.add(steward) + relation = KillHouseStewardGuildRelation(guild=guilds, steward=steward, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + guilds.province_accept_state = 'pending' + guilds.steward_register = True + guilds.save() + + + elif role == 'PosCompany': + guilds.province_accept_state = 'pending' + guilds.pos_company_register = True + guilds.save() + else: + if role_type == 'KillHouse': + kill_house = KillHouse.objects.get(key=owner_key) + + if guilds.steward == True: + guilds.steward_kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(steward=guilds, kill_house=kill_house, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + else: + guilds.kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(guild=guilds, kill_house=kill_house, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + else: + steward = Steward.objects.get(key=owner_key, trash=False) + guilds.stewards.add(steward) + relation = KillHouseStewardGuildRelation(guild=guilds, steward=steward, + allocation_limit=allocation_limit, + allocation_type=allocation_type) + relation.save() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + role = request.GET.get('role') + role_type = request.GET.get('role_type') + key = request.GET.get('key') + guild_type = request.GET.get('type') + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user).first() + if guild_type == 'guild': + guilds = Guilds.objects.filter(trash=False, province_accept_state__in=('pending', 'accepted'), + steward=False).exclude( + id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) + else: + guilds = Guilds.objects.filter(trash=False, province_accept_state__in=('pending', 'accepted'), + steward=True).exclude( + id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True)) + + elif role == 'Steward': + steward = Guilds.objects.get(user=user, steward=True, trash=False) + guilds = steward.guild_stewards.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + else: + if role_type == 'KillHouse': + kill_house = KillHouse.objects.get(key=key) + if guild_type == 'guild': + guilds = Guilds.objects.filter(trash=False, province_accept_state__in=('pending', 'accepted'), + steward=False).exclude( + id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) + else: + guilds = Guilds.objects.filter(trash=False, province_accept_state__in=('pending', 'accepted'), + steward=True).exclude( + id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True)) + + else: + steward = Guilds.objects.get(key=key) + guilds = steward.guild_stewards.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + serializer = self.serializer_class(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + guilds = Guilds.objects.get(key=request.data['guilds_key'], trash=False) + system_user_profile = SystemUserProfile.objects.get(key=guilds.user.key, trash=False) + address = SystemAddress.objects.get(key=guilds.address.key, trash=False) + + if 'choose' in request.data.keys(): + role_type = request.data['type'] + if role_type == 'KillHouse': + kill_house = KillHouse.objects.get(key=request.data['owner_key']) + if request.data['choose_type'] == 'guild': + guilds.kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(guild=guilds, kill_house=kill_house, + allocation_limit=request.data['allocation_limit'], + allocation_type=request.data['allocation_type']) + else: + guilds.steward_kill_house.add(kill_house) + relation = KillHouseStewardGuildRelation(steward=guilds, kill_house=kill_house, + allocation_limit=request.data['allocation_limit'], + allocation_type=request.data['allocation_type']) + + relation.save() + + else: + + steward = Guilds.objects.get(key=request.data['owner_key']) + guilds.stewards.add(steward) + relation = KillHouseStewardGuildRelation(guild=guilds, steward=steward, + allocation_limit=request.data['allocation_limit'], + allocation_type=request.data['allocation_type']) + relation.save() + request.data.pop('choose') + request.data.pop('type') + request.data.pop('owner_key') + request.data.pop('allocation_limit') + request.data.pop('allocation_type') + request.data.pop('choose_type') + + if 'KillHouseList' in request.data.keys(): + kill_houses = KillHouse.objects.filter(key__in=request.data['KillHouseList']).order_by('id') + guilds.kill_house.set(kill_houses) + KillHouseStewardGuildRelation.objects.filter(guild=guilds, kill_house__isnull=False).delete() + + relations = [ + KillHouseStewardGuildRelation(guild=guilds, kill_house=kill_house) + for kill_house in kill_houses + ] + + KillHouseStewardGuildRelation.objects.bulk_create(relations) + # guilds.guild_kill_houses.clear() + # guilds.guild_kill_houses.add(*kill_houses) + if 'StewardList' in request.data.keys(): + stewards = Guilds.objects.filter(key__in=request.data['StewardList']).order_by('id') + guilds.stewards.set(stewards) + request.data.pop('StewardList') + + if 'StewardKillHouseList' in request.data.keys(): + kill_houses = KillHouse.objects.filter(key__in=request.data['StewardKillHouseList']).order_by('id') + guilds.steward_kill_house.set(kill_houses) + request.data.pop('StewardKillHouseList') + + if 'type_activity' in request.data.keys(): + type_activity = TypeActivity.objects.get(title=request.data['type_activity']) + area_activity = AreaActivity.objects.get(title=request.data['area_activity']) + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.save() + request.data.pop('type_activity') + request.data.pop('area_activity') + + if 'first_name' in request.data.keys(): + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.national_id = request.data['national_id'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + request.data.pop('mobile') + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + city = City.objects.get(name=request.data['city']) + province = Province.objects.get(key=city.province.key) + address.city = city + address.province = province + address.address = request.data['address'] + address.postal_code = request.data['postal_code'] + address.save() + request.data.pop('guilds_key') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('city') + serializer = self.serializer_class(guilds) + serializer.update(instance=guilds, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class RegisterGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = RealGuildsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + def set_filter(self, role, status): + filters = {'trash': False} + if status == 'temporary_registration': + filters['temporary_registration'] = True + + return filters + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + group = Group.objects.get(name__exact="Guilds") + role = request.data.pop('role', None) + city = request.data.pop('city', None) + mobile = request.data.pop('mobile', None) + first_name = request.data.pop('first_name', None) + last_name = request.data.pop('last_name', None) + address = request.data.pop('address', None) + national_id = request.data.pop('national_id', None) + postal_code = request.data.pop('postal_code', None) + type_activity = request.data.pop('type_activity', None) + area_activity = request.data.pop('area_activity', None) + license_file = request.data.pop('license_file', None) + type_activity = TypeActivity.objects.get(title=type_activity) + area_activity = AreaActivity.objects.get(title=area_activity) + register = register_user(group, city, mobile, first_name, + last_name, national_id, postal_code, + address) + if not register: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است"}, status=status.HTTP_403_FORBIDDEN) + + if register == 'exist': + return Response({"result": "این صنف قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + guilds = serializer.create(validated_data=request.data) + guilds.user = register["system_profile"] + guilds.address = register["address"] + guilds.wallet = register["wallet"] + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.registerar_role = role + guilds.registerar_fullname = user.fullname + guilds.registerar_mobile = user.mobile + if license_file: + guilds.license_file = send_image_to_server(license_file) + guilds.license = True + guilds.final_accept = True + else: + guilds.temporary_registration = True + + guilds.save() + + if guilds.license_file: + parent_product = NewProduct.objects.all().first() + approved_type = True if parent_product.approved_price_status == True else False + approved_price = parent_product.approved_price + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + status = request.GET.get('status') + filters = self.set_filter(role, status) if role and status else {} + guilds = Guilds.objects.filter(**filters).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds.distinct()) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardForColdHouseViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PosGuildsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def list(self, request, *args, **kwargs): + if 'total' in request.GET: + guilds = Guilds.objects.filter(trash=False, steward=True, + pk__in=ColdHouse.objects.filter(steward__isnull=False).values_list('steward', + flat=True)).order_by( + 'id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds.distinct()) + if page is not None: + serializer = GuildsForTotalColdHouseSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = GuildsForTotalColdHouseSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + guilds = Guilds.objects.filter(trash=False, steward=True).exclude( + pk__in=ColdHouse.objects.filter(steward__isnull=False).values_list('steward', flat=True)).order_by( + 'id').select_related('user', 'user__city', 'user__province').only('user', 'user__city', 'user__province') + serializer = GuildsForColdHouseSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + +class StewardColdHousesViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardColdHousesSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(user=user, trash=False) + serializer = self.get_serializer(steward) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [AllowAny] + serializer_class = PosGuildsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + rel_type = request.GET.get('rel_type') + type = request.GET.get('type') + + if pos.kill_house: + if rel_type and type: + if rel_type == "free": + if type == 'guild': + guilds = Guilds.objects.filter(trash=False, steward=False, active=True).exclude( + id__in=pos.kill_house.guild_kill_houses.values_list('id', flat=True) + ).order_by('id').only( + 'guilds_name', 'type_activity', 'area_activity', 'guilds_id', 'steward' + ) + else: + guilds = Guilds.objects.filter(trash=False, steward=True, active=True).exclude( + id__in=pos.kill_house.steward_kill_houses.values_list('id', flat=True)).order_by('id').only( + 'guilds_name', 'type_activity', 'area_activity', 'guilds_id', 'steward' + ) + + else: + if type == 'guild': + guilds = Guilds.objects.filter( + id__in=pos.kill_house.guild_kill_houses.all().values_list('id', flat=True), + steward=False, active=True).order_by( + 'id').only('guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward') + + else: + guilds = Guilds.objects.filter( + id__in=pos.kill_house.steward_kill_houses.all().values_list('id', flat=True), + steward=True, active=True).order_by( + 'steward').only('guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', + 'steward') + + else: + guilds = Guilds.objects.filter(trash=False) + + else: + if rel_type and type: + if rel_type == "free": + if type == 'guild': + guilds = Guilds.objects.filter(trash=False, steward=False, active=True).exclude( + id__in=Guilds.objects.filter(stewards=pos.guild, trash=False, + province_accept_state__in=('pending', 'accepted')).values_list( + 'id', + flat=True)).only( + 'guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward') + + else: + + guilds = Guilds.objects.filter(trash=False, steward=True, active=True).exclude( + id=pos.guild.id).only( + 'guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward') + + else: + if type == 'guild': + guilds = Guilds.objects.filter(stewards=pos.guild, trash=False, + province_accept_state__in=('pending', 'accepted'), + steward=False, active=True).order_by('id').only( + 'guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward') + else: + guilds = Guilds.objects.filter(stewards=pos.guild, trash=False, + province_accept_state__in=('pending', 'accepted'), + steward=True, active=True).order_by( + 'id').only( + 'guilds_name', 'user', 'type_activity', 'area_activity', 'guilds_id', 'steward') + else: + guilds = Guilds.objects.filter(trash=False).order_by('steward') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds.distinct()) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PosGuildsForBroadcastManagementSerializer(guilds.distinct(), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + +class ProvinceCheckKillHouseGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsSerializer + + def create(self, request, *args, **kwargs): + guilds = Guilds.objects.get(key=request.data['guilds_key']) + request.data.pop('guilds_key') + role = request.data.pop('role') + + steward = Steward.objects.filter(guilds=guilds, trash=False).last() + if request.data['state'] == 'accepted': + guilds.province_accept_state = 'accepted' + if guilds.active_register_code and guilds.logged_register_code is None: + code = request.data.get('code') + if code != guilds.register_code: + return Response({'result': "کد وارد شده معتبر نمیباشد!"}, status=status.HTTP_403_FORBIDDEN) + if role not in ['AdminX', 'SuperAdmin', 'ProvinceOperator']: + guilds.province_accept_state = 'pending' + guilds.logged_register_code = code + guilds.active_register_code = True + guilds.is_registered = True + guilds.save() + if steward: + steward.province_accept_state = 'accepted' + steward.save() + + else: + guilds.province_accept_state = 'rejected' + guilds.province_message = request.data['message'] + guilds.save() + if steward: + steward.province_accept_state = 'rejected' + steward.save() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_200_OK) + + +class TotalGuildsForCompaniesViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsForCompaniesSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + filterset_fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'address__city__name', + 'guilds_name', + 'type_activity', + 'area_activity', + + ] + + def update(self, request, pk=None, *args, **kwargs): + guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + serializer = self.serializer_class(guild) + serializer.update(instance=guild, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + def list(self, request, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + pos_company = PosCompany.objects.get(user=user, trash=False) + # pos = POSMachine.objects.filter(pos_company=pos_company, trash=False).select_related('guild').only( + # 'guild').values_list('guild', flat=True).distinct() + + guilds = Guilds.objects.filter(trash=False, + address__province=user.province).order_by('-has_pos') + # guilds = Guilds.objects.filter(Q(id__in=pos) | Q(has_pos=False), trash=False, + # address__province=user.province).order_by('-has_pos') + + if 'value' in request.GET and request.GET['value'] == 'undefined': + pass + else: + value = request.GET.get('value') + search = request.GET.get('search') + guilds_list = [] + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + self.build_query(value) + ) + # if request.GET['search'] == 'filter': + # if request.GET['value'] != "": + # for item in self.filterset_fields: + # query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + # if (self.filterset_class( + # data=query, + # queryset=guilds + # ) + # ).filter(): + # ps = self.filterset_class(data=query, queryset=guilds) + # guilds_list = ps.filter() + # guilds = [] if len(guilds_list) == 0 else guilds_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds) + if page is not None: + serializer = self.get_serializer(page, context={'company': pos_company.name}, many=True) + return self.get_paginated_response(serializer.data) + + serializer = GuildsForCompaniesSerializer(guilds, context={'company': pos_company.name}, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalGuildsForInspectionViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [AllowAny] + serializer_class = GuildsForCompaniesSerializer + + def list(self, request, *args, **kwargs): + guilds = Guilds.objects.filter(trash=False, province_accept_state='accepted') + serializer = GuildsForInspectionSerializer(guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def list(self, request, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] in ['CityCommerce', 'CityOperator', 'CityJahad', 'CityPoultry']: + guilds = Guilds.objects.filter(trash=False, province_accept_state='accepted', + address__city=user.city).exclude(user__national_id='0').order_by('id') + elif request.GET['role'] == 'Steward': + + steward = Guilds.objects.get(user=user, trash=False).exclude(user__national_id='0') + guilds = Guilds.objects.filter(stewards=steward).exclude(user__national_id='0').order_by('id') + + + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'steward' in request.GET and request.GET['steward'] == 'true': + guilds = kill_house.steward_kill_houses.all().filter(trash=False, steward=True, + province_accept_state__in=( + 'pending', 'accepted')).exclude( + user__national_id='0').order_by( + '-is_registered', '-id') + else: + # guilds = kill_house.guild_kill_houses.all().filter(trash=False, + # province_accept_state__in=( + # 'pending', 'accepted')).order_by('id') + guilds = Guilds.objects.filter( + Q(id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) | Q( + id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True))).exclude( + user__national_id='0').order_by( + '-is_registered', '-id') + + else: + if 'check' in request.GET: + if request.GET['state'] == 'pending': + guilds = Guilds.objects.filter( + # Q(kill_house_register=True) | Q(steward_register=True) | Q(pos_company_register=True), + province_accept_state='pending', + trash=False).exclude(user__national_id='0').order_by('-id') + else: + guilds = Guilds.objects.filter(kill_house_register=True, + trash=False).exclude(user__national_id='0').order_by('id') + else: + is_real_person = request.GET.get('is_real_person') + filters = {"province_accept_state": "accepted", "trash": False} + active = request.GET.get('active_state') + if active == 'active': + filters['active'] = True + elif active == 'deactive': + filters['active'] = False + if is_real_person: + if is_real_person == 'false': + filters["is_real_person"] = False + else: + filters["is_real_person"] = True + if 'steward' in request.GET and request.GET['steward'] == 'true': + guilds = Guilds.objects.filter(**filters, steward=True).exclude(user__national_id='0').order_by( + 'id') + else: + guilds = Guilds.objects.filter(**filters).exclude(user__national_id='0').order_by('id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds.distinct()) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = GuildsSerializer(guilds.distinct(), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + +# class TotalGuildsDistributionManagementViewSet(viewsets.ModelViewSet): +# queryset = Guilds.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = GuildsForDistributionManagementSerializer +# pagination_class = CustomPagination +# filter_backends = [DjangoFilterBackend] +# filterset_class = GuildsFilterSet +# +# def build_query(self, value): +# from django.db.models import Q +# query = Q() +# for field in self.filterset_class.Meta.fields: +# query |= Q(**{f"{field}__icontains": value}) +# return query +# +# def list(self, request, *args, **kwargs): +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# management_type = request.GET.get('management_type') +# role_type = request.GET.get('role_type') +# type = request.GET.get('type') +# +# if role_type == 'KillHouse': +# kill_house = KillHouse.objects.get(key=request.GET.get('key')) +# if management_type == 'subcategories': +# if type == 'guild': +# guilds = kill_house.guild_kill_houses.all().filter(trash=False, province_accept_state__in=( +# 'pending', 'accepted')).order_by('id') +# elif type == 'steward': +# guilds = kill_house.steward_kill_houses.all().filter(trash=False, steward=True, +# province_accept_state__in=( +# 'pending', 'accepted')).order_by('id') +# else: +# guilds = Guilds.objects.filter( +# Q(id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) | Q( +# id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True))).order_by( +# 'steward') +# else: +# if type == 'guild': +# guilds = Guilds.objects.filter(trash=False, steward=False, +# province_accept_state__in=('pending', 'accepted')).exclude( +# kill_house.guild_kill_houses.all()).order_by('id') +# elif type == 'steward': +# guilds = Guilds.objects.filter(trash=False, steward=True, +# province_accept_state__in=('pending', 'accepted')).exclude( +# kill_house.steward_kill_houses.all()).order_by('id') +# else: +# guilds = Guilds.objects.filter(trash=False, steward=True, +# province_accept_state__in=('pending', 'accepted')).exclude( +# Q(id__in=kill_house.guild_kill_houses.all().values_list('id', flat=True)) | Q( +# id__in=kill_house.steward_kill_houses.all().values_list('id', flat=True))).order_by( +# 'steward') +# else: +# steward = Guilds.objects.get(key=request.GET.get('key')) +# if management_type == 'subcategories': +# guilds = steward.guild_stewards.all().filter(trash=False, province_accept_state__in=( +# 'pending', 'accepted')).order_by('id') +# +# else: +# guilds = Guilds.objects.filter(trash=False, steward=True, +# province_accept_state__in=('pending', 'accepted')).exclude( +# id__in=steward.guild_stewards.all().values_list('id', flat=True)).order_by('id') +# +# value = request.GET.get('value') +# search = request.GET.get('search') +# if value and search == 'filter': +# if value != 'undefined' and value.strip(): +# guilds = guilds.filter( +# self.build_query(value) +# ) +# +# page_size = request.query_params.get('page_size', None) +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(guilds.distinct()) +# if page is not None: +# if management_type == 'subcategories' and role_type == 'KillHouse': +# serializer = self.get_serializer(page, many=True, +# context={'role_type': 'KillHouse', 'role_object': kill_house, +# 'type': type}) +# elif management_type == 'subcategories' and role_type == 'Steward': +# serializer = self.get_serializer(page, many=True, +# context={'role_type': 'Steward', 'role_object': steward}) +# else: +# serializer = self.get_serializer(page, many=True, context={'role_type': None}) +# return self.get_paginated_response(serializer.data) +# if management_type == 'subcategories' and role_type == 'KillHouse': +# serializer = GuildsForDistributionManagementSerializer(guilds.distinct(), many=True, +# context={'role_type': 'KillHouse', +# 'role_object': kill_house, 'type': type}) +# elif management_type == 'subcategories' and role_type == 'Steward': +# serializer = GuildsForDistributionManagementSerializer(guilds.distinct(), many=True, +# context={'role_type': 'Steward', +# 'role_object': steward}) +# else: +# +# serializer = GuildsForDistributionManagementSerializer(guilds.distinct(), many=True, +# context={'role_type': None}) +# return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalGuildsDistributionManagementViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsForDistributionManagementSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="Guilds") + role = request.data['role'] + type_activity = TypeActivity.objects.get(title=request.data['type_activity']) + area_activity = AreaActivity.objects.get(title=request.data['area_activity']) + register = register_user(group, request.data['city'], request.data['mobile'], request.data['first_name'], + request.data['last_name'], request.data['national_id'], request.data['postal_code'], + request.data['address']) + if not register: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است"}, status=status.HTTP_403_FORBIDDEN) + request.data.pop('city') + request.data.pop('role') + request.data.pop('mobile') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('address') + request.data.pop('national_id') + request.data.pop('postal_code') + request.data.pop('type_activity') + request.data.pop('area_activity') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + guilds = serializer.create(validated_data=request.data) + guilds.user = register["system_profile"] + guilds.address = register["address"] + guilds.wallet = register["wallet"] + guilds.type_activity = type_activity.title + guilds.area_activity = area_activity.title + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.save() + parent_product = NewProduct.objects.all().first() + approved_type = True if parent_product.approved_price_status == True else False + approved_price = parent_product.approved_price + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + if role == 'KillHouse': + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).order_by( + 'id').first() + guilds.kill_house_centers_allocation = [ + {"label": kill_house.name, "value": str(kill_house.key)}] + guilds.province_accept_state = 'pending' + guilds.kill_house_register = True + + guilds.save() + + if guilds.steward == True: + guilds.steward_kill_house.add(kill_house) + + else: + guilds.kill_house.add(kill_house) + + elif role == 'Guilds': + user = SystemUserProfile.objects.get(user=request.user) + steward = Steward.objects.get(guilds__user=user, trash=False) + + guilds.centers_allocation = [ + {"label": steward.guilds.user.fullname, "value": str(steward.key)}] + guilds.province_accept_state = 'pending' + guilds.steward_register = True + guilds.save() + + elif role == 'PosCompany': + guilds.province_accept_state = 'pending' + guilds.pos_company_register = True + guilds.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + type = request.GET.get('type') + role = request.GET.get('role') + role_type = request.GET.get('role_type') + key = request.GET.get('key') + city_name = request.GET.get('city_name') + type_activity = request.GET.get('type_activity') + user_level = request.GET.get('user_level') + role_object = None + type_object = None + + if role == 'KillHouse': + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if type == 'guild': + guilds = kill_house.guild_kill_houses.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + else: + guilds = kill_house.steward_kill_houses.all().filter(trash=False, steward=True, + province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + role_object = kill_house + type_object = 'KillHouse' + + + elif role == 'Steward': + steward = Guilds.objects.get(user=user, trash=False) + guilds = steward.guild_stewards.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + role_object = steward + type_object = 'Steward' + + + else: + if key: + if role_type == 'KillHouse': + kill_house = KillHouse.objects.get(key=key, trash=False) + if type == 'guild': + guilds = kill_house.guild_kill_houses.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + else: + guilds = kill_house.steward_kill_houses.all().filter(trash=False, steward=True, + province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + role_object = kill_house + type_object = 'KillHouse' + else: + steward = Guilds.objects.get(key=key, trash=False) + guilds = steward.guild_stewards.all().filter(trash=False, province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + role_object = steward + type_object = 'Steward' + else: + if type == 'guild': + + guilds = Guilds.objects.filter(trash=False, steward=False, + province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + else: + guilds = Guilds.objects.filter(trash=False, steward=True, + province_accept_state__in=( + 'pending', 'accepted')).order_by('id') + + if city_name: + guilds = guilds.filter(user__city__name__icontains=city_name) + + if type_activity: + guilds = guilds.filter(type_activity__icontains=type_activity) + if user_level: + guilds = guilds.filter(user_level__fa_title__icontains=user_level) + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds.distinct()) + if page is not None: + serializer = self.get_serializer(page, many=True, + context={'role_object': role_object, 'type_object': type_object, + 'type': type}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(guilds.distinct(), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TestTotalGuildsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TestGuildsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = TestGuildsFilterSet + + def list(self, request, *args, **kwargs): + guilds = Guilds.objects.filter(province_accept_state='accepted', trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + filtered_guilds = guilds.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(filtered_guilds) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = GuildsSerializer(filtered_guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + +# class StewardViewSet(viewsets.ModelViewSet): +# # queryset = Steward.objects.all() +# # permission_classes = [TokenHasReadWriteScope] +# # serializer_class = StewardSerializer +# queryset = Guilds.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = GuildsSerializer +# pagination_class = CustomPagination +# filter_backends = [DjangoFilterBackend] +# filterset_class = GuildsFilterSet +# filterset_fields = [ +# 'user__mobile', +# 'user__first_name', +# 'user__last_name', +# 'user__city__name', +# 'user__province__name', +# 'address__city__name', +# 'guilds_name', +# 'type_activity', +# 'area_activity', +# +# ] +# +# def create(self, request, *args, **kwargs): +# guilds = Guilds.objects.get(key=request.data['guilds_key']) +# request.data.pop('guilds_key') +# if Steward.objects.filter(guilds=guilds, trash=False).exists(): +# return Response({"result": "این صنف قبلا به عنوان مباشر ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) +# serializer = self.serializer_class(data=request.data) +# if serializer.is_valid(): +# steward = serializer.create(validated_data=request.data) +# steward.guilds = guilds +# steward.save() +# guilds.steward = True +# guilds.save() +# return Response(serializer.data, status=status.HTTP_201_CREATED) +# return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) +# +# def update(self, request, pk=None, *args, **kwargs): +# steward = Steward.objects.get(key=request.data['steward_key'], trash=False) +# guild = Guilds.objects.get(key=steward.guilds.key, trash=False) +# if 'allocation_limit' in request.data.keys(): +# if request.data['allocation_limit'] == "": +# steward.allocation_limit = None +# steward.save() +# request.data.pop('allocation_limit') +# request.data.pop('steward_key') +# if 'centers_allocation' in request.data.keys() and request.data['centers_allocation'] != None: +# guild.kill_house_centers_allocation = request.data['centers_allocation'] +# guild.save() +# serializer = self.serializer_class(steward) +# serializer.update(instance=steward, validated_data=request.data) +# return Response(serializer.data, status=status.HTTP_200_OK) +# +# def list(self, request, *args, **kwargs): +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# +# if request.GET['role'] in ['CityCommerce', 'CityJahad', 'CityPoultry']: +# stewards = Guilds.objects.filter(trash=False, address__city=user.city).order_by('id') +# +# elif request.GET['role'] in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', +# 'ImprovingLivestock', 'AdminX', 'Supporter']: +# stewards = Guilds.objects.filter(trash=False, address__province=user.province, +# steward=True).order_by('id') +# +# else: +# stewards = Guilds.objects.filter(steward=True, trash=False).order_by('id') +# if 'kill_house_key' in request.GET: +# kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) +# else: +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() +# # now = datetime.now().date() +# # date = datetime.strptime(str(request.GET['date']), +# # '%Y-%m-%d').date() if 'date' in request.GET else now +# # stewards_list = [] +# # if 'kill_house_key' in request.GET: +# # # if 'allocation' in request.GET: +# # for steward in stewards: +# # if steward.centers_allocation != None: +# # for center_allocation in steward.centers_allocation: +# # if request.GET['kill_house_key'] == center_allocation['value']: +# # if not StewardAllocation.objects.filter( +# # Q(type='manual') | Q(type='auto', +# # system_registration_code=True), date__date=date, +# # steward=steward, +# # ware_house__kill_house=kill_house, trash=False).exists(): +# # stewards_list.append(steward) +# # else: +# # for steward in stewards: +# # if steward.centers_allocation == None: +# # stewards_list.append(steward) +# # else: +# # counter = 0 +# # if len(steward.centers_allocation) == 0: +# # continue +# # for center_allocation in steward.centers_allocation: +# # +# # if str(kill_house.key) != center_allocation['value']: +# # counter += 1 +# # if steward not in stewards_list and counter == len(steward.centers_allocation): +# # stewards_list.append(steward) +# # +# # stewards = stewards_list +# +# if 'search' in request.GET: +# if 'value' in request.GET and request.GET['value'] == 'undefined': +# pass +# else: +# # if 'search' in request.GET: +# steward_list = [] +# if request.GET['search'] == 'filter': +# if request.GET['value'] != "": +# for item in self.filterset_fields: +# query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) +# if (self.filterset_class( +# data=query, +# queryset=stewards +# ) +# ).filter(): +# ps = self.filterset_class(data=query, queryset=stewards) +# steward_list = ps.filter() +# stewards = [] if len(steward_list) == 0 else steward_list +# if 'page_size' in request.GET: +# page_size = request.query_params.get('page_size', None) +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(stewards) +# if page is not None: +# serializer = self.get_serializer(page, many=True) +# return self.get_paginated_response(serializer.data) +# +# serializer = GuildsForStewardMenueSerializer(stewards, many=True) +# return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardViewSet(viewsets.ModelViewSet): + queryset = Steward.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardSerializer + + def create(self, request, *args, **kwargs): + guilds = Guilds.objects.get(key=request.data['guilds_key']) + request.data.pop('guilds_key') + if Steward.objects.filter(guilds=guilds, trash=False).exists(): + return Response({"result": "این صنف قبلا به عنوان مباشر ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + steward = serializer.create(validated_data=request.data) + steward.guilds = guilds + steward.save() + guilds.steward = True + guilds.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + steward = Steward.objects.get(key=request.data['steward_key'], trash=False) + guild = Guilds.objects.get(key=steward.guilds.key, trash=False) + if 'allocation_limit' in request.data.keys(): + if request.data['allocation_limit'] == "": + steward.allocation_limit = None + steward.save() + request.data.pop('allocation_limit') + request.data.pop('steward_key') + if 'centers_allocation' in request.data.keys() and request.data['centers_allocation'] != None: + guild.kill_house_centers_allocation = request.data['centers_allocation'] + guild.save() + serializer = self.serializer_class(steward) + serializer.update(instance=steward, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + stewards = Steward.objects.filter(trash=False, guilds__address__province=user.province, + guilds__steward=True).exclude( + guilds__user__national_id='0').select_related('guilds').order_by('id') + elif request.GET['role'] == 'CityCommerce': + stewards = Steward.objects.filter(trash=False, guilds__address__city=user.city).exclude( + guilds__user__national_id='0').order_by('id') + + + else: + stewards = Steward.objects.filter(guilds__steward=True, trash=False).exclude( + guilds__user__national_id='0').order_by('id') + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + stewards_list = [] + if 'kill_house_key' in request.GET: + # if 'allocation' in request.GET: + for steward in stewards: + if steward.centers_allocation != None: + for center_allocation in steward.centers_allocation: + if request.GET['kill_house_key'] == center_allocation['value']: + if not StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', + system_registration_code=True), date__date=date, + steward=steward, + ware_house__kill_house=kill_house, trash=False).exists(): + stewards_list.append(steward) + else: + for steward in stewards: + if steward.centers_allocation == None: + stewards_list.append(steward) + else: + counter = 0 + if len(steward.centers_allocation) == 0: + continue + for center_allocation in steward.centers_allocation: + + if str(kill_house.key) != center_allocation['value']: + counter += 1 + if steward not in stewards_list and counter == len(steward.centers_allocation): + stewards_list.append(steward) + + stewards = stewards_list + + serializer = StewardSerializer(stewards, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def steward_allocations_sms(allocations_list): + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list, + trash=False) + for steward_allocation in steward_allocations: + buyer = None + if steward_allocation.to_steward: + buyer = steward_allocation.to_steward.guilds_name + if steward_allocation.to_guilds: + buyer = steward_allocation.to_guilds.guilds_name + + date_str = str(steward_allocation.date.date()) + date = datetime.strptime(date_str, '%Y-%m-%d') + date = jdatetime.datetime.fromgregorian(year=date.year, month=date.month, day=date.day).strftime( + '%Y-%m-%d') + date_list = reversed(date.split('-')) + separate = "-" + date = separate.join(date_list) + number = str(steward_allocation.registration_code) + quantity = str(steward_allocation.number_of_carcasses) + weight = str(int(steward_allocation.weight_of_carcasses)) + # kill_house = str(steward_allocation.ware_house.kill_house.name) + if steward_allocation.kill_house: + seller = steward_allocation.kill_house.name + + elif steward_allocation.to_cold_house: + seller = steward_allocation.to_cold_house.kill_house.name + + elif steward_allocation.steward: + seller = steward_allocation.steward.user.fullname + else: + seller = steward_allocation.guilds.user.fullname + if steward_allocation.interface_number: + mobile = steward_allocation.interface_number + else: + if steward_allocation.to_steward: + mobile = steward_allocation.to_steward.user.mobile + + elif steward_allocation.to_guilds: + mobile = steward_allocation.to_guilds.user.mobile + elif steward_allocation.to_cold_house: + if steward_allocation.to_cold_house.kill_house: + mobile = steward_allocation.to_cold_house.kill_house.kill_house_operator.user.mobile + else: + mobile = steward_allocation.to_cold_house.live_stock_support.user.mobile + + mobile = steward_allocation.to_guilds.user.mobile + else: + mobile = steward_allocation.to_kill_house.kill_house_operator.user.mobile + + steward_allocation_sms(mobile, date, weight, seller, number, buyer, steward_allocation.amount) + + +def automatic_steward_allocations_sms(allocations_list): + steward_allocations = AutomaticStewardAllocation.objects.filter(key__in=allocations_list, + trash=False) + for steward_allocation in steward_allocations: + buyer = None + if steward_allocation.to_steward: + buyer = steward_allocation.to_steward.guilds_name + if steward_allocation.to_guilds: + buyer = steward_allocation.to_guilds.guilds_name + + date_str = str(steward_allocation.date.date()) + date = datetime.strptime(date_str, '%Y-%m-%d') + date = jdatetime.datetime.fromgregorian(year=date.year, month=date.month, day=date.day).strftime( + '%Y-%m-%d') + date_list = reversed(date.split('-')) + separate = "-" + date = separate.join(date_list) + number = str(steward_allocation.registration_code) + quantity = str(steward_allocation.number_of_carcasses) + weight = str(int(steward_allocation.weight_of_carcasses)) + # kill_house = str(steward_allocation.ware_house.kill_house.name) + if steward_allocation.kill_house: + seller = steward_allocation.kill_house.name + + elif steward_allocation.to_cold_house: + seller = steward_allocation.to_cold_house.kill_house.name + + elif steward_allocation.steward: + seller = steward_allocation.steward.user.fullname + else: + seller = steward_allocation.guilds.user.fullname + if steward_allocation.interface_number: + mobile = steward_allocation.interface_number + else: + if steward_allocation.to_steward: + mobile = steward_allocation.to_steward.user.mobile + + elif steward_allocation.to_guilds: + mobile = steward_allocation.to_guilds.user.mobile + elif steward_allocation.to_cold_house: + if steward_allocation.to_cold_house.kill_house: + mobile = steward_allocation.to_cold_house.kill_house.kill_house_operator.user.mobile + else: + mobile = steward_allocation.to_cold_house.live_stock_support.user.mobile + + mobile = steward_allocation.to_guilds.user.mobile + else: + mobile = steward_allocation.to_kill_house.kill_house_operator.user.mobile + + steward_allocation_sms(mobile, date, weight, seller, number, buyer, steward_allocation.amount) + + +def first_auto_steward_allocation(kill_house_key, quantity, weight, date): + kill_house = KillHouse.objects.get(key=kill_house_key, trash=False) + ware_house = KillHouseWareHouse.objects.get(kill_house=kill_house, date__date=date.date()) + stewards = Steward.objects.filter(guilds__steward=True, trash=False).order_by('id') + stewards_list = [] + allocatated_quantity = 0 + kill_house_total_quantity = 0 + for steward in stewards: + if steward.centers_allocation != None: + for center_allocation in steward.centers_allocation: + if str(kill_house.key) == center_allocation['value']: + kill_house_total_quantity += steward.allocation_limit + stewards_list.append(steward) + if len(stewards_list) > 0: + for steward_list in stewards_list: + allocatated_quantity = (steward_list.allocation_limit / kill_house_total_quantity) * quantity + auto_allocation = StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='auto', trash=False, + date__date=date.date()).first() + + if auto_allocation: + if StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='manual', trash=False, + date__date=date.date()).exists(): + + # auto_allocation.delete() + auto_allocation.trash = True + auto_allocation.save() + else: + auto_allocation.number_of_carcasses = allocatated_quantity + auto_allocation.real_number_of_carcasses = allocatated_quantity + auto_allocation.weight_of_carcasses = int(allocatated_quantity * (weight / quantity)) + auto_allocation.real_weight_of_carcasses = int(allocatated_quantity * (weight / quantity)) + auto_allocation.save() + else: + if not StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='manual', trash=False, + date__date=date.date()).exists(): + auto_allocation = StewardAllocation( + kill_house=kill_house, + ware_house=ware_house, + steward=steward_list, + number_of_carcasses=allocatated_quantity, + real_number_of_carcasses=allocatated_quantity, + weight_of_carcasses=int(allocatated_quantity * (weight / quantity)), + real_weight_of_carcasses=int(allocatated_quantity * (weight / quantity)), + type='auto', + date=date + ) + auto_allocation.save() + + +class StewardFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = StewardFreeBarInformation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardFreeBarInformationSerializer + pagination_class = CustomPagination + filterset_class = StewardFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house_name', + 'kill_house_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'pelak', + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'steward__guilds_name', + + ] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(user=user, active=True, trash=False) + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + request.data.pop('product_key') + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + try: + image = request.data['bar_image'] + request.data.pop('bar_image') + except: + image = None + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + steward_free_bar_info = serializer.create(validated_data=request.data) + if image != None: + steward_free_bar_info.bar_image = send_image_to_server(image) + steward_free_bar_info.steward = steward + steward_free_bar_info.product = product + steward_free_bar_info.dispenser = dispenser if dispenser else None + steward_free_bar_info.representative = representative if representative else None + steward_free_bar_info.save() + guild_steward_free_buying_product_warehousing(product) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + guild = Guilds.objects.get(user=user, active=True, trash=False) + if date1: + bars = StewardFreeBarInformation.objects.filter(Q(steward=guild) | Q(guild=guild), + date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('-date') + else: + bars = StewardFreeBarInformation.objects.filter(Q(steward=guild) | Q(guild=guild), + trash=False).order_by('-date') + + if 'search' in request.GET and 'value' in request.GET: + bars_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bars + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bars) + bars_list = ps.filter() + bars = [] if len(bars_list) == 0 else bars_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(bars) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(bars, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + free_bar = StewardFreeBarInformation.objects.get(key=request.data['key']) + if 'bar_image' in request.data.keys(): + if request.data['bar_image'] != "" or request.data['bar_image'] != " ": + image = request.data['bar_image'] + free_bar.bar_image = send_image_to_server(image) + free_bar.save() + request.data.pop('bar_image') + + serializer = self.serializer_class(free_bar) + serializer.update(instance=free_bar, validated_data=request.data) + guild_steward_free_buying_product_warehousing(free_bar.product) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_bar = StewardFreeBarInformation.objects.get(key=request.GET['key']) + free_bar.trash = True + free_bar.save() + guild_steward_free_buying_product_warehousing(free_bar.product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class StewardFreeBarInformationDashboardViewSet(viewsets.ModelViewSet): + queryset = StewardFreeBarInformation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardFreeBarInformationSerializer + filterset_class = StewardFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house_name', + 'kill_house_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'pelak', + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'steward__guilds_name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + guild = Guilds.objects.get(user=user, active=True, trash=False) + product = RolesProducts.objects.get(guild=guild, trash=False) + if date1: + bars = StewardFreeBarInformation.objects.filter(Q(steward=guild) | Q(guild=guild), + date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('-date') + else: + bars = StewardFreeBarInformation.objects.filter(Q(steward=guild) | Q(guild=guild), + trash=False).order_by('-date') + + if 'search' in request.GET and 'value' in request.GET: + bars_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bars + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bars) + bars_list = ps.filter() + bars = [] if len(bars_list) == 0 else bars_list + total_quantity = bars.aggregate(total=Sum('number_of_carcasses'))['total'] + total_weight = bars.aggregate(total=Sum('weight_of_carcasses'))['total'] + result = { + "product": product.key, + "total_bars": len(bars), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class PosStewardFreeBarInformationViewSet(viewsets.ModelViewSet): + queryset = StewardFreeBarInformation.objects.all() + permission_classes = [AllowAny] + serializer_class = PosStewardFreeBarInformationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = StewardFreeBarInformationFilterSet + filterset_fields = [ + 'kill_house_name', + 'kill_house_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'pelak', + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'steward__guilds_name', + + ] + + def create(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + steward = Guilds.objects.get(id=pos.guild.id, trash=False) + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + request.data.pop('product_key') + try: + image = request.data['bar_image'] + request.data.pop('bar_image') + except: + image = None + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + steward_free_bar_info = serializer.create(validated_data=request.data) + if image != None: + steward_free_bar_info.bar_image = send_image_to_server(image) + steward_free_bar_info.steward = steward + steward_free_bar_info.product = product + steward_free_bar_info.date = datetime.now() + steward_free_bar_info.save() + guild_steward_free_buying_product_warehousing(product) + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + bars = StewardFreeBarInformation.objects.filter(Q(steward=pos.guild) | Q(guild=pos.guild), + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + if 'search' in request.GET and 'value' in request.GET: + bars_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bars + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bars) + bars_list = ps.filter() + bars = [] if len(bars_list) == 0 else bars_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(bars) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(bars, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + bar = StewardFreeBarInformation.objects.get(key=request.data['key']) + if 'bar_image' in request.data.keys(): + if request.data['bar_image'] != "" or request.data['bar_image'] != " ": + image = request.data['bar_image'] + bar.bar_image = send_image_to_server(image) + bar.save() + request.data.pop('bar_image') + + serializer = self.serializer_class(bar) + serializer.update(instance=bar, validated_data=request.data) + guild_steward_free_buying_product_warehousing(bar.product) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_bar = StewardFreeBarInformation.objects.get(key=request.GET['key']) + free_bar.trash = True + free_bar.save() + guild_steward_free_buying_product_warehousing(free_bar.product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class StewardFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = StewardFreeSaleBarInformation.objects.all() + serializer_class = StewardFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filterset_class = StewardFreeSaleBarInformationFilterSet + filterset_fields = [ + 'steward__user__fullname', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__mobile', + 'buyer__user__fullname', + 'buyer__user__first_name', + 'buyer__user__last_name', + 'buyer__user__mobile', + 'province', + 'city', + 'province' + 'buyer_name' + 'buyer_mobile' + + ] + + def create(self, request, *args, **kwargs): + now_time = datetime.now().time() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(user=user, active=True, trash=False) + product = RolesProducts.objects.get(key=request.data.pop('product_key', None), trash=False) + buyer = OutProvinceCarcassesBuyer.objects.get(key=request.data.pop('buyer_key', None), trash=False) + date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + date = datetime(year=date.year, month=date.month, day=date.day, hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + carcass_distribution = RestrictionCarcassDistribution.objects.filter(trash=False, + distribution_type='Steward', + allow=True, + out=True).first() + if carcass_distribution and datetime.now().time() > carcass_distribution.time: + return Response({"result": "لطفا در ساعات مجاز اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + request.data.pop('date') + request.data.pop('production_date') + quota = request.data['quota'] + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not steward.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if steward.total_input_warehouse_governmental_weight < ( + steward.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward.total_input_warehouse_free_weight < ( + steward.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + free_sale_type = request.data['sale_type'] + if steward.governmental_selling_permission: + if free_sale_type == 'free': + if not steward.free_sale_form_governmental_quota: + if steward.total_commitment_selling_in_province_governmental_weight > steward.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward.total_commitment_selling_in_province_governmental_weight > steward.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if steward.total_commitment_selling_out_province_governmental_weight > 0: + if steward.total_selling_out_province_governmental_weight + request.data[ + 'weight_of_carcasses'] > steward.total_commitment_selling_out_province_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward.free_selling_permission: + if steward.total_commitment_selling_in_province_free_weight > steward.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if steward.total_commitment_selling_out_province_free_weight > 0: + if steward.total_selling_out_province_free_weight + request.data[ + 'weight_of_carcasses'] > steward.total_commitment_selling_out_province_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if product.total_remain_weight < request.data['weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار است!"}, status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + steward_free_sale_bar_info = serializer.create(validated_data=request.data) + steward_free_sale_bar_info.steward = steward + steward_free_sale_bar_info.buyer = buyer + steward_free_sale_bar_info.buyer_name = buyer.fullname + steward_free_sale_bar_info.buyer_mobile = buyer.mobile + steward_free_sale_bar_info.city = buyer.city + steward_free_sale_bar_info.province = buyer.province + steward_free_sale_bar_info.date = date + steward_free_sale_bar_info.production_date = production_date + steward_free_sale_bar_info.product = product + steward_free_sale_bar_info.dispenser = dispenser if dispenser else None + steward_free_sale_bar_info.representative = representative if representative else None + steward_free_sale_bar_info.save() + allow_register_code = AllowRegisterCodeForStewardFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + number = random.randint(10000, 99000) + steward_free_sale_bar_info.registration_code = number + steward_free_sale_bar_info.system_registration_code = True + if int(allow_register_code.time) > 0: + steward_free_sale_bar_info.active_expire_date_time = True + steward_free_sale_bar_info.expire_date_time_registration_code = datetime.now() + timedelta( + minutes=int(allow_register_code.time)) + steward_free_sale_bar_info.save() + send_sms_for_sale_bar_for_steward(steward_free_sale_bar_info) + guild_steward_free_sale_product_warehousing(product) + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + filters = {'trash': False} + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + steward_key = request.GET.get('steward_key') + + if role == 'Steward': + steward = Guilds.objects.get(user=user, active=True, trash=False) + filters['steward'] = steward + elif role in ['CityJahad']: + filters['steward__user__city'] = user.city + + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + if steward_key and steward_key != 'all': + filters['steward__key'] = steward_key + + bars = StewardFreeSaleBarInformation.objects.filter(**filters).order_by('-date') + + if 'search' in request.GET and 'value' in request.GET: + bars_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bars + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bars) + bars_list = ps.filter() + bars = [] if len(bars_list) == 0 else bars_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(bars) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(bars, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + free_sale_bar = StewardFreeSaleBarInformation.objects.get(key=request.data['key']) + allow_register_code = AllowRegisterCodeForStewardFreeSaleBarInformation.objects.filter(trash=False, + active=True).first() + if allow_register_code: + if 'register_code' in request.data.keys(): + code = request.data['register_code'] + if code != free_sale_bar.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + free_sale_bar.logged_registration_code = code + free_sale_bar.save() + request.data.pop('register_code') + if free_sale_bar.quota == 'governmental': + if free_sale_bar.steward.total_input_warehouse_governmental_weight < ( + ( + free_sale_bar.steward.total_selling_warehouse_governmental_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if free_sale_bar.steward.total_input_warehouse_free_weight < ( + (free_sale_bar.steward.total_selling_warehouse_free_weight - free_sale_bar.weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + if free_sale_bar.product.total_remain_weight + free_sale_bar.weight_of_carcasses < request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار است!"}, status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(free_sale_bar) + serializer.update(instance=free_sale_bar, validated_data=request.data) + + guild_steward_free_sale_product_warehousing(free_sale_bar.product) + + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + free_sale_bar = StewardFreeSaleBarInformation.objects.get(key=request.GET['key']) + free_sale_bar.trash = True + free_sale_bar.save() + guild_steward_free_sale_product_warehousing(free_sale_bar.product) + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class StewardFreeSaleBarInformationDashboardViewSet(viewsets.ModelViewSet): + queryset = StewardFreeSaleBarInformation.objects.all() + serializer_class = StewardFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filterset_class = StewardFreeSaleBarInformationFilterSet + filterset_fields = [ + 'steward__user__fullname', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__mobile', + 'buyer__user__fullname', + 'buyer__user__first_name', + 'buyer__user__last_name', + 'buyer__user__mobile', + 'province', + 'city', + 'province' + 'buyer_name' + 'buyer_mobile' + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + filters = {'trash': False} + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + steward_key = request.GET.get('steward_key') + + if role == 'Steward': + steward = Guilds.objects.get(user=user, active=True, trash=False) + filters['steward'] = steward + + elif role in ['CityJahad']: + filters['steward__user__city'] = user.city + + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + if steward_key and steward_key != 'all': + filters['steward__key'] = steward_key + + bars = StewardFreeSaleBarInformation.objects.filter(**filters) + if 'search' in request.GET and 'value' in request.GET: + bars_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=bars + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=bars) + bars_list = ps.filter() + bars = [] if len(bars_list) == 0 else bars_list + buyers = len(bars.values_list('buyer', flat=True).distinct()) + + result = { + "number_of_bars": len(bars), + "number_of_buyers": buyers, + "bars_quantity": + bars.aggregate(total=Sum('number_of_carcasses'))['total'] or 0, + "bars_weight": + bars.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0, + + } + + return Response(result, status=status.HTTP_200_OK) + + +class FirstAutomaticStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AutomaticStewardAllocationSerializer + + def create(self, request, *args, **kwargs): + input_date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + one_day_ago = input_date - timedelta(days=1) + # if date_of_now == now: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + kill_house_requests = KillHouseRequest.objects.filter(killhouse_user=kill_house, + province_kill_request__kill_request__recive_date__date=one_day_ago, + trash=False).annotate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight')) + + total_requests_quantity = kill_house_requests.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = kill_house_requests.aggregate(total=Sum('total_weight'))['total'] + + if len(kill_house_requests) == 0: + return Response({"result": "به تاریخ امروز برای شما باری وجود ندارد!"}, + status=status.HTTP_400_BAD_REQUEST) + + date = datetime.now().date() + # date = kill_house_requests.last().create_date + timedelta(days=1) + + ware_house = KillHouseWareHouse.objects.get(kill_house=kill_house, date__date=input_date) + stewards = Steward.objects.filter(guilds__steward=True, trash=False).order_by('id') + stewards_list = [] + allocatated_weight = 0 + kill_house_total_weight = 0 + for steward in stewards: + if steward.centers_allocation != None: + for center_allocation in steward.centers_allocation: + if str(kill_house.key) == center_allocation['value']: + kill_house_total_weight += steward.allocation_limit + stewards_list.append(steward) + if len(stewards_list) > 0: + for steward_list in stewards_list: + allocatated_weight = int( + (steward_list.allocation_limit / kill_house_total_weight) * total_requests_weight) + + auto_allocation = StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='auto', trash=False, + date__date=input_date).first() + + if auto_allocation: + if StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='manual', trash=False, + date__date=input_date).exists(): + + # auto_allocation.delete() + auto_allocation.trash = True + auto_allocation.save() + else: + + auto_allocation.number_of_carcasses = int(allocatated_weight / ( + ware_house.final_total_weight_of_carcasses / ware_house.final_total_number_of_carcasses)) + auto_allocation.real_number_of_carcasses = int(allocatated_weight / ( + ware_house.final_total_weight_of_carcasses / ware_house.final_total_number_of_carcasses)) + auto_allocation.weight_of_carcasses = allocatated_weight + auto_allocation.real_weight_of_carcasses = allocatated_weight + auto_allocation.save() + else: + if not StewardAllocation.objects.filter(steward=steward_list, allocation_state='pending', + kill_house=kill_house, type='manual', trash=False, + date__date=input_date).exists(): + steward_date = datetime(year=date.year, month=date.month, day=date.day, hour=10, + minute=1, second=1) + auto_allocation = StewardAllocation( + kill_house=kill_house, + ware_house=ware_house, + steward=steward_list, + number_of_carcasses=int(allocatated_weight / ( + ware_house.final_total_weight_of_carcasses / ware_house.final_total_number_of_carcasses)), + real_number_of_carcasses=0, + weight_of_carcasses=allocatated_weight, + real_weight_of_carcasses=0, + type='auto', + sell_type='exclusive', + allocation_type='kill_house_broadcast', + seller_type='steward', + date=steward_date + ) + auto_allocation.save() + steward_ware_house = StewardWareHouse.objects.filter(steward=steward_list, + date__date=date).first() + if not steward_ware_house: + steward_ware_house = StewardWareHouse(steward=steward_list, date=steward_date) + steward_ware_house.save() + + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class AutomaticStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AutomaticStewardAllocationSerializer + + def list(self, request, *args, **kwargs): + + kill_house = KillHouse.objects.filter(key=request.GET['kill_house_key']) + date = datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + + auto_allocations = StewardAllocation.objects.filter(date__date=date, kill_house__in=kill_house, + type='auto', trash=False).order_by( + '-real_number_of_carcasses') + serializer = self.serializer_class(auto_allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + + if 'confirm_information' in request.data.keys(): + auto_allocation = StewardAllocation.objects.get(key=request.data['steward_allocation_key']) + request.data.pop('steward_allocation_key') + request.data.pop('confirm_information') + auto_allocation.state = 'accepted' + auto_allocation.save() + serializer = self.serializer_class(auto_allocation) + serializer.update(instance=auto_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + + elif 'send_registration_code' in request.data.keys(): + allocations_list = request.data['steward_allocation_list'] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list, + trash=False) + request.data.pop('steward_allocation_list') + for steward_allocation in steward_allocations: + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.state = 'accepted' + steward_allocation.system_registration_code = True + # steward_allocation.final_registration = True + steward_allocation.save() + steward_ware_house = StewardWareHouse.objects.filter(steward=steward_allocation.steward, + date__date=steward_allocation.date.date()).first() + if not steward_ware_house: + steward_ware_house = StewardWareHouse(steward=steward_allocation.steward, + date=steward_allocation.date) + steward_ware_house.save() + steward_ware_house.bar_quantity += 1 + steward_ware_house.number_of_carcasses += steward_allocation.real_number_of_carcasses + steward_ware_house.weight_of_carcasses += steward_allocation.real_weight_of_carcasses + steward_ware_house.save() + + ware_house = KillHouseWareHouse.objects.get(key=steward_allocation.ware_house.key) + ware_house.allocated_total_number_of_carcasses += steward_allocation.real_number_of_carcasses + ware_house.allocated_total_weight_of_carcasses += steward_allocation.real_weight_of_carcasses + ware_house.save() + + sms_steward_allocations = threading.Thread(target=automatic_steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + auto_allocation = StewardAllocation.objects.get(key=request.data['steward_allocation_key']) + + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != auto_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + auto_allocation.role = { + "role": request.data['role'], + "fullname": user.fullname, + "mobile": user.mobile, + "date_register": str(datetime.now()) + } + request.data.pop('role') + auto_allocation.final_registration = True + auto_allocation.save() + serializer = self.serializer_class(auto_allocation) + serializer.update(instance=auto_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + def create(self, request, *args, **kwargs): + now = datetime.now() + now_time = now.time() + production_date = None + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + + date = datetime(year=date.year, month=date.month, day=date.day, hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + if 'production_date' in request.data.keys(): + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('production_date') + request.data.pop('date') + # if OperationLimitation.objects.all().first().kill_house_steward_guild_allocation_limitation == True: + # if now.date() != date: + # return Response({"result": "به علت مغایرت تاریخ امکان تخصیص وجود ندارد!"}, + # status=status.HTTP_403_FORBIDDEN) + product = None + user = SystemUserProfile.objects.get(user=request.user, trash=False) + seller_type = request.data['seller_type'] + buyer_type = request.data['buyer_type'] + request.data.pop('buyer_type') + if seller_type != 'ColdHouse': + product = RolesProducts.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + + if seller_type == 'KillHouse': + carcass_distribution = RestrictionCarcassDistribution.objects.filter(trash=False, + distribution_type='KillHouse', + allow=True, out=False).first() + if carcass_distribution and datetime.now().time() > carcass_distribution.time: + return Response({"result": "لطفا در ساعات مجاز اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + quota = request.data['quota'] + if not quota: + return Response({"result": "بدون انتخاب سهمیه مجاز به فروش نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if request.data['approved_price_status'] == False: + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_free_weight == 0 and not kill_house.free_sale_from_free_quota_in_province: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + elif seller_type == 'Steward': + carcass_distribution = RestrictionCarcassDistribution.objects.filter(trash=False, + distribution_type='Steward', + allow=True, + out=False).first() + if carcass_distribution and datetime.now().time() > carcass_distribution.time: + return Response({"result": "لطفا در ساعات مجاز اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + + steward = Guilds.objects.filter(user=user, steward=True, trash=False, active=True).first() + quota = request.data['quota'] + if not quota: + return Response({"result": "بدون انتخاب سهمیه مجاز به فروش نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if request.data['approved_price_status'] == False: + if quota == 'governmental': + if not steward.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + if steward.total_input_warehouse_governmental_weight < ( + steward.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward.total_commitment_selling_in_province_free_weight == 0 and not steward.free_sale_from_free_quota_in_province: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if steward.total_input_warehouse_free_weight < ( + steward.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + elif seller_type == 'ColdHouse': + to_cold_house = ColdHouse.objects.get(key=request.data['cold_house_key'], trash=False) + request.data.pop('cold_house_key') + else: + guild = Guilds.objects.filter(user=user, trash=False).first() + + if buyer_type == 'Steward': + to_steward = Guilds.objects.get(key=request.data['steward_key'], trash=False) + request.data.pop('steward_key') + elif buyer_type == 'Guild': + to_guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + + elif buyer_type == 'ColdHouse': + if seller_type == 'ColdHouse': + other_cold_house = ColdHouse.objects.get(key=request.data['other_cold_house_key'], trash=False) + request.data.pop('other_cold_house_key') + else: + to_cold_house = ColdHouse.objects.get(key=request.data['cold_house_key'], trash=False) + request.data.pop('cold_house_key') + else: + to_kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + image = None + if 'image' in request.data.keys(): + image = request.data['image'] + request.data.pop('image') + + if seller_type == 'KillHouse' and buyer_type == 'ColdHouse': + quota = request.data['quota'] + kill_house_total_input_warehouse_governmental_weight = kill_house.total_input_warehouse_governmental_weight + kill_house_total_input_warehouse_free_weight = kill_house.total_input_warehouse_free_weight + if quota == 'governmental': + kill_house_sale_type = request.data['approved_price_status'] + if kill_house.governmental_selling_permission: + if kill_house_sale_type: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_cold_house_governmental_weight > 0: + if kill_house.total_cold_house_governmental_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_cold_house_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_cold_house_free_weight > 0: + if kill_house.total_cold_house_free_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_cold_house_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation = serializer.create(validated_data=request.data) + allow = AllowRegisterCodeForStewardAllocation.objects.filter(trash=False, active=True).first() + if allow: + allocation.active_expire_date_time = True + if image and image != "": + allocation.image = send_image_to_server(image) + allocation.date = date + allocation.dispenser = dispenser if dispenser else None + allocation.representative = representative if representative else None + allocation.production_date = production_date if production_date else date + allocation.real_number_of_carcasses = allocation.number_of_carcasses + allocation.real_weight_of_carcasses = int(allocation.weight_of_carcasses) + allocation.weight_of_carcasses = int(request.data['weight_of_carcasses']) + allocation.product = product + if seller_type == 'KillHouse': + allocation.kill_house = kill_house + + elif seller_type == 'Steward': + allocation.steward = steward + + elif seller_type == 'ColdHouse': + allocation.to_cold_house = to_cold_house + + + else: + allocation.guilds = guild + + if buyer_type == 'Steward': + allocation.to_steward = to_steward + elif buyer_type == 'Guild': + allocation.to_guilds = to_guild + + elif buyer_type == 'ColdHouse': + if seller_type == 'ColdHouse': + allocation.other_cold_house = other_cold_house + else: + allocation.to_cold_house = to_cold_house + + else: + allocation.to_kill_house = to_kill_house + + allocation.save() + + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + if buyer_type == 'ColdHouse' and to_cold_house.kill_house: + allocation.receiver_state = 'accepted' + allocation.system_registration_code = True + allocation.registration_code = 0 + allocation.save() + kill_house_cold_house_allocations(to_cold_house) + + elif seller_type == 'ColdHouse': + cold_house_warehousing(to_cold_house) + if buyer_type == 'ColdHouse': + allocation.receiver_state = 'accepted' + allocation.system_registration_code = True + allocation.registration_code = 0 + allocation.save() + cold_house_warehousing(other_cold_house) + + + else: + guild_steward_allocations_product_warehousing(product) + return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if 'steward' in request.data.keys() or 'guild' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + elif 'check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + receiver_real_weight_of_carcasses = int(request.data['receiver_real_weight_of_carcasses']) + weight_loss_of_carcasses = 0 + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + if 'weight_loss_of_carcasses' in request.data.keys(): + weight_loss_of_carcasses = request.data['weight_loss_of_carcasses'] + maximum_weight_limit = int(request.data['receiver_real_weight_of_carcasses']) * 0.07 + if weight_loss_of_carcasses > maximum_weight_limit: + return Response({"result": "افت وزن وارد شده بیشتر از حد مجاز است!"}, + status=status.HTTP_403_FORBIDDEN) + + receiver_real_weight_of_carcasses -= weight_loss_of_carcasses + steward_allocation.weight_loss_of_carcasses = weight_loss_of_carcasses + + steward_allocation.receiver_real_number_of_carcasses = receiver_real_number_of_carcasses + steward_allocation.receiver_real_weight_of_carcasses = receiver_real_weight_of_carcasses + steward_allocation.real_number_of_carcasses = receiver_real_number_of_carcasses + steward_allocation.real_weight_of_carcasses = receiver_real_weight_of_carcasses + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'steward_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'guild_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'allocation_key' in request.data.keys() and 'logged_registration_code' not in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], trash=False) + if steward_allocation.receiver_state == 'accepted': + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guildso, trash=False, + parent_product=steward_allocation.product.parent_product) + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, trash=False, + parent_product=steward_allocation.product.parent_product) + + + elif steward_allocation.to_kill_house: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, trash=False, + parent_product=steward_allocation.product.parent_product) + else: + buyer_product = None + + if buyer_product: + if buyer_product.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.to_cold_house: + if steward_allocation.other_cold_house: + if steward_allocation.other_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.to_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + if steward_allocation.product: + if steward_allocation.product.kill_house: + if steward_allocation.quota == 'governmental': + if steward_allocation.product.kill_house.total_input_warehouse_governmental_weight < ( + ( + steward_allocation.product.kill_house.total_selling_warehouse_governmental_weight - steward_allocation.real_weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.product.kill_house.total_input_warehouse_free_weight < ( + ( + steward_allocation.product.kill_house.total_selling_warehouse_free_weight - steward_allocation.real_weight_of_carcasses) + + request.data['weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.quota == 'governmental': + if steward_allocation.product.guild.total_input_warehouse_governmental_weight < ( + ( + steward_allocation.product.guild.total_selling_warehouse_governmental_weight - steward_allocation.real_weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.product.guild.total_input_warehouse_free_weight < ( + ( + steward_allocation.product.guild.total_selling_warehouse_free_weight - steward_allocation.real_weight_of_carcasses) + + request.data['weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + if steward_allocation.product.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار است!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.to_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + if steward_allocation.to_cold_house: + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + else: + + steward_allocation.real_number_of_carcasses = request.data['number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + steward_allocation.save() + seller_product = steward_allocation.product + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + if steward_allocation.to_cold_house and steward_allocation.to_cold_house.kill_house == steward_allocation.kill_house: + kill_house_cold_house_allocations(steward_allocation.to_cold_house) + + elif steward_allocation.seller_type == 'ColdHouse': + cold_house_warehousing(steward_allocation.to_cold_house) + if steward_allocation.other_cold_house: + cold_house_warehousing(steward_allocation.other_cold_house) + + else: + guild_steward_allocations_product_warehousing(seller_product) + if 'image' in request.data.keys(): + image = request.data['image'] + request.data.pop('image') + if image: + steward_allocation.image = send_image_to_server(image) + steward_allocation.save() + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'steward_allocation_list' in request.data.keys(): + allocations_list_temp = request.data['steward_allocation_list'] + allocations_list = [] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list_temp, + trash=False) + request.data.pop('steward_allocation_list') + for steward_allocation in steward_allocations: + if steward_allocation.system_registration_code == True: + continue + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.system_registration_code = True + allocations_list.append(str(steward_allocation.key)) + steward_allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).select_related('ware_house__kill_house', + 'ware_house__kill_house__kill_house_operator__user').last() + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + steward_allocation.role = { + "role": request.data['role'], + "fullname": user.fullname, + "mobile": user.mobile, + "date_register": str(datetime.now()) + } + if 'logged_registration_code' in request.data.keys(): + steward_allocation.state = 'accepted' + steward_allocation.receiver_state = 'accepted' + steward_allocation.receiver_real_weight_of_carcasses = steward_allocation.real_weight_of_carcasses + steward_allocation.receiver_real_number_of_carcasses = steward_allocation.real_number_of_carcasses + steward_allocation.save() + steward_guild = steward_allocation.to_guilds if steward_allocation.to_guilds else steward_allocation.to_steward + if steward_guild: + buyer_product = RolesProducts.objects.get(guild=steward_guild, trash=False, + parent_product=steward_allocation.product.parent_product) + guild_steward_allocations_product_warehousing(buyer_product) + + request.data.pop('role') + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allocations = [] + allocations_list = [] + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + allocations_type = request.GET.get('type') + if 'role' in request.GET: + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'type' in request.GET: + if request.GET['type'] == 'input': + allocations = StewardAllocation.objects.filter( + Q(to_cold_house=cold_house, kill_house__isnull=False) | Q( + other_cold_house=cold_house, + kill_house__isnull=True), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-id', + '-date') + else: + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=True, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-id', + '-date') + else: + allocations = StewardAllocation.objects.filter( + Q(to_cold_house=cold_house) | Q(other_cold_house=cold_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-id', '-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-id', '-date') + else: + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + if 'type' in request.GET: + if request.GET['type'] == 'input': + allocations = StewardAllocation.objects.filter( + Q(to_cold_house=cold_house, kill_house__isnull=False) | Q( + other_cold_house=cold_house, + kill_house__isnull=True), + trash=False).order_by('-id', '-date') + + else: + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=True, + trash=False).order_by('-id', '-date') + else: + + allocations = StewardAllocation.objects.filter( + Q(to_cold_house=cold_house) | Q(other_cold_house=cold_house), + trash=False).order_by('-id', '-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + + # kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, date__date=date).last() + # allocations = StewardAllocation.objects.filter( + # Q(type='manual') | Q(type='auto', + # system_registration_code=True), + # kill_house=kill_house, trash=False, + # date__date=date).order_by('id') + elif request.GET['role'] == 'Steward': + guild = Guilds.objects.get(user=user, active=True, trash=False) + if allocations_type: + if allocations_type == 'not_entered': + receiver_state = 'pending' + elif allocations_type == 'all': + receiver_state = ('pending', 'accepted') + else: + receiver_state = 'accepted' + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if allocations_type == 'all': + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + date__date__gte=date1, date__date__lte=date2, + trash=False, system_registration_code=True, + receiver_state__in=receiver_state + ).order_by('-id', '-date') + else: + + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + date__date__gte=date1, date__date__lte=date2, + trash=False, system_registration_code=True, + receiver_state=receiver_state + ).order_by('-id', '-date') + else: + + if allocations_type == 'all': + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + trash=False, + system_registration_code=True, + receiver_state__in=receiver_state + ).order_by('-id', '-date') + else: + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + trash=False, + system_registration_code=True, + receiver_state=receiver_state + ).order_by('-id', '-date') + + else: + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + allocations = StewardAllocation.objects.filter(Q(steward=guild) | Q(guilds=guild), + date__date__gte=date1, date__date__lte=date2, + trash=False, + ).order_by('-id', '-date') + else: + + allocations = StewardAllocation.objects.filter(Q(steward=guild) | Q(guilds=guild), + trash=False, + ).order_by('-id', '-date') + + elif 'guild' in request.GET: + guild = Guilds.objects.get(user=user, active=True, trash=False) + allocations = StewardAllocation.objects.filter( + Q(allocation_type='steward_broadcast') | Q(allocation_type='kill_house_broadcast'), guilds=guild, + trash=False, system_registration_code=True).order_by('-date') + + elif 'steward_guilds_allocations' in request.GET: + steward = Steward.objects.get(guilds__user=user, active=True, trash=False) + steward_ware_house = StewardWareHouse.objects.get(date__date=date, steward=steward, trash=False) + + allocations = StewardAllocation.objects.filter(steward_ware_house__steward=steward, trash=False, + steward_ware_house=steward_ware_house, + date__date=date).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = StewardAllocationSerializer(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = StewardAllocation.objects.get(key=request.GET["steward_allocation_key"]) + if allocation.receiver_state == 'accepted': + if allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=allocation.to_steward, trash=False, + parent_product=allocation.product.parent_product) + elif allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=allocation.to_guilds, trash=False, + parent_product=allocation.product.parent_product) + + + elif allocation.to_kill_house: + buyer_product = RolesProducts.objects.get(kill_house=allocation.to_kill_house, trash=False, + parent_product=allocation.product.parent_product) + + else: + buyer_product = None + + if buyer_product: + if buyer_product.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن حذف شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if allocation.to_cold_house: + if allocation.other_cold_house: + if allocation.other_cold_house.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if allocation.to_cold_house.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + product = allocation.product + seller_type = allocation.seller_type + to_cold_house = allocation.to_cold_house + other_cold_house = allocation.other_cold_house if allocation.other_cold_house else None + allocation.delete() + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + if to_cold_house and to_cold_house.kill_house == product.kill_house: + kill_house_cold_house_allocations(to_cold_house) + + elif seller_type == 'ColdHouse': + cold_house_warehousing(to_cold_house) + if other_cold_house: + cold_house_warehousing(other_cold_house) + + + else: + guild_steward_allocations_product_warehousing(product) + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class InProvinceAllocationDashboardViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + filterset_class = StewardAllocationDashboardFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + value = request.GET.get('value') + search = request.GET.get('search') + trash = request.GET.get('trash') + return_trash = request.GET.get('return_trash') + kill_house_key = request.GET.get('kill_house_key') + steward_key = request.GET.get('steward_key') + + allocations_type = request.GET.get('type') + filters = { + 'to_cold_house__isnull': True, + 'calculate_status': True, + } + if trash == 'true': + filters['trash'] = True + filters['active_expire_date_time'] = True + else: + filters['trash'] = False + + if return_trash == 'true': + filters['return_trash'] = True + + if allocations_type == 'KillHouse': + filters['kill_house__isnull'] = False + elif allocations_type == 'Steward': + filters['steward__isnull'] = False + + if kill_house_key and kill_house_key != 'all': + filters['kill_house__key'] = kill_house_key + if steward_key and steward_key != 'all': + filters['steward__key'] = steward_key + + if date1: + filters['date__date__gte'] = datetime.strptime(str(date1), '%Y-%m-%d').date() + filters['date__date__lte'] = datetime.strptime(str(date2), '%Y-%m-%d').date() + + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + filters['kill_house'] = kill_house + elif role == 'Steward': + steward = Guilds.objects.get(user=user, trash=False) + filters['steward'] = steward + elif role in ['CityJahad']: + if allocations_type == 'KillHouse': + filters['kill_house__kill_house_operator__user__city'] = user.city + else: + filters['steward__user__city'] = user.city + + allocations = StewardAllocation.objects.filter(**filters) + if value and search == 'filter': + if value != 'undefined' and value.strip(): + allocations = allocations.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + allocations_aggregates = allocations.aggregate( + total_count=Count('id', receiver_state__in=('pending', 'accepted')), + total_weight=Sum('real_weight_of_carcasses', filter=Q(receiver_state__in=('pending', 'accepted'))), + total_steward_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state__in=('pending', 'accepted'))), + total_guild_weight=Sum('real_weight_of_carcasses', + filter=Q(to_guilds__isnull=False, receiver_state__in=('pending', 'accepted'))), + ) + + result = { + "number_of_allocations": allocations_aggregates['total_count'] or 0, + "total_weight": int(allocations_aggregates['total_weight'] or 0), + "total_steward_weight": int(allocations_aggregates['total_steward_weight'] or 0), + "total_guild_weight": int(allocations_aggregates['total_guild_weight'] or 0), + } + + return Response(result, status=status.HTTP_200_OK) + + +class TotalStewardDashboardViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + filterset_class = StewardAllocationDashboardFilterSet + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + stewards_filter = {'trash': False, 'steward': True, 'active': True} + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role in ['CityJahad']: + stewards_filter['user__city'] = user.city + stewards = Guilds.objects.filter(**stewards_filter).select_related('user').only('user', 'guilds_name', + 'steward').order_by( + 'id') + + products = RolesProducts.objects.filter(guild__in=stewards, trash=False, name='مرغ گرم').first() + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, allocation_to_steward__date__date__lte=date2, + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True, + date__date__gte=date1, date__date__lte=date2, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False, + date__date__gte=date1, + date__date__lte=date2, warehouse=True) + segmentations = PosSegmentation.objects.filter(guild__in=stewards, trash=False, warehouse=True, + date__date__gte=date1, date__date__lte=date2) + transactions = ProductsTransactions.objects.filter(product=products, transaction__paid=True, + transaction__date__date__gte=date1, + transaction__date__date__lte=date2, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward__in=stewards) | Q(guild__in=stewards), trash=False, + date__date__gte=date1, date__lte=date2, + warehouse=True) + + + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count').values_list('id', flat=True) + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count').values_list('id', flat=True) + + stewards = (list(chain(allocation_stewards, free_bar_stewards))) + + allocations = StewardAllocation.objects.filter( + Q(steward__in=stewards) | Q(to_steward__in=stewards), + trash=False, calculate_status=True, to_cold_house__isnull=True, warehouse=True, steward_warehouse=True) + + free_bars = StewardFreeBarInformation.objects.filter(steward__in=stewards, trash=False, warehouse=True) + free_sale_bars = StewardFreeSaleBarInformation.objects.filter(steward__in=stewards, trash=False, + warehouse=True) + segmentations = PosSegmentation.objects.filter(guild__in=stewards, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=products, transaction__paid=True, trash=False, + warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward__in=stewards) | Q(guild__in=stewards), trash=False, + warehouse=True) + + allocations_aggregates = allocations.aggregate( + total_input_bars_count=Count('id', filter=Q(to_steward__isnull=False)), + total_input_bars_weight=Sum('real_weight_of_carcasses', filter=Q(to_steward__isnull=False)), + total_input_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, quota='governmental')), + total_input_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, quota='free')), + total_output_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, receiver_state__in=('pending', 'accepted'))), + total_output_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, + receiver_state__in=('pending', 'accepted'), + quota='governmental')), + total_output_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(steward__isnull=False, + receiver_state__in=('pending', 'accepted'), quota='free')), + total_input_entered_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state='accepted')), + + total_input_entered_governmental_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, + receiver_state='accepted', quota='governmental')), + + total_input_entered_free_bars_weight=Sum('real_weight_of_carcasses', + filter=Q(to_steward__isnull=False, receiver_state='accepted', + quota='free')), + + ) + + free_bars_aggregates = free_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses') + ) + + free_sale_bars_aggregates = free_sale_bars.aggregate( + total_count=Count('id'), + total_weight=Sum('weight_of_carcasses'), + total_governmental_weight=Sum('weight_of_carcasses', quota='governmental'), + total_free_weight=Sum('weight_of_carcasses', quota='free'), + + ) + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_weight=Sum('weight'), + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + + total_in_province_governmental_input_weight = allocations_aggregates[ + 'total_input_entered_governmental_bars_weight'] or 0 + total_in_province_free_input_weight = allocations_aggregates['total_input_entered_free_bars_weight'] or 0 + total_free_buying_input_weight = free_bars_aggregates['total_weight'] or 0 + + total_in_province_governmental_output_weight = allocations_aggregates[ + 'total_output_governmental_bars_weight'] or 0 + total_in_province_free_output_weight = allocations_aggregates['total_output_free_bars_weight'] or 0 + total_governmental_free_sale_weight = free_sale_bars_aggregates['total_governmental_weight'] or 0 + total_free_free_sale_weight = free_sale_bars_aggregates['total_free_weight'] or 0 + archives_weight = archives_info['archives_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_governmental_input_weight = total_in_province_governmental_input_weight + total_free_input_weight = total_in_province_free_input_weight + total_free_buying_input_weight + total_input_weight = total_governmental_input_weight + total_free_input_weight + + total_governmental_output_weight = total_in_province_governmental_output_weight + total_governmental_free_sale_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_in_province_free_output_weight + total_free_free_sale_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + total_output_weight = total_governmental_output_weight + total_free_output_weight + + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight if ( + ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight) > 0 else 0 + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - archives_free_weight if ( + ( + total_free_input_weight - total_free_output_weight) - archives_free_weight) > 0 else 0 + total_remain_weight = total_governmental_remain_weight + total_free_remain_weight + + input_allocations_weight = allocations_aggregates['total_input_bars_weight'] or 0 + input_entered_allocations_weight = allocations_aggregates['total_input_entered_bars_weight'] or 0 + output_allocations_weight = allocations_aggregates['total_output_bars_weight'] or 0 + free_bars_weight = free_bars_aggregates['total_weight'] or 0 + free_sale_bars_weight = free_sale_bars_aggregates['total_weight'] or 0 + remain_weight = int( + (input_entered_allocations_weight + free_bars_weight) - ( + free_sale_bars_weight + output_allocations_weight + archives_weight)) + + result = { + "total_bars_weight": int(input_allocations_weight + free_bars_weight), + "total_entered_bars_weight": int(input_entered_allocations_weight + free_bars_weight), + "in_province_bars_weight": int(output_allocations_weight), + "out_province_bars_weight": int(free_sale_bars_weight), + "remain_weight": remain_weight, + "total_governmental_input_weight": total_governmental_input_weight, + "total_free_input_weight": total_free_input_weight, + "total_input_weight": total_input_weight, + "total_governmental_output_weight": total_governmental_output_weight, + "total_free_output_weight": total_free_output_weight, + "total_output_weight": total_output_weight, + "total_governmental_remain_weight": total_governmental_remain_weight, + "total_free_remain_weight": total_free_remain_weight, + "total_remain_weight": total_remain_weight, + "segmentations_weight": segmentations_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "archives_weight": archives_weight, + "archives_governmental_weight": archives_governmental_weight, + "archives_free_weight": archives_free_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class TotalStewardDashboarDetailViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = RealGuildsForDashboardSerializer + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + stewards_filter = {'trash': False, 'steward': True, 'active': True} + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role in ['CityJahad']: + stewards_filter['user__city'] = user.city + + stewards = Guilds.objects.filter(**stewards_filter).select_related('user').only('user', 'guilds_name', + 'steward').order_by( + 'id') + + if date1: + date1 = datetime.strptime(str(date1), '%Y-%m-%d').date() + date2 = datetime.strptime(str(date2), '%Y-%m-%d').date() + + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__date__date__gte=date1, allocation_to_steward__date__date__lte=date2, + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards = list(set(chain(allocation_stewards, free_bar_stewards))) + + else: + allocation_stewards = stewards.annotate( + allocation_count=Count( + 'allocation_to_steward', + filter=Q(allocation_to_steward__receiver_state__in=['pending', 'accepted'], + allocation_to_steward__warehouse=True, allocation_to_steward__steward_warehouse=True) + ) + ).filter(allocation_count__gt=0).order_by('-allocation_count') + + free_bar_stewards = stewards.annotate( + free_bar_count=Count( + 'free_bar_info_steward' + ) + ).filter(free_bar_count__gt=0).order_by('-free_bar_count') + + stewards = list(set(chain(allocation_stewards, free_bar_stewards))) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(stewards) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + +class InProvinceAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = InProvinceAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = StewardAllocationDashboardFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + value = request.GET.get('value') + search = request.GET.get('search') + kill_house_key = request.GET.get('kill_house_key') + steward_key = request.GET.get('steward_key') + allocations_type = request.GET.get('type') + trash = request.GET.get('trash') + return_trash = request.GET.get('return_trash') + filters = { + 'to_cold_house__isnull': True, + 'calculate_status': True, + } + if trash == 'true': + filters['trash'] = True + filters['active_expire_date_time'] = True + else: + filters['trash'] = False + + if return_trash == 'true': + filters['return_trash'] = True + + if allocations_type == 'KillHouse': + filters['kill_house__isnull'] = False + elif allocations_type == 'Steward': + filters['steward__isnull'] = False + + if kill_house_key and kill_house_key != 'all': + filters['kill_house__key'] = kill_house_key + if steward_key and steward_key != 'all': + filters['steward__key'] = steward_key + + if date1: + filters['date__date__gte'] = datetime.strptime(str(date1), '%Y-%m-%d').date() + filters['date__date__lte'] = datetime.strptime(str(date2), '%Y-%m-%d').date() + + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + filters['kill_house'] = kill_house + elif role == 'Steward': + steward = Guilds.objects.get(user=user, trash=False) + filters['steward'] = steward + + elif role in ['CityJahad']: + if allocations_type == 'KillHouse': + filters['kill_house__kill_house_operator__user__city'] = user.city + else: + filters['steward__user__city'] = user.city + allocations = StewardAllocation.objects.filter(**filters).order_by('-date') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + allocations = allocations.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + # return self.get_paginated_response(serializer.data) + + +class BatchStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + def create(self, request, *args, **kwargs): + + # houre = datetime.now().time() + # allocations_list = request.data['allocations_list'] + # + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # + # main_seller_type = allocations_list[0]['seller_type'] + # product = RolesProducts.objects.get(key=allocations_list[0]['product_key']) + # + # if main_seller_type == 'KillHouse': + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # elif main_seller_type == 'Steward': + # steward = Guilds.objects.filter(user=user, steward=True, trash=False).first() + # elif main_seller_type == 'ColdHouse': + # to_cold_house = ColdHouse.objects.get(key=allocations_list[0]['cold_house_key'], trash=False) + # else: + # guild = Guilds.objects.filter(user=user, trash=False).first() + # + # allocation_instances = [] + # + # for allocation_obj in allocations_list: + # date = datetime.strptime(str(allocation_obj['date']), '%Y-%m-%d').date() + # full_date = datetime(year=date.year, month=date.month, day=date.day, + # hour=houre.hour, minute=houre.minute, second=houre.second) + # seller_type = allocation_obj['seller_type'] + # buyer_type = allocation_obj['buyer_type'] + # + # if seller_type == 'KillHouse': + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # elif seller_type == 'Steward': + # steward = Guilds.objects.filter(user=user, steward=True, trash=False).first() + # elif seller_type == 'ColdHouse': + # to_cold_house = ColdHouse.objects.get(key=allocation_obj['cold_house_key'], trash=False) + # else: + # guild = Guilds.objects.filter(user=user, trash=False).first() + # + # if buyer_type == 'Steward': + # to_steward = Guilds.objects.get(key=allocation_obj['steward_key'], trash=False) + # elif buyer_type == 'Guild': + # to_guild = Guilds.objects.get(key=allocation_obj['guild_key'], trash=False) + # elif buyer_type == 'ColdHouse': + # to_cold_house = ColdHouse.objects.get(key=allocation_obj['cold_house_key'], trash=False) + # else: + # to_kill_house = KillHouse.objects.get(key=allocation_obj['kill_house_key'], trash=False) + # + # allocation_obj.pop('date', None) + # allocation_obj.pop('product_key', None) + # allocation_obj.pop('steward_key', None) + # allocation_obj.pop('guild_key', None) + # allocation_obj.pop('kill_house_key', None) + # allocation_obj.pop('cold_house_key', None) + # image = None + # if 'image' in allocation_obj.keys() and allocation_obj['image']: + # image = allocation_obj['image'] + # allocation_obj.pop('image', None) + # serializer = self.serializer_class(data=allocation_obj) + # serializer.is_valid(raise_exception=True) + # allocation = StewardAllocation(**serializer.validated_data) + # if image: + # ran = ''.join(random.choices(string.ascii_uppercase + string.digits, k=15)) + # upload_object_resize(image_data=image, bucket_name="profileimagedefault", + # object_name="{0}.jpg".format(str(ran))) + # + # allocation.image = ARVAN_Kill_house_URL + "{0}.jpg".format(str(ran)) + # + # allocation.date = full_date + # allocation.real_number_of_carcasses = allocation.number_of_carcasses + # allocation.real_weight_of_carcasses = int(allocation.weight_of_carcasses) + # + # if seller_type == 'KillHouse': + # allocation.kill_house = kill_house + # elif seller_type == 'Steward': + # allocation.steward = steward + # elif seller_type == 'ColdHouse': + # allocation.to_cold_house = to_cold_house + # else: + # allocation.guilds = guild + # + # if buyer_type == 'Steward': + # allocation.to_steward = to_steward + # elif buyer_type == 'Guild': + # allocation.to_guilds = to_guild + # elif buyer_type == 'ColdHouse': + # allocation.to_cold_house = to_cold_house + # else: + # allocation.to_kill_house = to_kill_house + # + # if product: + # allocation.product = product + # + # allocation_instances.append(allocation) + # + # StewardAllocation.objects.bulk_create(allocation_instances) + # + # if main_seller_type == 'KillHouse': + # kill_house_allocations_product_warehousing(product) + # elif main_seller_type == 'ColdHouse': + # cold_house_warehousing(to_cold_house) + # else: + # guild_steward_allocations_product_warehousing(product) + + # return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + return Response({"result": "امکان ثبت بصورت موقت غیر فعال می باشد!"}, status=status.HTTP_201_CREATED) + + # houre = datetime.now().time() + # allocations_list=request.data['allocations_list'] + # for allocation_obj in allocations_list: + # date = datetime.strptime(str(allocation_obj['date']), '%Y-%m-%d').date() + # date = datetime(year=date.year, month=date.month, day=date.day, hour=houre.hour, + # minute=houre.minute, + # second=houre.second) + # allocation_obj.pop('date') + # # if OperationLimitation.objects.all().first().kill_house_steward_guild_allocation_limitation == True: + # # if now.date() != date: + # # return Response({"result": "به علت مغایرت تاریخ امکان تخصیص وجود ندارد!"}, + # # status=status.HTTP_403_FORBIDDEN) + # product = None + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # seller_type = allocation_obj['seller_type'] + # buyer_type = allocation_obj['buyer_type'] + # allocation_obj.pop('buyer_type') + # if seller_type != 'ColdHouse': + # product = RolesProducts.objects.get(key=allocation_obj['product_key']) + # allocation_obj.pop('product_key') + # + # if seller_type == 'KillHouse': + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # + # elif seller_type == 'Steward': + # steward = Guilds.objects.filter(user=user, steward=True, trash=False).first() + # + # elif seller_type == 'ColdHouse': + # to_cold_house = ColdHouse.objects.get(key=allocation_obj['cold_house_key'], trash=False) + # allocation_obj.pop('cold_house_key') + # else: + # guild = Guilds.objects.filter(user=user, trash=False).first() + # + # if buyer_type == 'Steward': + # to_steward = Guilds.objects.get(key=allocation_obj['steward_key'], trash=False) + # allocation_obj.pop('steward_key') + # elif buyer_type == 'Guild': + # to_guild = Guilds.objects.get(key=allocation_obj['guild_key'], trash=False) + # allocation_obj.pop('guild_key') + # + # elif buyer_type == 'ColdHouse': + # to_cold_house = ColdHouse.objects.get(key=allocation_obj['cold_house_key'], trash=False) + # allocation_obj.pop('cold_house_key') + # else: + # to_kill_house = KillHouse.objects.get(key=allocation_obj['kill_house_key'], trash=False) + # allocation_obj.pop('kill_house_key') + # + # serializer = self.serializer_class(data=allocation_obj) + # if serializer.is_valid(): + # allocation = serializer.create(validated_data=serializer.validated_data) + # allocation.date = date + # allocation.real_number_of_carcasses = allocation.number_of_carcasses + # allocation.real_weight_of_carcasses = int(allocation.weight_of_carcasses) + # allocation.weight_of_carcasses = int(allocation_obj['weight_of_carcasses']) + # allocation.product = product + # if seller_type == 'KillHouse': + # allocation.kill_house = kill_house + # + # elif seller_type == 'Steward': + # allocation.steward = steward + # + # elif seller_type == 'ColdHouse': + # allocation.to_cold_house = to_cold_house + # + # + # else: + # allocation.guilds = guild + # + # if buyer_type == 'Steward': + # allocation.to_steward = to_steward + # elif buyer_type == 'Guild': + # allocation.to_guilds = to_guild + # + # elif buyer_type == 'ColdHouse': + # allocation.to_cold_house = to_cold_house + # + # else: + # allocation.to_kill_house = to_kill_house + # + # allocation.save() + # + # if seller_type == 'KillHouse': + # kill_house_allocations_product_warehousing(product) + # if buyer_type == 'ColdHouse' and to_cold_house.kill_house: + # allocation.receiver_state = 'accepted' + # allocation.system_registration_code = True + # allocation.registration_code = 0 + # allocation.save() + # kill_house_cold_house_allocations(to_cold_house) + # + # elif seller_type == 'ColdHouse': + # cold_house_warehousing(to_cold_house) + # + # else: + # guild_steward_allocations_product_warehousing(product) + # return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if 'steward' in request.data.keys() or 'guild' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + elif 'check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + receiver_real_weight_of_carcasses = int(request.data['receiver_real_weight_of_carcasses']) + weight_loss_of_carcasses = 0 + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + if 'weight_loss_of_carcasses' in request.data.keys(): + weight_loss_of_carcasses = request.data['weight_loss_of_carcasses'] + maximum_weight_limit = int(request.data['receiver_real_weight_of_carcasses']) * 0.07 + if weight_loss_of_carcasses > maximum_weight_limit: + return Response({"result": "افت وزن وارد شده بیشتر از حد مجاز است!"}, + status=status.HTTP_403_FORBIDDEN) + + receiver_real_weight_of_carcasses -= weight_loss_of_carcasses + steward_allocation.weight_loss_of_carcasses = weight_loss_of_carcasses + + steward_allocation.receiver_real_number_of_carcasses = receiver_real_number_of_carcasses + steward_allocation.receiver_real_weight_of_carcasses = receiver_real_weight_of_carcasses + steward_allocation.real_number_of_carcasses = receiver_real_number_of_carcasses + steward_allocation.real_weight_of_carcasses = receiver_real_weight_of_carcasses + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'steward_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'guild_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'allocation_key' in request.data.keys() and 'logged_registration_code' not in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], trash=False) + if steward_allocation.to_cold_house: + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + else: + + steward_allocation.real_number_of_carcasses = request.data['number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + steward_allocation.save() + seller_product = steward_allocation.product + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + if steward_allocation.to_cold_house and steward_allocation.to_cold_house.kill_house == steward_allocation.kill_house: + kill_house_cold_house_allocations(steward_allocation.to_cold_house) + + elif steward_allocation.seller_type == 'ColdHouse': + cold_house_warehousing(steward_allocation.to_cold_house) + + else: + guild_steward_allocations_product_warehousing(seller_product) + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'steward_allocation_list' in request.data.keys(): + allocations_list_temp = request.data['steward_allocation_list'] + allocations_list = [] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list_temp, + trash=False) + request.data.pop('steward_allocation_list') + for steward_allocation in steward_allocations: + if steward_allocation.system_registration_code == True: + continue + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.system_registration_code = True + allocations_list.append(str(steward_allocation.key)) + steward_allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).select_related('ware_house__kill_house', + 'ware_house__kill_house__kill_house_operator__user').last() + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + steward_allocation.role = { + "role": request.data['role'], + "fullname": user.fullname, + "mobile": user.mobile, + "date_register": str(datetime.now()) + } + if 'logged_registration_code' in request.data.keys(): + steward_allocation.state = 'accepted' + steward_allocation.save() + request.data.pop('role') + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allocations = [] + allocations_list = [] + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + allocations_type = request.GET.get('type') + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + if 'type' in request.GET: + if request.GET['type'] == 'input': + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=False, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + else: + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=True, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + else: + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('id') + else: + if 'cold_house' in request.GET: + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + if 'type' in request.GET: + if request.GET['type'] == 'input': + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=False, + trash=False).order_by('-date') + else: + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + kill_house__isnull=True, + trash=False).order_by('-date') + else: + + allocations = StewardAllocation.objects.filter(to_cold_house=cold_house, + trash=False).order_by('-date') + + else: + allocations = StewardAllocation.objects.filter( + Q(kill_house=kill_house) | Q(to_kill_house=kill_house), + trash=False).order_by('id') + + # kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, date__date=date).last() + # allocations = StewardAllocation.objects.filter( + # Q(type='manual') | Q(type='auto', + # system_registration_code=True), + # kill_house=kill_house, trash=False, + # date__date=date).order_by('id') + elif request.GET['role'] == 'Steward': + guild = Guilds.objects.get(user=user, trash=False) + if allocations_type: + receiver_state = 'pending' if allocations_type == 'not_entered' else 'accepted' + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + date__date__gte=date1, date__date__lte=date2, + trash=False, system_registration_code=True, + receiver_state=receiver_state + ).order_by('-date') + else: + + allocations = StewardAllocation.objects.filter(Q(to_steward=guild) | Q(to_guilds=guild), + trash=False, + system_registration_code=True, + receiver_state=receiver_state + ).order_by('-date') + + else: + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + allocations = StewardAllocation.objects.filter(Q(steward=guild) | Q(guilds=guild), + date__date__gte=date1, date__date__lte=date2, + trash=False, + ).order_by('-date') + else: + + allocations = StewardAllocation.objects.filter(Q(steward=guild) | Q(guilds=guild), + trash=False, + ).order_by('-date') + + elif 'guild' in request.GET: + guild = Guilds.objects.get(user=user, trash=False) + allocations = StewardAllocation.objects.filter( + Q(allocation_type='steward_broadcast') | Q(allocation_type='kill_house_broadcast'), guilds=guild, + trash=False, system_registration_code=True).order_by('-date') + + elif 'steward_guilds_allocations' in request.GET: + steward = Steward.objects.get(guilds__user=user, trash=False) + steward_ware_house = StewardWareHouse.objects.get(date__date=date, steward=steward, trash=False) + + allocations = StewardAllocation.objects.filter(steward_ware_house__steward=steward, trash=False, + steward_ware_house=steward_ware_house, + date__date=date).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = StewardAllocationSerializer(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = StewardAllocation.objects.get(key=request.GET["steward_allocation_key"]) + product = allocation.product + seller_type = allocation.seller_type + to_cold_house = allocation.to_cold_house + allocation.delete() + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + if to_cold_house and to_cold_house.kill_house == product.kill_house: + kill_house_cold_house_allocations(to_cold_house) + + elif seller_type == 'ColdHouse': + cold_house_warehousing(to_cold_house) + + + else: + guild_steward_allocations_product_warehousing(product) + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class PosStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [AllowAny] + serializer_class = PosStewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'guilds__guilds_name', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'steward__guilds_name', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_guilds__guilds_name', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_steward__guilds_name', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + def create(self, request, *args, **kwargs): + # validation_response = validate_headers(request) + # if validation_response: + # return validation_response + now = datetime.now() + pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False) + product = RolesProducts.objects.get(key=request.data['product_key']) + seller_type = request.data['seller_type'] + buyer_type = request.data['buyer_type'] + request.data.pop('buyer_type') + request.data.pop('product_key') + request.data.pop('pos-id') + + if seller_type == 'KillHouse': + kill_house = pos.kill_house + + elif seller_type == 'Steward': + steward = pos.guild + + else: + guild = pos.guild + + if buyer_type == 'Steward': + to_steward = Guilds.objects.get(key=request.data['steward_key'], trash=False) + request.data.pop('steward_key') + elif buyer_type == 'Guild': + to_guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + else: + to_kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation = serializer.create(validated_data=request.data) + allocation.date = now + allocation.allocation_type = allocation.allocation_type.lower() + allocation.real_number_of_carcasses = allocation.number_of_carcasses + allocation.real_weight_of_carcasses = int(allocation.weight_of_carcasses) + allocation.weight_of_carcasses = int(request.data['weight_of_carcasses']) + # allocation.real_weight_of_carcasses = allocation.weight_of_carcasses + allocation.product = product + if seller_type == 'KillHouse': + allocation.kill_house = kill_house + + elif seller_type == 'Steward': + allocation.steward = steward + + else: + allocation.guilds = guild + + if buyer_type == 'Steward': + allocation.to_steward = to_steward + elif buyer_type == 'Guild': + allocation.to_guilds = to_guild + else: + allocation.to_kill_house = to_kill_house + + allocation.save() + + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + + else: + guild_steward_allocations_product_warehousing(product) + + allocations_list = [] + number = random.randint(10000, 99000) + allocation.registration_code = number + allocation.system_registration_code = True + allocations_list.append(str(allocation.key)) + allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + if 'steward' in request.data.keys() or 'guild' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + + steward_allocation.save() + + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + elif 'check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = int( + request.data['receiver_real_weight_of_carcasses']) + steward_allocation.real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = int(request.data['receiver_real_weight_of_carcasses']) + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'guild_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'allocation_key' in request.data.keys() and 'logged_registration_code' not in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], trash=False) + steward_allocation.real_number_of_carcasses = request.data['number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = request.data['weight_of_carcasses'] + seller_product = steward_allocation.product + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + steward_allocation.save() + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'allocation_list' in request.data.keys(): + allocations_list_temp = request.data['allocation_list'] + allocations_list = [] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list_temp, + trash=False) + request.data.pop('allocation_list') + for steward_allocation in steward_allocations: + if steward_allocation.system_registration_code == True: + continue + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.system_registration_code = True + allocations_list.append(str(steward_allocation.key)) + steward_allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).select_related('ware_house__kill_house', + 'ware_house__kill_house__kill_house_operator__user').last() + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + if 'logged_registration_code' in request.data.keys(): + steward_allocation.state = 'accepted' + steward_allocation.save() + request.data.pop('role') + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allocations = [] + allocations_list = [] + state = request.GET.get('state') + type = request.GET.get('type') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + + if pos.kill_house: + if state and type: + if type == 'output': + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + receiver_state=state, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + receiver_state=state, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', + 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + receiver_state=state, + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', + 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if state == 'all': + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + trash=False, + system_registration_code=True).order_by( + '-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + receiver_state=state, + trash=False, + system_registration_code=True).order_by( + '-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(to_kill_house=pos.kill_house) | Q(kill_house=pos.kill_house), + trash=False).order_by('-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + + + + else: + if state and type: + + if type == 'output': + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + receiver_state=state, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + receiver_state=state, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, date__date__gte=date1, + receiver_state=state, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, + system_registration_code=True).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, + receiver_state=state, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild) | Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False).order_by('-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + if 'search' in request.GET and 'value' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = PosStewardAllocationSerializer(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = StewardAllocation.objects.get(key=request.GET["allocation_key"]) + product = allocation.product + seller_type = allocation.seller_type + allocation.delete() + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + + else: + guild_steward_allocations_product_warehousing(product) + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class NewPosStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [AllowAny] + serializer_class = PosStewardAllocationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = StewardAllocationFilterSet + filterset_fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'guilds__guilds_name', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'steward__guilds_name', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_guilds__guilds_name', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_steward__guilds_name', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + def create(self, request, *args, **kwargs): + now = datetime.now() + now_time = now.time() + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + + pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False) + product = RolesProducts.objects.get(key=request.data['product_key']) + seller_type = request.data['seller_type'] + buyer_type = request.data['buyer_type'] + request.data.pop('buyer_type') + request.data.pop('product_key') + request.data.pop('pos-id') + request.data.pop('production_date') + + if seller_type == 'KillHouse': + kill_house = pos.kill_house + quota = request.data['quota'] + if request.data['approved_price_status'] == False: + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_free_weight == 0 and not kill_house.free_sale_from_free_quota_in_province: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + elif seller_type == 'Steward': + steward = pos.guild + quota = request.data['quota'] + if request.data['approved_price_status'] == False: + if quota == 'governmental': + if not steward.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + if steward.total_input_warehouse_governmental_weight < ( + steward.total_selling_warehouse_governmental_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward.total_commitment_selling_in_province_free_weight == 0 and not steward.free_sale_from_free_quota_in_province: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if steward.total_input_warehouse_free_weight < ( + steward.total_selling_warehouse_free_weight + request.data['weight_of_carcasses']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + guild = pos.guild + + if buyer_type == 'Steward': + to_steward = Guilds.objects.get(key=request.data['steward_key'], trash=False) + request.data.pop('steward_key') + elif buyer_type == 'Guild': + to_guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + else: + to_kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + + if seller_type == 'KillHouse' and buyer_type == 'ColdHouse': + kill_house = pos.kill_house + quota = request.data['quota'] + if quota == 'governmental': + kill_house_sale_type = request.data['approved_price_status'] + if kill_house.governmental_selling_permission: + if kill_house_sale_type: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_cold_house_governmental_weight > 0: + if kill_house.total_cold_house_governmental_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_cold_house_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_cold_house_free_weight > 0: + if kill_house.total_cold_house_free_weight + request.data[ + 'weight_of_carcasses'] > kill_house.total_commitment_cold_house_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation = serializer.create(validated_data=request.data) + allow = AllowRegisterCodeForStewardAllocation.objects.filter(trash=False, active=True).first() + if allow: + allocation.active_expire_date_time = True + allocation.date = now + allocation.production_date = production_date + allocation.allocation_type = allocation.allocation_type.lower() + allocation.real_number_of_carcasses = allocation.number_of_carcasses + allocation.real_weight_of_carcasses = int(allocation.weight_of_carcasses) + allocation.weight_of_carcasses = int(request.data['weight_of_carcasses']) + # allocation.real_weight_of_carcasses = allocation.weight_of_carcasses + allocation.product = product + if seller_type == 'KillHouse': + allocation.kill_house = kill_house + + elif seller_type == 'Steward': + allocation.steward = steward + + else: + allocation.guilds = guild + + if buyer_type == 'Steward': + allocation.to_steward = to_steward + elif buyer_type == 'Guild': + allocation.to_guilds = to_guild + else: + allocation.to_kill_house = to_kill_house + + allocation.save() + + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + + else: + guild_steward_allocations_product_warehousing(product) + + allocations_list = [] + number = random.randint(10000, 99000) + allocation.registration_code = number + allocation.system_registration_code = True + allocations_list.append(str(allocation.key)) + allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, pk=None, *args, **kwargs): + if 'steward' in request.data.keys() or 'guild' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + + steward_allocation.save() + + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + elif 'check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + seller_product = steward_allocation.product + + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = int( + request.data['receiver_real_weight_of_carcasses']) + steward_allocation.real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = int(request.data['receiver_real_weight_of_carcasses']) + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guilds, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + guild_steward_allocations_product_warehousing(buyer_product) + else: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, + parent_product=seller_product.parent_product) + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + kill_house_allocations_product_warehousing(buyer_product) + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + else: + guild_steward_allocations_product_warehousing(seller_product) + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'guild_check_allocation' in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], + trash=False) + if request.data['state'] == 'accepted': + if 'registration_code' in request.data.keys(): + if request.data['registration_code'] != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + steward_allocation.logged_registration_code = request.data['registration_code'] + steward_allocation.receiver_real_number_of_carcasses = request.data['receiver_real_number_of_carcasses'] + steward_allocation.receiver_real_weight_of_carcasses = request.data['receiver_real_weight_of_carcasses'] + steward_allocation.save() + steward_allocation.receiver_state = 'accepted' + steward_allocation.save() + else: + steward_allocation.receiver_state = 'rejected' + steward_allocation.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + elif 'allocation_key' in request.data.keys() and 'logged_registration_code' not in request.data.keys(): + steward_allocation = StewardAllocation.objects.get(key=request.data['allocation_key'], trash=False) + if steward_allocation.receiver_state == 'accepted': + if steward_allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_guildso, trash=False, + parent_product=steward_allocation.product.parent_product) + elif steward_allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=steward_allocation.to_steward, trash=False, + parent_product=steward_allocation.product.parent_product) + + + elif steward_allocation.to_kill_house: + buyer_product = RolesProducts.objects.get(kill_house=steward_allocation.to_kill_house, trash=False, + parent_product=steward_allocation.product.parent_product) + else: + buyer_product = None + + if buyer_product: + if buyer_product.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.to_cold_house: + if steward_allocation.other_cold_house: + if steward_allocation.other_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.to_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + if steward_allocation.product: + if steward_allocation.product.kill_house: + if steward_allocation.quota == 'governmental': + if steward_allocation.product.kill_house.total_input_warehouse_governmental_weight < ( + ( + steward_allocation.product.kill_house.total_selling_warehouse_governmental_weight - steward_allocation.real_weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.product.kill_house.total_input_warehouse_free_weight < ( + ( + steward_allocation.product.kill_house.total_selling_warehouse_free_weight - steward_allocation.real_weight_of_carcasses) + + request.data['weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.quota == 'governmental': + if steward_allocation.product.guild.total_input_warehouse_governmental_weight < ( + ( + steward_allocation.product.guild.total_selling_warehouse_governmental_weight - steward_allocation.real_weight_of_carcasses) + + request.data[ + 'weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if steward_allocation.product.guild.total_input_warehouse_free_weight < ( + ( + steward_allocation.product.guild.total_selling_warehouse_free_weight - steward_allocation.real_weight_of_carcasses) + + request.data['weight_of_carcasses']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + if steward_allocation.product.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار است!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if steward_allocation.to_cold_house.total_remain_weight + steward_allocation.real_weight_of_carcasses < \ + request.data[ + 'weight_of_carcasses']: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + if steward_allocation.to_cold_house: + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + else: + + steward_allocation.real_number_of_carcasses = request.data['number_of_carcasses'] + steward_allocation.real_weight_of_carcasses = int(request.data['weight_of_carcasses']) + steward_allocation.save() + seller_product = steward_allocation.product + if steward_allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(seller_product) + if steward_allocation.to_cold_house and steward_allocation.to_cold_house.kill_house == steward_allocation.kill_house: + kill_house_cold_house_allocations(steward_allocation.to_cold_house) + + elif steward_allocation.seller_type == 'ColdHouse': + cold_house_warehousing(steward_allocation.to_cold_house) + if steward_allocation.other_cold_house: + cold_house_warehousing(steward_allocation.other_cold_house) + + else: + guild_steward_allocations_product_warehousing(seller_product) + # steward_allocation.real_number_of_carcasses = request.data['number_of_carcasses'] + # steward_allocation.real_weight_of_carcasses = request.data['weight_of_carcasses'] + # seller_product = steward_allocation.product + # if steward_allocation.seller_type == 'KillHouse': + # kill_house_allocations_product_warehousing(seller_product) + # else: + # guild_steward_allocations_product_warehousing(seller_product) + # steward_allocation.save() + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'allocation_list' in request.data.keys(): + allocations_list_temp = request.data['allocation_list'] + allocations_list = [] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list_temp, + trash=False) + request.data.pop('allocation_list') + for steward_allocation in steward_allocations: + if steward_allocation.system_registration_code == True: + continue + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.system_registration_code = True + allocations_list.append(str(steward_allocation.key)) + steward_allocation.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).select_related('ware_house__kill_house', + 'ware_house__kill_house__kill_house_operator__user').last() + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + if 'logged_registration_code' in request.data.keys(): + steward_allocation.state = 'accepted' + steward_allocation.save() + request.data.pop('role') + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allocations = [] + allocations_list = [] + state = request.GET.get('state') + type = request.GET.get('type') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + + if pos.kill_house: + if state and type: + if type == 'output': + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + receiver_state=state, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + kill_house=pos.kill_house, + receiver_state=state, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', + 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + receiver_state=state, + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', + 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if state == 'all': + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + trash=False, + system_registration_code=True).order_by( + '-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter(to_kill_house=pos.kill_house, + receiver_state=state, + trash=False, + system_registration_code=True).order_by( + '-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(to_kill_house=pos.kill_house) | Q(kill_house=pos.kill_house), + trash=False).order_by('-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + + + + else: + if state and type: + + if type == 'output': + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + receiver_state=state, + trash=False, date__date__gte=date1, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + allocations = StewardAllocation.objects.filter( + Q(steward=pos.guild) | Q(guilds=pos.guild), + receiver_state=state, + trash=False).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if date1 and date2: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, date__date__gte=date1, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, date__date__gte=date1, + receiver_state=state, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + else: + if state == 'all': + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, + system_registration_code=True).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild), + trash=False, + receiver_state=state, + system_registration_code=True, + date__date__lte=date2).order_by('-date', 'system_registration_code').exclude( + to_cold_house__isnull=False) + + + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward=pos.guild) | Q(to_guilds=pos.guild) | Q(steward=pos.guild) | Q(guilds=pos.guild), + trash=False).order_by('-date', 'system_registration_code').exclude(to_cold_house__isnull=False) + + if 'search' in request.GET and 'value' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = PosStewardAllocationSerializer(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # def destroy(self, request, pk=None, *args, **kwargs): + # allocation = StewardAllocation.objects.get(key=request.GET["allocation_key"]) + # product = allocation.product + # seller_type = allocation.seller_type + # allocation.delete() + # if seller_type == 'KillHouse': + # kill_house_allocations_product_warehousing(product) + # + # else: + # guild_steward_allocations_product_warehousing(product) + # return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + def destroy(self, request, pk=None, *args, **kwargs): + allocation = StewardAllocation.objects.get(key=request.GET["steward_allocation_key"]) + if allocation.receiver_state == 'accepted': + if allocation.to_steward: + buyer_product = RolesProducts.objects.get(guild=allocation.to_guildso, trash=False, + parent_product=allocation.product.parent_product) + elif allocation.to_guilds: + buyer_product = RolesProducts.objects.get(guild=allocation.to_steward, trash=False, + parent_product=allocation.product.parent_product) + + + elif allocation.to_kill_house: + buyer_product = RolesProducts.objects.get(kill_house=allocation.to_kill_house, trash=False, + parent_product=allocation.product.parent_product) + + else: + buyer_product = None + + if buyer_product: + if buyer_product.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن حذف شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if allocation.to_cold_house: + if allocation.other_cold_house: + if allocation.other_cold_house.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if allocation.to_cold_house.total_remain_weight < allocation.real_weight_of_carcasses: + return Response({"result": "وزن وارد شده بیشتر از موجودی انبار خریدار است!"}, + status=status.HTTP_403_FORBIDDEN) + + product = allocation.product + seller_type = allocation.seller_type + to_cold_house = allocation.to_cold_house + other_cold_house = allocation.other_cold_house if allocation.other_cold_house else None + allocation.trash = True + allocation.save() + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + if to_cold_house and to_cold_house.kill_house == product.kill_house: + kill_house_cold_house_allocations(to_cold_house) + + elif seller_type == 'ColdHouse': + cold_house_warehousing(to_cold_house) + if other_cold_house: + cold_house_warehousing(other_cold_house) + + + else: + guild_steward_allocations_product_warehousing(product) + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class DispenserAllocationDashboardViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DispenserAllocationSerializer + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = StewardAllocation.objects.filter(dispenser__key=request.GET['dispenser_key'], trash=False, + date__date__gte=date1, + date__date__lte=date2, + ).order_by('id') + total_quantity = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + total_weight = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + stewards_allocations = allocations.filter(steward__isnull=False) + steward_total_quantity = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + steward_total_weight = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + guilds_allocations = allocations.filter(guilds__isnull=False) + guild_total_quantity = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + guild_total_weight = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + allocation_info = { + "number_of_allocations": len(allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + "number_of_stewards_allocations": len(stewards_allocations), + "steward_total_quantity": steward_total_quantity, + "steward_total_weight": steward_total_weight, + "number_of_guilds_allocations": len(guilds_allocations), + "guild_total_quantity": guild_total_quantity, + "guild_total_weight": guild_total_weight, + } + return Response(allocation_info, status=status.HTTP_200_OK) + + +class DispenserAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DispenserAllocationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = DispenserAllocationFilterSet + filterset_fields = [ + 'dispenser__user__first_name', + 'dispenser__user__last_name', + 'dispenser__user__fullname', + 'dispenser__user__mobile', + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__guilds__user__first_name', + 'steward__guilds__user__last_name', + 'steward__guilds__user__fullname', + 'steward__guilds__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name' + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + allocations_list = [] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'Dispenser': + allocations = StewardAllocation.objects.filter(dispenser__user=user, trash=False, + date__date__gte=date1, + date__date__lte=date2, + ).order_by('-date') + else: + allocations = StewardAllocation.objects.filter(dispenser__key=request.GET['dispenser_key'], trash=False, + date__date__gte=date1, + date__date__lte=date2, + ).order_by('-date') + else: + if request.GET['role'] == 'Dispenser': + allocations = StewardAllocation.objects.filter(dispenser__user=user, trash=False + ).order_by('-date') + else: + allocations = StewardAllocation.objects.filter(dispenser__key=request.GET['dispenser_key'], + trash=False).order_by('-date') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardGuildAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'steward_allocation_key' in request.data.keys() and 'logged_registration_code' not in request.data.keys(): + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).select_related('steward_ware_house', + 'steward_ware_house__steward').first() + request.data.pop('steward_allocation_key') + increase_number_of_carcasses = int( + request.data['number_of_carcasses']) - steward_allocation.number_of_carcasses + decrease_number_of_carcasses = steward_allocation.number_of_carcasses - int( + request.data['number_of_carcasses']) + increase_weight_of_carcasses = float( + request.data['weight_of_carcasses']) - steward_allocation.weight_of_carcasses + decrease_weight_of_carcasses = steward_allocation.weight_of_carcasses - float( + request.data['weight_of_carcasses']) + steward_ware_house = StewardWareHouse.objects.get(key=steward_allocation.steward_ware_house.key) + + if int(request.data['number_of_carcasses']) > steward_allocation.number_of_carcasses: + if increase_number_of_carcasses > steward_ware_house.remain_total_number_of_carcasses: + return Response({"result": "تعداد وارد شده از موجودی انبار بیشتر است"}, + status=status.HTTP_403_FORBIDDEN) + steward_ware_house.allocated_total_number_of_carcasses += increase_number_of_carcasses + + else: + steward_ware_house.allocated_total_number_of_carcasses -= decrease_number_of_carcasses + + if float(request.data['weight_of_carcasses']) > steward_allocation.weight_of_carcasses: + if increase_weight_of_carcasses > steward_ware_house.remain_total_weight_of_carcasses: + return Response({"result": "مقدار وارد شده از موجودی انبار بیشتر است"}, + status=status.HTTP_403_FORBIDDEN) + steward_ware_house.allocated_total_weight_of_carcasses += increase_weight_of_carcasses + + else: + steward_ware_house.allocated_total_weight_of_carcasses -= decrease_weight_of_carcasses + + steward_ware_house.save() + + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'steward_guild_allocation_list' in request.data.keys(): + allocations_list_temp = request.data['steward_guild_allocation_list'] + allocations_list = [] + steward_allocations = StewardAllocation.objects.filter(key__in=allocations_list_temp, + trash=False) + request.data.pop('steward_guild_allocation_list') + for steward_allocation in steward_allocations: + if steward_allocation.system_registration_code == True: + continue + number = random.randint(10000, 99000) + steward_allocation.registration_code = number + steward_allocation.system_registration_code = True + allocations_list.append(str(steward_allocation.key)) + + # steward_allocation.final_registration = True + steward_allocation.save() + # steward_ware_house = StewardWareHouse.objects.filter(steward=steward_allocation.steward, + # date__date=steward_allocation.date.date()).first() + # if not steward_ware_house: + # steward_ware_house = StewardWareHouse(steward=steward_allocation.steward, + # date=steward_allocation.date) + # steward_ware_house.save() + # steward_ware_house.bar_quantity += 1 + # steward_ware_house.number_of_carcasses += steward_allocation.real_number_of_carcasses + # steward_ware_house.weight_of_carcasses += steward_allocation.real_weight_of_carcasses + # steward_ware_house.save() + + sms_steward_allocations = threading.Thread(target=steward_allocations_sms, + args=(allocations_list,)) + + sms_steward_allocations.start() + + return Response({"result": "عملیات با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + else: + + steward_allocation = StewardAllocation.objects.filter(key=request.data['steward_allocation_key'], + trash=False).last() + request.data.pop('steward_allocation_key') + if int(request.data['logged_registration_code']) != steward_allocation.registration_code: + return Response({"result": "کد وارد شده صحیح نیست"}, status=status.HTTP_403_FORBIDDEN) + + steward_allocation.role = { + "role": request.data['role'], + "fullname": user.fullname, + "mobile": user.mobile, + "date_register": str(datetime.now()) + } + if 'logged_registration_code' in request.data.keys(): + steward_allocation.state = 'accepted' + steward_allocation.save() + request.data.pop('role') + serializer = self.serializer_class(steward_allocation) + serializer.update(instance=steward_allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = StewardAllocation.objects.get(key=request.GET["steward_allocation_key"]) + steward_ware_house = StewardWareHouse.objects.get(key=allocation.steward_ware_house.key, trash=False) + steward_ware_house.allocated_total_number_of_carcasses -= allocation.number_of_carcasses + steward_ware_house.allocated_total_weight_of_carcasses -= allocation.weight_of_carcasses + steward_ware_house.save() + allocation.delete() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class StewardWareHouseViewSet(viewsets.ModelViewSet): + queryset = StewardWareHouse.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardWareHouseSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + date = datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else now + + steward = Steward.objects.get(guilds__user=user, trash=False) + steward_ware_house = StewardWareHouse.objects.filter(steward=steward, + date__date=date, + trash=False).last() + + if steward_ware_house is None: + ware_house_date = datetime(year=date.year, month=date.month, day=date.day, hour=1, minute=12, second=20) + steward_ware_house = StewardWareHouse( + steward=steward, + date=ware_house_date + ) + steward_ware_house.save() + + bar_quantity = 0 + number_of_carcasses = 0 + real_number_of_carcasses = 0 + weight_of_carcasses = 0 + real_weight_of_carcasses = 0 + ave_weight_of_carcasses = 0 + free_sale_number_of_carcasses = 0 + free_sale_weight_of_carcasses = 0 + + allocations = StewardAllocation.objects.filter(steward=steward, system_registration_code=True, date__date=date, + trash=False, state='accepted', + receiver_state__in=('pending', 'accepted')) + + if allocations.count() > 0: + for allocation in allocations: + bar_quantity += 1 + number_of_carcasses += allocation.number_of_carcasses + weight_of_carcasses += allocation.weight_of_carcasses + if allocation.receiver_state == 'accepted': + real_number_of_carcasses += allocation.receiver_real_number_of_carcasses + real_weight_of_carcasses += allocation.receiver_real_weight_of_carcasses + ave_weight_of_carcasses += weight_of_carcasses / number_of_carcasses + free_bars = StewardFreeBarInformation.objects.filter(steward=steward, date__date=date, trash=False) + total_quantity_free_bar = 0 + total_weight_free_bar = 0 + number_of_free_bar = 0 + if len(free_bars) > 0: + for free_bar in free_bars: + number_of_free_bar += 1 + total_quantity_free_bar += free_bar.number_of_carcasses + total_weight_free_bar += free_bar.weight_of_carcasses + steward_free_sale_bar_infos = StewardFreeSaleBarInformation.objects.filter(steward=steward, + date__date=date, + trash=False) + + free_sale_number_of_carcasses = steward_free_sale_bar_infos.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] or 0 + free_sale_weight_of_carcasses = steward_free_sale_bar_infos.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + steward_ware_house.bar_quantity = bar_quantity + steward_ware_house.number_of_carcasses = number_of_carcasses + steward_ware_house.real_number_of_carcasses = real_number_of_carcasses + total_quantity_free_bar + steward_ware_house.weight_of_carcasses = weight_of_carcasses + steward_ware_house.real_weight_of_carcasses = real_weight_of_carcasses + total_weight_free_bar + steward_ware_house.free_bar_quantity = number_of_free_bar + steward_ware_house.number_of_free_carcasses = total_quantity_free_bar + steward_ware_house.weight_of_free_carcasses = total_weight_free_bar + steward_ware_house.free_sale_quantity = free_sale_number_of_carcasses + steward_ware_house.free_sale_weight = free_sale_weight_of_carcasses + steward_ware_house.remain_total_number_of_carcasses = steward_ware_house.real_number_of_carcasses - steward_ware_house.allocated_total_number_of_carcasses + steward_ware_house.remain_total_weight_of_carcasses = steward_ware_house.real_weight_of_carcasses - steward_ware_house.allocated_total_weight_of_carcasses + steward_ware_house.save() + return Response({ + "steward_key": steward.key, + "bar_quantity": bar_quantity, + "number_of_carcasses": steward_ware_house.number_of_carcasses, + "real_number_of_carcasses": steward_ware_house.real_number_of_carcasses, + "weight_of_carcasses": steward_ware_house.weight_of_carcasses, + "real_weight_of_carcasses": steward_ware_house.real_weight_of_carcasses, + "free_bar_quantity": steward_ware_house.free_bar_quantity, + "number_of_free_carcasses": steward_ware_house.number_of_free_carcasses, + "weight_of_free_carcasses": steward_ware_house.weight_of_free_carcasses, + "allocated_total_number_of_carcasses": steward_ware_house.allocated_total_number_of_carcasses, + "allocated_total_weight_of_carcasses": steward_ware_house.allocated_total_weight_of_carcasses, + "remain_total_number_of_carcasses": steward_ware_house.remain_total_number_of_carcasses, + "remain_total_weight_of_carcasses": steward_ware_house.remain_total_weight_of_carcasses, + "free_sale_quantity": steward_ware_house.free_sale_quantity, + "free_sale_weight": steward_ware_house.free_sale_weight, + "total_average_weight_of_carcasses": round( + steward_ware_house.real_weight_of_carcasses / steward_ware_house.real_number_of_carcasses, + 2) if steward_ware_house.real_number_of_carcasses > 0 else 0, + }, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + ware_house = KillHouseWareHouse.objects.get(key=request.data['key']) + ware_house.updated_number_of_carcasses = request.data['updated_number_of_carcasses'] + ware_house.updated_weight_of_carcasses = request.data['updated_weight_of_carcasses'] + ware_house.total_weight_of_carcasses = request.data[ + 'updated_weight_of_carcasses'] + ware_house.weight_of_carcasses + ware_house.total_number_of_carcasses = request.data[ + 'updated_number_of_carcasses'] + ware_house.number_of_carcasses + ware_house.save() + serializer = self.serializer_class(ware_house) + serializer.update(instance=ware_house, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalReportOfStewardWareHouseForDailyBroadCastViewSet(viewsets.ModelViewSet): + queryset = StewardWareHouse.objects.all() + serializer_class = StewardWareHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + + number_of_steward = Steward.objects.filter( + pk__in=steward_ware_houses.values('steward') + ) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + return Response({ + "buyers": len(number_of_steward), + "incoming_quantity_of_cold_house": 0, + "incoming_weight_of_cold_house": 0, + "total_pre_cold_quantity": 0, + "total_pre_cold_weight": 0, + "total_number_of_free_carcasses": total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + "total_free_weight_of_carcasses": total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + "total_number_of_carcasses": total_number_of_carcasses if total_number_of_carcasses != None else 0, + "total_weight_of_carcasses": total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + "final_total_number_of_carcasses": final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + "final_total_weight_of_carcasses": final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + "total_allocated_quantity": total_allocated_quantity if total_allocated_quantity != None else 0, + "total_allocated_weight": total_allocated_weight if total_allocated_weight != None else 0, + "total_accepted_allocated_quantity": total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + "total_accepted_allocated_weight": total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + "total_remain_quantity": total_remain_quantity if total_remain_quantity != None else 0, + "total_remain_weight": total_remain_weight if total_remain_weight != None else 0, + "number_of_guild": number_of_guild, + + }) + + +class TotalReportOfStewardWareHouseForDailyBroadCastInDetailsViewSet(viewsets.ModelViewSet): + queryset = Steward.objects.all() + serializer_class = StewardWareHouseForDailyBroadCastOInDetailsSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + stewards = Steward.objects.filter( + pk__in=steward_ware_houses.values('steward') + ) + + serializer = self.serializer_class(stewards, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChooseProductForGuildViewSet(viewsets.ModelViewSet): + queryset = Product.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProductSerializer + + # def update(self, request, pk=None, *args, **kwargs): + # product = Product.objects.get(key=request.data['product_key']) + # gulid = Guilds.objects.get(key=request.data['guild_key']) + # request.data.pop('product_key') + # request.data.pop('guild_key') + # if Product.objects.filter(guild=gulid,name=product.name).exists(): + # return Response({"result":"این محصول قبلا ثبت شده"}) + # serializer = self.serializer_class(product) + # serializer.update(instance=product, validated_data=request.data) + # return Response(serializer.data, status=status.HTTP_200_OK) + + +class GuildsWareHouseTotalProductViewSet(viewsets.ModelViewSet): + queryset = Product.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProductSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + guild = Guilds.objects.get(user=user, trash=False) + products = Product.objects.filter(Q(general=False, guild=guild) | Q(general=True, guild__isnull=True), + trash=False).order_by('priority') + product_serializer = ProductSerializer(products, many=True) + return Response(product_serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + product = Product.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + serializer = self.serializer_class(product) + serializer.update(instance=product, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class GuildsWareHouseProductViewSet(viewsets.ModelViewSet): + queryset = Product.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProductSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + guild = Guilds.objects.get(user=user, trash=False) + products = Product.objects.filter( + Q(general=False, guild=guild, show=True) | Q(general=True, guild__isnull=True), + trash=False).order_by('priority') + product_serializer = ProductSerializer(products, many=True) + return Response(product_serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + product = Product.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + serializer = self.serializer_class(product) + serializer.update(instance=product, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def change_product_state(product_key): + additional_product = AdditionalProducts.objects.get(key=product_key) + products = Product.objects.filter(name=additional_product.name, trash=False) + if products: + for product in products: + product.selling_approved_price = additional_product.selling_approved_price + product.selling_free_price = additional_product.selling_free_price + product.selling_more_than_inventory = additional_product.selling_more_than_inventory + product.selling_other_products = additional_product.selling_other_products + product.price = additional_product.price + product.save() + + +def change_roles_products_state(state, price, steward_price, guild_price): + roles_products = RolesProducts.objects.filter(trash=False) + for roles_product in roles_products: + if roles_product.kill_house: + roles_product.approved_price_status = state + roles_product.approved_price = price + else: + if roles_product.guild.steward: + roles_product.approved_price = steward_price + roles_product.approved_price_status = state if steward_price > 0 else False + else: + roles_product.approved_price = guild_price + roles_product.approved_price_status = state if guild_price > 0 else False + if state: + roles_product.free_price = 0 + + roles_product.save() + + +class ServerMainProductsViewSet(viewsets.ModelViewSet): + queryset = AdditionalProducts.objects.all() + permission_classes = [AllowAny] + serializer_class = AdditionalProductsSerializer + + def list(self, request, *args, **kwargs): + products = AdditionalProducts.objects.filter(trash=False).order_by('id') + + product_serializer = AdditionalProductsSerializer(products, many=True) + return Response(product_serializer.data, status=status.HTTP_200_OK) + + +class AdditionalProductsViewSet(viewsets.ModelViewSet): + queryset = AdditionalProducts.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AdditionalProductsSerializer + + def list(self, request, *args, **kwargs): + products = AdditionalProducts.objects.filter(trash=False).order_by('id') + + product_serializer = AdditionalProductsSerializer(products, many=True) + return Response(product_serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + product = AdditionalProducts.objects.get(key=request.data['product_key']) + request.data.pop('product_key') + serializer = self.serializer_class(product) + serializer.update(instance=product, validated_data=request.data) + change_guild_products_info = threading.Thread(target=change_product_state, + args=(product.key,)) + + change_guild_products_info.start() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class GuildsWareHouseViewSet(viewsets.ModelViewSet): + queryset = GuildsWareHouse.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsWareHouseSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + date = datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else now + + guild = Guilds.objects.get(user=user, trash=False) + guild_ware_house = GuildsWareHouse.objects.filter(guilds=guild, + # date__date=date, + trash=False).first() + + if guild_ware_house is None: + ware_house_date = datetime(year=date.year, month=date.month, day=date.day, hour=1, minute=12, second=20) + guild_ware_house = GuildsWareHouse( + guilds=guild, + date=ware_house_date + ) + guild_ware_house.save() + + bar_quantity = 0 + number_of_carcasses = 0 + real_number_of_carcasses = 0 + weight_of_carcasses = 0 + real_weight_of_carcasses = 0 + ave_weight_of_carcasses = 0 + + allocations = StewardAllocation.objects.filter( + (Q(allocation_type='steward_broadcast') | Q(allocation_type='kill_house_broadcast')), guilds=guild, + system_registration_code=True, + # date__date=date, + trash=False, state='accepted', receiver_state__in=('pending', 'accepted')) + accepted_allocations = allocations.filter(receiver_state='accepted') + if len(allocations) > 0: + bar_quantity = len(allocations) + number_of_carcasses = allocations.aggregate(total=Sum('number_of_carcasses'))['total'] or 0 + real_number_of_carcasses = accepted_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] or 0 + weight_of_carcasses = allocations.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + real_weight_of_carcasses = accepted_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] or 0 + ave_weight_of_carcasses = weight_of_carcasses / number_of_carcasses if number_of_carcasses > 0 else 0 + + # if allocations.count() > 0: + # for allocation in allocations: + # bar_quantity += 1 + # number_of_carcasses += allocation.number_of_carcasses + # real_number_of_carcasses += allocation.receiver_real_number_of_carcasses + # weight_of_carcasses += allocation.weight_of_carcasses + # real_weight_of_carcasses += allocation.receiver_real_weight_of_carcasses + # ave_weight_of_carcasses += weight_of_carcasses / number_of_carcasses + guild_ware_house.bar_quantity = bar_quantity + guild_ware_house.number_of_carcasses = number_of_carcasses + guild_ware_house.real_number_of_carcasses = real_number_of_carcasses + guild_ware_house.weight_of_carcasses = weight_of_carcasses + guild_ware_house.real_weight_of_carcasses = real_weight_of_carcasses + guild_ware_house.remain_total_number_of_carcasses = guild_ware_house.real_number_of_carcasses - guild_ware_house.allocated_total_number_of_carcasses if guild_ware_house.real_number_of_carcasses > 0 else 0 + guild_ware_house.remain_total_weight_of_carcasses = guild_ware_house.real_weight_of_carcasses - guild_ware_house.allocated_total_weight_of_carcasses if guild_ware_house.real_weight_of_carcasses > 0 else 0 + guild_ware_house.save() + return Response({ + "bar_quantity": bar_quantity, + "number_of_carcasses": guild_ware_house.number_of_carcasses, + "real_number_of_carcasses": guild_ware_house.real_number_of_carcasses, + "weight_of_carcasses": guild_ware_house.weight_of_carcasses, + "real_weight_of_carcasses": guild_ware_house.real_weight_of_carcasses, + "allocated_total_number_of_carcasses": guild_ware_house.allocated_total_number_of_carcasses, + "allocated_total_weight_of_carcasses": guild_ware_house.allocated_total_weight_of_carcasses, + "remain_total_number_of_carcasses": guild_ware_house.remain_total_number_of_carcasses, + "remain_total_weight_of_carcasses": guild_ware_house.remain_total_weight_of_carcasses, + "total_average_weight_of_carcasses": round( + guild_ware_house.real_weight_of_carcasses / guild_ware_house.real_number_of_carcasses, + 2) if guild_ware_house.real_number_of_carcasses > 0 else 0, + }, status=status.HTTP_200_OK) + + +class VetSupervisorViewSet(viewsets.ModelViewSet): + queryset = VetSupervisor.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetSupervisorSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + operator = user.supervisor_user.all() + + # send to serializer + serializer = self.serializer_class(operator[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityVetViewSet(viewsets.ModelViewSet): + queryset = CityVet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityVetSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + operator = user.city_vet_user.all().last() + + serializer = self.serializer_class(operator) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceCheckKillRequestViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckOperatorRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceCheckOperatorRequestSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + now = datetime.now() + state = request.data['state'] + request.data.pop('state') + if 'quantity' in request.data.keys() and request.data['quantity'] != None: + quantity = request.data['quantity'] + request.data.pop('quantity') + else: + quantity = None + # request.data.pop('quantity') + if 'breed' in request.data.keys() and request.data['breed'] != None: + breed = request.data['breed'] + request.data.pop('breed') + else: + breed = None + # request.data.pop('breed') + + kill_request = KillRequest.objects.get(key=request.data['kill_request_key']) + request.data.pop('kill_request_key') + if state == 'accepted': + kill_request.province_state = 'accepted' + if quantity != None: + kill_request.province_quantity = kill_request.kill_capacity + kill_request.kill_capacity = int(quantity) + kill_request.remain_quantity = int(quantity) + if breed != None: + kill_request.old_chicken_breed = kill_request.chicken_breed + kill_request.chicken_breed = breed + kill_request.save() + price = Pricing.objects.all() + if price.count() > 0: + price = price.last() + factor = KillRequestFactor( + kill_request=kill_request, + amount=round((kill_request.kill_capacity * kill_request.Index_weight) * price.live_chicken_price, + 0), + # amount=round((kill_request.kill_capacity * kill_request.Index_weight) * price.live_chicken_price, + # 0) * 1000, + minimum_amount=round( + ((kill_request.kill_capacity * kill_request.Index_weight) * price.live_chicken_price) * ( + 70 / 100), + 0) + + ) + factor.save() + kill_request.factor_amount = factor.amount + kill_request.save() + mobile = kill_request.kill_house.kill_house_operator.user.mobile + kill_house_name = kill_request.kill_house.name + # sms_province_kill_request_accept_sms = threading.Thread( + # target=province_kill_request_accept_sms, + # args=( + # mobile, kill_house_name)) + # sms_province_kill_request_accept_sms.start() + confirmation_of_the_need_for_slaughterhouse = threading.Thread( + target=confirmation_of_the_need_for_slaughterhouse_sms_threading, + args=( + kill_request.kill_house.name)) + confirmation_of_the_need_for_slaughterhouse.start() + else: + mobile = kill_request.kill_house.kill_house_operator.user.mobile + kill_house_name = kill_request.kill_house.name + sms_province_kill_request_reject_sms = threading.Thread( + target=province_kill_request_reject_sms, + args=( + mobile, kill_house_name)) + sms_province_kill_request_reject_sms.start() + + kill_request.province_state = 'rejected' + kill_request.message = request.data['msg'] + kill_request.state = 'archive' + kill_request.save() + return Response(status=status.HTTP_201_CREATED) + + +class VetCheckAllocationsViewSet(viewsets.ModelViewSet): + queryset = VetCheckAllocations.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetCheckAllocationsSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + vet_superviser = VetSupervisor.objects.filter(address__province=user.province) + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key']) + clearance_code = request.data['code'] + role = request.data['role'] + if 'code' in request.data.keys(): + date_time_of_now = datetime.now().date() + if OperationLimitation.objects.all().first().vet_farm_limitation == True and role not in ['Supporter', + 'AdminX', + 'Supporter']: + + if date_time_of_now > kill_house_request.kill_request.recive_date.date() + timedelta(days=1): + return Response( + {"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + if KillHouseRequest.objects.filter(clearance_code=clearance_code, trash=False).exists(): + return Response({"result": "کد وارد شده تکراری میباشد!"}, status=status.HTTP_403_FORBIDDEN) + + request.data.pop('kill_house_request_key') + request.data.pop('role') + request.data.pop('code') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + check_request = serializer.create(validated_data=request.data) + now = datetime.now() + formatted_now = now.strftime('%Y-%m-%dT%H:%M:%S') + + if role == 'ProvinceOperator': + if vet_superviser.count() > 0: + vet_superviser = vet_superviser.last() + check_request.vet = vet_superviser.vet + check_request.save() + kill_house_request.clearance_code = clearance_code + + kill_house_request.registrar_clearance_code = { + 'role': role, + 'name': user.fullname, + 'mobile': user.mobile, + 'date': str(formatted_now), + } + kill_house_request.save() + try: + get_gid(kill_house_request.clearance_code) + except: + pass + check_request.kill_house_request = kill_house_request + try: + vet = Vet.objects.get(user=user) + check_request.vet = vet + check_request.reviewer = { + 'role': role, + 'name': vet.user.fullname, + 'mobile': vet.user.mobile, + } + except: + check_request.reviewer = { + 'role': role, + 'name': user.fullname, + 'mobile': user.mobile, + } + + check_request.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def update(self, request, pk=None, selected_kill_house_request=None, *args, **kwargs): + + code = request.data['code'] + kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key'], trash=False) + if KillHouseRequest.objects.filter(clearance_code=code, trash=False).exists(): + return Response( + {"result": "کد وارد شده تکراری میباشد!"}, + status=status.HTTP_403_FORBIDDEN + ) + if kill_house_request.aggregate_status == True: + kill_house_requests = KillHouseRequest.objects.filter( + aggregate_code=kill_house_request.aggregate_code).order_by('id') + + for kill_house_request in kill_house_requests: + if 'code' in request.data.keys(): + kill_house_request.clearance_code = request.data['code'] + if 'traffic_code' in request.data.keys(): + kill_house_request.traffic_code = request.data['traffic_code'] + + kill_house_request.save() + else: + kill_house_request.clearance_code = code + kill_house_request.save() + try: + get_gid(kill_house_request.clearance_code) + except: + pass + return Response({"result": "کد ترخیص با موفقیت ویرایش شد"}, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + kill = KillHouseRequest.objects.get(key=request.GET['kill_house_request_key'], trash=False) + + vat_check_request = VetCheckAllocations.objects.get(kill_house_request=kill, trash=False) + vat_check_request.delete() + kill.clearance_code = None + kill.traffic_code = None + kill.aggregate_status = False + kill.aggregate_code = None + kill.save() + return Response({'msg': f'بار به شماره {kill.bar_code} از تجمیع خارج شد.'}, status=status.HTTP_200_OK) + + +class AggregateVetCheckAllocationsViewSet(viewsets.ModelViewSet): + queryset = VetCheckAllocations.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetCheckAllocationsSerializer + + def create(self, request, *args, **kwargs): + # Extract necessary data from request + user = get_object_or_404(SystemUserProfile, user=request.user) + province = user.province + clearance_code = request.data.get('code') + traffic_code = request.data.get('traffic_code') + role = request.data.get('role') + kill_house_request_keys = request.data['kill_house_requests_list'] + + # Fetch related objects in a single query + kill_house_requests = KillHouseRequest.objects.filter(key__in=kill_house_request_keys).order_by('id') + aggregate_code = kill_house_requests.first().bar_code + vet_supervisor = VetSupervisor.objects.filter(address__province=province).last() + operation_limitation = OperationLimitation.objects.first() + if clearance_code is not None and KillHouseRequest.objects.filter(clearance_code=clearance_code, + trash=False).exists(): + return Response( + {"result": "کد وارد شده تکراری میباشد!"}, + status=status.HTTP_403_FORBIDDEN + ) + # Validation + if clearance_code and operation_limitation.vet_farm_limitation and role not in ['Supporter', 'AdminX']: + first_kill_house_request = kill_house_requests.first() + if first_kill_house_request and now().date() > ( + first_kill_house_request.kill_request.recive_date.date() + timedelta(days=1)): + return Response( + {"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN + ) + + # Prepare data for saving + request_data = request.data.copy() # Use copy to avoid modifying original request data + request_data.pop('kill_house_requests_list', None) + request_data.pop('role', None) + request_data.pop('code', None) + now_formatted = now().strftime('%Y-%m-%dT%H:%M:%S') + + for kill_house_request in kill_house_requests: + if kill_house_request.aggregate_status: + check_request = get_object_or_404(VetCheckAllocations, kill_house_request=kill_house_request, + trash=False) + else: + serializer = self.serializer_class(data=request_data) + if serializer.is_valid(): + check_request = serializer.save() + kill_house_request.aggregate_status = True + kill_house_request.aggregate_code = aggregate_code + else: + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + # Update vet and reviewer information + if role == 'ProvinceOperator' and vet_supervisor: + check_request.vet = vet_supervisor.vet + + if clearance_code: + kill_house_request.clearance_code = clearance_code + kill_house_request.traffic_code = traffic_code + kill_house_request.registrar_clearance_code = { + 'role': role, + 'name': user.fullname, + 'mobile': user.mobile, + 'date': now_formatted, + } + + # Set reviewer information + try: + vet = Vet.objects.get(user=user) + check_request.vet = vet + check_request.reviewer = { + 'role': role, + 'name': vet.user.fullname, + 'mobile': vet.user.mobile, + } + except Vet.DoesNotExist: + check_request.reviewer = { + 'role': role, + 'name': user.fullname, + 'mobile': user.mobile, + } + + # Save changes + kill_house_request.save() + check_request.kill_house_request = kill_house_request + check_request.save() + try: + if kill_house_requests.first().clearance_code is not None: + get_gid(kill_house_requests.first().clearance_code) + except: + pass + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + + type = request.data.get('type') + if type == 'cancel_aggregate': + selected_kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key']) + kill_house_requests = KillHouseRequest.objects.filter( + aggregate_code=selected_kill_house_request.aggregate_code).order_by('id') + for kill_house_request in kill_house_requests: + check_request = get_object_or_404(VetCheckAllocations, kill_house_request=kill_house_request, + trash=False) + check_request.delete() + kill_house_request.aggregate_status = False + kill_house_request.aggregate_code = None + kill_house_request.save() + else: + selected_kill_house_request = KillHouseRequest.objects.get(key=request.data['kill_house_request_key']) + kill_house_requests = KillHouseRequest.objects.filter( + aggregate_code=selected_kill_house_request.aggregate_code).order_by('id') + + for kill_house_request in kill_house_requests: + if 'code' in request.data.keys(): + kill_house_request.clearance_code = request.data['code'] + if 'traffic_code' in request.data.keys(): + kill_house_request.traffic_code = request.data['traffic_code'] + + kill_house_request.save() + try: + if kill_house_requests.first().clearance_code is not None: + get_gid(kill_house_requests.first().clearance_code) + except: + pass + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +class ProvincePercentLeftOverViewSet(viewsets.ModelViewSet): + queryset = ProvincePercentLeftOver.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvincePercentLeftOverSerializer + + +# ویوست مربوط یه قیمت گذاری +class PricingViewSet(viewsets.ModelViewSet): + queryset = Pricing.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PricingSerializer + + # تابع مربوط یه قیمت گذاری + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + # role = request.data['role'] + # request.data.pop('role') + user = SystemUserProfile.objects.get(user=request.user) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + prices = Pricing.objects.filter(trash=False) + date1 = (datetime.strptime(request.data['date'], '%Y-%m-%d %H:%M:%S')).date() + for price in prices: + if price.date.year == date1.year and price.date.month == date1.month and price.date.day == date1.day: + price.live_chicken_price = float(request.data['live_chicken_price']) + price.ceiling_price = float(request.data['ceiling_price']) + price.floor_price = float(request.data['floor_price']) + # price.dead_chicken_price = float(request.data['dead_chicken_price']) + # price.major_seller_price = float(request.data['major_seller_price']) + # price.retail_seller_price = float(request.data['retail_seller_price']) + price.save() + return Response({"result": "object update"}, status=status.HTTP_200_OK) + pricing = serializer.create(validated_data=request.data) + # pricing.role = role + pricing.operator = user + pricing.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط یه نمایش قیمت های ثبت شده + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + if 'role' in request.GET: + # if request.GET['role'] == 'Poultry': + now = datetime.now().date() + # pricing = Pricing.objects.filter(date__year=now.year, date__month=now.month, date__day=now.day, + # trash=False) + pricing = Pricing.objects.all() + if pricing.count() > 0: + queryset = pricing.last() + serializer = PricingSerializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + else: + queryset = [] + return Response(queryset, status=status.HTTP_200_OK) + + else: + queryset = Pricing.objects.filter(trash=False).order_by('-date') + serializer = PricingSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class ProvinceCheckOperatorOutRequestViewSet(viewsets.ModelViewSet): +# queryset = ProvinceCheckOperatorOutRequest.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = ProvinceCheckOperatorOutRequestSerializer +# +# def create(self, request, *args, **kwargs): +# # refresh(request.user.id) +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key'], trash=False) +# hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) +# wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() +# request.data.pop('poultry_request_key') +# state = request.data['state'] +# message = request.data['message'] +# request.data.pop('message') +# # if state == 'accepted': +# # if wage_type and wage_type.status == True: +# # if 'payer_type' in request.data.keys() and request.data['payer_type'] is not None: +# # poultry_request.payer_type = request.data['payer_type'] +# # if request.data['payer_type'] == 'buyer': +# # poultry_request.payer_fullname = poultry_request.buyer['firstName'] + " " + \ +# # poultry_request.buyer[ +# # 'lastName'] +# # else: +# # poultry_request.payer_fullname = poultry_request.poultry.user.fullname +# # poultry_request.save() +# # +# # request.data.pop('payer_type') +# # mobile_sms = '' +# # if 'buyer_mobile' in request.data.keys() and request.data['buyer_mobile'] is not None: +# # poultry_request.buyer['mobile'] = request.data['buyer_mobile'] +# # mobile_sms = request.data['buyer_mobile'] +# # poultry_request.save() +# # # request.data.pop('buyer_mobile') +# # if 'poultry_mobile' in request.data.keys() and request.data['poultry_mobile'] is not None: +# # if poultry_request.poultry.user.mobile != request.data['poultry_mobile']: +# # first_mobile_number = poultry_request.poultry.user.mobile +# # second_mobile_number = request.data['poultry_mobile'] +# # # request.data.pop('poultry_mobile') +# # system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) +# # user = User.objects.get(id=system_user_profile.user.id) +# # +# # if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): +# # return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, +# # status=status.HTTP_403_FORBIDDEN) +# # data = { +# # "first_mobile_number": first_mobile_number, +# # "second_mobile_number": second_mobile_number, +# # } +# # req = requests.post( +# # url=ARTA_URL_CHANGE_MOBILE_NUMBER, +# # data=data, +# # verify=False +# # ) +# # if req.status_code == 200: +# # user.username = second_mobile_number +# # user.save() +# # system_user_profile.mobile = second_mobile_number +# # system_user_profile.save() +# # mobile_sms = poultry_request.poultry.user.mobile +# # request.data.pop('buyer_mobile') +# # request.data.pop('poultry_mobile') +# serializer = self.serializer_class(data=request.data) +# if serializer.is_valid(): +# check_out = serializer.create(validated_data=request.data) +# check_out.poultry_request = poultry_request +# check_out.save() +# if state == 'accepted': +# poultry_request.state_process = 'accepted' +# poultry_request.province_state = 'accepted' +# poultry_request.agent = { +# "role": None, +# "fullname": user.fullname, +# "mobile": user.mobile, +# "date": str(datetime.now()), +# } +# # if wage_type and wage_type.status == False: +# hatching.out_province_killed_weight += int(poultry_request.quantity * poultry_request.Index_weight) +# +# hatching.out_province_killed_quantity += poultry_request.quantity +# hatching.save() +# poultry_request.hatching_left_over = hatching.left_over +# # poultry_request.archive_wage = True +# # else: +# # province_out_request_transaction_sms(province=hatching.poultry.address.province.name, +# # buyer=poultry_request.buyer['firstName'] + " " + +# # poultry_request.buyer[ +# # 'lastName'], +# # poultry_name=poultry_request.poultry.user.fullname, +# # quantity=poultry_request.quantity, +# # index_weight=poultry_request.Index_weight, +# # wage=poultry_request.total_wage_amount, +# # mobile=mobile_sms, order_code=poultry_request.order_code, +# # date=poultry_request.send_date.date()) +# +# else: +# poultry_request.state_process = 'rejected' +# poultry_request.province_state = 'rejected' +# poultry_request.agent = { +# "role": None, +# "fullname": user.fullname, +# "mobile": user.mobile, +# "date": str(datetime.now()), +# } +# poultry_request.message = message if message != "" else None +# +# poultry_request.final_state = 'archive' +# poultry_request.save() +# check_serializer = self.serializer_class(check_out) +# +# return Response(check_serializer.data, status=status.HTTP_201_CREATED) +# return Response(serializer.errors) +# +# def destroy(self, request, *args, **kwargs): +# # refresh(request.user.id) +# poultry_request = PoultryRequest.objects.get(key=request.GET['poultry_request_key'], trash=False) +# hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) +# check = ProvinceCheckOperatorOutRequest.objects.get(poultry_request=poultry_request, trash=False) +# check.trash = True +# check.save() +# hatching.out_province_killed_weight -= int(poultry_request.quantity * poultry_request.Index_weight) +# +# hatching.out_province_killed_quantity -= poultry_request.quantity +# hatching.save() +# poultry_request.state_process = 'deleted' +# poultry_request.province_state = 'deleted' +# poultry_request.save() +# return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) +# +# def update(self, request, *args, **kwargs): +# poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key'], trash=False) +# if 'quantity' in request.data.keys() and request.data['quantity'] is not None: +# poultry_request.quantity = request.data['quantity'] +# poultry_request.Index_weight = request.data['Index_weight'] +# poultry_request.save() +# poultry_request.total_wage_amount = int( +# (poultry_request.Index_weight * poultry_request.quantity) * poultry_request.wage) +# poultry_request.save() +# union_percent = poultry_request.union_share_percent / 100 if poultry_request.union_share_percent > 0 else 0 +# company_percent = poultry_request.company_share_percent / 100 if poultry_request.company_share_percent > 0 else 0 +# guilds_percent = poultry_request.guilds_share_percent / 100 if poultry_request.guilds_share_percent > 0 else 0 +# city_share_percent = poultry_request.city_share_percent / 100 if poultry_request.city_share_percent > 0 else 0 +# wallet_share_percent = poultry_request.wallet_share_percent / 100 if poultry_request.wallet_share_percent > 0 else 0 +# other_share_percent = poultry_request.other_share_percent / 100 if poultry_request.other_share_percent > 0 else 0 +# poultry_request.union_share = int(union_percent * poultry_request.total_wage_amount) +# poultry_request.company_share = int(company_percent * poultry_request.total_wage_amount) +# poultry_request.guilds_share = int(guilds_percent * poultry_request.total_wage_amount) +# poultry_request.city_share = int(city_share_percent * poultry_request.total_wage_amount) +# poultry_request.wallet_share = int(wallet_share_percent * poultry_request.total_wage_amount) +# poultry_request.other_share = int(other_share_percent * poultry_request.total_wage_amount) +# poultry_request.save() +# if 'payer_type' in request.data.keys() and request.data['payer_type'] is not None: +# poultry_request.payer_type = request.data['payer_type'] +# if request.data['payer_type'] == 'buyer': +# poultry_request.payer_fullname = poultry_request.buyer['firstName'] + " " + poultry_request.buyer[ +# 'lastName'] +# else: +# poultry_request.payer_fullname = poultry_request.poultry.user.fullname +# poultry_request.save() +# +# mobile_sms = '' +# if 'buyer_mobile' in request.data.keys() and request.data['buyer_mobile'] is not None: +# poultry_request.buyer['mobile'] = request.data['buyer_mobile'] +# mobile_sms = request.data['buyer_mobile'] +# poultry_request.save() +# if 'poultry_mobile' in request.data.keys() and request.data['poultry_mobile'] is not None: +# if poultry_request.poultry.user.mobile != request.data['poultry_mobile']: +# first_mobile_number = poultry_request.poultry.user.mobile +# second_mobile_number = request.data['poultry_mobile'] +# system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) +# user = User.objects.get(id=system_user_profile.user.id) +# +# if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): +# return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, +# status=status.HTTP_403_FORBIDDEN) +# data = { +# "first_mobile_number": first_mobile_number, +# "second_mobile_number": second_mobile_number, +# } +# req = requests.post( +# url=ARTA_URL_CHANGE_MOBILE_NUMBER, +# data=data, +# verify=False +# ) +# if req.status_code == 200: +# user.username = second_mobile_number +# user.save() +# system_user_profile.mobile = second_mobile_number +# system_user_profile.save() +# mobile_sms = poultry_request.poultry.user.mobile +# wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() +# if wage_type and wage_type.status == True: +# province_out_request_transaction_sms(province=poultry_request.poultry.address.province.name, +# buyer=poultry_request.buyer['firstName'] + " " + poultry_request.buyer[ +# 'lastName'], +# poultry_name=poultry_request.poultry.user.fullname, +# quantity=poultry_request.quantity, +# index_weight=poultry_request.Index_weight, +# wage=poultry_request.total_wage_amount, +# mobile=mobile_sms, order_code=poultry_request.order_code, +# date=poultry_request.send_date.date(), +# amount=poultry_request.amount, +# sale_type=poultry_request.free_sale_in_province) +# +# return Response({'result': 'با موفقیت انجام شد.'}, status=status.HTTP_201_CREATED) +class ProvinceCheckOperatorOutRequestViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckOperatorOutRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceCheckOperatorOutRequestSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_requests = PoultryRequest.objects.filter(key=request.data['poultry_request_key'], trash=False) + request.data.pop('poultry_request_key') + now = datetime.now().date() + poultry = SystemUserProfile.objects.filter( + key__in=poultry_requests.filter(payer_type='poultry', sms=False).values_list('poultry__user__key', + flat=True)).values_list('id', + flat=True) + buyer = SystemUserProfile.objects.filter( + key__in=poultry_requests.filter(payer_type='buyer', sms=False).values_list( + 'out_province_poultry_request_buyer__user__key', + flat=True)).values_list('id', flat=True) + poultry_requests_for_sms = poultry_requests.filter(payer_type='poultry').values_list('id', flat=True).distinct() + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + if wage_type and wage_type.status == True: + sms = threading.Thread(target=send_sms_for_final_approval_out_province_threading, + args=(list(buyer), list(poultry_requests_for_sms))) + sms.start() + for poultry_request in poultry_requests: + # if poultry_request.has_wage == False: + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if hatching.left_over >= poultry_request.quantity: + hatching.out_province_killed_weight += int(poultry_request.quantity * poultry_request.Index_weight) + hatching.out_province_killed_quantity += poultry_request.quantity + hatching.save() + else: + different_quantity = poultry_request.quantity - hatching.left_over + hatching.out_province_killed_weight += int(hatching.left_over * poultry_request.Index_weight) + hatching.out_province_killed_quantity += hatching.left_over + hatching.extra_killed_quantity += different_quantity + hatching.save() + url = f'https://rasadyar.net/pay/{base_url_for_sms_report}' + if poultry_request.payer_type == 'poultry': + poultry_request.payment_link = f'{url}/p{poultry_request.poultry.user.user_gate_way_id}{poultry_request.order_code}' + else: + poultry_request.payment_link = f'{url}/b{poultry_request.out_province_poultry_request_buyer.user.user_gate_way_id}' + poultry_request.final_state = 'archive' + poultry_request.province_state = 'accepted' + poultry_request.state_process = 'accepted' + poultry_request.agent = { + "role": None, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + poultry_request.hatching_left_over = poultry_request.hatching.left_over + + poultry_request.save() + + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_201_CREATED) + + def destroy(self, request, *args, **kwargs): + # refresh(request.user.id) + poultry_request = PoultryRequest.objects.get(key=request.GET['poultry_request_key'], trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + check = ProvinceCheckOperatorOutRequest.objects.get(poultry_request=poultry_request, trash=False) + check.trash = True + check.save() + hatching.out_province_killed_weight -= int(poultry_request.quantity * poultry_request.Index_weight) + + hatching.out_province_killed_quantity -= poultry_request.quantity + hatching.save() + poultry_request.state_process = 'deleted' + poultry_request.province_state = 'deleted' + poultry_request.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key'], trash=False) + if 'quantity' in request.data.keys() and request.data['quantity'] is not None: + poultry_request.quantity = request.data['quantity'] + poultry_request.Index_weight = request.data['Index_weight'] + poultry_request.save() + poultry_request.total_wage_amount = int( + (poultry_request.Index_weight * poultry_request.quantity) * poultry_request.wage) + poultry_request.save() + union_percent = poultry_request.union_share_percent / 100 if poultry_request.union_share_percent > 0 else 0 + company_percent = poultry_request.company_share_percent / 100 if poultry_request.company_share_percent > 0 else 0 + guilds_percent = poultry_request.guilds_share_percent / 100 if poultry_request.guilds_share_percent > 0 else 0 + city_share_percent = poultry_request.city_share_percent / 100 if poultry_request.city_share_percent > 0 else 0 + wallet_share_percent = poultry_request.wallet_share_percent / 100 if poultry_request.wallet_share_percent > 0 else 0 + other_share_percent = poultry_request.other_share_percent / 100 if poultry_request.other_share_percent > 0 else 0 + poultry_request.union_share = int(union_percent * poultry_request.total_wage_amount) + poultry_request.company_share = int(company_percent * poultry_request.total_wage_amount) + poultry_request.guilds_share = int(guilds_percent * poultry_request.total_wage_amount) + poultry_request.city_share = int(city_share_percent * poultry_request.total_wage_amount) + poultry_request.wallet_share = int(wallet_share_percent * poultry_request.total_wage_amount) + poultry_request.other_share = int(other_share_percent * poultry_request.total_wage_amount) + poultry_request.save() + if 'payer_type' in request.data.keys() and request.data['payer_type'] is not None: + poultry_request.payer_type = request.data['payer_type'] + if request.data['payer_type'] == 'buyer': + poultry_request.payer_fullname = poultry_request.buyer['firstName'] + " " + poultry_request.buyer[ + 'lastName'] + else: + poultry_request.payer_fullname = poultry_request.poultry.user.fullname + poultry_request.save() + + mobile_sms = '' + if 'buyer_mobile' in request.data.keys() and request.data['buyer_mobile'] is not None: + poultry_request.buyer['mobile'] = request.data['buyer_mobile'] + mobile_sms = request.data['buyer_mobile'] + poultry_request.save() + if 'poultry_mobile' in request.data.keys() and request.data['poultry_mobile'] is not None: + if poultry_request.poultry.user.mobile != request.data['poultry_mobile']: + first_mobile_number = poultry_request.poultry.user.mobile + second_mobile_number = request.data['poultry_mobile'] + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + user = User.objects.get(id=system_user_profile.user.id) + + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + mobile_sms = poultry_request.poultry.user.mobile + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + if wage_type and wage_type.status == True: + province_out_request_transaction_sms(province=poultry_request.poultry.address.province.name, + buyer=poultry_request.buyer['firstName'] + " " + poultry_request.buyer[ + 'lastName'], + poultry_name=poultry_request.poultry.user.fullname, + quantity=poultry_request.quantity, + index_weight=poultry_request.Index_weight, + wage=poultry_request.total_wage_amount, + mobile=mobile_sms, order_code=poultry_request.order_code, + date=poultry_request.send_date.date(), + amount=poultry_request.amount, + sale_type=poultry_request.free_sale_in_province) + + return Response({'result': 'با موفقیت انجام شد.'}, status=status.HTTP_201_CREATED) + + +# ویوست مربوط به تایید یا رد درخواست تایید شده شهرستان +class ProvinceCheckOperatorRequestViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckOperatorRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceCheckOperatorRequestSerializer + + # تابع مربوط به تایید یا رد درخواست تایید شده شهرستان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + state = request.data['state'] + + try: + key = request.data['key'] + request.data.pop('key') + except: + key = None + + try: + poultry_key = request.data['poultry_key'] + request.data.pop('poultry_key') + factor_fee = request.data['factor_fee'] + real_quantity = request.data['real_quantity'] + real_weight = request.data['real_weight'] + request.data.pop('factor_fee') + request.data.pop('real_quantity') + request.data.pop('real_weight') + except: + poultry_key = None + factor_fee = None + real_quantity = None + real_weight = None + + if key != None: + + city_request = CityOperatorCheckRequest.objects.get(key=key, trash=False) + poultry_request = PoultryRequest.objects.get(id=city_request.poultry_request.id, trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + else: + poultry_request = PoultryRequest.objects.get(key=poultry_key, trash=False) + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + province_operator = ProvinceOperator.objects.get(user=user, trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + if key != None: + if ProvinceCheckOperatorRequest.objects.filter(city_request_Poultry=city_request, trash=False).exists(): + return Response({"result": "already exist"}, status=status.HTTP_403_FORBIDDEN) + check = serializer.create(validated_data=request.data) + province_fee = Pricing.objects.all() + if province_fee.count() > 0: + province_fee = province_fee.last().live_chicken_price + check.fee = province_fee + + if key != None: + check.city_request_Poultry = city_request + check.province_operator_system = province_operator + check.quantity = poultry_request.quantity + send_date = poultry_request.send_date.date() + price = Pricing.objects.filter(date__year=send_date.year, date__month=send_date.month, + date__day=send_date.day, trash=False) + if price: + check.fee = price[0].live_chicken_price + else: + check.fee = 0 + + check.poultry_request = poultry_request + check.save() + if state == 'reject': + # poultry_request.state = { + # "city_operator": city_request.city_operator_system.user.first_name + " " + city_request.city_operator_system.user.last_name, + # "city_state": "accepted", + # "city_operator_mobile": city_request.city_operator_system.user.mobile, + # "city_operator_date_time_accepted": str(city_request.create_date), + # "province_operator": user.first_name + " " + user.last_name, + # "province_operator_mobile": user.mobile, + # "province_state": "rejected", + # "province_operator_date_time_accepted": str(check.create_date), + # + # } + poultry_request.province_state = 'rejected' + poultry_request.save() + if poultry_request.kill_house_list != None and len(poultry_request.kill_house_list) > 0: + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=poultry_request.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + kill_request.remain_quantity_for_poultry -= poultry_request.quantity + kill_request.save() + if key != None: + city_request.province_state = 'reject' + message = UserMessage( + message="درخواست شما با کد سفارش {0} از طرف کارشناس استان {1} رد شده است ".format( + poultry_request.order_code, user.fullname), + heading="پیام سیستم ثبت شده در تاریخ {0}".format(datetime.now()), + sender=user + ) + message.save() + message.users.add(poultry_request.poultry.user) + # hatching.left_over += (poultry_request.quantity + poultry_request.losses) + hatching.losses -= poultry_request.losses + hatching.state = 'pending' + hatching.allow_hatching = 'pending' + hatching.save() + elif state == 'accept': + if poultry_key != None: + poultry_factor = ProvinceFactorToKillHouseForPoultry( + province_check_req=check, + total_weight=float(real_weight), + factor_fee=float(factor_fee), + real_weight=float(real_quantity), + out=True + + ) + poultry_factor.save() + if poultry_key != None: + if poultry_request.poultry.user_bank_info != None: + poultry_bank = BankCard.objects.get( + key=poultry_request.poultry.user_bank_info.key) + poultry_factor.bank = poultry_bank + poultry_factor.total_price = poultry_factor.total_weight * poultry_factor.factor_fee + poultry_factor.shares = { + "poultryShareWithProfit": poultry_factor.total_weight * poultry_factor.factor_fee, + } + poultry_factor.save() + poultry_factor.save() + province_factor = ProvinceFactorToKillHouse( + province_check_req=check, + total_weight=float(real_weight), + factor_fee=float(factor_fee), + real_weight=float(real_quantity), + out=True + + ) + province_factor.save() + financial_operator = ProvinceOperator.objects.filter(user__role__name='ProvinceFinancial', + address__province=poultry_request.poultry.address.province) + if financial_operator.count() > 0: + financial_operator = financial_operator.last() + if financial_operator.user_bank_info != None: + province_bank = BankCard.objects.get(id=financial_operator.user_bank_info.id, trash=False) + province_factor.bank = province_bank + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + percent = MonthlyProfitPercentage.objects.all().last() + percent = (percent.percent / 100) / percent.days + union = province_factor.total_weight * share_allocation.total + city_share = province_factor.total_weight * share_allocation.city_union + province_share = province_factor.total_weight * share_allocation.province_union + company_share = province_factor.total_weight * share_allocation.company + fanava_share = province_factor.total_weight * share_allocation.fanava + central_union_share = province_factor.total_weight * share_allocation.central_union + province_factor.total_price = (union * percent) + union + province_factor.shares = { + "unionShareWithProfit": (union * percent) + union, + "city_share": (city_share * percent) + city_share, + "province_share": (province_share * percent) + province_share, + "company_share": (company_share * percent) + company_share, + "fanava_share": (fanava_share * percent) + fanava_share, + "central_union_share": (central_union_share * percent) + central_union_share, + } + province_factor.poultry_factor = poultry_factor + province_factor.save() + + poultry_request.province_state = 'accepted' + poultry_request.save() + if key != None: + city_request.province_state = 'accept' + message = UserMessage( + message="درخواست شما با کد سفارش {0} از طرف کارشناس استان {1} تایید شده است ".format( + poultry_request.order_code, user.fullname), + heading="پیام سیستم ثبت شده در تاریخ {0}".format(datetime.now()), + sender=user + ) + message.save() + message.users.add(poultry_request.poultry.user) + if SmsLicense.objects.filter(province_approval=True).exists(): + poultry_mobile = check.poultry_request.poultry.user.mobile + order_code = check.poultry_request.order_code + # poultry_request_receive_province_accept_sms(poultry_mobile, order_code + # ) + # sms_poultry_request_receive_province_accept_sms = threading.Thread( + # target=poultry_request_receive_province_accept_sms, + # args=( + # poultry_mobile, order_code)) + # sms_poultry_request_receive_province_accept_sms.start() + + if key != None: + city_request.save() + if poultry_request.out == True: + poultry_request.final_state = 'archive' + poultry_request.save() + check_serializer = self.serializer_class(check) + + return Response(check_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش درخواست های تایید شده استان + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + info_dict = [] + info_list = [] + info_province_assignments_list = [] + if 'key' in request.GET: + poultry_request = PoultryRequest.objects.get(key=request.GET['key'], trash=False) + province_request = ProvinceCheckOperatorRequest.objects.filter( + city_request_Poultry__poultry_request=poultry_request, trash=False + ) + if province_request.count() > 0: + province_request = province_request.last() + send__date = province_request.city_request_Poultry.poultry_request.send_date + kill_req = KillRequest.objects.filter(recive_date__year=send__date.year, + recive_date__month=send__date.month, + recive_date__day=send__date.day, trash=False) + if kill_req: + is_car = True + else: + is_car = False + internal_dict_poultry = { + "id": province_request.city_request_Poultry.poultry_request.id, + "full_name": province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + "city": province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + "province": province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + "mobile": province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + "gis_code": province_request.city_request_Poultry.poultry_request.poultry.gis_code, + "poultry_request_quantity": province_request.city_request_Poultry.poultry_request.quantity, + "poultry_request_id": province_request.city_request_Poultry.poultry_request.id, + "poultry_request_inspector": province_request.city_request_Poultry.poultry_request.inspector, + "price": province_request.fee, + "date": province_request.city_request_Poultry.poultry_request.send_date, + "freezing": province_request.city_request_Poultry.poultry_request.freezing, + "register_date": province_request.city_request_Poultry.poultry_request.create_date, + "breed": province_request.city_request_Poultry.poultry_request.chicken_breed, + "order_code": province_request.city_request_Poultry.poultry_request.order_code, + "index_weight": province_request.city_request_Poultry.poultry_request.Index_weight, + "quantity": province_request.quantity, + "chicken_date": province_request.city_request_Poultry.poultry_request.poultry.incubation_date, + "age": ( + datetime.now() - province_request.city_request_Poultry.poultry_request.hatching.date).days, + "key": province_request.key, + "is_car": is_car, + "province_assignments": "", + "kill_house_assignments": "" + } + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.filter(user=user, trash=False) + if kill_house_operator.count() > 0: + kill_house_operator = kill_house_operator.last() + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request=province_request, killhouse_user__in=kill_house, trash=False) + elif request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.filter(user=user, trash=False) + if vet.count() > 0: + vet = vet.last() + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + kill_house_vet = kill_house_vet.last() + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request=province_request, killhouse_user=kill_house_vet.kill_house, + trash=False) + else: + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request=province_request, trash=False) + if province_kill_requests.count() > 0: + kill_house_check = None + for province_kill_request in province_kill_requests: + check = KillHouseCheckRequest.objects.filter(province_kill_request=province_kill_request) + if check.count() > 0: + kill_house_check = check.last().key + kill_house_reqs = True if KillHouseRequest.objects.filter( + province_kill_request=province_kill_request, trash=False) else False + bar = True if KillHouseAssignmentInformation.objects.filter( + kill_house_request__province_kill_request=province_kill_request, trash=False) else False + internal_dict_province_kill_request_infos = { + "province_kill_request_key": province_kill_request.key, + "automatic_state": province_kill_request.automatic, + "return_to_province": province_kill_request.return_to_province, + "kill_house_check_key": kill_house_check, + "payment_type": province_kill_request.payment_type, + "payment_dead_line": province_kill_request.payment_dead_line, + "kill_req_key": province_kill_request.kill_request.key, + "market": province_kill_request.kill_request.market, + "province_kill_request_state": province_kill_request.state, + "kill_house_key": province_kill_request.kill_request.kill_house.key, + "kill_house_name": province_kill_request.kill_request.kill_house.name, + "kill_house_user_name": province_kill_request.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": province_kill_request.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_mobile": province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": province_kill_request.quantity, + "main_quantity": province_kill_request.main_quantity, + "time": province_kill_request.kill_request.recive_time, + "date": province_kill_request.kill_request.recive_date, + "province_kill_request_message": province_kill_request.message, + "kill_house_requests": kill_house_reqs, + "bar_information": bar, + } + + info_province_assignments_list.append(internal_dict_province_kill_request_infos) + + internal_dict_poultry["province_assignments"] = info_province_assignments_list + elif province_kill_requests.count() == 0: + internal_dict_poultry["province_assignments"] = None + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + + kill_house_operator = KillHouseOperator.objects.filter(user=user, trash=False) + if kill_house_operator.count() > 0: + kill_house_operator = kill_house_operator.last() + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + kill_house_requests = KillHouseRequest.objects.filter( + province_request=province_request, killhouse_user__in=kill_house, trash=False) + else: + kill_house_requests = KillHouseRequest.objects.filter( + province_request=province_request, trash=False) + if kill_house_requests.count() > 0: + for kill_house_req_obj in kill_house_requests: + internal_dict_infos = { + "kill_house_req_key": kill_house_req_obj.key, + "kill_req_key": kill_house_req_obj.kill_request.key, + "barcod": kill_house_req_obj.bar_code, + "kill_house_state": kill_house_req_obj.state, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_user_name": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "show_kill_house": kill_house_req_obj.show_kill_house, + "kill_house_message": kill_house_req_obj.kill_house_message, + } + + info_list.append(internal_dict_infos) + + internal_dict_poultry["kill_house_assignments"] = info_list + elif kill_house_requests.count() == 0: + internal_dict_poultry["kill_house_assignments"] = None + return Response(internal_dict_poultry, status=status.HTTP_200_OK) + else: + return Response([], status=status.HTTP_200_OK) + + province_requests = ProvinceCheckOperatorRequest.objects.filter(state='accept', end_state='active', trash=False + ).order_by( + 'city_request_Poultry__poultry_request__send_date') + + for province_request in province_requests: + send__date = province_request.city_request_Poultry.poultry_request.send_date + kill_req = KillRequest.objects.filter(recive_date__year=send__date.year, + recive_date__month=send__date.month, recive_date__day=send__date.day, + trash=False) + if kill_req: + is_car = True + else: + is_car = False + + internal_dict_poultry = { + "id": province_request.city_request_Poultry.poultry_request.id, + "full_name": province_request.city_request_Poultry.poultry_request.user.fullname, + "city": province_request.city_request_Poultry.poultry_request.user.address.city, + "province": province_request.city_request_Poultry.poultry_request.user.address.province, + "mobile": province_request.city_request_Poultry.poultry_request.user.mobile, + "gis_code": province_request.city_request_Poultry.poultry_request.user.gis_code, + "poultry_request_quantity": province_request.city_request_Poultry.poultry_request.quantity, + "poultry_request_id": province_request.city_request_Poultry.poultry_request.id, + "poultry_request_inspector": province_request.city_request_Poultry.poultry_request.inspector, + "price": province_request.fee, + "date": province_request.city_request_Poultry.poultry_request.send_date, + "freezing": province_request.city_request_Poultry.poultry_request.freezing, + "register_date": province_request.city_request_Poultry.poultry_request.create_date, + "breed": province_request.city_request_Poultry.poultry_request.chicken_breed, + "order_code": province_request.city_request_Poultry.poultry_request.order_code, + "index_weight": province_request.city_request_Poultry.poultry_request.Index_weight, + "quantity": province_request.quantity, + "chicken_date": province_request.city_request_Poultry.poultry_request.user.incubation_date, + "age": ( + province_request.city_request_Poultry.poultry_request.send_date - province_request.city_request_Poultry.poultry_request.user.incubation_date).days + 2, + "key": province_request.key, + "is_car": is_car, + "province_assignments": "", + "Assignments": "" + } + + for province_kill_request in ProvinceKillRequest.objects.filter( + province_request=province_request, trash=False): + internal_dict_province_kill_request_infos = { + "province_kill_request_key": province_kill_request.key, + "automatic_state": province_kill_request.automatic, + "kill_req_key": province_kill_request.kill_request.key, + "market": province_kill_request.kill_request.market, + "province_kill_request_state": province_kill_request.state, + "kill_house_name": province_kill_request.kill_request.kill_house.name, + "kill_house_user_name": province_kill_request.kill_request.kill_house.user.fullname, + "kill_house_user_city": province_kill_request.kill_request.kill_house.user.address.city, + "kill_house_mobile": province_kill_request.kill_request.kill_house.user.mobile, + "quantity": province_kill_request.quantity, + "time": province_kill_request.kill_request.recive_time, + "date": province_kill_request.kill_request.recive_date, + "province_kill_request_message": province_kill_request.kill_house_message, + } + + info_province_assignments_list.append(internal_dict_province_kill_request_infos) + + internal_dict_poultry["province_assignments"] = info_province_assignments_list + + for kill_house_req_obj in KillHouseRequest.objects.filter( + province_request=province_request, trash=False): + internal_dict_infos = { + "kill_house_req_key": kill_house_req_obj.key, + "kill_req_key": kill_house_req_obj.kill_request.key, + "barcod": kill_house_req_obj.bar_code, + "kill_house_state": kill_house_req_obj.state, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_user_name": kill_house_req_obj.kill_request.kill_house.user.fullname, + "kill_house_user_city": kill_house_req_obj.kill_request.kill_house.user.address.city, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "show_kill_house": kill_house_req_obj.show_kill_house, + "kill_house_message": kill_house_req_obj.kill_house_message, + } + + info_list.append(internal_dict_infos) + + internal_dict_poultry["Assignments"] = info_list + # info_dict.update(internal_dict_poultry) + info_dict.append(internal_dict_poultry) + info_list = [] + + return Response(info_dict, status=status.HTTP_200_OK) + + +# ویوست مربوط به تایید یا رد درخواست تایید شده شهرستان +class ProvinceRequestActionViewSet(viewsets.ModelViewSet): + queryset = ProvinceRequestAction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceRequestActionSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + operator = ProvinceOperator.objects.get(user=user, trash=False) + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key'], trash=False) + auction_list = request.data['auction_list'] + request.data.pop('poultry_request_key') + request.data.pop('auction_list') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + province_auction = serializer.create(validated_data=request.data) + province_auction.poultry_request = poultry_request + if len(auction_list) > 0: + i = 0 + for auction in auction_list: + poultry_request_auction = PoultryRequestAuction( + poultry_request=poultry_request, + pricing=Pricing.objects.all(), + fee=auction['fee'], + hour=auction['hour'] + ) + poultry_request_auction.save() + poultry_auction = PoultryRequestAuction.objects.filter(poultry_request=poultry_request, + state__in=('active', 'inactive'), + trash=False).order_by( + 'auction_date') + if poultry_auction.count() > 0: + if i == 0: + poultry_request_auction.auction_date = datetime.now() + timedelta( + hours=int(poultry_request_auction.hour)) + poultry_request_auction.state = 'active' + else: + poultry_request_auction.auction_date = poultry_auction[i - 1].auction_date + timedelta( + hours=int(poultry_request_auction.hour)) + i += 1 + poultry_request_auction.save() + + poultry_request.auction = True + poultry_request.save() + province_auction.province_operator_system = operator + province_auction.state = 'active' + province_auction.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به تایید یا رد اطلاعات بار وارد شده از سمت کشتارگاه +class ProvinceCheckInformationViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckInformation.objects.all() + serializer_class = ProvinceCheckInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به تایید یا رد اطلاعات بار وارد شده از سمت کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + poultry_cost_wallet = 0 + city_cost_wallet = 0 + province_cost_wallet = 0 + kill_house_cost_wallet = 0 + if 'pay' in request.data.keys(): + pay = request.data['pay'] + request.data.pop('pay') + else: + if 'pay' in request.data.keys(): + request.data.pop('pay') + pay = None + + if 'reason' in request.data.keys() and request.data['reason'] != None: + reason = request.data['reason'] + request.data.pop('reason') + else: + if 'reason' in request.data.keys(): + request.data.pop('reason') + reason = None + + if 'province_input_wage' in request.data.keys() and request.data['province_input_wage'] != None: + province_input_wage = float(request.data['province_input_wage']) + request.data.pop('province_input_wage') + else: + if 'province_input_wage' in request.data.keys(): + request.data.pop('province_input_wage') + + province_input_wage = None + + if 'province_input_amount' in request.data.keys() and 'province_input_amount_state' in request.data.keys() and \ + request.data['province_input_amount'] != None and request.data['province_input_amount_state'] != None: + province_input_amount = float(request.data['province_input_amount']) + request.data.pop('province_input_amount') + province_input_amount_state = request.data['province_input_amount_state'] + request.data.pop('province_input_amount_state') + else: + if 'province_input_amount' in request.data.keys() and 'province_input_amount_state' in request.data.keys(): + request.data.pop('province_input_amount') + request.data.pop('province_input_amount_state') + + province_input_amount = None + province_input_amount_state = None + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + operator = ProvinceOperator.objects.get(user=user, trash=False) + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + # total = share_allocation.total + # else: + # total = 0 + + kill_house_info = KillHouseAssignmentInformation.objects.get(key=request.data['kill_house_info_key'], + trash=False) + request.data.pop('kill_house_info_key') + if 'bank' in request.data.keys(): + factor_person_type = request.data['bank'] + if request.data['bank'] == 'poultry': + poultry = Poultry.objects.get( + key=kill_house_info.kill_house_request.province_request.poultry_request.poultry.key, trash=False) + if poultry.user_bank_info != None: + bank = BankCard.objects.get(id=poultry.user_bank_info.id, trash=False) + else: + return Response({"result": "اطلاعات مالی مرغدار وارد نشده است"}, status=status.HTTP_403_FORBIDDEN) + elif request.data['bank'] == 'union': + if operator.user_bank_info != None: + bank = BankCard.objects.get(id=operator.user_bank_info.id, trash=False) + else: + return Response({"result": "اطلاعات مالی استان وارد نشده است"}, status=status.HTTP_403_FORBIDDEN) + request.data.pop('bank') + + if 'real_weight' in request.data.keys(): + real_weight = float(request.data['real_weight']) + request.data.pop('real_weight') + else: + real_weight = 0 + if 'fee' in request.data.keys(): + fee = request.data['fee'] + request.data.pop('fee') + else: + fee = 0 + + if kill_house_info.kill_house_request.province_kill_request != None: + province_check = kill_house_info.kill_house_check.province_kill_request.province_request + pou_req = kill_house_info.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request + else: + province_check = None + + try: + kill_house_image_without_load = request.data['kill_house_image_without_load'] + request.data.pop('kill_house_image_without_load') + except: + kill_house_image_without_load = None + + try: + kill_house_image_with_load = request.data['kill_house_image_with_load'] + request.data.pop('kill_house_image_with_load') + except: + kill_house_image_with_load = None + + try: + kill_house_car_weight_without_load = request.data['kill_house_car_weight_without_load'] + request.data.pop('kill_house_car_weight_without_load') + + except: + kill_house_car_weight_without_load = None + try: + kill_house_car_weight_with_load = request.data['kill_house_car_weight_with_load'] + request.data.pop('kill_house_car_weight_with_load') + + except: + kill_house_car_weight_with_load = None + + if KillHouseComplaint.objects.filter(bar=kill_house_info, state='pending').exists(): + return Response({"result": "can not create"}, status=status.HTTP_406_NOT_ACCEPTABLE) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + province_info = serializer.create(validated_data=request.data) + province_info.kill_house_assignment = kill_house_info + province_info.save() + if province_info.state == 'accepted': + kill_house_info.state = 'accepted' + if kill_house_image_without_load != None: + kill_house_info.car_weight_without_load_image = send_image_to_server(kill_house_image_without_load) + elif kill_house_image_with_load != None: + kill_house_info.car_weight_with_load_image = send_image_to_server(kill_house_image_with_load) + elif kill_house_car_weight_without_load != None: + kill_house_info.car_weight_without_load = kill_house_car_weight_without_load + elif kill_house_car_weight_with_load != None: + kill_house_info.car_weight_with_load = kill_house_car_weight_with_load + kill_house_info.save() + if pay == 'together': + province_info.kill_house_assignment = kill_house_info + province_info.save() + if province_check != None: + if KillHouseComplaint.objects.filter(state='accepted', bar=kill_house_info).exists(): + t_weight = kill_house_info.weight_withs_losses + else: + t_weight = kill_house_info.net_weight + + list1 = KillHouseRequest.objects.filter( + province_kill_request=kill_house_info.kill_house_request.province_kill_request) + + factor = ProvinceFactorToKillHouse( + province_check_info=province_info, + total_weight=t_weight, + factor_fee=float(fee), + factor_person_type=factor_person_type, + # factor_fee=kill_house_info.kill_house_check.province_kill_request.fee, + factor_date=kill_house_info.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date, + factor_bar_code=kill_house_info.kill_house_request.bar_code, + real_weight=real_weight, + province_check_req=kill_house_info.kill_house_check.province_kill_request.province_request, + ) + factor.save() + province_factors_count = 0 + poultry_factors_count = 0 + total_count = 0 + province_factors_counter = 0 + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request, + poultry_factor__isnull=True) + poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request) + if province_factors.count() > 0: + province_factors_count = province_factors.count() + if poultry_factors.count() > 0: + poultry_factors_count = poultry_factors.count() + for poultry in poultry_factors: + if ProvinceFactorToKillHouse.objects.filter(poultry_factor=poultry).exists(): + province_factors_counter += 1 + if poultry_factors_count == province_factors_counter or province_factors_counter == 0: + total_count = province_factors_count + poultry_factors_count + if province_factors_counter > 0: + if poultry_factors_count > 0: + poultry_factors_count -= province_factors_counter + total_count = province_factors_count + poultry_factors_count + else: + total_count = province_factors_count + if bank != None: + factor.bank = bank + factor.save() + province_check.total_weight_at_end += factor.total_weight + province_check.save() + province_info.save() + province_kill_req = ProvinceKillRequest.objects.get( + key=kill_house_info.kill_house_check.province_kill_request.key) + + province_kill_req.fee = fee + if province_kill_req.payment_type == 'credit': + percent = MonthlyProfitPercentage.objects.all().last() + percent = (percent.percent / 100) / percent.days + total = factor.total_weight * factor.factor_fee + union = factor.total_weight * share_allocation.total + city_share = factor.total_weight * share_allocation.city_union + province_share = factor.total_weight * share_allocation.province_union + company_share = factor.total_weight * share_allocation.company + fanava_share = factor.total_weight * share_allocation.fanava + central_union_share = factor.total_weight * share_allocation.central_union + factor.total_price = ((total + union) * percent) + (total + union) + factor.shares = { + "poultryShareWithProfit": (total * percent) + total, + "unionShareWithProfit": (union * percent) + union, + "city_share": (city_share * percent) + city_share, + "province_share": (province_share * percent) + province_share, + "company_share": (company_share * percent) + company_share, + "fanava_share": (fanava_share * percent) + fanava_share, + "central_union_share": (central_union_share * percent) + central_union_share, + } + factor.save() + # factor.today_price = total + + if list1.count() > 0 and total_count > 0: + if list1.count() == total_count: + dead_line = PaymentDeadLine.objects.all().last() + province_kill_req.payment_dead_line = datetime.now().date() + timedelta( + days=dead_line.days) + else: + if province_input_wage != None: + province_share_allocation = province_input_wage + factor.province_wage = province_input_wage + else: + province_share_allocation = share_allocation.total + factor.province_wage = share_allocation.total + if province_input_amount != None: + if province_input_amount_state != None and province_input_amount_state == 'decrease': + factor.total_price = (factor.total_weight * factor.factor_fee) + ( + factor.total_weight * province_share_allocation) - province_input_amount + factor.province_input_amount_type = 'decrease' + factor.province_input_amount = province_input_amount + else: + factor.total_price = (factor.total_weight * factor.factor_fee) + ( + factor.total_weight * province_share_allocation) + province_input_amount + factor.province_input_amount_type = 'plus' + factor.province_input_amount = province_input_amount + if reason != None: + factor.reason = reason + + else: + factor.total_price = (factor.total_weight * factor.factor_fee) + ( + factor.total_weight * province_share_allocation) + kill_request_sms_payment = KillRequest.objects.filter( + key=kill_house_info.kill_house_check.province_kill_request.kill_request.key) + if kill_request_sms_payment.count() > 0: + kill_request_sms_payment = kill_request_sms_payment.last() + if kill_request_sms_payment.sms_payment == True: + factor.total_price += 50000 + factor.shares = { + "poultryShareWithProfit": factor.total_weight * factor.factor_fee, + "unionShareWithProfit": factor.total_weight * province_share_allocation, + "poultry_share": factor.total_weight * factor.factor_fee, + "city_share": 0, + "province_share": factor.total_weight * province_share_allocation, + "company_share": 0, + "fanava_share": 0, + "central_union_share": 0, + # "city_share": factor.total_weight * share_allocation.city_union, + # "province_share": factor.total_weight * share_allocation.province_union, + # "company_share": factor.total_weight * share_allocation.company, + # "fanava_share": factor.total_weight * share_allocation.fanava, + # "central_union_share": factor.total_weight * share_allocation.central_union, + } + factor.save() + + province_kill_req.save() + poultry_cost_wallet = factor.shares['poultryShareWithProfit'] + city_cost_wallet = factor.shares['city_share'] + province_cost_wallet = factor.shares['province_share'] + kill_house_cost_wallet = factor.shares['poultryShareWithProfit'] + factor.shares[ + 'unionShareWithProfit'] + + else: + factor = ProvinceFactorToKillHouse( + province_check_info=province_info, + total_weight=kill_house_info.net_weight, + factor_fee=float(fee), + # factor_fee=kill_house_info.kill_house_request.kill_house_request_auction_winner.fee, + factor_date=kill_house_info.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date, + factor_bar_code=kill_house_info.kill_house_request.bar_code, + real_weight=real_weight, + province_check_req=kill_house_info.kill_house_check.province_kill_request.province_request, + + ) + factor.save() + if bank != None: + factor.bank = bank + factor.total_price = (factor.total_weight * factor.factor_fee) + ( + factor.total_weight * share_allocation.total) + factor.save() + province_info.province_operator = operator + province_info.save() + auction_winner = KillHouseRequestActionWinner.objects.get( + key=kill_house_info.kill_house_request.kill_house_request_auction_winner.key) + auction_winner.fee = fee + auction_winner.save() + + province_factors_count = 0 + poultry_factors_count = 0 + total_count = 0 + province_factors_counter = 0 + kill_house_requests = KillHouseRequest.objects.filter( + province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request) + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request, + poultry_factor__isnull=True) + poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request) + if province_factors.count() > 0: + province_factors_count = province_factors.count() + if poultry_factors.count() > 0: + poultry_factors_count = poultry_factors.count() + for poultry in poultry_factors: + if ProvinceFactorToKillHouse.objects.filter(poultry_factor=poultry).exists(): + province_factors_counter += 1 + if poultry_factors_count == province_factors_counter or province_factors_counter == 0: + total_count = province_factors_count + poultry_factors_count + if province_factors_counter > 0: + if poultry_factors_count > 0: + poultry_factors_count -= province_factors_counter + total_count = province_factors_count + poultry_factors_count + else: + total_count = province_factors_count + + if kill_house_requests.count() == total_count: + poultry_request = PoultryRequest.objects.get( + key=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.key) + poultry_request.awaiting_payment = True + poultry_request.save() + poultry_wallet = pou_req.poultry.wallet + city_wallet = CityOperator.objects.get(key=pou_req.city_operator.key).wallet + province_wallet = operator.wallet + + poultry_transaction = Itransaction( + wallet=pou_req.poultry.wallet, + transfer_amount=poultry_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + ) + poultry_transaction.save() + # poultry_wallet.inventory += poultry_transaction.transfer_amount + # poultry_wallet.save() + + kill_housse_wallet = kill_house_info.kill_house_request.province_kill_request.kill_request.kill_house.kill_house_operator.wallet + kill_house_transaction = Itransaction( + wallet=kill_housse_wallet, + transfer_amount=kill_house_cost_wallet, + transaction_type='debtor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + kill_house_transaction.save() + # kill_housse_wallet.inventory -= kill_house_transaction.transfer_amount + # kill_housse_wallet.save() + + if city_cost_wallet > 0 and province_cost_wallet > 0: + city_transaction = Itransaction( + wallet=city_wallet, + transfer_amount=city_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + city_transaction.save() + # city_wallet.inventory += city_transaction.transfer_amount + # city_wallet.save() + + province_transaction = Itransaction( + wallet=province_wallet, + transfer_amount=province_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + province_transaction.save() + # province_wallet.inventory += city_transaction.transfer_amount + # province_wallet.save() + if factor.total_price == 0: + kill_house_factor = KillHouseFactorToProvince( + province_factor=factor, + importer='ProvinceOperator', + first_payment=True, + ) + kill_house_factor.save() + factor.kill_house_factor_info = 'accepted' + factor.paid_state = 'paid' + factor.decreasing_amount = factor.total_price + + factor.save() + else: + kill_house_factor_payment = KillRequestFactorPayment.objects.filter( + kill_request_factor__kill_request=kill_house_info.kill_house_check.province_kill_request.kill_request) + + if kill_house_factor_payment.count() > 0: + kill_house_factor_payment = kill_house_factor_payment.last() + factor.kill_house_factor_payment = kill_house_factor_payment.remain_amount + factor.save() + if factor.total_price > kill_house_factor_payment.remain_amount and kill_house_factor_payment.remain_amount > 0: + factor.previous_amount = factor.total_price + factor.decreasing_amount = kill_house_factor_payment.remain_amount + factor.total_price -= kill_house_factor_payment.remain_amount + kill_house = KillHouse.objects.get( + key=kill_house_info.kill_house_check.province_kill_request.kill_request.kill_house.key) + kill_house.wallet_amount -= kill_house_factor_payment.remain_amount + kill_house.save() + kill_house_factor_payment.remain_amount = 0 + kill_house_factor_payment.save() + + else: + + kill_house_factor = KillHouseFactorToProvince( + province_factor=factor, + payment_code=kill_house_factor_payment.payment_code, + factor_image=kill_house_factor_payment.image, + importer='ProvinceOperator', + first_payment=True, + ) + kill_house_factor.save() + factor.kill_house_factor_info = 'accepted' + factor.paid_state = 'paid' + factor.decreasing_amount = factor.total_price + + factor.save() + kill_house = KillHouse.objects.get( + key=kill_house_info.kill_house_check.province_kill_request.kill_request.kill_house.key) + kill_house.wallet_amount -= factor.total_price + kill_house.save() + kill_house_factor_payment.remain_amount -= factor.total_price + kill_house_factor_payment.save() + + province_info_serializer = self.serializer_class(province_info) + return Response(province_info_serializer.data, status=status.HTTP_201_CREATED) + + else: + if province_check != None: + if KillHouseComplaint.objects.filter(state='accepted', bar=kill_house_info).exists(): + t_weight = kill_house_info.weight_withs_losses + else: + t_weight = kill_house_info.net_weight + # list1 = KillHouseRequest.objects.filter( + # province_kill_request=kill_house_info.kill_house_request.province_kill_request) + + poultry_factor = ProvinceFactorToKillHouseForPoultry( + province_check_info=province_info, + total_weight=t_weight, + factor_fee=float(fee), + # factor_fee=kill_house_info.kill_house_check.province_kill_request.fee, + factor_date=kill_house_info.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date, + factor_bar_code=kill_house_info.kill_house_request.bar_code, + real_weight=real_weight, + province_check_req=kill_house_info.kill_house_check.province_kill_request.province_request, + + ) + poultry_factor.save() + if province_check.city_request_Poultry.poultry_request.poultry.user_bank_info != None: + poultry_bank = BankCard.objects.get( + key=province_check.city_request_Poultry.poultry_request.poultry.user_bank_info.key) + poultry_factor.bank = poultry_bank + poultry_factor.save() + # province_factors_count = 0 + # poultry_factors_count = 0 + # total_count = 0 + # province_factors_counter = 0 + # province_factors = ProvinceFactorToKillHouse.objects.filter( + # province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request) + # # poultry_factor__isnull=True) + # poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + # province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request) + # if province_factors.count() > 0: + # province_factors_count = province_factors.count() + # if poultry_factors.count() > 0: + # poultry_factors_count = poultry_factors.count() + # for poultry in poultry_factors: + # if ProvinceFactorToKillHouse.objects.filter(poultry_factor=poultry).exists(): + # province_factors_counter += 1 + # + # if poultry_factors_count == province_factors_counter or province_factors_counter == 0: + # if poultry_factors_count == province_factors_counter and poultry_factors_count != 0: + # if province_factors_count == province_factors_counter: + # total_count = poultry_factors_count + # elif province_factors_count > province_factors_counter: + # total_count = poultry_factors_count + ( + # province_factors_count - province_factors_counter) + # total_count = province_factors_count + poultry_factors_count + # if province_factors_counter > 0: + # if poultry_factors_count > 0: + # poultry_factors_count -= province_factors_counter + # total_count = province_factors_count + poultry_factors_count + # else: + # total_count = province_factors_count + + province_kill_req = ProvinceKillRequest.objects.get( + key=kill_house_info.kill_house_check.province_kill_request.key) + + if province_kill_req.payment_type == 'credit': + percent = MonthlyProfitPercentage.objects.all().last() + percent = (percent.percent / 100) / percent.days + total = poultry_factor.total_weight * poultry_factor.factor_fee + poultry_factor.total_price = (total * percent) + total + poultry_factor.shares = { + "poultryShareWithProfit": (total * percent) + total, + } + poultry_factor.save() + + # if list1.count() > 0 and total_count > 0: + # if list1.count() == total_count: + if province_kill_req.payment_dead_line == None: + dead_line = PaymentDeadLine.objects.all().last() + province_kill_req.payment_dead_line = datetime.now().date() + timedelta( + days=dead_line.days) + else: + poultry_factor.total_price = (poultry_factor.total_weight * poultry_factor.factor_fee) + poultry_factor.shares = { + "poultryShareWithProfit": poultry_factor.total_weight * poultry_factor.factor_fee, + } + poultry_factor.save() + province_check.save() + province_info.save() + poultry_cost_wallet = poultry_factor.shares['poultryShareWithProfit'] + kill_house_cost_wallet = poultry_factor.shares['poultryShareWithProfit'] + if share_allocation.total != 0: + if KillHouseComplaint.objects.filter(state='accepted', bar=kill_house_info).exists(): + t_weight = kill_house_info.weight_withs_losses + else: + t_weight = kill_house_info.net_weight + factor = ProvinceFactorToKillHouse( + province_check_info=province_info, + total_weight=t_weight, + factor_fee=float(fee), + # factor_fee=kill_house_info.kill_house_check.province_kill_request.fee, + factor_date=kill_house_info.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date, + factor_bar_code=kill_house_info.kill_house_request.bar_code, + real_weight=real_weight, + province_check_req=kill_house_info.kill_house_check.province_kill_request.province_request, + ) + factor.save() + # province_factors_count = 0 + # poultry_factors_count = 0 + # total_count = 0 + # province_factors_counter = 0 + # province_factors = ProvinceFactorToKillHouse.objects.filter( + # province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request) + # # poultry_factor__isnull=True) + # poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + # province_check_info__kill_house_assignment__kill_house_request__province_kill_request=kill_house_info.kill_house_request.province_kill_request) + # if province_factors.count() > 0: + # province_factors_count = province_factors.count() + # if poultry_factors.count() > 0: + # poultry_factors_count = poultry_factors.count() + # for poultry in poultry_factors: + # if ProvinceFactorToKillHouse.objects.filter(poultry_factor=poultry).exists(): + # province_factors_counter += 1 + # if poultry_factors_count == province_factors_counter or province_factors_counter == 0: + # if poultry_factors_count == province_factors_counter and poultry_factors_count != 0: + # if province_factors_count == province_factors_counter: + # total_count = poultry_factors_count + # elif province_factors_count > province_factors_counter: + # total_count = poultry_factors_count + ( + # province_factors_count - province_factors_counter) + + # total_count = province_factors_count + poultry_factors_count + # if province_factors_counter > 0: + # if poultry_factors_count > 0: + # poultry_factors_count -= province_factors_counter + # total_count = province_factors_count + poultry_factors_count + # else: + # total_count = province_factors_count + + if bank != None: + factor.bank = bank + factor.save() + province_check.total_weight_at_end += factor.total_weight + province_check.save() + province_info.save() + province_kill_req = ProvinceKillRequest.objects.get( + key=kill_house_info.kill_house_check.province_kill_request.key) + province_kill_req.fee = fee + if province_kill_req.payment_type == 'credit': + percent = MonthlyProfitPercentage.objects.all().last() + percent = (percent.percent / 100) / percent.days + union = factor.total_weight * share_allocation.total + city_share = factor.total_weight * share_allocation.city_union + province_share = factor.total_weight * share_allocation.province_union + company_share = factor.total_weight * share_allocation.company + fanava_share = factor.total_weight * share_allocation.fanava + central_union_share = factor.total_weight * share_allocation.central_union + factor.total_price = (union * percent) + union + factor.shares = { + "unionShareWithProfit": (union * percent) + union, + "city_share": (city_share * percent) + city_share, + "province_share": (province_share * percent) + province_share, + "company_share": (company_share * percent) + company_share, + "fanava_share": (fanava_share * percent) + fanava_share, + "central_union_share": (central_union_share * percent) + central_union_share, + } + factor.poultry_factor = poultry_factor + factor.save() + # factor.today_price = total + + + # if list1.count() > 0 and total_count > 0: + # if list1.count() == total_count: + if province_kill_req.payment_dead_line == None: + dead_line = PaymentDeadLine.objects.all().last() + province_kill_req.payment_dead_line = datetime.now().date() + timedelta( + days=dead_line.days) + else: + factor.total_price = factor.total_weight * share_allocation.total + factor.shares = { + "unionShareWithProfit": factor.total_weight * share_allocation.total, + "city_share": factor.total_weight * share_allocation.city_union, + "province_share": factor.total_weight * share_allocation.province_union, + "company_share": factor.total_weight * share_allocation.company, + "fanava_share": factor.total_weight * share_allocation.fanava, + "central_union_share": factor.total_weight * share_allocation.central_union, + } + factor.poultry_factor = poultry_factor + factor.save() + kill_house_cost_wallet += factor.shares['unionShareWithProfit'] + city_cost_wallet = factor.shares['city_share'] + province_cost_wallet = factor.shares['province_share'] + province_info.save() + province_kill_req.save() + + else: + factor = ProvinceFactorToKillHouse( + province_check_info=province_info, + total_weight=kill_house_info.net_weight, + factor_fee=float(fee), + # factor_fee=kill_house_info.kill_house_request.kill_house_request_auction_winner.fee, + factor_date=kill_house_info.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request.send_date, + factor_bar_code=kill_house_info.kill_house_request.bar_code, + real_weight=real_weight, + + ) + factor.save() + if bank != None: + factor.bank = bank + factor.total_price = (factor.total_weight * factor.factor_fee) + ( + factor.total_weight * share_allocation.total) + factor.save() + province_info.province_operator = operator + province_info.save() + auction_winner = KillHouseRequestActionWinner.objects.get( + key=kill_house_info.kill_house_request.kill_house_request_auction_winner.key) + auction_winner.fee = fee + auction_winner.save() + + province_factors_count = 0 + poultry_factors_count = 0 + total_count = 0 + province_factors_counter = 0 + kill_house_requests = KillHouseRequest.objects.filter( + province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request) + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request, + poultry_factor__isnull=True) + poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request__province_request__city_request_Poultry__poultry_request=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request) + if province_factors.count() > 0: + province_factors_count = province_factors.count() + if poultry_factors.count() > 0: + poultry_factors_count = poultry_factors.count() + for poultry in poultry_factors: + if ProvinceFactorToKillHouse.objects.filter(poultry_factor=poultry).exists(): + province_factors_counter += 1 + if poultry_factors_count == province_factors_counter or province_factors_counter == 0: + total_count = province_factors_count + poultry_factors_count + if province_factors_counter > 0: + if poultry_factors_count > 0: + poultry_factors_count -= province_factors_counter + total_count = province_factors_count + poultry_factors_count + else: + total_count = province_factors_count + + if kill_house_requests.count() == total_count: + poultry_request = PoultryRequest.objects.get( + key=kill_house_info.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.key) + poultry_request.awaiting_payment = True + poultry_request.save() + poultry_wallet = pou_req.poultry.wallet + city_wallet = CityOperator.objects.get(key=pou_req.city_operator.key).wallet + province_wallet = operator.wallet + + poultry_transaction = Itransaction( + wallet=pou_req.poultry.wallet, + transfer_amount=poultry_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + poultry_transaction.save() + # poultry_wallet.inventory += poultry_transaction.transfer_amount + # poultry_wallet.save() + + kill_housse_wallet = kill_house_info.kill_house_request.province_kill_request.kill_request.kill_house.kill_house_operator.wallet + kill_house_transaction = Itransaction( + wallet=kill_housse_wallet, + transfer_amount=kill_house_cost_wallet, + transaction_type='debtor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + kill_house_transaction.save() + # kill_housse_wallet.inventory -= kill_house_transaction.transfer_amount + # kill_housse_wallet.save() + + if city_cost_wallet > 0 and province_cost_wallet > 0: + city_transaction = Itransaction( + wallet=city_wallet, + transfer_amount=city_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + city_transaction.save() + # city_wallet.inventory += city_transaction.transfer_amount + # city_wallet.save() + + province_transaction = Itransaction( + wallet=province_wallet, + transfer_amount=province_cost_wallet, + transaction_type='creditor', + payment_code=kill_house_info.kill_house_request.bar_code, + file_id=pou_req.id, + + ) + province_transaction.save() + # province_wallet.inventory += city_transaction.transfer_amount + # province_wallet.save() + + province_info_serializer = self.serializer_class(province_info) + return Response(province_info_serializer.data, status=status.HTTP_201_CREATED) + + + + elif province_info.state == 'rejected': + kill_house_info.state = 'rejected' + kill_house_info.message = province_info.message + kill_house_info.save() + # province_check.save() + province_info.province_operator = operator + province_info.save() + province_info_serializer = self.serializer_class(province_info) + return Response(province_info_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش اطلاعات بار وارد شده از سمت کشتارگاه + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + province_operator = UserProfile.objects.get(user=request.user, trash=False) + # info_dict = {} + info_dict = [] + info_list = [] + province_requests = ProvinceCheckOperatorRequest.objects.filter(state='accept', end_state='active', trash=False) + + for province_request in province_requests: + internal_dict_poultry = { + "id": province_request.city_request_Poultry.poultry_request.id, + "full_name": province_request.city_request_Poultry.poultry_request.user.fullname, + "mobile": province_request.city_request_Poultry.poultry_request.user.mobile, + "poultry_request_quantity": province_request.city_request_Poultry.poultry_request.quantity, + "price": province_request.fee, + "date": province_request.city_request_Poultry.poultry_request.send_date, + "breed": province_request.city_request_Poultry.poultry_request.chicken_breed, + "order_code": province_request.city_request_Poultry.poultry_request.order_code, + "informations": "" + } + for kill_house_req_obj in KillHouseRequest.objects.filter(state='accepted', active_state='active', + province_request=province_request, trash=False): + province_req = kill_house_req_obj.province_request + + kill_house_assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_check__province_kill_request__province_request=province_req, trash=False) + # poultry_assignment = PoultryAssignmentInformation.objects.filter( + # kill_house_check_poultry__kill_house_request__bar_code=kill_house_req_obj.bar_code) + if kill_house_assignment: + # return Response (kill_house_assignment[0].car_weight_without_load) + internal_dict_infos = { + "barcod": kill_house_req_obj.bar_code, + "kill_house_state": kill_house_req_obj.state, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_user_name": kill_house_req_obj.kill_request.kill_house.user.fullname, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "kill_house_assigment_key": kill_house_assignment[0].key, + "kill_house_assigment_state": kill_house_assignment[0].state, + "kill_house_weight_without_load": kill_house_assignment[0].car_weight_without_load, + "kill_house_weight_with_load": kill_house_assignment[0].car_weight_with_load, + "kill_house_image_without_load": kill_house_assignment[0].car_weight_without_load_image, + "kill_house_image_with_load": kill_house_assignment[0].car_weight_with_load_image, + "kill_house_net_weight": kill_house_assignment[0].net_weight, + } + if kill_house_assignment[0].state == 'accepted': + province_check_info = ProvinceCheckInformation.objects.get( + kill_house_assignment=kill_house_assignment[0], + state='accepted', trash=False) + internal_dict_infos.update({"province_operator": province_operator.fullname, + "date_of_registration": province_check_info.create_date}) + + info_list.append(internal_dict_infos) + + if not kill_house_assignment: + internal_dict_infos = { + "barcod": kill_house_req_obj.bar_code, + "kill_house_state": kill_house_req_obj.state, + "kill_house_name": kill_house_req_obj.kill_request.kill_house.name, + "kill_house_user_name": kill_house_req_obj.kill_request.kill_house.user.fullname, + "kill_house_mobile": kill_house_req_obj.kill_request.kill_house.user.mobile, + "quantity": kill_house_req_obj.quantity, + "time": kill_house_req_obj.kill_request.recive_time, + "date": kill_house_req_obj.kill_request.recive_date, + "cars": kill_house_req_obj.car, + "kill_house_assigment_key": "", + "poultry_assigment_key": "", + "kill_house_weight_without_load": "", + "kill_house_weight_with_load": "", + "poultry_weight_without_load": "", + "poultry_weight_with_load": "", + "kill_house_image_without_load": "", + "kill_house_image_with_load": "", + "poultry_image_without_load": "", + "poultry_image_with_load": "", + "kill_house_net_weight": "", + "poultry_net_weight": "" + } + info_list.append(internal_dict_infos) + + internal_dict_poultry["informations"] = info_list + info_dict.append(internal_dict_poultry) + info_list = [] + + return Response(info_dict, status=status.HTTP_200_OK) + + +class ProvinceFactorToKillHouseForPoultryViewSet(viewsets.ModelViewSet): + queryset = ProvinceFactorToKillHouseForPoultry.objects.all() + serializer_class = ProvinceFactorToKillHouseForPoultrySerializer + permission_classes = [TokenHasReadWriteScope] + + +# ویوست مربوط به فاکتور استان برای کشتارگاه +class ProvinceFactorToKillHouseViewSet(viewsets.ModelViewSet): + queryset = ProvinceFactorToKillHouse.objects.all() + serializer_class = ProvinceFactorToKillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به نمایش فاکتور استان برای کشتارگاه + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + factors = [] + operator = KillHouseOperator.objects.get(user=user) + kill_house = KillHouse.objects.filter(kill_house_operator=operator) + factor_list = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user__in=kill_house) + factors = [ + factor for factor in factor_list + if date1 <= factor.province_check_req.poultry_request.send_date.date() <= date2 + ] + factor_serializer = self.serializer_class(factors, many=True) + return Response(factor_serializer.data, status=status.HTTP_200_OK) + elif request.GET['role'] == 'ProvinceFinancial': + factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user__system_address__province=user.province, + paid_state='pending') + factor_serializer = self.serializer_class(factors, many=True) + return Response(factor_serializer.data, status=status.HTTP_200_OK) + + elif request.GET['role'] == 'ProvinceOperator': + + factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user__system_address__province=user.province, + paid_state='pending') + factor_serializer = self.serializer_class(factors, many=True) + return Response(factor_serializer.data, status=status.HTTP_200_OK) + + + elif request.GET['role'] == 'CityOperator': + factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__killhouse_user__system_address__city=user.city, + paid_state='pending') + factor_serializer = self.serializer_class(factors, many=True) + return Response(factor_serializer.data, status=status.HTTP_200_OK) + + elif request.GET['role'] == 'Poultry': + + factors = ProvinceFactorToKillHouse.objects.filter( + province_check_req__poultry_request__poultry__user=user, + paid_state='pending', trash=False) + factor_serializer = self.serializer_class(factors, many=True) + return Response(factor_serializer.data, status=status.HTTP_200_OK) + + if request.GET['type'] == 'kill_house': + key = request.GET['key'] + # user = UserProfile.objects.get(user=request.user) + # # kill_house = KillHouse.objects.get(user=user) + # # factor_dict_list = [] + factor_list = [] + provinc_factor_to_kill_house = ProvinceFactorToKillHouse.objects.get( + province_check_info__kill_house_assignment__key=key, trash=False) + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor=provinc_factor_to_kill_house, trash=False) + internal_dict_factors = { + "full_name": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.user.fullname, + "mobile": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.user.mobile, + "weight": provinc_factor_to_kill_house.total_weight, + "bar_code": provinc_factor_to_kill_house.factor_bar_code, + "date": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date, + "gis_code": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request.user.gis_code, + "fee": provinc_factor_to_kill_house.factor_fee, + "total_amount": provinc_factor_to_kill_house.total_price, + "total_amount_char": words(provinc_factor_to_kill_house.total_price) + " " + "ریال", + "bank": provinc_factor_to_kill_house.bank, + "key": provinc_factor_to_kill_house.key, + + } + if kill_house_factor: + internal_dict_factors.update({ + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "kill_house_factor_state": kill_house_factor[0].state, + + }) + if not kill_house_factor: + internal_dict_factors.update({ + "payment_code": None, + "factor_image": None, + "kill_house_factor_state": None, + + }) + + factor_list.append(internal_dict_factors) + + return Response(factor_list, status=status.HTTP_200_OK) + + if request.GET['type'] == 'province': + + factor_dict_list = [] + factor_list = [] + for province_check in ProvinceCheckOperatorRequest.objects.filter(state='accept', + financial_archive='pending', trash=False): + poultry_req = province_check.city_request_Poultry.poultry_request + internal_dict_poultry = {"full_name": poultry_req.user.fullname, "mobile": poultry_req.user.mobile, + "gis_code": poultry_req.user.gis_code, + "poultry_request_id": poultry_req.id, + "date": poultry_req.send_date, + "weight": province_check.total_weight_at_end, + "price": province_check.fee, + "breed": poultry_req.chicken_breed, + "inspector": poultry_req.inspector, + "order_code": poultry_req.order_code, "factors": ""} + + for provinc_factor_to_kill_house in ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request=province_check, + trash=False): + + internal_dict_factors = { + "province_operator": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator.fullname, + "province_mobile": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator.mobile, + "weight": provinc_factor_to_kill_house.total_weight, + "bar_code": provinc_factor_to_kill_house.factor_bar_code, + "kill_house_name": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": provinc_factor_to_kill_house.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.user.mobile, + "cost": provinc_factor_to_kill_house.total_price, + "bank": provinc_factor_to_kill_house.bank, + "factor": provinc_factor_to_kill_house.bank, + } + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor=provinc_factor_to_kill_house) + if kill_house_factor: + internal_dict_factors.update({ + "kill_house_Send_factor_information": "accepted", + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "factor_key": kill_house_factor[0].key, + "factor_state": kill_house_factor[0].state + }) + else: + internal_dict_factors.update({ + "kill_house_Send_factor_information": "pending", + "payment_code": "", + "factor_image": "", + "factor_key": "", + "factor_state": "" + }) + + factor_list.append(internal_dict_factors) + internal_dict_poultry["factors"] = factor_list + factor_dict_list.append(internal_dict_poultry) + factor_list = [] + + return Response(factor_dict_list, status=status.HTTP_200_OK) + + +class KillHouseFactorToPoultryViewSet(viewsets.ModelViewSet): + queryset = KillHouseFactorToPoultry.objects.all() + serializer_class = KillHouseFactorToPoultrySerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ایجاد فاکتور کشتارگاه برای استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + role = request.data['role'] + province_factor = ProvinceFactorToKillHouseForPoultry.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + request.data.pop('role') + try: + factor_image = request.data['factor_image'] + request.data.pop('factor_image') + except: + factor_image = None + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + factor = serializer.create(validated_data=request.data) + if factor_image != None: + factor.factor_image = send_image_to_server(factor_image) + + factor.province_factor = province_factor + factor.importer = role + factor.save() + province_factor.kill_house_factor_info = 'accepted' + province_factor.paid_state = 'paid' + province_factor.save() + factor_serializer = self.serializer_class(factor) + return Response(factor_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + role = request.data['role'] + kill_house_factor = KillHouseFactorToPoultry.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + request.data.pop('role') + try: + image = request.data['factor_image'] + request.data.pop('factor_image') + except: + image = None + if image != None: + kill_house_factor.factor_image = send_image_to_server(image) + kill_house_factor.state = 'pending' + kill_house_factor.importer = role + kill_house_factor.save() + + serializer = self.serializer_class(kill_house_factor) + serializer.update(instance=kill_house_factor, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به فاکتور کشتارگاه برای استان +class KillHouseFactorToProvinceViewSet(viewsets.ModelViewSet): + queryset = KillHouseFactorToProvince.objects.all() + serializer_class = KillHouseFactorToProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ایجاد فاکتور کشتارگاه برای استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + role = request.data['role'] + province_factor = ProvinceFactorToKillHouse.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + request.data.pop('role') + try: + factor_image = request.data['factor_image'] + request.data.pop('factor_image') + except: + factor_image = None + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + factor = serializer.create(validated_data=request.data) + if factor_image != None: + factor.factor_image = send_image_to_server(factor_image) + + factor.province_factor = province_factor + factor.importer = role + factor.save() + province_factor.kill_house_factor_info = 'accepted' + province_factor.paid_state = 'paid' + province_factor.save() + factor_serializer = self.serializer_class(factor) + return Response(factor_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + role = request.data['role'] + kill_house_factor = KillHouseFactorToProvince.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + request.data.pop('role') + try: + image = request.data['factor_image'] + request.data.pop('factor_image') + except: + image = None + if image != None: + kill_house_factor.factor_image = send_image_to_server(image) + kill_house_factor.state = 'pending' + kill_house_factor.message = None + kill_house_factor.importer = role + kill_house_factor.save() + + serializer = self.serializer_class(kill_house_factor) + serializer.update(instance=kill_house_factor, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + now = datetime.now().date() + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + kill_house_operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator) + factor_list = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__killhouse_user__in=kill_house) + + factors = [ + factor for factor in factor_list + if date1 <= factor.modify_date.date() <= date2 + ] + + + elif request.GET['role'] == 'ProvinceFinancial': + factors = KillHouseFactorToProvince.objects.filter(state__in=('pending', 'accepted'), + province_factor__province_check_info__kill_house_assignment__kill_house_request__killhouse_user__system_address__province=user.province) + serializer = self.serializer_class(factors, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceImportKillHouseOutFactorsViewSet(viewsets.ModelViewSet): + queryset = ProvinceImportKillHouseOutFactors.objects.all() + serializer_class = ProvinceImportKillHouseOutFactorsSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ایجاد فاکتور کشتارگاه برای استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + if 'poultry_factor_key' in request.data.keys(): + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.get(key=request.data['poultry_factor_key']) + request.data.pop('poultry_factor_key') + province_check_request = ProvinceCheckOperatorRequest.objects.get(key=poultry_factor.province_check_req.key) + else: + poultry_factor = None + + if 'province_factor_key' in request.data.keys(): + province_factor = ProvinceFactorToKillHouse.objects.get(key=request.data['province_factor_key']) + request.data.pop('province_factor_key') + province_check_request = ProvinceCheckOperatorRequest.objects.get( + key=province_factor.province_check_req.key) + + else: + province_factor = None + image = request.data['image'] + request.data.pop('image') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + payment_factor = serializer.create(validated_data=request.data) + payment_factor.province_check = province_check_request + payment_factor.image = send_image_to_server(image) + if poultry_factor != None: + payment_factor.kill_house_factor_poultry = poultry_factor + poultry_factor.paid_state = 'paid' + poultry_factor.save() + else: + payment_factor.kill_house_factor = province_factor + province_factor.paid_state = 'paid' + province_factor.save() + + payment_factor.save() + deposit_allocation = DepositAllocation.objects.filter(poultry=province_check_request.poultry_request) + if deposit_allocation.count() > 0: + deposit_allocation = deposit_allocation.last() + if poultry_factor != None: + deposit_allocation.poultry_share += poultry_factor.shares['poultryShareWithProfit'] + else: + deposit_allocation.city_share += province_factor.shares['city_share'] + deposit_allocation.province_share += province_factor.shares['province_share'] + deposit_allocation.company_share += province_factor.shares['company_share'] + deposit_allocation.central_union_share += province_factor.shares['central_union_share'] + deposit_allocation.fanava_share += province_factor.shares['fanava_share'] + deposit_allocation.save() + else: + + if poultry_factor != None: + + deposit_allocation = DepositAllocation(poultry=province_check_request.poultry_request, + poultry_share=poultry_factor.shares[ + 'poultryShareWithProfit'], + ) + deposit_allocation.save() + + else: + deposit_allocation = DepositAllocation(poultry=province_check_request.poultry_request, + city_share=province_factor.shares['city_share'], + province_share=province_factor.shares['province_share'], + company_share=province_factor.shares['company_share'], + central_union_share=province_factor.shares[ + 'central_union_share'], + fanava_share=province_factor.shares['fanava_share'], + ) + + deposit_allocation.save() + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_req=province_check_request).count() + poultry_factors = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_req=province_check_request).count() + out_factors = ProvinceImportKillHouseOutFactors.objects.filter( + province_check=province_check_request).count() + if out_factors == province_factors + poultry_factors: + poultry_request = PoultryRequest.objects.get(key=province_check_request.poultry_request.key) + poultry_request.final_state = 'archive' + poultry_request.save() + + factor_serializer = self.serializer_class(payment_factor) + return Response(factor_serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به تایید یا رذ فاکتورهای ارسالی از سمت کشتارگاه +class ProvinceCheckKillHouseFactorViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckKillHouseFactor.objects.all() + serializer_class = ProvinceCheckKillHouseFactorSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به تایید یا رذ فاکتورهای ارسالی از سمت کشتارگاه + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + kill_house_factor = None + kill_house_poultry_factor = None + if request.data['type'] == 'province': + kill_house_factor = KillHouseFactorToProvince.objects.get(key=request.data['key'], trash=False) + request.data.pop('key') + request.data.pop('type') + + else: + kill_house_poultry_factor = KillHouseFactorToPoultry.objects.get(key=request.data['key']) + request.data.pop('key') + request.data.pop('type') + + if kill_house_factor != None: + if kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner != None: + auction = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner + poultry_request = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request + else: + auction = None + if auction == None: + if kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request != None: + province_check = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request + poultry_request = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request + else: + if kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner != None: + auction = kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner + poultry_request = kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.poultry_request + else: + auction = None + if auction == None: + if kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request != None: + province_check = kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request + poultry_request = kill_house_poultry_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.city_request_Poultry.poultry_request + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + check = serializer.create(validated_data=request.data) + if check.state == 'accepted': + + if kill_house_factor != None: + check.kill_house_factor = kill_house_factor + kill_house_factor.state = 'accepted' + kill_house_factor.save() + else: + check.kill_house_factor_poultry = kill_house_poultry_factor + kill_house_poultry_factor.state = 'accepted' + kill_house_poultry_factor.save() + + if auction != None: + kill_house_factors = KillHouseFactorToProvince.objects.filter(state='accepted', + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + trash=False) + kill_house_poultry_factors = KillHouseFactorToPoultry.objects.filter(state='accepted', + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + trash=False) + # kill_house_requests = KillHouseRequest.objects.filter( + # kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + # state='accepted', + # active_state='inactive', trash=False) + else: + kill_house_factors = KillHouseFactorToProvince.objects.filter(state='accepted', + province_factor__province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request=province_check, + trash=False, + province_factor__sum_state='pending') + kill_house_poultry_factors = KillHouseFactorToPoultry.objects.filter(state='accepted', + province_factor__province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request=province_check, + trash=False, + province_factor__sum_state='pending') + # kill_house_requests = KillHouseRequest.objects.filter(province_request=province_check, + # state='accepted', + # active_state='inactive', trash=False) + + # kill_house_requests_counter = len(kill_house_requests) + # kill_house_factors_counter = len(kill_house_factors) + # if kill_house_factors_counter == kill_house_requests_counter: + total_amount = 0 + total_weight = 0 + poultry_share = 0 + city_share = 0 + province_share = 0 + company_share = 0 + central_union_share = 0 + fanava_share = 0 + if kill_house_factor != None: + for factor in kill_house_factors: + total_amount += factor.province_factor.total_price + total_weight += factor.province_factor.total_weight + if 'poultryShareWithProfit' in factor.province_factor.shares: + poultry_share += factor.province_factor.shares['poultryShareWithProfit'] + else: + poultry_share = 0 + city_share += factor.province_factor.shares['city_share'] + province_share += factor.province_factor.shares['province_share'] + company_share += factor.province_factor.shares['company_share'] + central_union_share += factor.province_factor.shares['central_union_share'] + fanava_share += factor.province_factor.shares['fanava_share'] + f = ProvinceFactorToKillHouse.objects.get(key=factor.province_factor.key) + f.sum_state = 'complete' + f.save() + + deposit_allocation = DepositAllocation.objects.filter(poultry=poultry_request) + if deposit_allocation.count() > 0: + deposit_allocation = deposit_allocation.last() + deposit_allocation.poultry_share += poultry_share + deposit_allocation.city_share += city_share + deposit_allocation.province_share += province_share + deposit_allocation.company_share += company_share + deposit_allocation.central_union_share += central_union_share + deposit_allocation.fanava_share += fanava_share + deposit_allocation.save() + else: + + deposit_allocation = DepositAllocation(poultry=poultry_request, + poultry_share=poultry_share, + city_share=city_share, + province_share=province_share, + company_share=company_share, + central_union_share=central_union_share, + fanava_share=fanava_share, + ) + + deposit_allocation.save() + else: + + for factor in kill_house_poultry_factors: + total_amount += factor.province_factor.total_price + total_weight += factor.province_factor.total_weight + poultry_share += factor.province_factor.total_price + # poultry_share += factor.province_factor.shares['poultryShareWithProfit'] + fa = ProvinceFactorToKillHouseForPoultry.objects.get(key=factor.province_factor.key) + fa.sum_state = 'complete' + fa.save() + deposit_allocation = DepositAllocation.objects.filter(poultry=poultry_request) + if deposit_allocation.count() > 0: + deposit_allocation = deposit_allocation.last() + deposit_allocation.poultry_share += poultry_share + deposit_allocation.poultry_share_payment += poultry_share + deposit_allocation.save() + else: + + deposit_allocation = DepositAllocation(poultry=poultry_request, + poultry_share=poultry_share, + poultry_share_payment=poultry_share + ) + + deposit_allocation.save() + + if auction == None: + if province_check != None: + province_check.total_cost_at_end = total_amount + province_check.factor_state = 'accepted' + # province_check.financial_archive = 'accepted' + province_check.save() + # poultry_request.inspector = 'pending' + # poultry_request.save() + + province_factor_to_kill_house = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request__city_request_Poultry__poultry_request=deposit_allocation.poultry, + trash=False) + province_factor_to_kill_house_poultry = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request__city_request_Poultry__poultry_request=deposit_allocation.poultry, + trash=False) + + kill_house_requests = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=deposit_allocation.poultry, + state='accepted', + active_state='inactive', trash=False) + + # total = 0 + # if province_factor_to_kill_house.count() > 0: + # for factor in province_factor_to_kill_house: + # total += factor.total_price + # if province_factor_to_kill_house_poultry.count() > 0: + # for poultry_factor in province_factor_to_kill_house_poultry: + # total += poultry_factor.total_price + # deposit_total = deposit_allocation.poultry_share_payment + deposit_allocation.city_share_payment + deposit_allocation.province_share_payment + deposit_allocation.company_share_payment + deposit_allocation.central_union_share_payment + deposit_allocation.fanava_share_payment + # + # if total == deposit_total: + counter = 0 + if province_factor_to_kill_house.count() > 0: + counter = province_factor_to_kill_house.count() + for po_factor in province_factor_to_kill_house_poultry: + if ProvinceFactorToKillHouse.objects.filter(poultry_factor=po_factor).exists(): + continue + else: + counter += 1 + if counter == kill_house_requests.count(): + poultry_request = PoultryRequest.objects.get(key=deposit_allocation.poultry.key) + poultry_request.inspector = 'pending' + poultry_request.awaiting_payment = False + poultry_request.save() + + if check.state == 'rejected': + if kill_house_factor != None: + kill_house_factor.state = 'rejected' + check.kill_house_factor = kill_house_factor + kill_house_factor.message = check.message + kill_house_factor.save() + else: + kill_house_poultry_factor.state = 'rejected' + kill_house_poultry_factor.message = check.message + kill_house_poultry_factor.save() + + check.save() + check_serializer = self.serializer_class(check) + return Response(check_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors) + + +# ویوست مربوط به تخصیصات مالی برای استان و شهرستان و مرغدار +class DepositAllocationViewSet(viewsets.ModelViewSet): + queryset = DepositAllocation.objects.all() + serializer_class = DepositAllocationSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ویرایش تخصیصات مالی برای استان و شهرستان و مرغدار + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + deposit = DepositAllocation.objects.get(key__exact=request.data["key"], trash=False) + province_factor_to_kill_house = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request__city_request_Poultry__poultry_request=deposit.poultry, + trash=False) + province_factor_to_kill_house_poultry = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request__city_request_Poultry__poultry_request=deposit.poultry, + trash=False) + + kill_house_requests = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=deposit.poultry, + state='accepted', + active_state='inactive', trash=False) + + request.data.pop('key') + pay_for = request.data['type'] + request.data.pop('type') + image = request.data['image'] + pay = request.data['payment'] + request.data.pop('image') + request.data.pop('payment') + if pay_for == 'Poultry': + deposit.city_image = send_image_to_server(image) + deposit.poultry_share_payment += float(pay) + list1 = [] + if deposit.poultry_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.poultry_share_payment_info = list1 + else: + list1 = list(deposit.poultry_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.poultry_share_payment_info = list1 + deposit.save() + elif pay_for == 'CityOperator': + # deposit.city_image = send_image_to_server(image) + deposit.city_share_payment += float(pay) + list1 = [] + if deposit.city_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.city_share_payment_info = list1 + else: + list1 = list(deposit.city_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + # list1.append(list1.append({city_pay: ARVAN_deposit_URL + "{0}.jpg".format(str(ran))})) + deposit.city_share_payment_info = list1 + deposit.save() + elif pay_for == 'ProvinceOperator': + # deposit.city_image = send_image_to_server(image) + deposit.province_share_payment += float(pay) + list1 = [] + if deposit.province_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.province_share_payment_info = list1 + else: + list1 = list(deposit.province_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.province_share_payment_info = list1 + deposit.save() + elif pay_for == 'fanava': + # deposit.city_image = send_image_to_server(image) + deposit.fanava_share_payment += float(pay) + list1 = [] + if deposit.fanava_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.fanava_share_payment_info = list1 + else: + list1 = list(deposit.fanava_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.fanava_share_payment_info = list1 + deposit.save() + elif pay_for == 'company': + # deposit.city_image = send_image_to_server(image) + deposit.company_share_payment += float(pay) + list1 = [] + if deposit.company_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.company_share_payment_info = list1 + else: + list1 = list(deposit.company_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.company_share_payment_info = list1 + deposit.save() + elif pay_for == 'central': + # deposit.city_image = send_image_to_server(image) + deposit.central_union_share_payment += float(pay) + list1 = [] + if deposit.central_union_share_payment_info == list1: + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.central_union_share_payment_info = list1 + else: + list1 = list(deposit.central_union_share_payment_info) + list1.append({"pay": pay, "image": send_image_to_server(image)}) + deposit.central_union_share_payment_info = list1 + deposit.save() + # total = 0 + # if province_factor_to_kill_house.count() > 0: + # for factor in province_factor_to_kill_house: + # total += factor.total_price + # if province_factor_to_kill_house_poultry.count() > 0: + # for poultry_factor in province_factor_to_kill_house_poultry: + # total += poultry_factor.total_price + # deposit_total = deposit.poultry_share_payment + deposit.city_share_payment + deposit.province_share_payment + deposit.company_share_payment + deposit.central_union_share_payment + deposit.fanava_share_payment + # + # if total == deposit_total: + # counter = province_factor_to_kill_house.count() + # for po_factor in province_factor_to_kill_house_poultry: + # if ProvinceFactorToKillHouse.objects.filter(poultry_factor=po_factor).exists(): + # continue + # else: + # counter += 1 + # if counter == kill_house_requests.count(): + # poultry_request = PoultryRequest.objects.get(key=deposit.poultry.key) + # poultry_request.final_state = 'archive' + # poultry_request.save() + + serializer = self.serializer_class(deposit) + serializer.update(instance=deposit, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش تخصیصات مالی برای استان و شهرستان و مرغدار + # def list(self, request, *args, **kwargs): + # # refresh(request.user.id) + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # final_list = [] + # factor_dict_list = [] + # factor_list = [] + # for province_check_request in ProvinceCheckOperatorRequest.objects.filter(state='accept', + # factor_state='accepted', + # deposit_allocation_archive='pending', + # trash=False): + # poultry = province_check_request.city_request_Poultry.poultry_request.user + # city_operator = province_check_request.city_request_Poultry.city_operator + # deposit_allocation = DepositAllocation.objects.filter( + # poultry=province_check_request.city_request_Poultry.poultry_request) + # + # internal_dict_poultry = { + # "full_name": province_check_request.city_request_Poultry.poultry_request.user.fullname, + # "mobile": province_check_request.city_request_Poultry.poultry_request.user.mobile, + # "gis_code": province_check_request.city_request_Poultry.poultry_request.user.gis_code, + # "quantity": province_check_request.city_request_Poultry.poultry_request.quantity, + # "breed": province_check_request.city_request_Poultry.poultry_request.chicken_breed, + # "order_code": province_check_request.city_request_Poultry.poultry_request.order_code, + # "fee": province_check_request.fee, + # "date": province_check_request.city_request_Poultry.poultry_request.send_date, + # "total_weight": province_check_request.total_weight_at_end, + # "total_amount": province_check_request.total_cost_at_end, + # "factors": ""} + # + # if user.role.name == 'Poultry': + # if deposit_allocation: + # internal_dict_poultry.update({"poultry_share": deposit_allocation[0].poultry_share, + # "poultry_bank_name": user.user_bank_info.bank_name, + # "poultry_card_number": user.user_bank_info.card, + # "poultry_shaba": user.user_bank_info.shaba, + # "poultry_bank_account_number": user.user_bank_info.account, + # "poultry_image": deposit_allocation[0].poultry_image, + # "Union_share": deposit_allocation[0].province_share + + # deposit_allocation[0].city_share, + # "province": province_check_request.province_operator.address.province, + # }) + # factor_dict_list.append(internal_dict_poultry) + # factor_list = [] + # if user.role.name == 'CityOperator': + # if deposit_allocation: + # internal_dict_poultry.update({ + # "city": city_operator.address.city, + # "city_bank_name": city_operator.user_bank_info.bank_name, + # "name_of_bank_user": city_operator.user_bank_info.name_of_bank_user, + # "city_share": deposit_allocation[0].city_share, + # "city_image": deposit_allocation[0].city_image, + # }) + # factor_dict_list.append(internal_dict_poultry) + # factor_list = [] + # if user.role.name == 'ProvinceOperator': + # for kill_house_req_obj in KillHouseRequest.objects.filter(province_request=province_check_request, + # state='accepted', trash=False): + # province_req = kill_house_req_obj.province_request + # + # for kill_house_factor in KillHouseFactorToProvince.objects.filter( + # province_factor__province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request=province_req, + # state='accepted', trash=False): + # internal_dict_factors = { + # "barcod": kill_house_factor.province_factor.factor_bar_code, + # "kill_house_name": kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + # "kill_house_mobile": kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.user.mobile, + # "payment_code": kill_house_factor.payment_code, + # "cost": kill_house_factor.province_factor.total_price, + # "factor_key": kill_house_factor.key, + # "factor_state": kill_house_factor.state, + # "factor_payment_state": kill_house_factor.payment_state, + # "factor_payment_method": kill_house_factor.payment_method + # } + # factor_list.append(internal_dict_factors) + # internal_dict_poultry["factors"] = factor_list + # internal_dict_poultry.update({ + # "total_money": province_check_request.total_cost_at_end, + # }) + # deposit_allocation = DepositAllocation.objects.filter( + # poultry=province_check_request.city_request_Poultry.poultry_request) + # if deposit_allocation: + # if user.role.name == 'ProvinceOperator': + # internal_dict_poultry.update({"allocation_key": deposit_allocation[0].key, + # "poultry_share": deposit_allocation[0].poultry_share, + # "poultry_bank_info": poultry.user_bank_info.name_of_bank_user, + # "poultry_bank_name": user.user_bank_info.bank_name, + # "poultry_card_number": user.user_bank_info.card, + # "poultry_shaba": user.user_bank_info.shaba, + # "poultry_image": deposit_allocation[0].poultry_image, + # "city_share": deposit_allocation[0].city_share, + # "city_bank_info": city_operator.user_bank_info.name_of_bank_user, + # "city_bank_name": city_operator.user_bank_info.bank_name, + # "city_card_number": city_operator.user_bank_info.card, + # "city_shaba": city_operator.user_bank_info.shaba, + # "city_image": deposit_allocation[0].city_image, + # "province_share": deposit_allocation[0].province_share, + # "province_bank_info": province_check_request.province_operator.user_bank_info.name_of_bank_user, + # }) + # factor_dict_list.append(internal_dict_poultry) + # factor_list = [] + # + + # return Response(factor_dict_list, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + factor_list = [] + user = SystemUserProfile.objects.get(user=request.user) + allocations = DepositAllocation.objects.filter(poultry__poultry__address__province=user.province).order_by('id') + serializer_request = self.serializer_class(allocations, many=True) + return Response(serializer_request.data, status=status.HTTP_200_OK) + + +class InspectorOperatorViewSet(viewsets.ModelViewSet): + queryset = InspectorOperator.objects.all() + serializer_class = InspectorOperatorSerializer + permission_classes = [TokenHasReadWriteScope] + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + operator = InspectorOperator.objects.get(user=user, trash=False) + inspector_operator_serializer = InspectorOperatorSerializer(operator) + profile_info = { + 'inspector': inspector_operator_serializer.data, + } + return Response(profile_info, status=status.HTTP_200_OK) + + +# ویوست مربوط به تایید یا رد پرونده مرغدار توسط بازرس استان +class PovinceInspectorViewSet(viewsets.ModelViewSet): + queryset = PovinceInspector.objects.all() + serializer_class = PovinceInspectorSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به تایید یا رد پرونده مرغدار توسط بازرس استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + inspector = InspectorOperator.objects.get(user=user, trash=False) + key = request.data['key'] + request.data.pop('key') + poultry_request = PoultryRequest.objects.get(key=key, trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + inspector_req = serializer.create(validated_data=request.data) + inspector_req.poultry_request = poultry_request + if inspector_req.state == 'accepted': + poultry_request.inspector = 'accepted' + poultry_request.final_state = 'archive' + elif inspector_req.state == 'rejected': + poultry_request.inspector = 'rejected' + poultry_request.final_state = 'archive' + poultry_request.save() + inspector_req.inspector = user + inspector_req.inspector_operator = inspector + inspector_req.save() + serializer_request = self.serializer_class(inspector_req) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش پرونده های تایید شده یا رد شده توسط بازرس استان + # def list(self, request, *args, **kwargs): + # user = UserProfile.objects.get(user=request.user) + # final_list = [] + # factor_dict_list = [] + # factor_list = [] + # for province_check_request in ProvinceCheckOperatorRequest.objects.filter(state='accept', + # factor_state='accepted', + # deposit_allocation_archive='accepted'): + # poultry = province_check_request.city_request_Poultry.poultry_request.user + # city_operator = province_check_request.city_request_Poultry.city_operator + # deposit_allocation = DepositAllocation.objects.filter( + # poultry=province_check_request.city_request_Poultry.poultry_request) + # + # internal_dict_poultry = { + # "full_name": province_check_request.city_request_Poultry.poultry_request.user.fullname, + # "mobile": province_check_request.city_request_Poultry.poultry_request.user.mobile, + # "gis_code": province_check_request.city_request_Poultry.poultry_request.user.gis_code, + # "quantity": province_check_request.city_request_Poultry.poultry_request.quantity, + # "breed": province_check_request.city_request_Poultry.poultry_request.chicken_breed, + # "order_code": province_check_request.city_request_Poultry.poultry_request.order_code, + # "fee": province_check_request.fee, + # "date": province_check_request.city_request_Poultry.poultry_request.send_date, + # "total_weight": province_check_request.total_weight_at_end, + # "total_amount": province_check_request.total_cost_at_end, + # "factors": ""} + # if user.role.name == 'ProvinceOperator': + # for kill_house_req_obj in KillHouseRequest.objects.filter(province_request=province_check_request, + # state='accepted'): + # province_req = kill_house_req_obj.province_request + # + # for kill_house_factor in KillHouseFactorToProvince.objects.filter( + # province_factor__province_check_info__kill_house_assignment__kill_house_check__province_kill_request__province_request=province_req, + # state='accepted'): + # internal_dict_factors = { + # "barcod": kill_house_factor.province_factor.factor_bar_code, + # "kill_house_name": kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + # "kill_house_mobile": kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.user.mobile, + # "payment_code": kill_house_factor.payment_code, + # "cost": kill_house_factor.province_factor.total_price, + # "factor_key": kill_house_factor.key, + # "factor_state": kill_house_factor.state, + # "factor_payment_state": kill_house_factor.payment_state, + # "factor_payment_method": kill_house_factor.payment_method + # } + # factor_list.append(internal_dict_factors) + # internal_dict_poultry["factors"] = factor_list + # internal_dict_poultry.update({ + # "total_money": province_check_request.total_cost_at_end, + # }) + # deposit_allocation = DepositAllocation.objects.filter( + # poultry=province_check_request.city_request_Poultry.poultry_request) + # if deposit_allocation: + # if user.role.name == 'ProvinceOperator': + # internal_dict_poultry.update({"allocation_key": deposit_allocation[0].key, + # "poultry_share": deposit_allocation[0].poultry_share, + # "poultry_bank_info": poultry.user_bank_info.name_of_bank_user, + # "poultry_bank_name": user.user_bank_info.bank_name, + # "poultry_card_number": user.user_bank_info.card, + # "poultry_shaba": user.user_bank_info.shaba, + # "poultry_image": deposit_allocation[0].poultry_image, + # "city_share": deposit_allocation[0].city_share, + # "city_bank_info": city_operator.user_bank_info.name_of_bank_user, + # "city_bank_name": city_operator.user_bank_info.bank_name, + # "city_card_number": city_operator.user_bank_info.card, + # "city_shaba": city_operator.user_bank_info.shaba, + # "city_image": deposit_allocation[0].city_image, + # "province_share": deposit_allocation[0].province_share, + # "province_bank_info": province_check_request.province_operator.user_bank_info.name_of_bank_user, + # }) + # factor_dict_list.append(internal_dict_poultry) + # factor_list = [] + # + # return Response(factor_dict_list, status=status.HTTP_200_OK) + + +# ویوست مربوط به دریافت درخواست مرغدار که در هر مرحله ای رد شده باشه برای پنل استان +class RejectedRequestsViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به نمایش درخواست مرغدار که در هر مرحله ای رد شده باشه برای پنل استان + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + objects = [] + objects_list = [] + poultry_request = PoultryRequest.objects.filter(poultry__address__province=user.province) + # for value in self.queryset: + for value in poultry_request: + for i in value.poultry_check.filter(): + if i.state == "rejected" or i.state == "reject": + objects.append({ + 'rejected_position': 'city-operator', + 'rejected_position_farsi': 'اپراتور شهرستان', + 'city_operator': i.city_operator_system.user.fullname, + 'modify_date': i.modify_date, + 'reason_message': i.message, + 'value': self.serializer_class(value).data + }) + break + for item in i.Poultry_city_request_to_province.filter(): + if item.state == "rejected" or item.state == "reject": + objects.append({ + 'rejected_position': 'province-operator', + 'rejected_position_farsi': 'اپراتور استان', + 'province_operator': item.province_operator_system.user.fullname, + 'modify_date': item.modify_date, + 'city_operator': item.city_request_Poultry.city_operator_system.user.fullname, + 'reason_message': item.message, + 'value': self.serializer_class(value).data + }) + break + for x in item.kill_house_province.filter(): + if x.state == "rejected" or x.state == "reject": + objects.append({ + 'rejected_position': 'kill-house-request', + 'rejected_position_farsi': 'درخواست کشتارگاه', + 'kill_house': x.kill_request.kill_house.name, + 'modify_date': x.modify_date, + 'province_operator': x.province_request.province_operator_system.user.fullname, + 'city_operator': x.province_request.city_request_Poultry.city_operator_system.user.fullname, + 'reason_message': x.message, + 'value': self.serializer_class(value).data + }) + break + for y in x.province_kill_house_check.filter(): + for m in y.kill_house_check_req.filter(): + for n in m.kill_house_assign.filter(): + if n.state == "rejected" or n.state == "reject": + objects.append({ + 'rejected_position': 'financial', + 'rejected_position_farsi': 'مالی', + 'province_operator': n.kill_house_assignment.kill_house_check. + province_kill_request.province_request.province_operator_system.user.fullname, + 'kill_house': n.kill_house_assignment.kill_house_check.province_kill_request + .kill_request.kill_house.name, + 'city_operator': n.kill_house_assignment.kill_house_check.province_kill_request + .province_request.city_request_Poultry.city_operator_system.user.fullname, + 'modify_date': n.modify_date, + 'reason_message': n.message, + 'value': self.serializer_class(value).data + }) + for v in n.province_info.filter(): + pass + for i in value.poultry_request_inspector.filter(): + if i.state == "rejected" or i.state == "reject": + objects.append({ + 'rejected_position': 'inspector-operator', + 'rejected_position_farsi': 'اپراتور بازرس استان', + 'inspector_operator': i.inspector_operator.user.fullname, + 'modify_date': i.modify_date, + 'reason_message': i.message, + 'value': self.serializer_class(value).data + }) + break + for item in objects: + objects_dict = {} + kill_house_objects = [] + objects_dict['rejected_position'] = item['rejected_position'] + objects_dict['rejected_position_farsi'] = item['rejected_position_farsi'] + objects_dict['fullname'] = item['value']['poultry']['userprofile']['full_name'] + objects_dict['mobile'] = item['value']['poultry']['userprofile']['mobile'] + objects_dict['city'] = item['value']['poultry']['address']['city']['name'] + objects_dict['province'] = item['value']['poultry']['address']['province']['name'] + + if 'city_operator' in item.keys(): + objects_dict['city_operator'] = item['city_operator'] + if 'province_operator' in item.keys(): + objects_dict['province_operator'] = item['province_operator'] + if 'kill_house' in item.keys(): + objects_dict['kill_house'] = item['kill_house'] + objects_dict['modify_date'] = item['modify_date'] + objects_dict['reason_message'] = item['reason_message'] + if item['value']['process']['province_kill_requests'] is not None: + for kill_item in item['value']['process']['province_kill_requests']: + if kill_item['kill_house_requests']: + for i in kill_item['kill_house_requests']: + kill_dict = {} + kill_dict['kill_house_name'] = i['kill_house_name'] + kill_dict['kill_house_owner_name'] = i['kill_house_user_name'] + kill_dict['mobile'] = i['kill_house_mobile'] + kill_dict['quantity'] = i['quantity'] + kill_dict['date'] = i['date'] + kill_dict['time'] = i['time'] + kill_dict['barcode'] = i['barcod'] + kill_dict['car_model'] = i['type_car'] + kill_dict['pelak'] = i['pelak'] + kill_dict['car_quantity'] = i['capocity'] + kill_dict['driver_name'] = i['driver_name'] + kill_house_objects.append(kill_dict) + objects_dict['kill_house'] = kill_house_objects + objects_dict['poultry_quantity'] = item['value']['quantity'] + objects_dict['send_date'] = item['value']['send_date'] + objects_dict['chicken_breed'] = item['value']['chicken_breed'] + objects_dict['Index_weight'] = item['value']['Index_weight'] + objects_dict['order_code'] = item['value']['order_code'] + objects_dict['create_date'] = item['value']['create_date'] + objects_dict['id'] = item['value']['id'] + kill_date = datetime.strptime(str(item['value']['send_date']), '%Y-%m-%dT%H:%M:%S') + # objects_dict['age'] = (kill_date - chicken_date).days + 2 + objects_list.append(objects_dict) + return Response(objects_list) + + +# ویوست مربوط به بررسی قیمت گذاری برای پنل استان +class ProvinceCheckRequestsPriceViewSet(viewsets.ModelViewSet): + queryset = ProvinceCheckOperatorRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceCheckOperatorRequestSerializer + + # تابع مربوط به بررسی قیمت گذاری برای پنل استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + next_day = datetime.now() + timedelta(days=1) + now = datetime.now() + price = Pricing.objects.filter(date__gte=next_day.date(), trash=False) + if price: + pass + + elif not price and now.hour == 12: + user = UserProfile.objects.get(role__name='ProvinceFinancial', trash=False) + message = UserMessage( + message="کاربر گرامی {} 12 ساعت تا شزوع روز بعد باقی است لطفا قیمت های روز بعد را وارد نمایید ".format( + user.fullname)) + message.save() + message.users.add(user) + return Response('message_sent') + elif not price and now.hour == 17: + users = UserProfile.objects.filter(role__name__in=('ProvinceFinancial', 'ProvinceInspector'), trash=False) + for user in users: + message = UserMessage( + message="کاربر گرامی {} 7 ساعت تا شزوع روز بعد باقی است لطفا قیمت های روز بعد را وارد نمایید".format( + user.fullname)) + message.save() + message.users.add(user) + return Response('message_sent') + + elif not price and now.hour == 22: + users = UserProfile.objects.filter( + role__name__in=('ProvinceFinancial', 'ProvinceOperator', 'ProvinceInspector'), trash=False) + for user in users: + message = UserMessage( + message="کاربر گرامی {} 2 ساعت تا شزوع روز بعد باقی است لطفا قیمت های روز بعد را وارد نمایید".format( + user.fullname)) + message.save() + message.users.add(user) + price_reminder(user.mobile, user.fullname) + return Response('sms sent') + + +# ویوست مربوط به آنالیز قیمت گذاری برای پنل استان +class PriceAnalysisViewSet(viewsets.ModelViewSet): + queryset = PriceAnalysis.objects.all() + serializer_class = PriceAnalysisorSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به آنالیز قیمت گذاری برای پنل استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + price_analys = serializer.create(validated_data=request.data) + price_analys.corn_Ration_free_price = price_analys.anacorn_percent * price_analys.corn_free_price + price_analys.Soy_Ration_free_price = price_analys.Soy_percent * price_analys.Soy_free_price + price_analys.Oil_Ration_free_price = price_analys.Oil_percent * price_analys.Oil_free_price + price_analys.Dicalcium_Ration_free_price = price_analys.Dicalcium_percent * price_analys.Dicalcium_free_price + price_analys.Carbonate_Ration_free_price = price_analys.Carbonate_percent * price_analys.Carbonate_free_price + price_analys.mineral_Ration_supplement_free_price = price_analys.mineral_supplement_percent * price_analys.mineral_supplement_free_price + price_analys.vitamin_Ration_free_supplement_percent = price_analys.vitamin_supplement_percent * price_analys.vitamin_supplement_total_free_price + price_analys.baking_Ration_soda_free_price = price_analys.baking_soda_percent * price_analys.baking_soda_free_price + price_analys.Salt_Ration_free_price = price_analys.Salt_percent * price_analys.Salt_free_price + price_analys.metiunin_Ration_free_price = price_analys.metiunin_percent * price_analys.metiunin_free_price + price_analys.Lysine_Ration_free_price = price_analys.Lysine_percent * price_analys.Lysine_free_price + price_analys.threonine_Ration_free_price = price_analys.threonine_percent * price_analys.threonine_free_price + price_analys.Antifungal_Ration_free_price = price_analys.Antifungal_percent * price_analys.Antifungal_free_price + price_analys.Colleen_Ration_free_price = price_analys.Colleen_percent * price_analys.Colleen_free_price + price_analys.total_percent = price_analys.anacorn_percent + price_analys.Soy_percent + price_analys.Oil_percent + price_analys.Dicalcium_percent + price_analys.Carbonate_percent + price_analys.mineral_supplement_percent + price_analys.vitamin_supplement_percent + price_analys.baking_soda_percent + price_analys.Salt_percent + price_analys.metiunin_percent + price_analys.Lysine_percent + price_analys.threonine_percent + price_analys.Antifungal_percent + price_analys.Colleen_percent + price_analys.total_ration = price_analys.corn_Ration_free_price + price_analys.Soy_Ration_free_price + price_analys.Oil_Ration_free_price + price_analys.Dicalcium_Ration_free_price + price_analys.Carbonate_Ration_free_price + price_analys.mineral_Ration_supplement_free_price + price_analys.vitamin_Ration_free_supplement_percent + price_analys.baking_Ration_soda_free_price + price_analys.Salt_Ration_free_price + price_analys.metiunin_Ration_free_price + price_analys.Lysine_Ration_free_price + price_analys.threonine_Ration_free_price + price_analys.Antifungal_Ration_free_price + price_analys.Colleen_Ration_free_price + price_analys.corn_total_free_price = 5 * (price_analys.total_ration / 2.5) + price_analys.Soy_total_free_price = price_analys.period_chicken / 2.5 + price_analys.Oil_total_free_price = price_analys.Vaccination_period / 50000 + price_analys.Dicalcium_total_free_price = price_analys.Multivitamin_course / 50000 + price_analys.Carbonate_total_free_price = price_analys.directors_office / 50000 + price_analys.mineral_supplement_total_free_price = price_analys.Water_gas_electricity_period / 50000 + price_analys.vitamin_supplement_total_free_price = price_analys.Water_gas_the_current_cost_of_the_period_unit / 50000 + price_analys.baking_soda_total_free_price = price_analys.Course_repairs / 50000 + price_analys.Salt_free_total_price = price_analys.motfar_ga_durah / 50000 + price_analys.metiunin_total_free_price = price_analys.Paper_reel / 50000 + price_analys.Lysine_total_free_price = price_analys.Course_disinfection / 50000 + price_analys.threonine_total_free_price = price_analys.Lamp / 50000 + price_analys.Antifungal_total_free_price = 60 + price_analys.inulin_total_free_price = 50 + price_analys.Fire_total_emulsion_free_price = 25 + price_analys.Colleen_total_free_price = price_analys.Course_loss / 50000 + price_analys.chicken_price = price_analys.corn_total_free_price + price_analys.Soy_total_free_price + price_analys.Oil_total_free_price + price_analys.Dicalcium_total_free_price + price_analys.Carbonate_total_free_price + price_analys.mineral_supplement_total_free_price + price_analys.vitamin_supplement_total_free_price + price_analys.baking_soda_total_free_price + price_analys.Salt_free_total_price + price_analys.metiunin_total_free_price + price_analys.Lysine_total_free_price + price_analys.threonine_total_free_price + price_analys.Antifungal_total_free_price + price_analys.inulin_total_free_price + price_analys.Fire_total_emulsion_free_price + price_analys.Colleen_total_free_price + price_analys.save() + serializer_request = self.serializer_class(price_analys) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به ثبت درخواست مرغ منجمد و ایجاد فاکتور پنل استان +class WareHouseFactorViewSet(viewsets.ModelViewSet): + queryset = WareHouseFactor.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WareHouseFactorSerializer + + # نابع مربوط به ثبت درخواست مرغ منجمد و ایجاد فاکتور پنل استان + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = UserProfile.objects.get(user=request.user, trash=False) + role = Group.objects.get(name=user.role.name) + ware_factor = WareHouseFactor.objects.all() + letter_number = ware_factor.last().letter_number + 1 if len(ware_factor) > 0 else 100000 + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + ware_house_factor = serializer.create(validated_data=request.data) + if role.name == 'Jahad': + ware_house_factor.first_operator = user + today = jdatetime.datetime.now() + today = today.date() + + ware_house_factor.letter_number_jahad = int( + str(today.year) + str(today.month) + str(today.day) + str(ware_house_factor.letter_number)) + serializer_request = self.serializer_class(ware_house_factor) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + ware_house_factor.total_wage = float(ware_house_factor.weight) * float(ware_house_factor.wage) + ware_house_factor.total_fee = float(ware_house_factor.weight) * float(ware_house_factor.fee) + ware_house_factor.total_cost = ware_house_factor.total_fee + ware_house_factor.total_wage + ware_house_factor.second_operator = user + ware_house_factor.letter_number = letter_number + ware_house_factor.save() + serializer_request = self.serializer_class(ware_house_factor) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # نابع مربوط به ویرایش درخواست مرغ منجمد ثبت شده پنل استان + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + user = UserProfile.objects.get(user=request.user, trash=False) + role = Group.objects.get(name=user.role.name) + ware_house_factor = WareHouseFactor.objects.get(key__exact=request.data["key"], trash=False) + request.data.pop('key') + if role.name == 'Jahad': + if ware_house_factor.state == 'completed': + return Response({'result': 'can not update'}, status=status.HTTP_403_FORBIDDEN) + else: + ware_house_factor.first_operator = user + ware_house_factor.save() + serializer = self.serializer_class(ware_house_factor) + serializer.update(instance=ware_house_factor, validated_data=request.data) + + else: + try: + wage = float(request.data['wage']) + fee = float(request.data['fee']) + request.data.pop('wage') + request.data.pop('fee') + except: + wage = ware_house_factor.wage + fee = ware_house_factor.fee + + try: + weight = float(request.data['weight']) + request.data.pop('weight') + ware_house_factor.weight = weight + except: + weight = ware_house_factor.weight + ware_house_factor.state = 'completed' + ware_house_factor.fee = fee + ware_house_factor.wage = wage + ware_house_factor.total_wage = weight * wage + ware_house_factor.total_fee = weight * fee + ware_house_factor.total_cost = ware_house_factor.total_fee + ware_house_factor.total_wage + ware_house_factor.second_operator = user + ware_house_factor.save() + serializer = self.serializer_class(ware_house_factor) + serializer.update(instance=ware_house_factor, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # نابع مربوط به نمایش درخواست مرغ منجمد ثبت شده پنل استان + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + queryset = WareHouseFactor.objects.filter(trash=False).order_by('-create_date') + # queryset = WareHouseFactor.objects.all().order_by('-create_date') + serializer = WareHouseFactorSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # نابع مربوط به حذف درخواست مرغ منجمد ثبت شده پنل استان + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + queryset = WareHouseFactor.objects.get(id=pk, trash=False) + queryset.trash = True + queryset.save() + return Response(queryset.trash, status=status.HTTP_200_OK) + + +class ManageCarsByProvince(viewsets.ModelViewSet): + queryset = KillHouseADDCAR.objects.all() + serializer_class = KillHouseADDCARSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + """ + Show List Of KillHouse Cars To Province + """ + kill_house_object = KillHouse.objects.get(key=request.GET['key'], trash=False) + kill_house_cars = self.queryset.filter(kill_house=kill_house_object, trash=False) + + # Send Data To Serializer + serializer = self.serializer_class(kill_house_cars) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + """ + Update KillHouse Cars (activate cars) By Province Operator + """ + car_key = request.data['key'] + request.data.pop('key') + car_object = self.queryset.get(key=car_key, trash=False) + + # Sending Data To Serializer & Update Information + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + obj = serializer.update( + validated_data=request.data, + instance=car_object + ) + serializer = self.serializer_class(obj) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class KillHouseListForProvince(viewsets.ModelViewSet): + queryset = KillHouse.objects.all() + serializer_class = KillHouseSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + """ + show List of KillHouses for Province Operator To Manage + """ + userprofile = SystemUserProfile.objects.get( + user=request.user, trash=False + ) + if 'show_poultry' in request.GET: + kill_house_objects_list = [] + now = datetime.now().date() + date = datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + # poultry = Poultry.objects.filter(user=userprofile).last() + kill_house_objects = KillHouse.objects.filter( + system_address__province=userprofile.province, trash=False + ) + for kill_house_object in kill_house_objects: + quantity_sum = 0 + poultry_quantity_sum = 0 + first_quantity = 0 + kill_req_key = None + total_kill_request = KillRequest.objects.filter(kill_house=kill_house_object, recive_date__date=date, + trash=False, province_state__in=('pending', 'accepted')) + + kill_request = total_kill_request.filter(poultry__isnull=True, province_state='accepted').first() + direct_buying_export_kill_request = total_kill_request.filter(poultry__isnull=False, + province_state__in=( + 'pending', 'accepted')) + direct_buying_export_kill_request_quantity = \ + direct_buying_export_kill_request.aggregate(total=Sum('kill_capacity'))[ + 'total'] or 0 + + if kill_request: + # quantity_sum = kill_request.kill_capacity - ( + # kill_request.remain_quantity_for_poultry + direct_buying_export_kill_request_quantity) + quantity_sum = kill_request.kill_capacity - kill_request.remain_quantity_for_poultry + first_quantity = kill_request.kill_capacity + poultry_quantity_sum = kill_request.remain_quantity_for_poultry + kill_req_key = kill_request.key + + kill_house_dict = { + "name": kill_house_object.name, + "killer": kill_house_object.killer, + "fullname": kill_house_object.kill_house_operator.user.fullname, + "quantity_sum": quantity_sum, + "first_quantity": first_quantity, + "poultry_quantity_sum": poultry_quantity_sum, + "kill_req_key": kill_req_key, + } + kill_house_objects_list.append(kill_house_dict) + return Response(kill_house_objects_list, status=status.HTTP_200_OK) + + else: + + kill_house_objects = KillHouse.objects.filter( + system_address__province=userprofile.province, trash=False + ) + + # Send Data To Serializer + serializer = self.serializer_class(kill_house_objects, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ShareOfAllocationViewSet(viewsets.ModelViewSet): + queryset = ShareOfAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ShareOfAllocationSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + share = self.queryset + if share: + share = share.last() + else: + share = ShareOfAllocation(province=user.province) + share.save() + serializer = ShareOfAllocationSerializer(share) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + share = ShareOfAllocation.objects.all().last() + serializer = self.serializer_class(share) + serializer.update(instance=share, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PaymentDeadLineViewSet(viewsets.ModelViewSet): + queryset = PaymentDeadLine.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PaymentDeadLineSerializer + + +class MonthlyProfitPercentageViewSet(viewsets.ModelViewSet): + queryset = MonthlyProfitPercentage.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = MonthlyProfitPercentageSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + queryset = MonthlyProfitPercentage.objects.all().last() + serializer = MonthlyProfitPercentageSerializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + # + # def create(self, request, *args, **kwargs): + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # share = serializer.create(validated_data=request.data) + # serializer_request = self.serializer_class(ware_house_factor) + # return Response(serializer_request.data, status=status.HTTP_201_CREATED) + # return Response(serializer.errors) + + +def update_factor_total_price(): + factors = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_kill_request__payment_type='credit', + paid_state='pending') + for factor in factors: + total = factor.total_weight * factor.factor_fee + factor.total_price += (total * 0.001) + factor.save() + return Response({"result": "factors updated"}, status=status.HTTP_200_OK) + + +class WalletViewset(viewsets.ModelViewSet): + queryset = Wallet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = walletSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + new_wallet = serializer.create(validated_data=request.data) + new_wallet.save() + w = self.serializer_class(new_wallet) + return Response(w.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + queryset = self.queryset.get(key=request.GET['wallet_key']) + transactions = Itransaction.objects.filter(wallet=queryset, state__in=("pending", "waiting")).order_by( + 'create_date') + serializer = ItransactionSerializer(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ItransactionViewset(viewsets.ModelViewSet): + queryset = Itransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ItransactionSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + itransaction_list = [] + itransactions = Itransaction.objects.all() + + for transaction in itransactions: + itransaction_list.append(transaction) + + t = ItransactionSerializer(itransaction_list, many=True) + + return Response(t.data, status.HTTP_200_OK) + + +class DebttViewset(viewsets.ModelViewSet): + queryset = Debt.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DebtSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + wallet_receive = Wallet.objects.get(key=request.data['wallet_receive']) + user_receive = SystemUserProfile.objects.get(key=request.data['user_key']) + request.data.pop('wallet_receive') + request.data.pop('user_key') + image = request.data['image'] + request.data.pop('image') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + new_debt = serializer.create(validated_data=request.data) + new_debt.image = send_image_to_server(image) + # os.remove("{0}.jpg".format(str(ran))) + + itransactions = Itransaction.objects.filter(make_location_state='outside', wallet=wallet_receive).order_by( + 'create_date') + if itransactions.count() > 0: + itransactions = itransactions.last() + payment_code = itransactions.payment_code + 1 + else: + payment_code = int(str(user_receive.base_order) + '01') + new_transaction = Itransaction( + wallet=wallet_receive, + transfer_amount=new_debt.cost, + transaction_type='debtor', + payment_code=payment_code + ) + new_transaction.save() + new_debt.itransaction = new_transaction + new_debt.save() + wallet_receive.inventory -= new_debt.cost + wallet_receive.save() + d = self.serializer_class(new_debt) + return Response(d.data, status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + debt_list = [] + debts = Debt.objects.all() + for debt in debts: + debt_list.append(debt) + d = DebtSerializer(debt_list, many=True) + return Response(d.data, status=status.HTTP_200_OK) + + +class PenaltyViewset(viewsets.ModelViewSet): + queryset = Penalty.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PenaltySerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + wallet_receive = Wallet.objects.get(key=request.data['wallet_id']) + request.data.pop('wallet_id') + user_receive = SystemUserProfile.objects.get(key=request.data['user_key']) + request.data.pop('user_key') + image = request.data['image'] + request.data.pop('image') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + new_penalty = serializer.create(validated_data=request.data) + + new_penalty.image = send_image_to_server(image) + # os.remove("{0}.jpg".format(str(ran))) + itransactions = Itransaction.objects.filter(make_location_state='outside', + wallet=wallet_receive).order_by('create_date') + + if itransactions.count() > 0: + itransactions = itransactions.last() + payment_code = itransactions.payment_code + 1 + else: + payment_code = int(str(user_receive.base_order) + '01') + + new_transaction = Itransaction( + wallet=wallet_receive, + transfer_amount=new_penalty.cost, + transaction_type='penalty', + payment_code=payment_code + ) + new_transaction.save() + new_penalty.itransaction = new_transaction + new_penalty.save() + wallet_receive.inventory -= new_penalty.cost + wallet_receive.save() + p = self.serializer_class(new_penalty) + return Response(p.data, status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + penalty_list = [] + penaltys = Penalty.objects.all() + for penalty in penaltys: + penalty_list.append(penalty) + p = PenaltySerializer(penalty_list, many=True) + return Response(p.data, status=status.HTTP_200_OK) + + +class DepositViewset(viewsets.ModelViewSet): + queryset = Deposit.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = DepositSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + wallet_receive = Wallet.objects.get(key=request.data['wallet_key']) + request.data.pop('wallet_key') + user_receive = SystemUserProfile.objects.get(key=request.data['user_key']) + request.data.pop('user_key') + image = request.data['image'] + request.data.pop('image') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + new_deposit = serializer.create(validated_data=request.data) + new_deposit.image = send_image_to_server(image) + itransactions = Itransaction.objects.filter(make_location_state='outside', + wallet=wallet_receive).order_by('create_date') + + if itransactions.count() > 0: + itransactions = itransactions.last() + payment_code = itransactions.payment_code + 1 + else: + payment_code = int(str(user_receive.base_order) + '01') + new_transaction = Itransaction( + wallet=wallet_receive, + transfer_amount=new_deposit.cost, + transaction_type='deposit', + payment_code=payment_code + ) + new_transaction.save() + new_deposit.itransaction = new_transaction + new_deposit.save() + wallet_receive.inventory += new_deposit.cost + wallet_receive.save() + d = self.serializer_class(new_deposit) + return Response(d.data, status.HTTP_201_CREATED) + + +class FinancialDocumentViewset(viewsets.ModelViewSet): + queryset = FinancialDocument.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = FinancialDocumentSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + transaction_list = request.data['transaction_list'] + request.data.pop('transaction_list') + user = SystemUserProfile.objects.get(id=request.data['user_id']) + request.data.pop('user_id') + if 'image' in request.data.keys(): + images = request.data['image'] + request.data.pop('image') + else: + images = None + image_list = [] + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + new_financial_document = serializer.create(validated_data=request.data) + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + + new_financial_document.image = image_list + + for transaction in transaction_list: + tr = Itransaction.objects.get(key=transaction) + tr.state = "paid" + tr.save() + wallet = tr.wallet + + new_financial_document.wallet = wallet + new_financial_document.transaction_details = transaction_list + new_financial_document.save() + if new_financial_document.type != 'zero': + + itransactions = Itransaction.objects.filter(file_id=0, wallet=wallet).order_by( + 'create_date') + if itransactions.count() > 0: + itransactions = itransactions.last() + payment_code = itransactions.payment_code + 1 + else: + payment_code = int(str(user.base_order) + '01') + new_transaction = Itransaction( + wallet=wallet, + transfer_amount=new_financial_document.cost, + transaction_type=new_financial_document.type, + payment_code=payment_code, + + ) + new_transaction.save() + new_financial_document.payment_code = payment_code + new_financial_document.save() + + f = self.serializer_class(new_financial_document) + return Response(f.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(id=request.GET['user_id']) + if 'all' in request.GET: + documents = FinancialDocument.objects.all() + total_list = [] + if documents.count() > 0: + for document in documents: + total_debtor = 0 + total_creditor = 0 + transactions = Itransaction.objects.filter(key__in=document.transaction_details) + payment_code = document.payment_code + if transactions.count() > 0: + + for transaction in transactions: + if transaction.transaction_type == 'debtor' or transaction.transaction_type == 'penalty' or transaction.transaction_type == 'negative': + total_debtor += transaction.transfer_amount + elif transaction.transaction_type == "creditor" or transaction.transaction_type == 'deposit' or transaction.transaction_type == 'positive': + total_creditor += transaction.transfer_amount + inter_dict = { + "national_id": user.national_id, + "cost": document.cost, + "image": document.image, + "description": document.description, + "payment_code": payment_code, + "total_debtors": total_debtor, + "total_creditor": total_creditor + } + total_list.append(inter_dict) + + return Response(total_list, status=status.HTTP_200_OK) + + +class ReportingAllwalletRequestsViewset(viewsets.ModelViewSet): + poultery_query = Poultry.objects.all() + province_query = ProvinceOperator.objects.all() + killhouse_query = KillHouseOperator.objects.all() + vet_query = Vet.objects.all() + city_query = CityOperator.objects.all() + driver_query = KillHouseDriver.objects.all() + inspector_query = InspectorOperator.objects.all() + vet_query = Vet.objects.all() + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + poultry_filterset = PoultryFilterSet + serializer_class = PoultrySerializer + city_filterset = CityOperatorFilterSet + province_filterset = ProvinceOperatorFilterSet + killhouseoperator_filterset = KillHouseOperatorFilterSet + killhousedriver_filterset = KillHouseDriverFilterSet + inspector_filterset = InspectorOperatorFilterSet + vet_filterset = VetFilterSet + + filterset_fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__city__name', + 'user__province_name', + 'user__base_order', + 'user__national_id', + + ] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + total_list = [] + poultry_query_val = [] + province_query_val = [] + killhouse_query_val = [] + driver_query_val = [] + city_query_val = [] + inspector_query_val = [] + vet_query_val = [] + poultry_limited_dict = {} + province_limited_dict = {} + killhouse_limited_dict = {} + city_limited_dict = {} + driver_limited_dict = {} + inspector_limited_dict = {} + vet_limited_dict = {} + province_limited_query = [] + killhouse_limited_query = [] + city_limited_query = [] + driver_limited_query = [] + inspector_limited_query = [] + values_item = [] + province_query_var = [] + killhouse_query_var = [] + city_query_var = [] + driver_query_var = [] + inspector_query_var = [] + vet_query_var = [] + poultry_limited_query = [] + vet_limited_query = [] + + if 'type' in request.GET: + if request.GET['type'] == 'filter': + if 'value' in request.GET and request.GET['value'] != "": + values = request.GET['value'].split(',') + for item in values: + if item != "": + values_item.append(item) + for val in values_item: + if not poultry_query_val: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.poultry_filterset(data=query, queryset=self.poultery_query)).filter(): + ps = self.poultry_filterset(data=query, queryset=self.poultery_query) + filtered_poultry = ps.filter() + if filtered_poultry: + poultry_limited_query.append(query) + + if not province_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.province_filterset(data=query, + queryset=self.province_query)).filter(): + ps = self.province_filterset(data=query, + queryset=self.province_query) + filtered_province_operator = ps.filter() + if filtered_province_operator: + province_limited_query.append(query) + + if not killhouse_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.killhouseoperator_filterset(data=query, + queryset=self.killhouse_query)).filter(): + ps = self.killhouseoperator_filterset(data=query, + queryset=self.killhouse_query) + filtered_killhouse_operator = ps.filter() + if filtered_killhouse_operator: + killhouse_limited_query.append(query) + + if not city_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.city_filterset(data=query, + queryset=self.city_query)).filter(): + ps = self.city_filterset(data=query, + queryset=self.city_query) + filtered_city_operator = ps.filter() + if filtered_city_operator: + city_limited_query.append(query) + + if not driver_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.killhousedriver_filterset(data=query, + queryset=self.driver_query)).filter(): + ps = self.killhousedriver_filterset(data=query, + queryset=self.city_query) + filtered_driver = ps.filter() + if filtered_driver: + driver_limited_query.append(query) + + if not inspector_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.inspector_filterset(data=query, + queryset=self.inspector_query)).filter(): + ps = self.inspector_filterset(data=query, + queryset=self.inspector_query) + filtered_inspector_operator = ps.filter() + if filtered_inspector_operator: + inspector_limited_query.append(query) + + if not vet_query_var: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.vet_filterset(data=query, + queryset=self.vet_query)).filter(): + ps = self.vet_filterset(data=query, + queryset=self.vet_query) + filtered_vet = ps.filter() + if filtered_vet: + vet_limited_query.append(query) + + for i in poultry_limited_query: + for key, value in i.items(): + poultry_limited_dict[key] = value + + if len(poultry_limited_dict) > 0: + for i in Poultry.objects.filter(**poultry_limited_dict): + poultry_query_val.append(i) + + if len(poultry_query_val) > 0: + for poultry in poultry_query_val: + poulty_wallet = poultry.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=poulty_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": poultry.user.base_order, + "fullname": poultry.user.fullname, + "id": poultry.user.id, + # "role": poultry.user.name, + "mobile": poultry.user.mobile, + "national_id": poultry.user.national_id, + "wallet_key": poultry.wallet.key, + "inventory": poultry.wallet.inventory, + "city": poultry.user.city.name, + "province": poultry.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in province_limited_query: + for key, value in i.items(): + province_limited_dict[key] = value + if len(province_limited_dict) > 0: + if len(values_item) == len(province_limited_dict): + + for i in ProvinceOperator.objects.filter(**province_limited_dict): + province_query_val.append(i) + + if len(province_query_val) > 0: + for province in province_query_val: + province_wallet = province.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=province_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + internal_dict = { + "base_orde": province.user.base_order, + "fullname": province.user.fullname, + "id": province.user.id, + # "role": poultry.user.name, + "mobile": province.user.mobile, + "national_id": province.user.national_id, + "wallet_key": province.wallet.key, + "inventory": province.wallet.inventory, + "city": province.user.city.name, + "province": province.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in killhouse_limited_query: + for key, value in i.items(): + killhouse_limited_dict[key] = value + if len(killhouse_limited_dict) > 0: + if len(values_item) == len(killhouse_limited_dict): + + for i in KillHouseOperator.objects.filter(**killhouse_limited_dict): + killhouse_query_val.append(i) + + if len(killhouse_query_val) > 0: + for killhouse in killhouse_query_val: + killhouse_wallet = killhouse.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=killhouse_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": killhouse.user.base_order, + "fullname": killhouse.user.fullname, + "id": killhouse.user.id, + # "role": poultry.user.name, + "mobile": killhouse.user.mobile, + "national_id": killhouse.user.national_id, + "wallet_key": killhouse.wallet.key, + "inventory": killhouse.wallet.inventory, + "city": killhouse.user.city.name, + "province": killhouse.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in city_limited_query: + for key, value in i.items(): + city_limited_dict[key] = value + + if len(city_limited_dict) > 0: + if len(values_item) == len(city_limited_dict): + + for i in CityOperator.objects.filter(**city_limited_dict): + city_query_val.append(i) + + if len(city_query_val) > 0: + for city in city_query_val: + city_wallet = city.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=city_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": city.user.base_order, + "fullname": city.user.fullname, + "id": city.user.id, + # "role": city.user.name, + "mobile": city.user.mobile, + "national_id": city.user.national_id, + "wallet_key": city.wallet.key, + "inventory": city.wallet.inventory, + "city": city.user.city.name, + "province": city.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in driver_limited_query: + for key, value in i.items(): + driver_limited_dict[key] = value + if len(driver_limited_dict) > 0: + if len(values_item) == len(driver_limited_dict): + + for i in KillHouseDriver.objects.filter(**driver_limited_dict): + driver_query_val.append(i) + + if len(driver_query_val) > 0: + for driver in driver_query_val: + driver_wallet = driver.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=driver_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": driver.user.base_order, + "fullname": driver.user.fullname, + "id": driver.user.id, + # "role": driver.user.name, + "mobile": driver.user.mobile, + "national_id": driver.user.national_id, + "wallet_key": driver.wallet.key, + "inventory": driver.wallet.inventory, + "city": driver.user.city.name, + "province": driver.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in inspector_limited_query: + for key, value in i.items(): + inspector_limited_dict[key] = value + if len(inspector_limited_dict) > 0: + if len(values_item) == len(inspector_limited_dict): + for i in InspectorOperator.objects.filter(**inspector_limited_dict): + inspector_query_val.append(i) + + if len(inspector_query_val) > 0: + for inspector in inspector_query_val: + inspector_wallet = inspector.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=inspector_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": inspector.user.base_order, + "fullname": inspector.user.fullname, + "id": inspector.user.id, + # "role": inspector.user.name, + "mobile": inspector.user.mobile, + "national_id": inspector.user.national_id, + "wallet_key": inspector.wallet.key, + "inventory": inspector.wallet.inventory, + "city": inspector.user.city.name, + "province": inspector.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + for i in vet_limited_query: + for key, value in i.items(): + vet_limited_dict[key] = value + if len(vet_limited_dict) > 0: + if len(values_item) == len(vet_limited_dict): + + for i in Vet.objects.filter(**vet_limited_dict): + vet_query_val.append(i) + + if len(vet_query_val) > 0: + for vet in vet_query_val: + vet_wallet = vet.wallet + creditor = 0 + debtor = 0 + penalty = 0 + deposit = 0 + for i in Itransaction.objects.filter(wallet=vet_wallet): + if i.transaction_type == 'creditor': + creditor += i.transfer_amount + elif i.transaction_type == 'debtor': + debtor += i.transfer_amount + elif i.transaction_type == 'penalty': + penalty += i.transfer_amount + elif i.transaction_type == 'deposit': + deposit += i.transfer_amount + + internal_dict = { + "base_orde": vet.user.base_order, + "fullname": vet.user.fullname, + "id": vet.user.id, + # "role": vet.user.name, + "mobile": vet.user.mobile, + "national_id": vet.user.national_id, + "wallet_key": vet.wallet.key, + "inventory": vet.wallet.inventory, + "city": vet.user.city.name, + "province": vet.user.province.name, + "creditor": creditor, + "debtor": debtor, + "penalty": penalty, + "deposit": deposit, + "depositable": (creditor + deposit) - (debtor + penalty) + + } + total_list.append(internal_dict) + + return Response(total_list, status=status.HTTP_200_OK) + + +class FinancialTransactionViewset(viewsets.ModelViewSet): + queryset = FinancialTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = FinancialTransactionSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + wallet_receive = Wallet.objects.get(key=request.data['wallet_receive']) + user = SystemUserProfile.objects.get(id=request.data['user_id']) + user_system = SystemUserProfile.objects.get(user=request.user) + request.data.pop('wallet_receive') + request.data.pop('user_id') + + if 'image' in request.data.keys(): + images = request.data['image'] + request.data.pop('image') + else: + images = None + image_list = [] + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + finansial_transaction = serializer.create(validated_data=request.data) + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + + finansial_transaction.image = image_list + + itransactions = Itransaction.objects.filter(file_id=0, wallet=wallet_receive).order_by( + 'create_date') + if itransactions.count() > 0: + itransactions = itransactions.last() + payment_code = itransactions.payment_code + 1 + else: + payment_code = int(user.base_order) + 1 + + if finansial_transaction.type == 'deposit': + + # if user.id == user_system.id: + new_transaction = Itransaction( + wallet=wallet_receive, + transfer_amount=finansial_transaction.cost, + transaction_type=finansial_transaction.type, + payment_code=payment_code, + state='waiting' + ) + else: + + new_transaction = Itransaction( + wallet=wallet_receive, + transfer_amount=finansial_transaction.cost, + transaction_type=finansial_transaction.type, + payment_code=payment_code + ) + new_transaction.save() + finansial_transaction.itransaction = new_transaction + finansial_transaction.save() + new_object = self.serializer_class(finansial_transaction) + return Response(new_object.data, status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + if 'payment_code' in request.GET: + transaction = Itransaction.objects.get(payment_code=int(request.GET['payment_code'])) + financial = FinancialTransaction.objects.get(itransaction=transaction) + serializer = self.serializer_class(financial) + + else: + + query_list = [] + querys = FinancialTransaction.objects.filter(cost=0, trash=False) + + # for query in querys: + # query_list.append(query) + + serializer = self.serializer_class(querys) + return Response(serializer.data, status.HTTP_200_OK) + + +class AdminViewset(viewsets.ModelViewSet): + queryset = Admin.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AdminSerializer + + +class TypeCheckViewset(viewsets.ModelViewSet): + queryset = Itransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ItransactionSerializer + + def update(self, request, *args, **kwargs): + # refresh(request.user.id) + + transaction = Itransaction.objects.get(key=request.data['transaction_key']) + request.data.pop('transaction_key') + state = request.data['state'] + request.data.pop('state') + + if state == 'accepted': + transaction.state = 'pending' + transaction.save() + + elif state == 'rejected': + transaction.state = 'rejected' + transaction.save() + + return Response(status=status.HTTP_200_OK) + + +class HourLimitViewset(viewsets.ModelViewSet): + queryset = HourLimit.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = HourLimitSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + limit_hour = HourLimit.objects.all() + if limit_hour.count() > 0: + limit_hour = limit_hour.last() + limit_hour.hour = request.data['hour'] + limit_hour.active = request.data['active'] + limit_hour.save() + else: + limit_hour = serializer.create(validated_data=request.data) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + limit_hour = self.queryset.filter(trash=False).last() + if limit_hour == None: + limit_hour = HourLimit(hour=0) + limit_hour.save() + serializer = self.serializer_class(limit_hour) + return Response(serializer.data, status.HTTP_200_OK) + + +class KillHouseHourLimitViewset(viewsets.ModelViewSet): + queryset = KillHouseHourLimit.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseHourLimitSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + limit_hour = KillHouseHourLimit.objects.all() + if limit_hour.count() > 0: + limit_hour = limit_hour.last() + limit_hour.hour = request.data['hour'] + limit_hour.active = request.data['active'] + limit_hour.save() + else: + limit_hour = serializer.create(validated_data=request.data) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + limit_hour = self.queryset.filter(trash=False).last() + if limit_hour == None: + limit_hour = KillHouseHourLimit(hour=0) + limit_hour.save() + serializer = self.serializer_class(limit_hour) + return Response(serializer.data, status.HTTP_200_OK) + + +class SmsLicenseViewset(viewsets.ModelViewSet): + queryset = SmsLicense.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SmsLicenseSerializer + + def create(self, request, *args, **kwargs): + try: + sms_license = SmsLicense.objects.latest('id') + except SmsLicense.DoesNotExist: + sms_license = None + + serializer = self.serializer_class(sms_license, data=request.data) + if serializer.is_valid(): + serializer.save() + status_code = status.HTTP_200_OK if sms_license else status.HTTP_201_CREATED + return Response(serializer.data, status=status_code) + else: + return Response(serializer.errors) + + +class PoultryAllowCityProvinceViewset(viewsets.ModelViewSet): + queryset = PoultryAllowCityProvince.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryAllowCityProvinceSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + poultries = Poultry.objects.filter(user=user) + if poultries.count() > 0: + for poultry in poultries: + allow = PoultryAllowCityProvince.objects.filter(poultry=poultry) + if allow.count() > 0: + allow = allow.last() + if request.data['city'] != None: + allow.city = request.data['city'] + if request.data['province'] != None: + allow.province = request.data['province'] + allow.save() + else: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allow = serializer.create(validated_data=request.data) + allow.poultry = poultry + allow.save() + if allow.city == True: + # sms_allow_poultry_city_province_sms_sms = threading.Thread( + # target=allow_poultry_city_province_sms, + # args=( + # poultry.user.mobile)) + # sms_allow_poultry_city_province_sms_sms.start() + + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', + province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + sms_allow_poultry_city_province_sms_sms = threading.Thread( + target=allow_poultry_city_province_sms, + args=( + province_operator.user.mobile, poultry.unit_name)) + sms_allow_poultry_city_province_sms_sms.start() + + sms_allow_poultry_city_for_poultry_sms_sms = threading.Thread( + target=allow_poultry_city_for_poultry_sms, + args=( + poultry.user.mobile, poultry.unit_name)) + sms_allow_poultry_city_for_poultry_sms_sms.start() + if allow.province == True: + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', + province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + sms_allow_poultry_city_province_sms_sms = threading.Thread( + target=allow_poultry_city_province_sms, + args=( + province_operator.user.mobile, poultry.unit_name)) + sms_allow_poultry_city_province_sms_sms.start() + + sms_allow_poultry_province_for_poultry_sms_sms = threading.Thread( + target=allow_poultry_province_for_poultry_sms, + args=( + poultry.user.mobile, poultry.unit_name)) + sms_allow_poultry_province_for_poultry_sms_sms.start() + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultries = Poultry.objects.filter(user=user) + if poultries.count() > 0: + poultries = poultries.last() + allow = PoultryAllowCityProvince.objects.filter(poultry=poultries) + serializer = self.serializer_class(allow, many=True) + return Response(serializer.data, status.HTTP_200_OK) + + +class ProvinceAllowKillHouseRegisterCarViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseRegisterCar.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseRegisterCarSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + request.data.pop('kill_house_key') + # for kill_house in kill_house_list: + allow = ProvinceAllowKillHouseRegisterCar.objects.filter(kill_house=kill_house) + if allow.count() > 0: + allow = allow.last() + allow.allow = request.data['allow'] + allow.save() + + else: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allow = serializer.create(validated_data=request.data) + allow.kill_house = kill_house + allow.save() + + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + +def AllowKillHouseDirectBuying(allow_state, province): + kill_houses = KillHouse.objects.filter(system_address__province__name=province, trash=False) + for kill_house in kill_houses: + allow = ProvinceAllowKillHouseDirectBuying.objects.filter(kill_house=kill_house).last() + if allow: + allow.allow = allow_state + allow.save() + else: + allow = ProvinceAllowKillHouseDirectBuying( + kill_house=kill_house, + allow=allow_state, + + ) + allow.save() + + +class ProvinceAllowKillHouseDirectBuyingViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseDirectBuying.objects.all().order_by('id') + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseDirectBuyingSerializer + + def list(self, request, *args, **kwargs): + if 'role' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + kill_house_direct = ProvinceAllowKillHouseDirectBuying.objects.get(trash=False, kill_house=kill_house) + serializer = self.serializer_class(kill_house_direct) + + + else: + serializer = self.serializer_class(self.queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + direct_buying = ProvinceAllowKillHouseDirectBuying.objects.get(key=request.data['direct_buying_key'], + trash=False) + request.data.pop('direct_buying_key') + serializer = self.serializer_class(direct_buying) + serializer.update(instance=direct_buying, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + # allow = request.data['allow'] + # request.data.pop('allow') + # direct_buying.allow = allow + # direct_buying.save() + # return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class ProvinceAllowKillHouseDirectBuyingTotalViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseDirectBuyingTotal.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseDirectBuyingTotalSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + direct_buying_threading = threading.Thread( + target=AllowKillHouseDirectBuying, + args=( + request.data['allow'], + user.province.name)) + direct_buying_threading.start() + direct_buying = ProvinceAllowKillHouseDirectBuyingTotal.objects.all() + if direct_buying.count() > 0: + direct_buying = direct_buying.last() + direct_buying.allow = request.data['allow'] + else: + direct_buying = ProvinceAllowKillHouseDirectBuyingTotal( + allow=request.data['allow'], + + ) + direct_buying.save() + + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allow_state = False + direct_buying = ProvinceAllowKillHouseDirectBuyingTotal.objects.all() + if direct_buying.count() > 0: + allow_state = direct_buying.last().allow + + return Response({"allow_state": allow_state}, status.HTTP_200_OK) + + +def AllowKillHouseRegisterguild(allow_state, province): + kill_houses = KillHouse.objects.filter(system_address__province__name=province, trash=False) + for kill_house in kill_houses: + allow = ProvinceAllowKillHouseRegisterGuilds.objects.filter(kill_house=kill_house).last() + if allow: + allow.allow = allow_state + allow.save() + else: + allow = ProvinceAllowKillHouseRegisterGuilds( + kill_house=kill_house, + allow=allow_state, + + ) + allow.save() + + +class ProvinceAllowKillHouseRegisterGuildsViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseRegisterGuilds.objects.all().order_by('id') + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseRegisterGuildsSerializer + + def update(self, request, *args, **kwargs): + register_guilds = ProvinceAllowKillHouseRegisterGuilds.objects.get(key=request.data['register_guilds_key'], + trash=False) + request.data.pop('register_guilds_key') + allow = request.data['allow'] + request.data.pop('allow') + register_guilds.allow = allow + register_guilds.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class ProvinceAllowKillHouseRegisterGuildsTotalViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseRegisterGuildsTotal.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseRegisterGuildsTotalSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + register_guilds_threading = threading.Thread( + target=AllowKillHouseRegisterguild, + args=( + request.data['allow'], + user.province.name)) + register_guilds_threading.start() + register_guilds = ProvinceAllowKillHouseRegisterGuildsTotal.objects.all() + if register_guilds.count() > 0: + register_guilds = register_guilds.last() + register_guilds.allow = request.data['allow'] + else: + register_guilds = ProvinceAllowKillHouseRegisterGuildsTotal( + allow=request.data['allow'], + + ) + register_guilds.save() + + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + allow_state = False + register_guilds = ProvinceAllowKillHouseRegisterGuildsTotal.objects.all() + if register_guilds.count() > 0: + allow_state = register_guilds.last().allow + + return Response({"allow_state": allow_state}, status.HTTP_200_OK) + + +def PoultryChooseKillHouse(allow_state, mandatory, province): + poultries = Poultry.objects.filter(address__province__name=province, trash=False) + for poultry in poultries: + allow = ProvinceAllowPoultryChooseKillHouse.objects.filter(poultry=poultry) + if allow.count() > 0: + allow = allow.last() + allow.allow = allow_state + allow.mandatory = mandatory + allow.save() + + else: + allow = ProvinceAllowPoultryChooseKillHouse( + poultry=poultry, + allow=allow_state, + + ) + allow.save() + + +class ProvinceAllowPoultryChooseKillHouseViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowPoultryChooseKillHouse.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowPoultryChooseKillHouseSerializer + + def update(self, request, *args, **kwargs): + # refresh(request.user.id) + + poultry = Poultry.objects.get(key=request.data['poultry_key'], trash=False) + request.data.pop('poultry_key') + allow = request.data['allow'] + mandatory = request.data['mandatory'] + request.data.pop('allow') + request.data.pop('mandatory') + province_allow = ProvinceAllowPoultryChooseKillHouse.objects.filter(poultry=poultry, trash=False) + if province_allow.count() > 0: + province_allow = province_allow.last() + province_allow.allow = allow + province_allow.mandatory = mandatory + province_allow.save() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + else: + return Response({"result": "اجازه ای صادر نشده است !"}, status=status.HTTP_403_FORBIDDEN) + + +class ProvinceAllowPoultryChooseKillHouseTotalViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowPoultryChooseKillHouseTotal.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowPoultryChooseKillHouseTotalSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + PoultryChooseKillHouse_threading = threading.Thread( + target=PoultryChooseKillHouse, + args=( + request.data['allow'], + request.data['mandatory'], + user.province.name)) + PoultryChooseKillHouse_threading.start() + total_allow = ProvinceAllowPoultryChooseKillHouseTotal.objects.all() + if total_allow.count() > 0: + total_allow = total_allow.last() + total_allow.allow = request.data['allow'] + total_allow.mandatory = request.data['mandatory'] + else: + total_allow = ProvinceAllowPoultryChooseKillHouseTotal( + allow=request.data['allow'], + mandatory=request.data['mandatory'] + + ) + total_allow.save() + + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + allow_state = False + mandatory = False + total_allow = ProvinceAllowPoultryChooseKillHouseTotal.objects.all() + if total_allow.count() > 0: + allow_state = total_allow.last().allow + mandatory = total_allow.last().mandatory + + return Response({"allow_state": allow_state, "mandatory": mandatory}, status.HTTP_200_OK) + + +def PoultrySellFree(allow_state, province): + poultries = Poultry.objects.filter(address__province__name=province, trash=False) + for poultry in poultries: + allow = ProvinceAllowPoultrySellFree.objects.filter(poultry=poultry) + if allow.count() > 0: + allow = allow.last() + allow.allow = allow_state + allow.save() + + else: + allow = ProvinceAllowPoultrySellFree( + poultry=poultry, + allow=allow_state, + + ) + allow.save() + + +def KillHouseChooseSteward(steward, guilds, province): + kill_houses = KillHouse.objects.filter(system_address__province__name=province, trash=False) + for kill_house in kill_houses: + choose = ProvinceAllowKillHouseChooseStewardGuilds.objects.filter(kill_house=kill_house).last() + if choose: + choose.steward = steward + choose.guilds = guilds + choose.save() + + else: + choose = ProvinceAllowKillHouseChooseStewardGuilds( + kill_house=kill_house, + steward=steward, + guilds=guilds, + + ) + choose.save() + + +class ProvinceAllowPoultrySellFreeViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowPoultrySellFree.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowPoultrySellFreeSerializer + + def update(self, request, *args, **kwargs): + # refresh(request.user.id) + + poultry = Poultry.objects.get(key=request.data['poultry_key'], trash=False) + request.data.pop('poultry_key') + allow = request.data['allow'] + request.data.pop('allow') + province_allow = ProvinceAllowPoultrySellFree.objects.filter(poultry=poultry, trash=False) + if province_allow.count() > 0: + province_allow = province_allow.last() + province_allow.allow = allow + province_allow.save() + else: + province_allow = ProvinceAllowPoultrySellFree( + poultry=poultry, + allow=allow + ) + province_allow.save() + + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +def FreeSaleWithinprovinceThreadByWeight(weight, province): + hatchings = PoultryHatching.objects.filter(poultry__address__province__name=province, archive=False, + allow_hatching='pending', state='pending', trash=False) + for hatching in hatchings: + hatching.total_commitment = hatching.quantity * weight + hatching.total_commitment_quantity = 0 + hatching.save() + + +def FreeSaleWithinprovinceThreadByPercent(percent, province): + hatchings = PoultryHatching.objects.filter(poultry__address__province__name=province, archive=False, + allow_hatching='pending', state='pending', trash=False) + for hatching in hatchings: + # hatching.total_commitment_quantity = hatching.quantity * (percent / 100) + hatching.total_commitment_quantity = int((hatching.quantity - hatching.total_losses) * (percent / 100)) + hatching.total_free_commitment_quantity = ( + hatching.quantity - hatching.total_losses) - hatching.total_commitment_quantity + hatching.total_commitment = 0 + hatching.save() + + +def FreeCommitmentThread(province): + hatchings = PoultryHatching.objects.filter(poultry__address__province__name=province, archive=False, + allow_hatching='pending', state='pending', trash=False) + for hatching in hatchings: + hatching.total_free_commitment_quantity = hatching.quantity - hatching.total_losses + hatching.total_commitment = 0 + hatching.total_commitment_quantity = 0 + hatching.commitment_type = "free" + hatching.save() + + +class FreeSaleWithinprovinceViewset(viewsets.ModelViewSet): + queryset = FreeSaleWithinprovince.objects.all() + permission_classes = [AllowAny] + serializer_class = FreeSaleWithinprovinceSerializer + + def list(self, request, *args, **kwargs): + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if not free_sale_province: + free_sale_province = FreeSaleWithinprovince() + free_sale_province.save() + serializer = self.serializer_class(free_sale_province) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + free_sale = FreeSaleWithinprovince.objects.get(key=request.data['free_sale_key'], trash=False) + request.data.pop('free_sale_key') + if request.data['allow'] == True: + approved_price = ApprovedPrice.objects.filter(trash=False).first() + if approved_price.approved == False: + return Response({"result": "برای فعال کردن تعهد دولتی ابتدا قیمت مصوب مرغ زنده را فعال کنید!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(free_sale) + serializer.update(instance=free_sale, validated_data=request.data) + if request.data['allow'] == True and 'type' in request.data.keys(): + if request.data['type'] == 'weight': + FreeSaleWithinprovince_threading_weight = threading.Thread( + target=FreeSaleWithinprovinceThreadByWeight, + args=( + request.data['weight'], + user.province.name)) + FreeSaleWithinprovince_threading_weight.start() + else: + FreeSaleWithinprovince_threading_percent = threading.Thread( + target=FreeSaleWithinprovinceThreadByPercent, + args=( + request.data['percent'], + user.province.name)) + FreeSaleWithinprovince_threading_percent.start() + + else: + FreeCommitmentThread_Threading = threading.Thread( + target=FreeCommitmentThread, + args=(user.province.name,)) + + FreeCommitmentThread_Threading.start() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProvinceAllowPoultrySellFreeTotalViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowPoultrySellFreeTotal.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowPoultrySellFreeTotalSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + PoultrySellFree_threading = threading.Thread( + target=PoultrySellFree, + args=( + request.data['allow'], + user.province.name)) + PoultrySellFree_threading.start() + total_allow = ProvinceAllowPoultrySellFreeTotal.objects.all() + if total_allow.count() > 0: + total_allow = total_allow.last() + total_allow.allow = request.data['allow'] + else: + total_allow = ProvinceAllowPoultrySellFreeTotal( + allow=request.data['allow'] + + ) + total_allow.save() + + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + allow_state = False + total_allow = ProvinceAllowPoultrySellFreeTotal.objects.all() + if total_allow.count() > 0: + allow_state = total_allow.last().allow + + return Response(allow_state, status.HTTP_200_OK) + + +def AutoAcceptMakeRequest(province_kill_request_list): + allow = False + if AutoMakeKillHouseRequest.objects.filter(allow=True).exists(): + allow = True + province_kill_requests = ProvinceKillRequest.objects.filter(key__in=province_kill_request_list, + trash=False).select_related('killhouse_user', + 'kill_request', + 'province_request') + + for province_kill_request in province_kill_requests: + kill_house_check = KillHouseCheckRequest( + province_kill_request=province_kill_request, + role="ProvinceOperator", + state="accepted" + + ) + kill_house_check.save() + province_kill_request.state = 'accepted' + province_kill_request.save() + if allow == True: + user = province_kill_request.province_request.city_request_Poultry.poultry_request.poultry.user + if province_kill_request.kill_request.slaughter_house != None: + kill_house = province_kill_request.kill_request.slaughter_house + else: + kill_house = province_kill_request.kill_request.kill_house + + car = KillHouseADDCAR.objects.filter(kill_house=kill_house, trash=False).first() + bar_code = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request__poultry__user=user, trash=False).order_by( + 'create_date') + if bar_code.count() > 0: + if bar_code.last().bar_code != None: + bar_code_number = bar_code.last().bar_code + 1 + else: + bar_code_number = int( + str(province_kill_request.province_request.city_request_Poultry.poultry_request.order_code) + '0001') + if car: + kill_house_request = KillHouseRequest( + killhouse_user=province_kill_request.killhouse_user, + kill_request=province_kill_request.kill_request, + province_request=province_kill_request.province_request, + province_kill_request=province_kill_request, + bar_code=bar_code_number, + quantity=province_kill_request.quantity, + capacity=province_kill_request.quantity, + add_car=car, + state='accepted', + + ) + kill_house_request.save() + province_kill_request.quantity = 0 + province_kill_request.save() + + +class ProvinceAutoAllocationViewset(viewsets.ModelViewSet): + queryset = ProvinceAutoAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAutoAllocationSerializer + + def create(self, request, *args, **kwargs): + debt = False + filter_list = request.data['filter_list'] + for first_item in filter_list: + if 'minimum_allocation' in first_item: + minimum_allocation = int(first_item['minimum_allocation']) + del first_item['minimum_allocation'] + else: + minimum_allocation = 0 + + if 'no_debt' in first_item: + debt = True + del first_item['no_debt'] + + filter_list_keys = [] + request.data.pop('filter_list') + now = datetime.strptime(str(request.data['date']), '%Y-%m-%d') + request.data.pop('date') + + for item in filter_list: + filter_list_keys.extend(item.keys()) + if 'city' in filter_list_keys or 'kill_place' in filter_list_keys: + pass + else: + return Response({"result": "باید یکی از پارامتر های شهر یا محل کشتار را انتخاب کنید"}, + status=status.HTTP_403_FORBIDDEN) + + now = now + timedelta(hours=14, minutes=30, seconds=45) + quantity_sum = 0 + allocation_order_code = ProvinceAutoAllocation.objects.filter(trash=False).order_by('id') + allocation_order_code_number = allocation_order_code.last().allocation_order_code + 1 if allocation_order_code.count() > 0 else 1000 + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_requests = PoultryRequest.objects.filter( + trash=False, + province_state='accepted', + final_state='pending', + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day, + remain_quantity__gt=0, + poultry__address__province=user.province + ).order_by('-quantity') + + quantity_sum = poultry_requests.aggregate(total_quantity=Sum('remain_quantity')).get('total_quantity', 0) + if quantity_sum == None: + return Response({"result": "تعداد درخواست کشتار ها صفر است"}, status=status.HTTP_403_FORBIDDEN) + else: + percentages = KillHousePercentage.objects.filter(trash=False, + kill_house__system_address__province=user.province, + percent__gt=0).order_by( + '-percent') + add_quantity = 0 + for kill_house_percentage in percentages: + + kill_request_quantity = (kill_house_percentage.percent / 100) * quantity_sum + if kill_request_quantity.is_integer(): + kill_request_quantity = (kill_house_percentage.percent / 100) * quantity_sum + else: + kill_request_quantity = math.ceil((kill_house_percentage.percent / 100) * quantity_sum) + + kill_request = KillRequest( + kill_house=kill_house_percentage.kill_house, + kill_capacity=kill_request_quantity, + remain_quantity=kill_request_quantity, + recive_time='14 - 16', + province_state='accepted', + automatic=True, + recive_date=now + ) + kill_request.save() + + if debt == True: + if KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__killhouse_user=kill_request.kill_house, + state='pending').exists(): + kill_request.automatic_debt = True + kill_request.save() + + price = Pricing.objects.all() + if price.count() > 0: + price = price.last() + factor = KillRequestFactor( + kill_request=kill_request, + amount=round( + (kill_request.kill_capacity * 2.7) * price.live_chicken_price, + 0), + minimum_amount=round( + ((kill_request.kill_capacity * 2.7) * price.live_chicken_price) * ( + 70 / 100), + 0) + + ) + factor.save() + kill_request.factor_amount = factor.amount + kill_request.save() + + kill_house_daily_quota = KillHouseDailyQuota( + kill_house=kill_house_percentage.kill_house, + kill_request=kill_request, + percent=kill_house_percentage.percent, + quantity=kill_request_quantity, + remain_quantity=kill_request_quantity, + ) + kill_house_daily_quota.save() + if kill_house_percentage.kill_house_for_killer != None: + kill_request.slaughter_house = kill_house_percentage.kill_house_for_killer + kill_request.save() + kill_house_daily_quota.killer_kill_house = kill_house_percentage.kill_house_for_killer + kill_house_daily_quota.save() + # if add_quantity > 0 : + # daily_quotas_lists = KillHouseDailyQuota.objects.filter(trash=False, create_date__day=now.day, + # create_date__month=now.month, + # create_date__year=now.year).order_by( + # '-quantity') + # for daily in daily_quotas_lists: + # daily_quta=math.ceil((daily.percent/100) * add_quantity) + # # if daily_quta.is_integer(): + # # daily_quta = daily_quta + # # else: + # # daily_quta = math.ceil(daily_quta) + # daily.quantity += daily_quta + # daily.save() + # daily.kill_request.kill_capacity +=daily_quta + # daily.kill_request.remain_quantity +=daily_quta + # daily.kill_request.save() + + total_kill_house_daily_list = [] + for filter_key in filter_list_keys: + daily_quotas_lists = KillHouseDailyQuota.objects.filter(trash=False, create_date__day=now.day, + create_date__month=now.month, + create_date__year=now.year).order_by( + '-quantity') + if filter_key == 'kill_place' or filter_key == 'city': + + if len(total_kill_house_daily_list) == 0: + for poultry_request in poultry_requests: + if poultry_request.remain_quantity == 0: + continue + for daily_quotas_list in daily_quotas_lists: + if daily_quotas_list.killer_kill_house != None: + city = daily_quotas_list.killer_kill_house.system_address.city + if city == poultry_request.poultry.address.city: + if daily_quotas_list not in total_kill_house_daily_list: + for daily_quotas_list_kill_house_internal in daily_quotas_lists: + if daily_quotas_list_kill_house_internal.kill_house == daily_quotas_list.killer_kill_house: + if daily_quotas_list_kill_house_internal not in total_kill_house_daily_list: + total_kill_house_daily_list.append( + daily_quotas_list_kill_house_internal) + # break + total_kill_house_daily_list.append(daily_quotas_list) + for daily_quotas_list_first_internal in daily_quotas_lists: + if daily_quotas_list_first_internal.killer_kill_house == daily_quotas_list.killer_kill_house: + if not daily_quotas_list_first_internal in total_kill_house_daily_list: + total_kill_house_daily_list.append( + daily_quotas_list_first_internal) + else: + continue + else: + if daily_quotas_list.kill_house.system_address.city == poultry_request.poultry.address.city: + if daily_quotas_list not in total_kill_house_daily_list: + total_kill_house_daily_list.append(daily_quotas_list) + for daily_quotas_list_internal in daily_quotas_lists: + if daily_quotas_list_internal.killer_kill_house == daily_quotas_list.killer_kill_house: + if not daily_quotas_list_internal in total_kill_house_daily_list: + total_kill_house_daily_list.append(daily_quotas_list_internal) + else: + continue + for daily_quotas_remain_list in daily_quotas_lists: + if daily_quotas_remain_list not in total_kill_house_daily_list: + total_kill_house_daily_list.append(daily_quotas_remain_list) + + + + else: + internal_kill_place_list = total_kill_house_daily_list + total_kill_house_daily_list = [] + for poultry_request in poultry_requests: + if poultry_request.remain_quantity == 0: + continue + + for internal_daily_quotas_list in internal_kill_place_list: + if internal_daily_quotas_list.killer_kill_house != None: + city = internal_daily_quotas_list.killer_kill_house.system_address.city + if city == poultry_request.poultry.address.city: + if internal_daily_quotas_list not in total_kill_house_daily_list: + for daily_quotas_list_kill_house_internal_second in internal_kill_place_list: + if daily_quotas_list_kill_house_internal_second.kill_house == internal_daily_quotas_list.killer_kill_house: + if daily_quotas_list_kill_house_internal_second not in total_kill_house_daily_list: + total_kill_house_daily_list.append( + daily_quotas_list_kill_house_internal_second) + # break + total_kill_house_daily_list.append(internal_daily_quotas_list) + for internal_daily_quotas_list_first in daily_quotas_lists: + if internal_daily_quotas_list_first.killer_kill_house == internal_daily_quotas_list.killer_kill_house or internal_daily_quotas_list_first.kill_house == internal_daily_quotas_list.killer_kill_house: + if not internal_daily_quotas_list_first in total_kill_house_daily_list: + total_kill_house_daily_list.append( + internal_daily_quotas_list_first) + else: + continue + else: + if internal_daily_quotas_list.kill_house.system_address.city == poultry_request.poultry.address.city: + if internal_daily_quotas_list not in total_kill_house_daily_list: + total_kill_house_daily_list.append(internal_daily_quotas_list) + for daily_quotas_list_internal_second in internal_kill_place_list: + if daily_quotas_list_internal_second.killer_kill_house == internal_daily_quotas_list.killer_kill_house: + if not daily_quotas_list_internal_second in total_kill_house_daily_list: + total_kill_house_daily_list.append( + daily_quotas_list_internal_second) + else: + continue + + for internal_daily_quotas_remain_list in internal_kill_place_list: + if internal_daily_quotas_remain_list not in total_kill_house_daily_list: + total_kill_house_daily_list.append(internal_daily_quotas_remain_list) + + for poultry_request in poultry_requests: + + if poultry_request.remain_quantity == 0: + continue + province_ckeck = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + + for kill_house_daily in total_kill_house_daily_list: + kill_request = KillRequest.objects.get(key=kill_house_daily.kill_request.key, trash=False) + + if kill_request.remain_quantity == 0: + continue + + if poultry_request.remain_quantity == 0: + continue + if kill_house_daily.killer_kill_house != None: + city = kill_house_daily.killer_kill_house.system_address.city + else: + city = kill_house_daily.kill_house.system_address.city + + if city != poultry_request.poultry.address.city: + continue + if kill_request.remain_quantity > poultry_request.remain_quantity: + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=poultry_request.remain_quantity, + main_quantity=poultry_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=poultry_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + kill_request.remain_quantity -= poultry_request.remain_quantity + kill_request.save() + poultry_request.remain_quantity = 0 + poultry_request.save() + province_ckeck.quantity = 0 + province_ckeck.save() + elif kill_request.remain_quantity == poultry_request.remain_quantity: + + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=poultry_request.remain_quantity, + main_quantity=poultry_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=poultry_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + kill_request.remain_quantity = 0 + kill_request.save() + poultry_request.remain_quantity = 0 + poultry_request.save() + province_ckeck.quantity = 0 + province_ckeck.save() + else: + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=kill_request.remain_quantity, + main_quantity=kill_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=kill_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + poultry_request.remain_quantity -= kill_request.remain_quantity + poultry_request.save() + province_ckeck.quantity -= kill_request.remain_quantity + province_ckeck.save() + kill_request.remain_quantity = 0 + kill_request.save() + + for poultry_request in poultry_requests: + + if poultry_request.remain_quantity == 0: + continue + province_ckeck = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + + for kill_house_daily in total_kill_house_daily_list: + kill_request = KillRequest.objects.get(key=kill_house_daily.kill_request.key, trash=False) + + if kill_request.remain_quantity == 0: + continue + + if poultry_request.remain_quantity == 0: + continue + if kill_request.remain_quantity > poultry_request.remain_quantity: + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=poultry_request.remain_quantity, + main_quantity=poultry_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=poultry_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + kill_request.remain_quantity -= poultry_request.remain_quantity + kill_request.save() + poultry_request.remain_quantity = 0 + poultry_request.save() + province_ckeck.quantity = 0 + province_ckeck.save() + elif kill_request.remain_quantity == poultry_request.remain_quantity: + + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=poultry_request.remain_quantity, + main_quantity=poultry_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=poultry_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + kill_request.remain_quantity = 0 + kill_request.save() + poultry_request.remain_quantity = 0 + poultry_request.save() + province_ckeck.quantity = 0 + province_ckeck.save() + else: + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_request.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_ckeck, + quantity=kill_request.remain_quantity, + main_quantity=kill_request.remain_quantity, + automatic=True, + + ) + province_kill_request.save() + + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily, + poultry_request=poultry_request, + quantity=kill_request.remain_quantity, + allocation_order_code=allocation_order_code_number, + province_kill_request=province_kill_request, + + ) + allocation.save() + if minimum_allocation > 0 and allocation.quantity < minimum_allocation: + allocation.unauthorized_number = True + allocation.save() + poultry_request.remain_quantity -= kill_request.remain_quantity + poultry_request.save() + province_ckeck.quantity -= kill_request.remain_quantity + province_ckeck.save() + kill_request.remain_quantity = 0 + kill_request.save() + + return Response({"result": "تخصیص اتوماتیک با موفقیت انجام شد."}, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + poultry_requests_list = [] + date1 = datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + poultry_requests_lists = PoultryRequest.objects.filter( + trash=False, + province_state='accepted', + final_state='pending', + poultry__address__province=user.province + ).order_by('-quantity') + poultry_requests = [ + poultry_request_list for poultry_request_list in poultry_requests_lists + if date1 <= poultry_request_list.send_date.date() <= date2 + ] + if len(poultry_requests) > 0: + if request.GET['state'] == 'temporary': + + for poultry_request in poultry_requests: + allocations_sum = 0 + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request=poultry_request, trash=False, + state__in=('pending', 'accepted'), automatic=False) + if province_kill_requests.count() > 0: + for province_kill_request in province_kill_requests: + allocations_sum += province_kill_request.main_quantity + poultry_request_dict = { + "poultry_user_fullname": poultry_request.poultry.user.fullname, + "poultry_key": poultry_request.key, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_name": poultry_request.poultry.unit_name, + "poultry_address": poultry_request.poultry.address.city.name, + "poultry_quantity": poultry_request.quantity, + "poultry_request_index_weight": poultry_request.Index_weight, + "poultry_request_weight": poultry_request.quantity * poultry_request.Index_weight, + "poultry_request_key": poultry_request.key, + "poultry_remain_quantity": poultry_request.remain_quantity, + } + allocations_list = [] + allocations = ProvinceAutoAllocation.objects.filter(poultry_request=poultry_request, + state='temporary', trash=False) + if allocations.count() > 0: + + for allocation in allocations: + allocations_sum += allocation.quantity + if allocation.daily_quota.killer_kill_house != None: + Killing_place = allocation.daily_quota.killer_kill_house.name + buyer_address = allocation.daily_quota.killer_kill_house.system_address.city.name + else: + Killing_place = allocation.daily_quota.kill_house.name + buyer_address = allocation.daily_quota.kill_house.system_address.city.name + allocation_dict = { + "allocation_key": allocation.key, + "type": allocation.daily_quota.kill_house.killer, + "buyer_name": allocation.daily_quota.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": allocation.daily_quota.kill_house.kill_house_operator.user.mobile, + "buyer_address": buyer_address, + "allocation_quantity": allocation.quantity, + "allocation_weight": allocation.quantity * poultry_request.Index_weight, + "allocation_percent": allocation.daily_quota.percent, + "unauthorized_number": allocation.unauthorized_number, + "Killing_place": Killing_place, + "debt": allocation.daily_quota.kill_request.automatic_debt, + } + + allocations_list.append(allocation_dict) + + poultry_request_dict.update({ + "allocations": allocations_list, + "allocations_sum": allocations_sum, + }) + poultry_requests_list.append(poultry_request_dict) + return Response(poultry_requests_list, status=status.HTTP_200_OK) + # return Response({"result": "تعدادی برای تخصیص وجود ندارد!"}, status=status.HTTP_200_OK) + + else: + allocation_order_code_list = [] + final_allocation_list = [] + for poultry_request in poultry_requests: + allocations = ProvinceAutoAllocation.objects.filter(poultry_request=poultry_request, + state='final_registration', trash=False) + if allocations.count() > 0: + for allocation in allocations: + if allocation.allocation_order_code in allocation_order_code_list: + pass + else: + allocation_order_code_list.append(allocation.allocation_order_code) + + if len(allocation_order_code_list) > 0: + for allocation_order_code in sorted(allocation_order_code_list): + poultry_requests_list = [] + kill_house_list = [] + poultry_list = [] + allocated_quantity = 0 + total_quantity = 0 + internal_allocation_dict = { + "allocation_order_code": allocation_order_code, + "allocation_date": allocation_order_code, + } + + for poultry_request in poultry_requests: + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + allocations_sum = 0 + total_quantity += poultry_request.quantity + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request=poultry_request, trash=False, + state__in=('pending', 'accepted'), automatic=False) + if province_kill_requests.count() > 0: + for province_kill_request in province_kill_requests: + allocations_sum += province_kill_request.main_quantity + poultry_request_dict = { + "poultry_user_fullname": poultry_request.poultry.user.fullname, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_name": poultry_request.poultry.unit_name, + "poultry_address": poultry_request.poultry.address.city.name, + "poultry_quantity": poultry_request.quantity, + "poultry_request_key": poultry_request.key, + "poultry_request_index_weight": poultry_request.Index_weight, + "poultry_request__weight": poultry_request.quantity * poultry_request.Index_weight, + "poultry_remain_quantity": poultry_request.remain_quantity, + } + allocations_list = [] + allocations = ProvinceAutoAllocation.objects.filter(poultry_request=poultry_request, + state='final_registration', + allocation_order_code=allocation_order_code, + trash=False) + if allocations.count() > 0: + + for allocation in allocations: + debt = False + if allocation.daily_quota.kill_house in kill_house_list: + pass + else: + kill_house_list.append(allocation.daily_quota.kill_house) + allocation_date = str(allocation.create_date.date()) + allocations_sum += allocation.quantity + if allocation.daily_quota.killer_kill_house != None: + Killing_place = allocation.daily_quota.killer_kill_house.name + buyer_address = allocation.daily_quota.killer_kill_house.system_address.city.name + + else: + Killing_place = allocation.daily_quota.kill_house.name + buyer_address = allocation.daily_quota.kill_house.system_address.city.name + + # if KillHouseFactorToProvince.objects.filter( + # province_factor__province_check_info__kill_house_assignment__kill_house_request__killhouse_user=allocation.daily_quota.kill_house, + # state='pending').exists(): + + allocation_dict = { + "allocation_key": allocation.key, + "type": allocation.daily_quota.kill_house.killer, + "buyer_name": allocation.daily_quota.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": allocation.daily_quota.kill_house.kill_house_operator.user.mobile, + "buyer_address": buyer_address, + "allocation_quantity": allocation.quantity, + "allocation_weight": allocation.quantity * poultry_request.Index_weight, + "allocation_percent": allocation.daily_quota.percent, + "Killing_place": Killing_place, + "debt": allocation.daily_quota.kill_request.automatic_debt, + "unauthorized_number": allocation.unauthorized_number, + } + + allocations_list.append(allocation_dict) + + poultry_request_dict.update({ + "allocations": allocations_list, + "allocations_sum": allocations_sum, + }) + poultry_requests_list.append(poultry_request_dict) + allocated_quantity += allocations_sum + internal_allocation_dict.update({"allocations_list": poultry_requests_list, + "allocation_date": allocation.create_date, + "allocated_quantity": allocated_quantity, + "total_quantity": total_quantity, + "number_of_poultry": len(poultry_list), + "number_of_kill_house": len(kill_house_list)}) + final_allocation_list.append(internal_allocation_dict) + + return Response(final_allocation_list, status=status.HTTP_200_OK) + else: + if request.GET['state'] == 'temporary': + return Response({"result": "تعدادی برای تخصیص وجود ندارد!"}, status=status.HTTP_200_OK) + else: + return Response([], status=status.HTTP_200_OK) + # return Response({"result": "تعدادی برای بایگانی وجود ندارد!"}, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + if 'allocation_list' in request.data.keys(): + + allocation_lists = request.data['allocation_list'] + request.data.pop('allocation_list') + daily_quota_objects = [] + allocation_objects = [] + for allocation_list in allocation_lists: + allocation = ProvinceAutoAllocation.objects.get(key=allocation_list["allocationKey"], trash=False) + poultry_request = PoultryRequest.objects.get(key=allocation.poultry_request.key, trash=False) + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request) + if allocation.quantity > allocation_list["allocationQuantity"]: + province_check.quantity += allocation.quantity - allocation_list["allocationQuantity"] + poultry_request.remain_quantity += allocation.quantity - allocation_list["allocationQuantity"] + province_check.save() + poultry_request.save() + else: + province_check.quantity -= allocation_list["allocationQuantity"] - allocation.quantity + poultry_request.remain_quantity -= allocation_list["allocationQuantity"] - allocation.quantity + province_check.save() + poultry_request.save() + + allocation.quantity = allocation_list["allocationQuantity"] + allocation.save() + province_kill_request = ProvinceKillRequest.objects.get( + key=allocation.province_kill_request.key) + province_kill_request.quantity = allocation_list["allocationQuantity"] + province_kill_request.main_quantity = allocation_list["allocationQuantity"] + province_kill_request.save() + + allocation_objects.append(allocation) + daily_quota_objects.append(allocation.daily_quota) + for daily_quota_object in daily_quota_objects: + quantity = 0 + for allocation_object in allocation_objects: + if allocation_object.daily_quota == daily_quota_object: + quantity += allocation_object.quantity + daily_quota_object.quantity = quantity + daily_quota_object.save() + kill_request = KillRequest.objects.get(key=daily_quota_object.kill_request.key, trash=False) + kill_request.kill_capacity = quantity + kill_request.remain_quantity = 0 + kill_request.save() + + return Response({"result": "با موفقیت ویرایش شد."}, status=status.HTTP_200_OK) + elif 'allocation_delete_list' in request.data.keys(): + allocation_lists = request.data['allocation_delete_list'] + request.data.pop('allocation_delete_list') + for allocation_list in allocation_lists: + allocation = ProvinceAutoAllocation.objects.get(key=allocation_list["allocationKey"], trash=False) + province_kill_request = ProvinceKillRequest.objects.get( + key=allocation.province_kill_request.key) + province_check = ProvinceCheckOperatorRequest.objects.get( + key=province_kill_request.province_request.key) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + province_kill_request.trash = True + province_kill_request.save() + + daily_object = KillHouseDailyQuota.objects.get(key=allocation.daily_quota.key, trash=False) + poultry_request = PoultryRequest.objects.get(key=allocation.poultry_request.key) + poultry_request.remain_quantity += allocation.quantity + poultry_request.save() + kill_request = KillRequest.objects.get(key=allocation.daily_quota.kill_request.key, trash=False) + kill_request.trash = True + kill_request.save() + daily_object.trash = True + daily_object.save() + allocation.trash = True + allocation.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + elif 'final_registration_list' in request.data.keys(): + province_kill_requeest_list = [] + final_registration_list = request.data['final_registration_list'] + for allocation_list in final_registration_list: + final_registration = ProvinceAutoAllocation.objects.get(key=allocation_list["allocationKey"], + trash=False) + province_kill_request = ProvinceKillRequest.objects.get( + key=final_registration.province_kill_request.key, trash=False) + province_kill_request.dont_show_kill_house = False + province_kill_request.save() + final_registration.state = 'final_registration' + final_registration.save() + province_kill_requeest_list.append(province_kill_request.key) + if AutoAcceptProvinceKillRequest.objects.filter(allow=True).exists(): + AutoAcceptMakeRequest_threading = threading.Thread( + target=AutoAcceptMakeRequest, + args=( + province_kill_requeest_list, + )) + AutoAcceptMakeRequest_threading.start() + return Response({"result": "ثبت نهایی با موفقیت انجام شد."}) + elif 'cancellation' in request.data.keys(): + cancellation_allocations_list = request.data['cancellation'] + daily_quota_list = [] + for delete_allocation in cancellation_allocations_list: + + allocation = ProvinceAutoAllocation.objects.get(key=delete_allocation["allocationKey"], trash=False) + if allocation.daily_quota not in daily_quota_list: + daily_quota_list.append(allocation.daily_quota) + province_kill_request = ProvinceKillRequest.objects.get(key=allocation.province_kill_request.key, + trash=False) + province_check = ProvinceCheckOperatorRequest.objects.get( + key=province_kill_request.province_request.key) + province_check.quantity += province_kill_request.main_quantity + province_check.save() + poultry_request = PoultryRequest.objects.get(key=province_check.poultry_request.key, trash=False) + poultry_request.remain_quantity += province_kill_request.main_quantity + poultry_request.save() + + province_kill_request.delete() + allocation.delete() + + for daily_quota_internal_list in daily_quota_list: + daily_quota = KillHouseDailyQuota.objects.get(key=daily_quota_internal_list.key) + kill_request = KillRequest.objects.get(key=daily_quota.kill_request.key, trash=False) + factor = KillRequestFactor.objects.get(kill_request=kill_request, trash=False) + factor.delete() + kill_request.delete() + daily_quota.delete() + + return Response({"result": "ثبت نهایی با موفقیت انجام شد."}) + + else: + allocation_lists = request.data['allocation_add_list'] + request.data.pop('allocation_add_list') + + for allocation_list in allocation_lists: + + poultry_request = PoultryRequest.objects.get(key=allocation_list["poultry_request_key"]) + province_check = ProvinceCheckOperatorRequest.objects.get(poultry_request=poultry_request, trash=False) + kill_house_percentage = KillHousePercentage.objects.get( + kill_house__key=allocation_list["kill_house_key"]) + kill_request = KillRequest( + kill_house=kill_house_percentage.kill_house, + kill_capacity=int(allocation_list["quantity"]), + remain_quantity=0, + recive_time='14 - 16', + province_state='accepted', + automatic=True, + recive_date=datetime.now() + ) + kill_request.save() + price = Pricing.objects.all() + if price.count() > 0: + price = price.last() + factor = KillRequestFactor( + kill_request=kill_request, + amount=round( + (kill_request.kill_capacity * 2.7) * price.live_chicken_price, + 0), + minimum_amount=round( + ((kill_request.kill_capacity * 2.7) * price.live_chicken_price) * ( + 70 / 100), + 0) + + ) + factor.save() + kill_request.factor_amount = factor.amount + kill_request.save() + kill_house_daily_quota = KillHouseDailyQuota( + kill_house=kill_house_percentage.kill_house, + kill_request=kill_request, + percent=kill_house_percentage.percent, + quantity=kill_request.kill_capacity, + remain_quantity=kill_request.kill_capacity, + ) + kill_house_daily_quota.save() + if kill_house_percentage.kill_house_for_killer != None: + kill_request.slaughter_house = kill_house_percentage.kill_house_for_killer + kill_request.save() + kill_house_daily_quota.killer_kill_house = kill_house_percentage.kill_house_for_killer + kill_house_daily_quota.save() + poultry_request.remain_quantity -= int(allocation_list["quantity"]) + poultry_request.save() + allocation_list = ProvinceAutoAllocation.objects.all() + if allocation_list.count() > 0: + code = allocation_list.last().allocation_order_code + else: + code = 1000 + + province_kill_request = ProvinceKillRequest( + killhouse_user=kill_house_percentage.kill_house, + dont_show_kill_house=True, + kill_request=kill_request, + province_request=province_check, + quantity=kill_request.kill_capacity, + main_quantity=kill_request.kill_capacity, + automatic=True, + + ) + province_kill_request.save() + province_check = ProvinceCheckOperatorRequest.objects.get( + key=province_kill_request.province_request.key) + province_check.quantity -= province_kill_request.main_quantity + province_check.save() + + allocation = ProvinceAutoAllocation( + daily_quota=kill_house_daily_quota, + poultry_request=poultry_request, + quantity=kill_request.kill_capacity, + allocation_order_code=code, + province_kill_request=province_kill_request + + ) + allocation.save() + + return Response({"result": "تخصیص با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +# +# class ProvinceAutoAcceptAllocationProvinceKillRequestViewset(viewsets.ModelViewSet): +# queryset = ProvinceKillRequest.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = ProvinceKillRequestSerializer +# +# +# +# +# def create(self, request, *args, **kwargs): +# date=datetime.now().date() +# # allocations = ProvinceAutoAllocation.objects.filter(trash=False, create_date__date=date).select_related( +# # 'poultry_request', +# # 'province_kill_request', +# # 'daily_quota__kill_house__kill_house_operator__user', +# # 'daily_quota__killer_kill_house__kill_house_operator__user' +# # ) +# +# poultry_requests = PoultryRequest.objects.filter( +# poultry_request_auto_quantity_province__in=ProvinceAutoAllocation.objects.filter( +# trash=False, +# create_date__date=date +# ).values('poultry_request_id') +# ).distinct() +# +# +# +# return Response(poultry_requests.query, status=status.HTTP_201_CREATED) + + +class AutoAcceptProvinceKillRequestViewset(viewsets.ModelViewSet): + queryset = AutoAcceptProvinceKillRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AutoAcceptProvinceKillRequestSerializer + + def update(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data) + auto_accept = AutoAcceptProvinceKillRequest.objects.all().first() + if serializer.is_valid(): + + if auto_accept: + serializer.update(instance=auto_accept, validated_data=request.data) + else: + serializer.create(validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + auto_accept = AutoAcceptProvinceKillRequest.objects.all().first() + allow = False + if auto_accept: + allow = auto_accept.allow + return Response(allow, status=status.HTTP_200_OK) + + +class AutoMakeKillHouseRequestViewset(viewsets.ModelViewSet): + queryset = AutoMakeKillHouseRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AutoMakeKillHouseRequestSerializer + + def update(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data) + auto_accept = AutoMakeKillHouseRequest.objects.all().first() + if serializer.is_valid(): + + if auto_accept: + serializer.update(instance=auto_accept, validated_data=request.data) + else: + serializer.create(validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + auto_accept = AutoMakeKillHouseRequest.objects.all().first() + allow = False + if auto_accept: + allow = auto_accept.allow + return Response(allow, status=status.HTTP_200_OK) + + +class KillHousePercentageOfLossesViewset(viewsets.ModelViewSet): + queryset = KillHousePercentageOfLosses.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHousePercentageOfLossesSerializer + + +class ProvinceAllowKillHouseChooseStewardGuildsViewset(viewsets.ModelViewSet): + queryset = ProvinceAllowKillHouseChooseStewardGuilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceAllowKillHouseChooseStewardGuildsSerializer + + # def create(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user, trash=False) + # steward = False + # guilds = False + # kill_house_choose_threading = threading.Thread( + # target=KillHouseChooseSteward, + # args=( + # steward, + # # request.data['steward'], + # guilds, + # # request.data['guilds'], + # user.province.name)) + # kill_house_choose_threading.start() + # return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house_choose_threading = threading.Thread( + target=KillHouseChooseSteward, + args=( + request.data['steward'], + request.data['guilds'], + user.province.name)) + kill_house_choose_threading.start() + return Response({"result": "عملیات با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + if 'kill_house_key' in request.GET and request.GET['kill_house_key'] != None: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key']) + queryset = ProvinceAllowKillHouseChooseStewardGuilds.objects.get(kill_house=kill_house) + serializer = self.serializer_class(queryset) + else: + + queryset = ProvinceAllowKillHouseChooseStewardGuilds.objects.all().order_by('id') + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data, status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + choose_steward_guilds = ProvinceAllowKillHouseChooseStewardGuilds.objects.get( + key=request.data['choose_steward_guilds_key']) + request.data.pop('choose_steward_guilds_key') + serializer = self.serializer_class(choose_steward_guilds) + serializer.update(instance=choose_steward_guilds, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class WagePaymentGateWayUrlViewset(viewsets.ModelViewSet): +# queryset = WagePayment.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = WagePaymentSerializer +# +# def create(self, request, *args, **kwargs): + + +class WagePaymentBasedOnWeightViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WagePaymentSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = WagePaymentFilterSet + filterset_fields = [ + 'tracking_code', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_info', + + ] + + def create(self, request, *args, **kwargs): + now = datetime.now() + total_amount = 0 + final_total_amount = 0 + exclusive = False + slaughter_transaction_type = 'public' + killer = False + killer_kill_house = None + user = SystemUserProfile.objects.get(user=request.user, trash=False) + wage = ShareOfAllocation.objects.all().last() + wage = wage.province_union if wage else 0 + role = request.data['role'] + request.data.pop('role') + wallet = False + kill_house_key = None + if 'amount' in request.data.keys(): + wallet = True + input_amout = request.data['amount'] + input_amount_with_tax = request.data['amount_with_tax'] + kill_house_key = request.data['kill_house_key'] + request.data.pop('amount') + request.data.pop('amount_with_tax') + request.data.pop('kill_house_key') + kill_house_key = request.data['kill_house_key'] + request.data.pop('kill_house_key') + + kill_house = KillHouse.objects.filter(key=kill_house_key, trash=False).select_related( + 'kill_house_operator__user').first() + kill_house_percentage = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + if kill_house_percentage.kill_house_for_killer != None: + killer = True + if kill_house.type == 'exclusive': + exclusive = True + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + wage_payment = serializer.create(validated_data=request.data) + wage_payment.payer_info = user.fullname + wage_payment.payer = { + "role": role, + "payer": user.fullname, + "payment_type": wage_payment.payment_type, + "tracking_code": wage_payment.tracking_code, + "date": str(now) + + } + + if wallet == True: + kill_house_user = kill_house.kill_house_operator.user + creator = kill_house_user + receiver = kill_house_user + total_amount = input_amout + wage_payment.total_amount_with_tax = input_amount_with_tax + wage_payment.type = "wallet" + else: + + total_amount = wage_payment.total_amount + kill_house_user = kill_house.kill_house_operator.user + creator = kill_house_user + receiver = kill_house_user + wage_payment.total_amount_with_tax = total_amount + (total_amount * (10 / 100)) + + wage_payment.total_amount = total_amount + wage_payment.save() + + payment_gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) + company = payment_gate_way_percentage.company / 100 if payment_gate_way_percentage.company > 0 else 0 + union = payment_gate_way_percentage.union / 100 if payment_gate_way_percentage.union > 0 else 0 + guilds = payment_gate_way_percentage.guilds / 100 if payment_gate_way_percentage.guilds > 0 else 0 + + if user.province.name == 'لرستان': + province_deposit_id = sha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = test_order_id + + + elif user.province.name == 'آذربایجان شرقی': + province_deposit_id = sha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = sha_order_id + + elif user.province.name == 'اردبیل': + province_deposit_id = ar_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ar_order_id + + + + elif user.province.name == 'همدان': + province_deposit_id = ha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ha_order_id + + + elif user.province.name == 'مركزی': + province_deposit_id = ma_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ma_order_id + + order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, + now.minute, now.second) + # if user.province.name == 'مركزی': + # result = PaymentGateway( + # "{0},{1},0;{2},{3},0;".format(province_deposit_id, 100, + # arta_api_deposit_id, + # int(total_amount - 100)), int(total_amount), + # order_id) + # else: + + if wallet == True: + final_total_amount = input_amount_with_tax + else: + final_total_amount = total_amount + (total_amount * (10 / 100)) + if company > 0 and union > 0 and guilds > 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;{4},{5},0;".format(province_deposit_id, + int(final_total_amount * union), + arta_api_deposit_id, + int(final_total_amount * company), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + elif company > 0 and union > 0 and guilds == 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format(province_deposit_id, + int(final_total_amount * union), + arta_api_deposit_id, + int(final_total_amount * company)), + int(final_total_amount), + order_id) + + elif company > 0 and union == 0 and guilds > 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format( + + arta_api_deposit_id, + int(final_total_amount * company), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + else: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format(province_deposit_id, + int(final_total_amount * union), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + + # result = PaymentGateway( + # "{0},{1},0;{2},{3},0;".format(sha_deposit_id, 10000, arta_deposit_id, 10000),20000, order_id) + if '400' in result.keys(): + wage_payment.state = 'failed' + wage_payment.message = result[400] + wage_payment.save() + if wallet == True: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="failed", + type="deposit", + transaction_type="wallet", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + creator_role='KillHouse', + receiver_role='KillHouse', + payer=kill_house_user.fullname, + message=result[400] + + ) + transaction.save() + else: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="failed", + transaction_type="wage-gateway", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + creator_role='KillHouse', + receiver_role='ProvinceOperator', + payer=user.fullname, + message=result[400] + + ) + transaction.save() + return Response(result[400], status=status.HTTP_400_BAD_REQUEST) + else: + wage_payment.refId = result[200] + wage_payment.orderId = order_id + wage_payment.save() + if wallet == True: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="pending", + type="deposit", + transaction_type="wallet", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + receiver_role='KillHouse', + creator_role='KillHouse', + payer=kill_house_user.fullname, + refId=result[200], + orderId=order_id + + ) + transaction.save() + else: + + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="pending", + transaction_type="wage-gateway", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + receiver_role='KillHouse', + creator_role='ProvinceOperator', + payer=user.fullname, + refId=result[200], + orderId=order_id + + ) + transaction.save() + if killer == True: + parent_kill_house = kill_house_percentage.kill_house_for_killer + main_kill_house = kill_house_percentage.kill_house + if exclusive == True: + slaughter_transaction_type = 'exclusive' + else: + parent_kill_house = kill_house + main_kill_house = kill_house + + slaughter_transaction = SlaughterHouseTransaction( + kill_house=main_kill_house, + parent_kill_house=parent_kill_house, + type=slaughter_transaction_type, + amount=wage_payment.total_amount, + amount_with_tax=wage_payment.total_amount_with_tax, + transaction=transaction.id, + + ) + slaughter_transaction.save() + return Response({"refId": result[200]}, status=status.HTTP_201_CREATED) + + # return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + wage_payment_list = [] + + if request.GET['state'] == 'failed': + wage_payment = WagePayment.objects.filter( + create_date__date__gte=date1, + create_date__date__lte=date2, + state='failed', + trash=False).order_by('id') + else: + wage_payment = WagePayment.objects.filter( + create_date__date__gte=date1, + create_date__date__lte=date2, + state='completed', + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=wage_payment + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=wage_payment) + wage_payment_list = ps.filter() + wage_payment = [] if len(wage_payment_list) == 0 else wage_payment_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(wage_payment) + if page is not None: + serializer = WagePaymentSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = WagePaymentSerializer(wage_payment, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class WagePaymentWithLinkViewset(viewsets.ModelViewSet): +# queryset = WagePayment.objects.all() +# permission_classes = [AllowAny] +# serializer_class = WagePaymentSerializer +# +# def create(self, request, *args, **kwargs): +# link = True +# zarinpal_accounts = ZarinPalAccounts.objects.filter(trash=False) +# province_shaba_id = zarinpal_accounts.filter(en_name='union').first().account +# arta_shaba_id = zarinpal_accounts.filter(en_name='company').first().account +# guilds_shaba_id = zarinpal_accounts.filter(en_name='guilds').first().account +# other_shaba_id = zarinpal_accounts.filter(en_name='other').first().account +# now = datetime.now() +# wages = [] +# amount = 0 +# poultry_requests = None +# role = request.data['role'] +# request.data.pop('role') +# payer = None +# if 'order_codes' in request.data.keys(): +# if request.data['order_codes'] is not None: +# poultry_requests = PoultryRequest.objects.filter(order_code__in=request.data['order_codes']) +# request.data.pop('order_codes') +# user = SystemUserProfile.objects.get(key=request.data['user_key'], trash=False) +# request.data.pop('user_key') +# if role == 'Poultry': +# payer = 'poultry' +# payer_fullname = user.fullname +# phone = user.mobile +# +# # request.data.pop('user_key') +# elif role == 'Buyer': +# buyer = OutProvincePoultryRequestBuyer.objects.get(user=user, trash=False) +# payer = 'buyer' +# payer_fullname = user.fullname +# phone = user.mobile +# +# +# else: +# parent_kill_house = None +# if role == 'KillHouse': +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() +# parent_kill_house = kill_house +# if kill_house.killer == True and kill_house.type == 'exclusive': +# percentage = KillHousePercentage.objects.filter(kill_house=kill_house, trash=False).first() +# parent_kill_house = percentage.kill_house_for_killer if percentage else kill_house +# +# payer = 'kill_house' +# phone = kill_house.kill_house_operator.user.mobile +# +# else: +# chain_company = ChainCompany.objects.get(user=user, trash=False) +# payer = 'chain_company' +# phone = chain_company.user.mobile +# +# serializer = self.serializer_class(data=request.data) +# if serializer.is_valid(): +# wage_payment = serializer.create(validated_data=request.data) +# beneficiary_accounts = CompanyBeneficiaryAccount.objects.filter(trash=False, percent__gt=0) +# amount = int(wage_payment.total_amount) +# wage_payment.payer_info = user.fullname +# wage_payment.link_pay = True +# +# wage_payment.payer = { +# "role": role, +# "payer": user.fullname, +# "payment_type": wage_payment.payment_type, +# "tracking_code": wage_payment.tracking_code, +# "date": str(now) +# +# } +# if payer == 'kill_house': +# +# if kill_house.share_debt_counting_wage == False: +# company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 +# union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 +# guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 +# other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 +# else: +# percent_data = get_kill_house_percent(kill_house) +# if percent_data: +# company = percent_data['company'] / 100 if percent_data['company'] > 0 else 0 +# union = percent_data['union'] / 100 if percent_data['union'] > 0 else 0 +# guilds = percent_data['guilds'] / 100 if percent_data['guilds'] > 0 else 0 +# other = percent_data['vet'] / 100 if percent_data['vet'] > 0 else 0 +# else: +# company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 +# union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 +# guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 +# other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 +# else: +# wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() +# percentage_of_wage_type = PercentageOfWageType.objects.filter(trash=False, wage_type=wage_type) +# company_share = percentage_of_wage_type.filter(share_type__en_name='company').first().percent +# union_share = percentage_of_wage_type.filter(share_type__en_name='union').first().percent +# guilds_share = percentage_of_wage_type.filter(share_type__en_name='guilds').first().percent +# other_share = percentage_of_wage_type.filter(share_type__en_name='other').first().percent +# +# company = (company_share) / 100 if company_share > 0 else 0 +# union = union_share / 100 if union_share > 0 else 0 +# guilds = guilds_share / 100 if guilds_share > 0 else 0 +# other = other_share / 100 if other_share > 0 else 0 +# +# if user.province.name == 'همدان': +# gate_way_order_id = ha_order_id +# +# +# elif user.province.name == 'مركزی': +# gate_way_order_id = ma_order_id +# +# +# else: +# gate_way_order_id = test_order_id +# +# order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, +# now.minute, now.second) +# +# guild_id = 0 +# other_id = 0 +# province_other_wage = 0 +# if province_shaba_id == guilds_shaba_id: +# guild_id = 1 +# province_other_wage += (amount * guilds) +# if province_shaba_id == other_shaba_id: +# other_id = 1 +# province_other_wage += (amount * other) +# +# if company > 0: +# company_total_amount = amount * company +# total_remain_amount = company_total_amount +# account_amount = 0 +# if payer == 'kill_house': +# beneficiary_accounts = beneficiary_accounts.filter(in_province=True) +# else: +# beneficiary_accounts = beneficiary_accounts.filter(out_province=True) +# +# if beneficiary_accounts: +# for account in beneficiary_accounts: +# account_amount = int(company_total_amount * (account.percent / 100)) +# total_remain_amount -= account_amount +# wages.append( +# { +# "IBAN": account.shaba, +# "Amount": account_amount, +# } +# +# ) +# if total_remain_amount > 0: +# wages.append( +# { +# "IBAN": arta_shaba_id, +# "Amount": total_remain_amount, +# } +# +# ) +# +# +# +# else: +# +# wages.append( +# { +# "IBAN": arta_shaba_id, +# "Amount": amount * company, +# } +# +# ) +# +# if union > 0: +# wages.append( +# { +# "IBAN": province_shaba_id, +# "Amount": (amount * union) + province_other_wage +# } +# +# ) +# if guild_id == 0 or (union == 0 and guild_id == 1): +# if guilds > 0: +# wages.append( +# { +# "IBAN": guilds_shaba_id, +# "Amount": (amount * guilds), +# } +# +# ) +# if other_id == 0 or (union == 0 and other_id == 1): +# if other > 0: +# wages.append( +# { +# "IBAN": other_shaba_id, +# "Amount": (amount * other), +# } +# +# ) +# result = PaymentGatewayZarinPal(amount, phone, order_id, link, wages) +# if 500 in result.keys(): +# wage_payment.state = 'failed' +# wage_payment.message = result[500] +# wage_payment.save() +# if payer == 'kill_house': +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# kill_house=kill_house, +# parent_kill_house=parent_kill_house, +# payer_fullname=kill_house.kill_house_operator.user.fullname, +# payer_mobile=kill_house.kill_house_operator.user.mobile, +# payer_type='kill_house', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# link_pay=True, +# orderId=order_id, +# message=result[500] +# ) +# transaction.save() +# +# elif payer == 'poultry': +# +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# payer_type='poultry', +# poultry=poultry_requests.first().poultry, +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# user=user, +# payer_fullname=user.fullname, +# payer_mobile=user.mobile, +# link_pay=True, +# orderId=order_id, +# message=result[500] +# ) +# transaction.save() +# if poultry_requests is not None: +# transaction.poultry_request.add(*poultry_requests) +# +# elif payer == 'buyer': +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# payer_type='buyer', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# user=user, +# out_province_poultry_request_buyer=buyer, +# payer_fullname=buyer.user.fullname, +# payer_mobile=buyer.user.mobile, +# link_pay=True, +# orderId=order_id, +# message=result[500] +# ) +# transaction.save() +# if poultry_requests is not None: +# transaction.poultry_request.add(*poultry_requests) +# else: +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# chain_company=chain_company, +# payer_fullname=chain_company.user.fullname, +# payer_mobile=chain_company.user.mobile, +# payer_type='chain_company', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# link_pay=True, +# orderId=order_id, +# message=result[400] +# ) +# transaction.save() +# +# return Response(result[500], status=status.HTTP_400_BAD_REQUEST) +# else: +# wage_payment.authority = result[201] +# wage_payment.orderId = order_id +# wage_payment.save() +# if payer == 'kill_house': +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# transaction_type="wage-gateway-auto", +# kill_house=kill_house, +# parent_kill_house=parent_kill_house, +# payer_fullname=kill_house.kill_house_operator.user.fullname, +# payer_mobile=kill_house.kill_house_operator.user.mobile, +# payer_type='kill_house', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# link_pay=True, +# orderId=order_id +# +# ) +# transaction.save() +# +# elif payer == 'poultry': +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# transaction_type="wage-gateway-auto", +# payer_type='poultry', +# poultry=poultry_requests.first().poultry, +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# user=user, +# payer_fullname=user.fullname, +# payer_mobile=user.mobile, +# link_pay=True, +# orderId=order_id +# +# ) +# transaction.save() +# if poultry_requests is not None: +# transaction.poultry_request.add(*poultry_requests) +# +# +# elif payer == 'buyer': +# +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# transaction_type="wage-gateway-auto", +# payer_type='buyer', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# user=user, +# out_province_poultry_request_buyer=buyer, +# payer_fullname=buyer.user.fullname, +# payer_mobile=buyer.user.mobile, +# link_pay=True, +# orderId=order_id +# +# ) +# transaction.save() +# if poultry_requests is not None: +# transaction.poultry_request.add(*poultry_requests) +# +# +# else: +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# # is_complete=False, +# transaction_type="wage-gateway-auto", +# chain_company=chain_company, +# payer_fullname=chain_company.user.fullname, +# payer_mobile=chain_company.user.mobile, +# payer_type='chain_company', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# link_pay=True, +# orderId=order_id +# +# ) +# transaction.save() +# +# return Response({"token": result[201]}, status=status.HTTP_201_CREATED) +# +# # return Response(serializer.data, status=status.HTTP_201_CREATED) + +class WagePaymentWithLinkViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [AllowAny] + serializer_class = WagePaymentSerializer + + def create(self, request, *args, **kwargs): + link = True + zarinpal_accounts = ZarinPalAccounts.objects.filter(trash=False) + province_shaba_id = zarinpal_accounts.filter(en_name='union').first().account + arta_shaba_id = zarinpal_accounts.filter(en_name='company').first().account + guilds_shaba_id = zarinpal_accounts.filter(en_name='guilds').first().account + other_shaba_id = zarinpal_accounts.filter(en_name='other').first().account + now = datetime.now() + wages = [] + amount = 0 + poultry_requests = None + role = request.data['role'] + request.data.pop('role') + payer = None + if 'order_codes' in request.data.keys(): + if request.data['order_codes'] is not None: + poultry_requests = PoultryRequest.objects.filter(order_code__in=request.data['order_codes']) + request.data.pop('order_codes') + user = SystemUserProfile.objects.get(key=request.data['user_key'], trash=False) + request.data.pop('user_key') + if role == 'Poultry': + payer = 'poultry' + payer_fullname = user.fullname + phone = user.mobile + + # request.data.pop('user_key') + elif role == 'Buyer': + buyer = OutProvincePoultryRequestBuyer.objects.get(user=user, trash=False) + payer = 'buyer' + payer_fullname = user.fullname + phone = user.mobile + + + else: + parent_kill_house = None + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + parent_kill_house = kill_house + if kill_house.killer == True and kill_house.type == 'exclusive': + percentage = KillHousePercentage.objects.filter(kill_house=kill_house, trash=False).first() + parent_kill_house = percentage.kill_house_for_killer if percentage else kill_house + + payer = 'kill_house' + phone = kill_house.kill_house_operator.user.mobile + + else: + chain_company = ChainCompany.objects.get(user=user, trash=False) + payer = 'chain_company' + phone = chain_company.user.mobile + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + wage_payment = serializer.create(validated_data=request.data) + beneficiary_accounts = CompanyBeneficiaryAccount.objects.filter(trash=False, percent__gt=0) + amount = int(wage_payment.total_amount) + wage_payment.payer_info = user.fullname + wage_payment.link_pay = True + + wage_payment.payer = { + "role": role, + "payer": user.fullname, + "payment_type": wage_payment.payment_type, + "tracking_code": wage_payment.tracking_code, + "date": str(now) + + } + if payer == 'kill_house': + + if kill_house.share_debt_counting_wage == False: + company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 + union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 + guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 + other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 + else: + percent_data = get_kill_house_percent(kill_house) + if percent_data and ( + percent_data['union'] or percent_data['company'] or percent_data['guilds'] or percent_data[ + 'vet']): + company = percent_data['company'] / 100 if percent_data['company'] > 0 else 0 + union = percent_data['union'] / 100 if percent_data['union'] > 0 else 0 + guilds = percent_data['guilds'] / 100 if percent_data['guilds'] > 0 else 0 + other = percent_data['vet'] / 100 if percent_data['vet'] > 0 else 0 + else: + company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 + union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 + guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 + other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 + else: + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + percentage_of_wage_type = PercentageOfWageType.objects.filter(trash=False, wage_type=wage_type) + company_share = percentage_of_wage_type.filter(share_type__en_name='company').first().percent + union_share = percentage_of_wage_type.filter(share_type__en_name='union').first().percent + guilds_share = percentage_of_wage_type.filter(share_type__en_name='guilds').first().percent + other_share = percentage_of_wage_type.filter(share_type__en_name='other').first().percent + + company = (company_share) / 100 if company_share > 0 else 0 + union = union_share / 100 if union_share > 0 else 0 + guilds = guilds_share / 100 if guilds_share > 0 else 0 + other = other_share / 100 if other_share > 0 else 0 + + if user.province.name == 'همدان': + gate_way_order_id = ha_order_id + + + elif user.province.name == 'مركزی': + gate_way_order_id = ma_order_id + + + else: + gate_way_order_id = test_order_id + + order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, + now.minute, now.second) + zero_counter = 0 + zero_wages = 0 + + if arta_shaba_id == '-' and company > 0: + zero_wages += amount * company + + if province_shaba_id == '-' and union > 0: + zero_wages += amount * union + + if guilds_shaba_id == '-' and guilds > 0: + zero_wages += amount * guilds + + if other_shaba_id == '-' and other > 0: + zero_wages += amount * other + + if arta_shaba_id != '-' and company > 0: + zero_counter += 1 + + if province_shaba_id != '-' and union > 0: + zero_counter += 1 + + if guilds_shaba_id != '-' and guilds > 0: + zero_counter += 1 + + if other_shaba_id != '-' and other > 0: + zero_counter += 1 + + if zero_counter > 0 and zero_counter != zarinpal_accounts.count(): + zero_wages = zero_wages / (zarinpal_accounts.count() - zero_counter) + + guild_id = 0 + other_id = 0 + province_other_wage = 0 + if province_shaba_id == guilds_shaba_id: + if guilds > 0: + guild_id = 1 + province_other_wage += (amount * guilds) + zero_wages + if province_shaba_id == other_shaba_id: + if other > 0: + other_id = 1 + province_other_wage += (amount * other) + zero_wages + + if arta_shaba_id != '-': + if company > 0: + company_total_amount = (amount * company) + zero_wages + total_remain_amount = company_total_amount + account_amount = 0 + if payer == 'kill_house': + beneficiary_accounts = beneficiary_accounts.filter(in_province=True) + else: + beneficiary_accounts = beneficiary_accounts.filter(out_province=True) + + if beneficiary_accounts: + for account in beneficiary_accounts: + account_amount = int(company_total_amount * (account.percent / 100)) + total_remain_amount -= account_amount + + wages.append( + { + "IBAN": account.shaba, + "Amount": account_amount, + } + + ) + if total_remain_amount > 0: + wages.append( + { + "IBAN": arta_shaba_id, + "Amount": total_remain_amount, + } + + ) + + + + else: + wages.append( + { + "IBAN": arta_shaba_id, + "Amount": (amount * company) + zero_wages, + } + + ) + if province_shaba_id != '-': + if union > 0: + wages.append( + { + "IBAN": province_shaba_id, + "Amount": (amount * union) + province_other_wage + zero_wages + } + + ) + + if guilds_shaba_id != '-': + if guild_id == 0 or (union == 0 and guild_id == 1): + if guilds > 0: + wages.append( + { + "IBAN": guilds_shaba_id, + "Amount": (amount * guilds) + zero_wages, + } + + ) + if other_shaba_id != '-': + if other_id == 0 or (union == 0 and other_id == 1): + if other > 0: + wages.append( + { + "IBAN": other_shaba_id, + "Amount": (amount * other) + zero_wages, + } + + ) + result = PaymentGatewayZarinPal(amount, phone, order_id, link, wages) + if 500 in result.keys(): + wage_payment.state = 'failed' + wage_payment.message = result[500] + wage_payment.save() + if payer == 'kill_house': + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + kill_house=kill_house, + parent_kill_house=parent_kill_house, + payer_fullname=kill_house.kill_house_operator.user.fullname, + payer_mobile=kill_house.kill_house_operator.user.mobile, + payer_type='kill_house', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + link_pay=True, + orderId=order_id, + message=result[500] + ) + transaction.save() + + elif payer == 'poultry': + + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + payer_type='poultry', + poultry=poultry_requests.first().poultry, + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + user=user, + payer_fullname=user.fullname, + payer_mobile=user.mobile, + link_pay=True, + orderId=order_id, + message=result[500] + ) + transaction.save() + if poultry_requests is not None: + transaction.poultry_request.add(*poultry_requests) + + elif payer == 'buyer': + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + payer_type='buyer', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + user=user, + out_province_poultry_request_buyer=buyer, + payer_fullname=buyer.user.fullname, + payer_mobile=buyer.user.mobile, + link_pay=True, + orderId=order_id, + message=result[500] + ) + transaction.save() + if poultry_requests is not None: + transaction.poultry_request.add(*poultry_requests) + else: + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + chain_company=chain_company, + payer_fullname=chain_company.user.fullname, + payer_mobile=chain_company.user.mobile, + payer_type='chain_company', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + link_pay=True, + orderId=order_id, + message=result[400] + ) + transaction.save() + + return Response(result[500], status=status.HTTP_400_BAD_REQUEST) + else: + wage_payment.authority = result[201] + wage_payment.orderId = order_id + wage_payment.save() + if payer == 'kill_house': + transaction = InternalTransaction( + amount=amount, + status="pending", + transaction_type="wage-gateway-auto", + kill_house=kill_house, + parent_kill_house=parent_kill_house, + payer_fullname=kill_house.kill_house_operator.user.fullname, + payer_mobile=kill_house.kill_house_operator.user.mobile, + payer_type='kill_house', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + link_pay=True, + orderId=order_id + + ) + transaction.save() + + elif payer == 'poultry': + transaction = InternalTransaction( + amount=amount, + status="pending", + transaction_type="wage-gateway-auto", + payer_type='poultry', + poultry=poultry_requests.first().poultry, + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + user=user, + payer_fullname=user.fullname, + payer_mobile=user.mobile, + link_pay=True, + orderId=order_id + + ) + transaction.save() + if poultry_requests is not None: + transaction.poultry_request.add(*poultry_requests) + + + elif payer == 'buyer': + + transaction = InternalTransaction( + amount=amount, + status="pending", + transaction_type="wage-gateway-auto", + payer_type='buyer', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + user=user, + out_province_poultry_request_buyer=buyer, + payer_fullname=buyer.user.fullname, + payer_mobile=buyer.user.mobile, + link_pay=True, + orderId=order_id + + ) + transaction.save() + if poultry_requests is not None: + transaction.poultry_request.add(*poultry_requests) + + + else: + transaction = InternalTransaction( + amount=amount, + status="pending", + # is_complete=False, + transaction_type="wage-gateway-auto", + chain_company=chain_company, + payer_fullname=chain_company.user.fullname, + payer_mobile=chain_company.user.mobile, + payer_type='chain_company', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + link_pay=True, + orderId=order_id + + ) + transaction.save() + + return Response({"token": result[201]}, status=status.HTTP_201_CREATED) + + # return Response(serializer.data, status=status.HTTP_201_CREATED) + + +# class WagePaymentTotalViewset(viewsets.ModelViewSet): +# queryset = WagePayment.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = WagePaymentSerializer +# filter_backends = [DjangoFilterBackend] +# pagination_class = CustomPagination +# filterset_class = WagePaymentFilterSet +# filterset_fields = [ +# 'tracking_code', +# 'refId', +# 'orderId', +# 'cardHolderPan', +# 'payer_info', +# +# ] +# +# def create(self, request, *args, **kwargs): +# link = False +# zarinpal_accounts = ZarinPalAccounts.objects.filter(trash=False) +# beneficiary_accounts = CompanyBeneficiaryAccount.objects.filter(trash=False, percent__gt=0) +# province_shaba_id = zarinpal_accounts.filter(en_name='union').first().account +# arta_shaba_id = zarinpal_accounts.filter(en_name='company').first().account +# guilds_shaba_id = zarinpal_accounts.filter(en_name='guilds').first().account +# other_shaba_id = zarinpal_accounts.filter(en_name='other').first().account +# now = datetime.now() +# wages = [] +# amount = 0 +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# payer = None +# parent_kill_house = None +# role = request.data['role'] +# request.data.pop('role') +# if role == 'KillHouse': +# kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() +# parent_kill_house = kill_house +# if kill_house.killer == True and kill_house.type == 'exclusive': +# percentage = KillHousePercentage.objects.filter(kill_house=kill_house, trash=False).first() +# parent_kill_house = percentage.kill_house_for_killer if percentage else kill_house +# +# payer = 'kill_house' +# phone = kill_house.kill_house_operator.user.mobile +# else: +# chain_company = ChainCompany.objects.get(user=user, trash=False).first() +# payer = 'chain_company' +# phone = chain_company.user.mobile +# +# serializer = self.serializer_class(data=request.data) +# if serializer.is_valid(): +# wage_payment = serializer.create(validated_data=request.data) +# amount = wage_payment.total_amount +# wage_payment.payer_info = user.fullname +# wage_payment.payer = { +# "role": role, +# "payer": user.fullname, +# "payment_type": wage_payment.payment_type, +# "tracking_code": wage_payment.tracking_code, +# "date": str(now) +# +# } +# +# if payer == 'kill_house': +# if kill_house.share_debt_counting_wage == False: +# +# company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 +# union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 +# guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 +# other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 +# +# else: +# percent_data = get_kill_house_percent(kill_house) +# if percent_data: +# company = percent_data['company'] / 100 if percent_data['company'] > 0 else 0 +# union = percent_data['union'] / 100 if percent_data['union'] > 0 else 0 +# guilds = percent_data['guilds'] / 100 if percent_data['guilds'] > 0 else 0 +# other = percent_data['vet'] / 100 if percent_data['vet'] > 0 else 0 +# else: +# company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 +# union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 +# guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 +# other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 +# +# else: +# +# payment_gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) +# company = payment_gate_way_percentage.company / 100 if payment_gate_way_percentage.company > 0 else 0 +# union = payment_gate_way_percentage.union / 100 if payment_gate_way_percentage.union > 0 else 0 +# guilds = payment_gate_way_percentage.guilds / 100 if payment_gate_way_percentage.guilds > 0 else 0 +# other = payment_gate_way_percentage.other / 100 if payment_gate_way_percentage.other > 0 else 0 +# +# if user.province.name == 'همدان': +# gate_way_order_id = ha_order_id +# +# +# elif user.province.name == 'مركزی': +# gate_way_order_id = ma_order_id +# +# +# else: +# gate_way_order_id = test_order_id +# +# order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, +# now.minute, now.second) +# guild_id = 0 +# other_id = 0 +# province_other_wage = 0 +# if province_shaba_id == guilds_shaba_id: +# guild_id = 1 +# province_other_wage += (amount * guilds) +# if province_shaba_id == other_shaba_id: +# other_id = 1 +# province_other_wage += (amount * other) +# +# if company > 0: +# company_total_amount = amount * company +# total_remain_amount = company_total_amount +# account_amount = 0 +# beneficiary_accounts = beneficiary_accounts.filter(in_province=True) +# if beneficiary_accounts: +# for account in beneficiary_accounts: +# account_amount = int(company_total_amount * (account.percent / 100)) +# total_remain_amount -= account_amount +# wages.append( +# { +# "IBAN": account.shaba, +# "Amount": account_amount, +# } +# +# ) +# if total_remain_amount > 0: +# wages.append( +# { +# "IBAN": arta_shaba_id, +# "Amount": total_remain_amount, +# } +# +# ) +# +# +# +# else: +# +# wages.append( +# { +# "IBAN": arta_shaba_id, +# "Amount": amount * company, +# } +# +# ) +# +# if union > 0: +# wages.append( +# { +# "IBAN": province_shaba_id, +# "Amount": (amount * union) + province_other_wage +# } +# +# ) +# if guild_id == 0 or (union == 0 and guild_id == 1): +# if guilds > 0: +# wages.append( +# { +# "IBAN": guilds_shaba_id, +# "Amount": (amount * guilds), +# } +# +# ) +# if other_id == 0 or (union == 0 and other_id == 1): +# if other > 0: +# wages.append( +# { +# "IBAN": other_shaba_id, +# "Amount": (amount * other), +# } +# +# ) +# result = PaymentGatewayZarinPal(amount, phone, order_id, link, wages) +# if 500 in result.keys(): +# wage_payment.state = 'failed' +# wage_payment.message = result[500] +# wage_payment.save() +# if payer == 'kill_house': +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# kill_house=kill_house, +# parent_kill_house=parent_kill_house, +# payer_fullname=kill_house.kill_house_operator.user.fullname, +# payer_mobile=kill_house.kill_house_operator.user.mobile, +# payer_type='kill_house', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# orderId=order_id, +# message=result[500] +# ) +# transaction.save() +# else: +# transaction = InternalTransaction( +# amount=amount, +# status="failed", +# transaction_type="wage-gateway-auto", +# chain_company=chain_company, +# payer_fullname=chain_company.user.fullname, +# payer_mobile=chain_company.user.mobile, +# payer_type='chain_company', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# orderId=order_id, +# message=result[400] +# ) +# transaction.save() +# +# return Response(result[500], status=status.HTTP_400_BAD_REQUEST) +# else: +# wage_payment.authority = result[201] +# wage_payment.orderId = order_id +# wage_payment.save() +# if payer == 'kill_house': +# +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# transaction_type="wage-gateway-auto", +# kill_house=kill_house, +# parent_kill_house=parent_kill_house, +# payer_fullname=kill_house.kill_house_operator.user.fullname, +# payer_mobile=kill_house.kill_house_operator.user.mobile, +# payer_type='kill_house', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# orderId=order_id +# +# ) +# transaction.save() +# else: +# transaction = InternalTransaction( +# amount=amount, +# status="pending", +# # is_complete=False, +# transaction_type="wage-gateway-auto", +# chain_company=chain_company, +# payer_fullname=chain_company.user.fullname, +# payer_mobile=chain_company.user.mobile, +# payer_type='chain_company', +# union_share=amount * union, +# union_account=province_shaba_id, +# company_share=amount * company, +# company_account=arta_shaba_id, +# guilds_share=amount * guilds, +# guilds_account=guilds_shaba_id, +# other_share=amount * other, +# other_account=other_shaba_id, +# date=now, +# authority=result[201], +# orderId=order_id +# +# ) +# transaction.save() +# +# return Response({"token": result[201]}, status=status.HTTP_201_CREATED) +# +# # return Response(serializer.data, status=status.HTTP_201_CREATED) + +class WagePaymentTotalViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WagePaymentSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = WagePaymentFilterSet + filterset_fields = [ + 'tracking_code', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_info', + + ] + + def create(self, request, *args, **kwargs): + link = False + zarinpal_accounts = ZarinPalAccounts.objects.filter(trash=False) + beneficiary_accounts = CompanyBeneficiaryAccount.objects.filter(trash=False, percent__gt=0) + province_shaba_id = zarinpal_accounts.filter(en_name='union').first().account + arta_shaba_id = zarinpal_accounts.filter(en_name='company').first().account + guilds_shaba_id = zarinpal_accounts.filter(en_name='guilds').first().account + other_shaba_id = zarinpal_accounts.filter(en_name='other').first().account + now = datetime.now() + wages = [] + amount = 0 + user = SystemUserProfile.objects.get(user=request.user, trash=False) + payer = None + parent_kill_house = None + role = request.data['role'] + request.data.pop('role') + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + parent_kill_house = kill_house + if kill_house.killer == True and kill_house.type == 'exclusive': + percentage = KillHousePercentage.objects.filter(kill_house=kill_house, trash=False).first() + parent_kill_house = percentage.kill_house_for_killer if percentage else kill_house + + payer = 'kill_house' + phone = kill_house.kill_house_operator.user.mobile + else: + chain_company = ChainCompany.objects.get(user=user, trash=False).first() + payer = 'chain_company' + phone = chain_company.user.mobile + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + wage_payment = serializer.create(validated_data=request.data) + amount = wage_payment.total_amount + wage_payment.payer_info = user.fullname + wage_payment.payer = { + "role": role, + "payer": user.fullname, + "payment_type": wage_payment.payment_type, + "tracking_code": wage_payment.tracking_code, + "date": str(now) + + } + + if payer == 'kill_house': + if kill_house.share_debt_counting_wage == False: + + company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 + union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 + guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 + other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 + + else: + percent_data = get_kill_house_percent(kill_house) + if percent_data and ( + percent_data['union'] or percent_data['company'] or percent_data['guilds'] or percent_data[ + 'vet']): + company = percent_data['company'] / 100 if percent_data['company'] > 0 else 0 + union = percent_data['union'] / 100 if percent_data['union'] > 0 else 0 + guilds = percent_data['guilds'] / 100 if percent_data['guilds'] > 0 else 0 + other = percent_data['vet'] / 100 if percent_data['vet'] > 0 else 0 + else: + company = kill_house.company_gateway_percent / 100 if kill_house.company_gateway_percent > 0 else 0 + union = kill_house.union_gateway_percent / 100 if kill_house.union_gateway_percent > 0 else 0 + guilds = kill_house.guilds_gateway_percent / 100 if kill_house.guilds_gateway_percent > 0 else 0 + other = kill_house.other_gateway_percent / 100 if kill_house.other_gateway_percent > 0 else 0 + + else: + + payment_gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) + company = payment_gate_way_percentage.company / 100 if payment_gate_way_percentage.company > 0 else 0 + union = payment_gate_way_percentage.union / 100 if payment_gate_way_percentage.union > 0 else 0 + guilds = payment_gate_way_percentage.guilds / 100 if payment_gate_way_percentage.guilds > 0 else 0 + other = payment_gate_way_percentage.other / 100 if payment_gate_way_percentage.other > 0 else 0 + + if user.province.name == 'همدان': + gate_way_order_id = ha_order_id + + + elif user.province.name == 'مركزی': + gate_way_order_id = ma_order_id + + + else: + gate_way_order_id = test_order_id + + order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, + now.minute, now.second) + + zero_counter = 0 + zero_wages = 0 + + if arta_shaba_id == '-' and company > 0: + zero_wages += amount * company + + if province_shaba_id == '-' and union > 0: + zero_wages += amount * union + + if guilds_shaba_id == '-' and guilds > 0: + zero_wages += amount * guilds + + if other_shaba_id == '-' and other > 0: + zero_wages += amount * other + + if arta_shaba_id != '-' and company > 0: + zero_counter += 1 + + if province_shaba_id != '-' and union > 0: + zero_counter += 1 + + if guilds_shaba_id != '-' and guilds > 0: + zero_counter += 1 + + if other_shaba_id != '-' and other > 0: + zero_counter += 1 + + if zero_counter > 0 and zero_counter != zarinpal_accounts.count(): + zero_wages = zero_wages / (zarinpal_accounts.count() - zero_counter) + + guild_id = 0 + other_id = 0 + province_other_wage = 0 + if province_shaba_id == guilds_shaba_id: + if guilds > 0: + guild_id = 1 + province_other_wage += (amount * guilds) + zero_wages + if province_shaba_id == other_shaba_id: + if other > 0: + other_id = 1 + province_other_wage += (amount * other) + zero_wages + + if arta_shaba_id != '-': + + if company > 0: + company_total_amount = (amount * company) + zero_wages + total_remain_amount = company_total_amount + account_amount = 0 + beneficiary_accounts = beneficiary_accounts.filter(in_province=True) + if beneficiary_accounts: + for account in beneficiary_accounts: + account_amount = int(company_total_amount * (account.percent / 100)) + total_remain_amount -= account_amount + wages.append( + { + "IBAN": account.shaba, + "Amount": account_amount, + } + + ) + if total_remain_amount > 0: + wages.append( + { + "IBAN": arta_shaba_id, + "Amount": total_remain_amount, + } + + ) + + + + else: + + wages.append( + { + "IBAN": arta_shaba_id, + "Amount": (amount * company) + zero_wages, + } + + ) + + if province_shaba_id != '-': + + if union > 0: + wages.append( + { + "IBAN": province_shaba_id, + "Amount": (amount * union) + province_other_wage + zero_wages + } + + ) + + if guilds_shaba_id != '-': + + if guild_id == 0 or (union == 0 and guild_id == 1): + if guilds > 0: + wages.append( + { + "IBAN": guilds_shaba_id, + "Amount": (amount * guilds) + zero_wages, + } + + ) + if other_shaba_id != '-': + if other_id == 0 or (union == 0 and other_id == 1): + if other > 0: + wages.append( + { + "IBAN": other_shaba_id, + "Amount": (amount * other) + zero_wages, + } + + ) + result = PaymentGatewayZarinPal(amount, phone, order_id, link, wages) + if 500 in result.keys(): + wage_payment.state = 'failed' + wage_payment.message = result[500] + wage_payment.save() + if payer == 'kill_house': + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + kill_house=kill_house, + parent_kill_house=parent_kill_house, + payer_fullname=kill_house.kill_house_operator.user.fullname, + payer_mobile=kill_house.kill_house_operator.user.mobile, + payer_type='kill_house', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + orderId=order_id, + message=result[500] + ) + transaction.save() + else: + transaction = InternalTransaction( + amount=amount, + status="failed", + transaction_type="wage-gateway-auto", + chain_company=chain_company, + payer_fullname=chain_company.user.fullname, + payer_mobile=chain_company.user.mobile, + payer_type='chain_company', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + orderId=order_id, + message=result[400] + ) + transaction.save() + + return Response(result[500], status=status.HTTP_400_BAD_REQUEST) + else: + wage_payment.authority = result[201] + wage_payment.orderId = order_id + wage_payment.save() + if payer == 'kill_house': + + transaction = InternalTransaction( + amount=amount, + status="pending", + transaction_type="wage-gateway-auto", + kill_house=kill_house, + parent_kill_house=parent_kill_house, + payer_fullname=kill_house.kill_house_operator.user.fullname, + payer_mobile=kill_house.kill_house_operator.user.mobile, + payer_type='kill_house', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + orderId=order_id + + ) + transaction.save() + else: + transaction = InternalTransaction( + amount=amount, + status="pending", + # is_complete=False, + transaction_type="wage-gateway-auto", + chain_company=chain_company, + payer_fullname=chain_company.user.fullname, + payer_mobile=chain_company.user.mobile, + payer_type='chain_company', + union_share=(amount * union) + zero_wages if province_shaba_id != '-' and union > 0 else 0, + union_account=province_shaba_id, + company_share=(amount * company) + zero_wages if arta_shaba_id != '-' and company > 0 else 0, + company_account=arta_shaba_id, + guilds_share=(amount * guilds) + zero_wages if guilds_shaba_id != '-' and guilds > 0 else 0, + guilds_account=guilds_shaba_id, + other_share=(amount * other) + zero_wages if other_shaba_id != '-' and other > 0 else 0, + other_account=other_shaba_id, + date=now, + authority=result[201], + orderId=order_id + + ) + transaction.save() + + return Response({"token": result[201]}, status=status.HTTP_201_CREATED) + + # return Response(serializer.data, status=status.HTTP_201_CREATED) + + +class WagePaymentViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WagePaymentSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = WagePaymentFilterSet + filterset_fields = [ + 'tracking_code', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_info', + + ] + + def create(self, request, *args, **kwargs): + now = datetime.now() + total_amount = 0 + final_total_amount = 0 + user = SystemUserProfile.objects.get(user=request.user, trash=False) + wage = ShareOfAllocation.objects.all().last() + wage = wage.province_union if wage else 0 + role = request.data['role'] + request.data.pop('role') + wallet = False + kill_house_key = None + if 'amount' in request.data.keys(): + wallet = True + input_amout = request.data['amount'] + input_amount_with_tax = request.data['amount_with_tax'] + kill_house_key = request.data['kill_house_key'] + request.data.pop('amount') + request.data.pop('amount_with_tax') + request.data.pop('kill_house_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + wage_payment = serializer.create(validated_data=request.data) + wage_payment.payer_info = user.fullname + wage_payment.payer = { + "role": role, + "payer": user.fullname, + "payment_type": wage_payment.payment_type, + "tracking_code": wage_payment.tracking_code, + "date": str(now) + + } + if request.data['payment_type'] == 'manual': + for province_kill_request in wage_payment.province_kill_request: + kill_request = ProvinceKillRequest.objects.filter(key=province_kill_request).select_related( + 'province_request__poultry_request').last() + kill_request.wage_pay = True + kill_request.depositor = { + "role": role, + "payer": user.fullname, + "date": str(now), + "payment_type": wage_payment.payment_type, + "tracking_code": wage_payment.tracking_code, + "refId": 0, + "orderId": 0, + "total_amount": kill_request.total_killed_weight * kill_request.wage + } + kill_request.save() + + total_amount += kill_request.depositor['total_amount'] + kill_house = KillHouse.objects.filter( + key=kill_request.kill_request.kill_house.key).select_related( + 'kill_house_operator__user').first() + kill_house_user = kill_house.kill_house_operator.user + creator = kill_house.kill_house_operator.user if role == 'KillHouse' else user + receiver = user if role == 'KillHouse' else SystemUserProfile.objects.filter( + role__name='ProvinceOperator', + province=user.province).first() + wage_payment.total_amount = total_amount + wage_payment.state = "completed" + wage_payment.save() + transaction = ExternalTransaction( + amount=total_amount, + status="completed", + transaction_type="wage-manual", + is_complete=True, + saleReferenceId=wage_payment.tracking_code, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + creator_role='KillHouse', + receiver_role='ProvinceOperator', + payer=user.fullname + + ) + transaction.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + # return Response(serializer.errors) + + else: + if wallet == True: + + kill_house = KillHouse.objects.filter(key=kill_house_key, trash=False).select_related( + 'kill_house_operator__user').first() + kill_house_user = kill_house.kill_house_operator.user + creator = kill_house_user + receiver = kill_house_user + total_amount = input_amout + wage_payment.total_amount_with_tax = input_amount_with_tax + wage_payment.type = "wallet" + else: + + for province_kill_request in wage_payment.province_kill_request: + kill_request = ProvinceKillRequest.objects.filter(key=province_kill_request).select_related( + 'province_request__poultry_request').last() + # kill_request.wage_pay = True + kill_request.depositor = { + "role": role, + "payer": user.fullname, + "date": str(now), + "payment_type": wage_payment.payment_type, + "total_amount": kill_request.total_killed_weight * kill_request.wage + } + kill_request.save() + + total_amount += kill_request.depositor['total_amount'] + kill_house = KillHouse.objects.filter( + key=kill_request.kill_request.kill_house.key).select_related( + 'kill_house_operator__user').first() + kill_house_user = kill_house.kill_house_operator.user + creator = kill_house.kill_house_operator.user if role == 'KillHouse' else user + receiver = user if role == 'KillHouse' else SystemUserProfile.objects.filter( + role__name='ProvinceOperator', + province=user.province).first() + wage_payment.total_amount_with_tax = total_amount + (total_amount * (10 / 100)) + + wage_payment.total_amount = total_amount + wage_payment.save() + + payment_gate_way_percentage = PaymentGatewayPercentage.objects.get(trash=False) + company = payment_gate_way_percentage.company / 100 if payment_gate_way_percentage.company > 0 else 0 + union = payment_gate_way_percentage.union / 100 if payment_gate_way_percentage.union > 0 else 0 + guilds = payment_gate_way_percentage.guilds / 100 if payment_gate_way_percentage.guilds > 0 else 0 + + if user.province.name == 'لرستان': + province_deposit_id = sha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = test_order_id + + + elif user.province.name == 'آذربایجان شرقی': + province_deposit_id = sha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = sha_order_id + + elif user.province.name == 'اردبیل': + province_deposit_id = ar_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ar_order_id + + + + elif user.province.name == 'همدان': + province_deposit_id = ha_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ha_order_id + + + elif user.province.name == 'مركزی': + province_deposit_id = ma_deposit_id + province_deposit_percent = union + arta_api_deposit_id = arta_deposit_id + arta_api_deposit_percent = company + guilds_api_deposit_id = guilds_deposit_id + guilds_api_deposit_percent = guilds + gate_way_order_id = ma_order_id + + order_id = "{0}{1}{2}{3}{4}{5}{6}".format(gate_way_order_id, now.year, now.month, now.day, now.hour, + now.minute, now.second) + # if user.province.name == 'مركزی': + # result = PaymentGateway( + # "{0},{1},0;{2},{3},0;".format(province_deposit_id, 100, + # arta_api_deposit_id, + # int(total_amount - 100)), int(total_amount), + # order_id) + # else: + + if wallet == True: + final_total_amount = input_amount_with_tax + else: + final_total_amount = total_amount + (total_amount * (10 / 100)) + if company > 0 and union > 0 and guilds > 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;{4},{5},0;".format(province_deposit_id, + int(final_total_amount * union), + arta_api_deposit_id, + int(final_total_amount * company), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + elif company > 0 and union > 0 and guilds == 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format(province_deposit_id, + int(final_total_amount * union), + arta_api_deposit_id, + int(final_total_amount * company)), + int(final_total_amount), + order_id) + + elif company > 0 and union == 0 and guilds > 0: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format( + + arta_api_deposit_id, + int(final_total_amount * company), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + else: + result = PaymentGateway( + "{0},{1},0;{2},{3},0;".format(province_deposit_id, + int(final_total_amount * union), + guilds_api_deposit_id, + int(final_total_amount * guilds)), + int(final_total_amount), + order_id) + + # result = PaymentGateway( + # "{0},{1},0;{2},{3},0;".format(sha_deposit_id, 10000, arta_deposit_id, 10000),20000, order_id) + if '400' in result.keys(): + wage_payment.state = 'failed' + wage_payment.message = result[400] + wage_payment.save() + if wallet == True: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="failed", + type="deposit", + transaction_type="wallet", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + creator_role='KillHouse', + receiver_role='KillHouse', + payer=kill_house_user.fullname, + message=result[400] + + ) + transaction.save() + else: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="failed", + transaction_type="wage-gateway", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + creator_role='KillHouse', + receiver_role='ProvinceOperator', + payer=user.fullname, + message=result[400] + + ) + transaction.save() + return Response(result[400], status=status.HTTP_400_BAD_REQUEST) + else: + wage_payment.refId = result[200] + wage_payment.orderId = order_id + wage_payment.save() + if wallet == True: + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="pending", + type="deposit", + transaction_type="wallet", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + receiver_role='KillHouse', + creator_role='KillHouse', + payer=kill_house_user.fullname, + refId=result[200], + orderId=order_id + + ) + transaction.save() + else: + + transaction = ExternalTransaction( + amount=total_amount, + amount_with_tax=final_total_amount, + status="pending", + transaction_type="wage-gateway", + is_complete=False, + kill_house_user=kill_house_user, + creator=creator, + receiver=receiver, + receiver_role='KillHouse', + creator_role='ProvinceOperator', + payer=user.fullname, + refId=result[200], + orderId=order_id + + ) + transaction.save() + return Response({"refId": result[200]}, status=status.HTTP_201_CREATED) + + # return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + wage_payment_list = [] + + if request.GET['state'] == 'failed': + wage_payment = WagePayment.objects.filter( + create_date__date__gte=date1, + create_date__date__lte=date2, + state='failed', + trash=False).order_by('id') + else: + wage_payment = WagePayment.objects.filter( + create_date__date__gte=date1, + create_date__date__lte=date2, + state='completed', + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=wage_payment + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=wage_payment) + wage_payment_list = ps.filter() + wage_payment = [] if len(wage_payment_list) == 0 else wage_payment_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(wage_payment) + if page is not None: + serializer = WagePaymentSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = WagePaymentSerializer(wage_payment, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class WagePaymentFinalStepViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [AllowAny] + serializer_class = WagePaymentSerializer + + def create(self, request, *args, **kwargs): + ref_id = request.data['refId'] + wage_payment = WagePayment.objects.get(refId=ref_id, trash=False, state='pending') + transaction = InternalTransaction.objects.get(refId=ref_id, trash=False, status='pending') + + if 'error' in request.data.keys(): + wage_payment.state = "failed" + wage_payment.message = request.data['error'] + wage_payment.save() + transaction.status = "failed" + transaction.message = request.data['error'] + transaction.save() + + return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + else: + now = datetime.now() + wage_payment.payer['date'] = str(now) + wage_payment.payer['tracking_code'] = request.data['saleReferenceId'] + wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + wage_payment.refId = request.data['refId'] + wage_payment.orderId = request.data['saleOrderId'] + wage_payment.cardHolderPan = request.data['cardHolderPan'] + wage_payment.tracking_code = request.data['saleReferenceId'] + wage_payment.state = "completed" + wage_payment.save() + transaction.refId = request.data['refId'] + transaction.orderId = request.data['saleOrderId'] + transaction.cardHolderPan = request.data['cardHolderPan'] + transaction.saleReferenceId = request.data['saleReferenceId'] + transaction.status = "completed" + transaction.save() + text = [] + killer = '' + + if transaction.kill_house is not None: + user = transaction.kill_house.name + mobile = transaction.kill_house.kill_house_operator.user.mobile + killer = 'کشتارگاه' if transaction.kill_house.killer == False else 'کشتارکن' + + else: + user = transaction.chain_company.name + mobile = transaction.chain_company.user.mobile + from_date = jdatetime.date.fromgregorian( + year=transaction.date.year, + month=transaction.date.month, + day=transaction.date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + province = transaction.kill_house.kill_house_operator.user.province.name + if transaction.union_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.union_share, + 'mobile': UNION_NUMBER, + 'province': province, + 'killer': killer + + }) + if transaction.company_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.company_share, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }) + if transaction.guilds_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.guilds_share, + 'mobile': GUILD_NUMBER, + 'province': province, + 'killer': killer + + }) + text_for_company = [{ + 'payer': user, + 'date': date, + 'share': transaction.amount, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }] + transaction_for_eata(request, transaction) + send_sms_for_company = threading.Thread(target=transaction_sms_threading_for_company, + args=(text_for_company)) + send_sms_for_kill_house = threading.Thread(target=transaction_sms_threading_appreciation, + args=(user, mobile)) + send_sms = threading.Thread(target=transaction_sms_threading, args=(text)) + send_sms.start() + send_sms_for_company.start() + send_sms_for_kill_house.start() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + # def create(self, request, *args, **kwargs): + # ref_id = request.data['refId'] + # wage_payment = WagePayment.objects.get(refId=ref_id, trash=False, state='pending') + # transaction = ExternalTransaction.objects.get(refId=ref_id, trash=False, status='pending') + # + # if 'error' in request.data.keys(): + # wage_payment.state = "failed" + # wage_payment.message = request.data['error'] + # wage_payment.save() + # transaction.status = "failed" + # transaction.message = request.data['error'] + # transaction.save() + # + # return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + # else: + # now = datetime.now() + # wage_payment.payer['date'] = str(now) + # wage_payment.payer['tracking_code'] = request.data['saleReferenceId'] + # wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + # if wage_payment.type == None: + # + # for province_kill_request in wage_payment.province_kill_request: + # province_kill_request = ProvinceKillRequest.objects.filter( + # key=province_kill_request).select_related( + # 'province_request__poultry_request').last() + # province_kill_request.wage_pay = True + # province_kill_request.depositor['tracking_code'] = request.data['saleReferenceId'] + # province_kill_request.depositor['orderId'] = request.data['saleOrderId'] + # province_kill_request.depositor['refId'] = request.data['refId'] + # province_kill_request.depositor[ + # 'total_amount'] = province_kill_request.total_killed_weight * province_kill_request.wage + # # province_kill_request.depositor['total_amount'] = request.data['finalAmount'] + # province_kill_request.depositor['date'] = str(now) + # province_kill_request.depositor['cardHolderPan'] = request.data['cardHolderPan'] + # province_kill_request.save() + # + # wage_payment.total_amount_with_tax = request.data['finalAmount'] + # wage_payment.refId = request.data['refId'] + # wage_payment.orderId = request.data['saleOrderId'] + # wage_payment.cardHolderPan = request.data['cardHolderPan'] + # wage_payment.tracking_code = request.data['saleReferenceId'] + # wage_payment.state = "completed" + # wage_payment.save() + # transaction.amount_with_tax = request.data['finalAmount'] + # transaction.refId = request.data['refId'] + # transaction.orderId = request.data['saleOrderId'] + # transaction.cardHolderPan = request.data['cardHolderPan'] + # transaction.saleReferenceId = request.data['saleReferenceId'] + # transaction.status = "completed" + # transaction.save() + # + # return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class WagePaymentWithLinkFinalStepViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [AllowAny] + serializer_class = WagePaymentSerializer + + def create(self, request, *args, **kwargs): + authority = request.data['authority'] + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + # wage_payment = WagePayment.objects.get(authority=authority, trash=False, state='pending') + transaction = InternalTransaction.objects.get(authority=authority, trash=False, status='pending') + + if 'error' in request.data.keys(): + # wage_payment.state = "failed" + # wage_payment.message = request.data['error'] + # wage_payment.save() + transaction.status = "failed" + transaction.message = request.data['error'] + transaction.save() + + return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + else: + now = datetime.now() + # wage_payment.payer['date'] = str(now) + # wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + # wage_payment.refId = request.data['refId'] + # wage_payment.cardHolderPan = request.data['cardHolderPan'] + # wage_payment.state = "completed" + # wage_payment.save() + transaction.refId = request.data['refId'] + transaction.cardHolderPan = request.data['cardHolderPan'] + transaction.status = "completed" + transaction.save() + text = [] + + if transaction.payer_type == 'poultry': + # if transaction.poultry_request is not None: + # poultry_requests = PoultryRequest.objects.filter(id=transaction.poultry_request.id,trash=False) + # + # + # else: + # poultry_requests = PoultryRequest.objects.filter(payer_type='poultry', + # poultry__user=transaction.user, + # out_province_request_cancel=False, out=True, + # has_wage=True, + # province_state='accepted', wage_pay=False, trash=False) + poultry_requests = transaction.poultry_request.all() + for poultry_request in poultry_requests: + if poultry_request.has_wage == True and poultry_request.wage_pay == False: + # hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + # if hatching.left_over >= poultry_request.quantity: + # hatching.out_province_killed_weight += int( + # poultry_request.quantity * poultry_request.Index_weight) + # hatching.out_province_killed_quantity += poultry_request.quantity + # hatching.save() + # else: + # different_quantity = poultry_request.quantity - hatching.left_over + # hatching.out_province_killed_weight += int( + # hatching.left_over * poultry_request.Index_weight) + # hatching.out_province_killed_quantity += hatching.left_over + # hatching.extra_killed_quantity += different_quantity + # hatching.save() + poultry_request.wage_pay = True + poultry_request.save() + if wage_type and wage_type.status == True: + province_operator = ProvinceOperator.objects.filter(trash=False).last() + + vet = VetFarm.objects.filter(trash=False, poultry=poultry_request.poultry).first() + vet_number = vet.vet.user.mobile if vet else None + province_operator_mobile = province_operator.user.mobile + date_str = poultry_request.send_date + send_date = datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + poultry_fullname = poultry_request.poultry.unit_name + quantity = poultry_request.quantity + chicken_breed = poultry_request.chicken_breed + order_code = poultry_request.order_code + sms_operator_out_poultry_request_sms = threading.Thread( + target=operator_out_poultry_request_sms, + args=( + province_operator_mobile, + poultry_fullname, + quantity, chicken_breed, + order_code, send_date, + poultry_request.free_sale_in_province, + poultry_request.amount, + vet_number + )) + sms_operator_out_poultry_request_sms.start() + vet_farm = VetFarm.objects.filter(trash=False, poultry__in=poultry_requests.values_list('poultry', + flat=True).distinct()).first() + bot_eitaa_out_province_live_bar(request, poultry_requests, vet_farm) + if transaction.payer_type == 'buyer': + buyer = OutProvincePoultryRequestBuyer.objects.get(user=transaction.user, trash=False) + poultry_requests = transaction.poultry_request.all() + # poultry_requests = PoultryRequest.objects.filter(out_province_poultry_request_buyer=buyer, + # payer_type='buyer', out_province_request_cancel=False, + # out=True, has_wage=True, + # province_state='accepted', wage_pay=False, trash=False) + for poultry_request in poultry_requests: + if poultry_request.has_wage == True and poultry_request.wage_pay == False: + # hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + # if hatching.left_over >= poultry_request.quantity: + # hatching.out_province_killed_weight += int( + # poultry_request.quantity * poultry_request.Index_weight) + # hatching.out_province_killed_quantity += poultry_request.quantity + # hatching.save() + # else: + # different_quantity = poultry_request.quantity - hatching.left_over + # hatching.out_province_killed_weight += int( + # hatching.left_over * poultry_request.Index_weight) + # hatching.out_province_killed_quantity += hatching.left_over + # hatching.extra_killed_quantity += different_quantity + # hatching.save() + poultry_request.wage_pay = True + poultry_request.save() + + if wage_type and wage_type.status == True: + province_operator = ProvinceOperator.objects.filter(trash=False).last() + + vet = VetFarm.objects.filter(trash=False, poultry=poultry_request.poultry).first() + vet_number = vet.vet.user.mobile if vet else None + province_operator_mobile = province_operator.user.mobile + date_str = poultry_request.send_date + send_date = datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + poultry_fullname = poultry_request.poultry.unit_name + quantity = poultry_request.quantity + chicken_breed = poultry_request.chicken_breed + order_code = poultry_request.order_code + sms_operator_out_poultry_request_sms = threading.Thread( + target=operator_out_poultry_request_sms, + args=( + province_operator_mobile, + poultry_fullname, + quantity, chicken_breed, + order_code, send_date, + poultry_request.free_sale_in_province, + poultry_request.amount, + vet_number + )) + sms_operator_out_poultry_request_sms.start() + vet_farm = VetFarm.objects.filter(trash=False, poultry__in=poultry_requests.values_list('poultry', + flat=True).distinct()).first() + + bot_eitaa_out_province_live_bar(request, poultry_requests, vet_farm) + killer = '' + if transaction.kill_house is not None: + user = transaction.kill_house.name + mobile = transaction.kill_house.kill_house_operator.user.mobile + killer = 'کشتارگاه' if transaction.kill_house.killer == False else 'کشتارکن' + province = transaction.kill_house.kill_house_operator.user.province.name + elif transaction.out_province_poultry_request_buyer is not None: + buyer = OutProvincePoultryRequestBuyer.objects.get(user=transaction.user, trash=False) + user = buyer.user.fullname + mobile = buyer.user.mobile + province = buyer.province + + + + + # elif transaction.poultry_request is not None: + # poultry_request = PoultryRequest.objects.get(key=transaction.poultry_request.key, trash=False) + # poultry_request.wage_pay = True + # poultry_request.save() + # update_out_province_hatching(poultry_request.hatching) + # + # user = transaction.poultry_request.poultry.unit_name if transaction.poultry_request.payer_type == 'poultry' else transaction.poultry_request.payer_fullname + # mobile = transaction.poultry_request.poultry.user.mobile if transaction.poultry_request.payer_type == 'poultry' else \ + # transaction.poultry_request.buyer['mobile'] + + elif transaction.chain_company is not None: + user = transaction.chain_company.name + mobile = transaction.chain_company.user.mobile + province = transaction.chain_company.user.province.name + + else: + user = transaction.user.fullname + mobile = transaction.user.mobile + province = transaction.user.province.name + + from_date = jdatetime.date.fromgregorian( + year=transaction.date.year, + month=transaction.date.month, + day=transaction.date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + if transaction.union_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.union_share, + 'mobile': UNION_NUMBER, + 'province': province, + 'killer': killer + + }) + if transaction.company_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.company_share, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }) + if transaction.guilds_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.guilds_share, + 'mobile': GUILD_NUMBER, + 'province': province, + 'killer': killer + + }) + text_for_company = [{ + 'payer': user, + 'date': date, + 'share': transaction.amount, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }] + transaction_for_eata(request, transaction) + if transaction.kill_house is not None: + send_sms_for_zir_bakhs = threading.Thread(target=transaction_sms_threading_in_province, + args=(text)) + send_sms_for_zir_bakhs.start() + + send_sms_for_company = threading.Thread(target=transaction_sms_threading_for_company, + args=(text_for_company)) + send_sms_for_kill_house = threading.Thread(target=transaction_sms_threading_appreciation, + args=(user, mobile)) + send_sms = threading.Thread(target=transaction_sms_threading, args=(text)) + send_sms.start() + send_sms_for_company.start() + send_sms_for_kill_house.start() + + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + # def create(self, request, *args, **kwargs): + # ref_id = request.data['refId'] + # wage_payment = WagePayment.objects.get(refId=ref_id, trash=False, state='pending') + # transaction = ExternalTransaction.objects.get(refId=ref_id, trash=False, status='pending') + # + # if 'error' in request.data.keys(): + # wage_payment.state = "failed" + # wage_payment.message = request.data['error'] + # wage_payment.save() + # transaction.status = "failed" + # transaction.message = request.data['error'] + # transaction.save() + # + # return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + # else: + # now = datetime.now() + # wage_payment.payer['date'] = str(now) + # wage_payment.payer['tracking_code'] = request.data['saleReferenceId'] + # wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + # if wage_payment.type == None: + # + # for province_kill_request in wage_payment.province_kill_request: + # province_kill_request = ProvinceKillRequest.objects.filter( + # key=province_kill_request).select_related( + # 'province_request__poultry_request').last() + # province_kill_request.wage_pay = True + # province_kill_request.depositor['tracking_code'] = request.data['saleReferenceId'] + # province_kill_request.depositor['orderId'] = request.data['saleOrderId'] + # province_kill_request.depositor['refId'] = request.data['refId'] + # province_kill_request.depositor[ + # 'total_amount'] = province_kill_request.total_killed_weight * province_kill_request.wage + # # province_kill_request.depositor['total_amount'] = request.data['finalAmount'] + # province_kill_request.depositor['date'] = str(now) + # province_kill_request.depositor['cardHolderPan'] = request.data['cardHolderPan'] + # province_kill_request.save() + # + # wage_payment.total_amount_with_tax = request.data['finalAmount'] + # wage_payment.refId = request.data['refId'] + # wage_payment.orderId = request.data['saleOrderId'] + # wage_payment.cardHolderPan = request.data['cardHolderPan'] + # wage_payment.tracking_code = request.data['saleReferenceId'] + # wage_payment.state = "completed" + # wage_payment.save() + # transaction.amount_with_tax = request.data['finalAmount'] + # transaction.refId = request.data['refId'] + # transaction.orderId = request.data['saleOrderId'] + # transaction.cardHolderPan = request.data['cardHolderPan'] + # transaction.saleReferenceId = request.data['saleReferenceId'] + # transaction.status = "completed" + # transaction.save() + # + # return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class WagePaymentFinalStepZarinPalViewset(viewsets.ModelViewSet): + queryset = WagePayment.objects.all() + permission_classes = [AllowAny] + serializer_class = WagePaymentSerializer + + def create(self, request, *args, **kwargs): + authority = request.data['authority'] + # wage_payment = WagePayment.objects.get(authority=authority, trash=False, state='pending') + transaction = InternalTransaction.objects.get(authority=authority, trash=False, status='pending') + # ref_id = request.data['refId'] + # wage_payment = WagePayment.objects.get(refId=ref_id, trash=False, state='pending') + # transaction = InternalTransaction.objects.get(refId=ref_id, trash=False, status='pending') + + if 'error' in request.data.keys(): + # wage_payment.state = "failed" + # wage_payment.message = request.data['error'] + # wage_payment.save() + # transaction.status = "failed" + transaction.message = request.data['error'] + transaction.save() + + return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + else: + now = datetime.now() + # wage_payment.payer['date'] = str(now) + # wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + # wage_payment.refId = request.data['refId'] + # wage_payment.cardHolderPan = request.data['cardHolderPan'] + # wage_payment.state = "completed" + # wage_payment.save() + transaction.refId = request.data['refId'] + transaction.cardHolderPan = request.data['cardHolderPan'] + transaction.status = "completed" + transaction.save() + text = [] + killer = '' + + if transaction.kill_house is not None: + user = transaction.kill_house.name + mobile = transaction.kill_house.kill_house_operator.user.mobile + killer = 'کشتارگاه' if transaction.kill_house.killer == False else 'کشتارکن' + else: + user = transaction.chain_company.name + mobile = transaction.chain_company.user.mobile + from_date = jdatetime.date.fromgregorian( + year=transaction.date.year, + month=transaction.date.month, + day=transaction.date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + date = separate.join(reversed_date) + province = transaction.kill_house.kill_house_operator.user.province.name + + if transaction.union_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.union_share, + 'mobile': UNION_NUMBER, + 'province': province, + 'killer': killer + }) + if transaction.company_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.company_share, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }) + if transaction.guilds_share > 0: + text.append({ + 'payer': user, + 'date': date, + 'share': transaction.guilds_share, + 'mobile': GUILD_NUMBER, + 'province': province, + 'killer': killer + + }) + text_for_company = [{ + 'payer': user, + 'date': date, + 'share': transaction.amount, + 'mobile': COMPANY_NUMBER, + 'province': province, + 'killer': killer + + }] + transaction_for_eata(request, transaction) + send_sms_for_company = threading.Thread(target=transaction_sms_threading_for_company, + args=(text_for_company)) + send_sms_for_kill_house = threading.Thread(target=transaction_sms_threading_appreciation, + args=(user, mobile)) + send_sms = threading.Thread(target=transaction_sms_threading, args=(text)) + send_sms.start() + send_sms_for_company.start() + send_sms_for_kill_house.start() + return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + # def create(self, request, *args, **kwargs): + # ref_id = request.data['refId'] + # wage_payment = WagePayment.objects.get(refId=ref_id, trash=False, state='pending') + # transaction = ExternalTransaction.objects.get(refId=ref_id, trash=False, status='pending') + # + # if 'error' in request.data.keys(): + # wage_payment.state = "failed" + # wage_payment.message = request.data['error'] + # wage_payment.save() + # transaction.status = "failed" + # transaction.message = request.data['error'] + # transaction.save() + # + # return Response({"result": "با خطا مواجه شد"}, status=status.HTTP_200_OK) + # else: + # now = datetime.now() + # wage_payment.payer['date'] = str(now) + # wage_payment.payer['tracking_code'] = request.data['saleReferenceId'] + # wage_payment.payer['cardHolderPan'] = request.data['cardHolderPan'] + # if wage_payment.type == None: + # + # for province_kill_request in wage_payment.province_kill_request: + # province_kill_request = ProvinceKillRequest.objects.filter( + # key=province_kill_request).select_related( + # 'province_request__poultry_request').last() + # province_kill_request.wage_pay = True + # province_kill_request.depositor['tracking_code'] = request.data['saleReferenceId'] + # province_kill_request.depositor['orderId'] = request.data['saleOrderId'] + # province_kill_request.depositor['refId'] = request.data['refId'] + # province_kill_request.depositor[ + # 'total_amount'] = province_kill_request.total_killed_weight * province_kill_request.wage + # # province_kill_request.depositor['total_amount'] = request.data['finalAmount'] + # province_kill_request.depositor['date'] = str(now) + # province_kill_request.depositor['cardHolderPan'] = request.data['cardHolderPan'] + # province_kill_request.save() + # + # wage_payment.total_amount_with_tax = request.data['finalAmount'] + # wage_payment.refId = request.data['refId'] + # wage_payment.orderId = request.data['saleOrderId'] + # wage_payment.cardHolderPan = request.data['cardHolderPan'] + # wage_payment.tracking_code = request.data['saleReferenceId'] + # wage_payment.state = "completed" + # wage_payment.save() + # transaction.amount_with_tax = request.data['finalAmount'] + # transaction.refId = request.data['refId'] + # transaction.orderId = request.data['saleOrderId'] + # transaction.cardHolderPan = request.data['cardHolderPan'] + # transaction.saleReferenceId = request.data['saleReferenceId'] + # transaction.status = "completed" + # transaction.save() + # + # return Response({"result": "با موفقیت انجام شد"}, status=status.HTTP_200_OK) + + +class ObservatoryViewSet(viewsets.ModelViewSet): + queryset = Observatory.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ObservatorySerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + observatory = user.observatory_user.all() + + # send to serializer + serializer = self.serializer_class(observatory[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSTransactionsViewSet(viewsets.ModelViewSet): + queryset = POSTransactions.objects.all() + permission_classes = [AllowAny] + serializer_class = POSTransactionsSerializer + + def create(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.data['posid'], trash=False) + pos.Lat = request.data['lot'] + pos.Long = request.data['lng'] + pos.save() + guild = Guilds.objects.get(key=pos.guild.key, trash=False) + guilds_ware_house = GuildsWareHouse.objects.filter(guilds=guild).first() + if 'paid' in request.data.keys(): + if request.data['paid'] == False: + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + transaction = serializer.create(validated_data=request.data) + transaction.guild = guild + transaction.user = guild.user + transaction.registered = True + transaction.save() + serializer = self.serializer_class(transaction) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(self.serializer_class.errors, status=status.HTTP_400_BAD_REQUEST) + else: + if request.data['checkout'] == False: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + transaction = serializer.create(validated_data=request.data) + transaction.guild = guild + transaction.user = guild.user + transaction.registered = True + transaction.save() + else: + transaction = POSTransactions.objects.get(resnum=request.data['resnum']) + serializer = self.serializer_class(transaction) + serializer.update(instance=transaction, validated_data=request.data) + products = request.data['product'] + for product in products: + if product['name'] == 'مرغ گرم': + guild_product = Product.objects.get(name=product['name'], guild=guild, trash=False) + guild_product.sale_weight += product['cur_qty'] / 1000 + guild_product.remain_weight -= product['cur_qty'] / 1000 + guild_product.save() + guilds_ware_house.allocated_total_weight_of_carcasses += product['cur_qty'] / 1000 + guilds_ware_house.remain_total_weight_of_carcasses -= product['cur_qty'] / 1000 + guilds_ware_house.save() + serializer = self.serializer_class(transaction) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + # pos = POSMachine.objects.get(pos_id=request.GET['posid'], trash=False) + guild = Guilds.objects.get(key=request.GET['guild_key'], trash=False) + transactions = POSTransactions.objects.filter(guild=guild).order_by('-create_date') + serializer = self.serializer_class(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosVersionViewSet(viewsets.ModelViewSet): + queryset = PosVersion.objects.all() + permission_classes = [AllowAny] + serializer_class = PosVersiontSerializer + + def create(self, request, *args, **kwargs): + pos_version = PosVersion.objects.filter(trash=False).first() + if not pos_version: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_version = serializer.create(validated_data=request.data) + return Response(serializer.data, status=status.HTTP_201_CREATED) + else: + serializer = self.serializer_class(pos_version) + serializer.update(instance=pos_version, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + pos_version = PosVersion.objects.filter(trash=False).first() + serializer = self.serializer_class(pos_version) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosItemViewSet(viewsets.ModelViewSet): + queryset = PosItem.objects.all() + permission_classes = [AllowAny] + serializer_class = PosItemSerializer + + def create(self, request, *args, **kwargs): + try: + pos_item = PosItem.objects.get(name=request.data['name'], trash=False) + serializer = self.serializer_class(pos_item) + serializer.update(instance=pos_item, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + except: + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_version = serializer.create(validated_data=request.data) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + +class GuildRoomViewSet(viewsets.ModelViewSet): + queryset = GuildRoom.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildRoomSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + guild_room = user.guild_room_user.all() + + # send to serializer + serializer = self.serializer_class(guild_room[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSMachineForServerViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [AllowAny] + serializer_class = POSMachineForServerSerializer + + def list(self, request, *args, **kwargs): + guild = Guilds.objects.get(key=request.GET['guild_key'], trash=False) + pos_machine = POSMachine.objects.filter(guild=guild, trash=False) + serializer = self.serializer_class(pos_machine, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSMachineForInspectionViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [AllowAny] + serializer_class = POSMachineForInspectionSerializer + + def list(self, request, *args, **kwargs): + pos_machine = POSMachine.objects.filter(trash=False) + serializer = self.serializer_class(pos_machine, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def register_information_in_server(pos_machine, guild_key, server): + u = "https://pos.rasadyar.com/api/async/pos?id={}&shop={}&server={}".format( + pos_machine, guild_key, server) + + url = u.format() + + payload = {} + headers = {"Content-Type": "application/x-www-form-urlencoded"} + + response = requests.request("GET", url, headers=headers, data=payload) + if response.json()['code'] == 200: + pos = POSMachine.objects.get(pos_id=pos_machine, trash=False) + pos.server_register = True + pos.save() + + +class POSMachineViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [AllowAny] + serializer_class = POSMachineSerializer + + def create(self, request, *args, **kwargs): + import string + import random + server = None + guild = None + kill_house = None + if 'serial' in request.data.keys() and request.data['serial'] is not None: + exist_pos = POSMachine.objects.filter(serial=request.data['serial'], trash=False).first() + if exist_pos: + exist_pos.serial = "" + exist_pos.password = None + exist_pos.save() + # return Response({"result": "شماره سریال دستگاه وارد شده قبلا استفاده شده است! "}, + # status=status.HTTP_403_FORBIDDEN) + if 'password' in request.data.keys() and request.data['password'] is None: + return Response({"result": "کلمه عبور مدیریتی را وارد کنید! "}, + status=status.HTTP_403_FORBIDDEN) + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if user.province.name == 'مرکزی': + server = 'markazi' + elif user.province.name == 'همدان': + server = 'hamedan' + else: + server = 'test' + company = PosCompany.objects.get(user=user, trash=False) + if 'guild_key' in request.data.keys(): + guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + else: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + + while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + res = base_pos_id + res + if not POSMachine.objects.filter(pos_id=res).exists(): + break + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_machine = serializer.create(validated_data=request.data) + pos_machine.pos_id = res + if kill_house is not None: + pos_machine.user = kill_house.kill_house_operator.user + pos_machine.kill_house = kill_house + else: + pos_machine.user = guild.user + pos_machine.guild = guild + guild.has_pos = True + guild.save() + pos_machine.pos_company = company + pos_machine.save() + + # register_information_in_server_threading = threading.Thread( + # target=register_information_in_server, + # args=( + # pos_machine.pos_id, guild.key, server)) + # register_information_in_server_threading.start() + return Response({"result": "باموفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + if 'pos_id' in request.data.keys(): + pos = POSMachine.objects.get( + pos_id=request.data['pos_id']) + timestamp_date = request.data['timestamp_date'] + pos_date = datetime.fromtimestamp(timestamp_date) + request.data.pop('timestamp_date') + pos.last_check = pos_date + pos.save() + else: + pos = POSMachine.objects.get( + key=request.data['pos_key']) + request.data.pop('pos_key') + serializer = self.serializer_class(pos) + serializer.update(instance=pos, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class FinalPOSMachineViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [AllowAny] + serializer_class = NewPOSMachineSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = POSMachineFilterSet + filterset_fields = [ + 'pos_id', + 'serial', + 'password', + 'pos_company__name', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + ] + + def create(self, request, *args, **kwargs): + import string + import random + user = SystemUserProfile.objects.get(user=request.user, trash=False) + company = PosCompany.objects.get(user=user, trash=False) + if 'serial' in request.data.keys() and request.data['serial'] is not None: + exist_pos = POSMachine.objects.filter(serial=request.data['serial'], trash=False).first() + if exist_pos: + exist_pos.serial = "" + exist_pos.password = None + exist_pos.save() + # return Response({"result": "شماره سریال دستگاه وارد شده قبلا استفاده شده است! "}, + # status=status.HTTP_403_FORBIDDEN) + if 'password' in request.data.keys() and request.data['password'] is None: + return Response({"result": "کلمه عبور مدیریتی را وارد کنید! "}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_machine = serializer.create(validated_data=request.data) + pos_machine.pos_company = company + pos_machine.save() + return Response({"result": "باموفقیت ثبت شد!"}, status=status.HTTP_201_CREATED) + + def update(self, request, *args, **kwargs): + pos_machine = POSMachine.objects.get(key=request.data['key'], trash=False) + owner_type = request.data.get('owner_type') + if owner_type: + if owner_type == 'kill_house': + kill_house = KillHouse.objects.get(key=request.data['owner_key']) + pos_machine.kill_house = kill_house + pos_machine.guild = None + pos_machine.steward = None + pos_machine.user = kill_house.kill_house_operator.user + + else: + guild_steward = Guilds.objects.get(key=request.data['owner_key']) + pos_machine.guild = guild_steward + pos_machine.user = guild_steward.user + pos_machine.kill_house = None + pos_machine.steward = None + + if not pos_machine.pos_id: + while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=10)) + res = base_pos_id + res + if not POSMachine.objects.filter(pos_id=res).exists(): + break + pos_machine.pos_id = res + pos_machine.save() + request.data.pop('owner_type') + request.data.pop('owner_key') + serializer = self.serializer_class(pos_machine) + serializer.update(instance=pos_machine, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if role == 'PosCompany': + company = PosCompany.objects.get(user=user, trash=False) + pos_machines = POSMachine.objects.filter(pos_company=company, trash=False).order_by('-create_date') + + else: + pos_machines = POSMachine.objects.filter(trash=False, cooperative__isnull=True).order_by('-create_date') + + if 'search' in request.GET: + pos_machines_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=pos_machines + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=pos_machines) + pos_machines_list = ps.filter() + pos_machines = [] if len(pos_machines_list) == 0 else pos_machines_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(pos_machines) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(pos_machines, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class UserPOSMachineViewSet(viewsets.ModelViewSet): +# queryset = POSMachine.objects.all() +# +# def get_serializer_class(self): +# if self.action in ['list', 'retrieve']: +# return POSMachineReadSerializer +# return POSMachineTransferSerializer +# +# @action(detail=True, methods=['post']) +# def transfer(self, request, pk=None): +# pos = self.get_object() +# serializer = self.get_serializer( +# data=request.data, +# context={'pos': pos, 'request': request} +# ) +# serializer.is_valid(raise_exception=True) +# serializer.save() +# return Response({"detail": "انتقال با موفقیت انجام شد"}) + +class UserPOSMachineViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = UserPOSMachineSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = POSMachineFilterSet + filterset_fields = [ + 'pos_id', + 'serial', + 'receiver_number', + 'terminal_number', + 'pos_unique_id', + 'password', + 'pos_company__name', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'owner__first_name', + 'owner__last_name', + 'owner__fullname', + 'owner__mobile', + 'current_user__first_name', + 'current_user__last_name', + 'current_user__fullname', + 'current_user__mobile', + 'current_representative__first_name', + 'current_representative__last_name', + 'current_representative__mobile', + 'current_representative__city', + ] + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + pos_filter = { + 'trash': False + } + if role in ('KillHouse', 'Steward', 'Guilds'): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + pos_filter['owner'] = user + + pos = POSMachine.objects.filter(**pos_filter).order_by('id') + if 'search' in request.GET: + pos_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=pos + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=pos) + pos_list = ps.filter() + pos = [] if len(pos_list) == 0 else pos_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(pos) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(pos, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + performed_by = SystemUserProfile.objects.get(user=request.user, trash=False) + pos_machine = POSMachine.objects.get(key=request.data['key'], trash=False) + recipient_type = request.data.pop('recipient_type', None) + recipient = request.data.pop('recipient_key', None) + if recipient_type in ('owner', 'current_user'): + recipient = SystemUserProfile.objects.get(key=recipient, trash=False) + else: + recipient = Representative.objects.get(key=recipient, trash=False) + serializer = self.serializer_class(POSTransferService.transfer( + pos_machine, + recipient_type, + recipient, + performed_by + )) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSMachineForLiveStackViewSet(viewsets.ModelViewSet): + queryset = POSMachine.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = POSMachineForLiveStockSerializer + + def list(self, request, *args, **kwargs): + if 'cooperative_key' in request.GET: + cooperative = Cooperative.objects.get(key=request.GET['cooperative_key'], trash=False) + pos = POSMachine.objects.filter(trash=False, cooperative=cooperative).order_by('id') + + else: + pos = POSMachine.objects.filter(trash=False).order_by('id') + + serializer = self.serializer_class(pos, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSDeviceSessionViewSet(viewsets.ModelViewSet): + queryset = POSDeviceSession.objects.all() + permission_classes = [AllowAny] + serializer_class = POSDeviceSessionSerializer + + def create(self, request, *args, **kwargs): + password = None + + validator = PosDeviceValidator(request) + + validation_error = validator.validation_version() + if validation_error: + return validation_error + + device_mac = request.headers.get('device-mac') + device_name = request.headers.get('device-name') + device_sdk = request.headers.get('device-sdk') + device_serial = request.headers.get('device-serial') + device_provider = request.headers.get('device-provider') + device_version = request.headers.get('device-version') + device_lng = request.headers.get('device-lng') + device_lot = request.headers.get('device-lot') + + client_ip = get_client_ip(request) + pos = None + if not device_mac or not device_provider or not device_version: + return Response({"result": "مقادیر ارسالی صحیح نمیباشد!"}, status=status.HTTP_403_FORBIDDEN) + + if 'pos' in request.data and 'password' in request.data: + password = request.data['password'] + pos = POSMachine.objects.filter(pos_id=request.data['pos'], trash=False).first() + request.data.pop('password') + request.data.pop('pos') + if not pos and device_serial and device_serial != 'unknown': + pos = POSMachine.objects.filter(serial=device_serial, trash=False).first() + password = pos.password if pos else None + + if not pos: + return Response({"result": "کد پذیرنده نامعتبر میباشد!"}, status=status.HTTP_403_FORBIDDEN) + + if not pos.active: + return Response({"result": "این پذیرنده توسط مدیریت مسدود شده است!"}, status=status.HTTP_403_FORBIDDEN) + if pos.pos_company.en_name != device_provider and not pos.multi_device: + return Response({"result": f"کد پذیرنده برای {pos.pos_company.name} تعریف شده است"}, + status=status.HTTP_403_FORBIDDEN) + body_data = { + "mac": device_mac, + "name": device_name, + "sdk": device_sdk, + "serial": device_serial, + "version": device_version, + "lng": device_lng, + "lot": device_lot, + "ip": client_ip, + "password": password, + "session_create_date": datetime.now(), + "session_last_seen_date": datetime.now(), + } + + pos_session = POSDeviceSession.objects.filter(pos=pos, trash=False) + + if pos_session: + curent_session = pos_session.filter(mac=device_mac).first() + if curent_session: + serializer = self.serializer_class(curent_session) + serializer.update(instance=curent_session, validated_data=body_data) + return Response({"result": "خوش آمدید", "pos_id": pos.pos_id, "pos_password": password, + 'fullname': pos.user.fullname, 'mobile': pos.user.mobile}, + status=status.HTTP_200_OK) + elif not pos.multi_device: + return Response({"result": "کد پذیرنده توسط دستگاه دیگری درحال استفاده میباشد!"}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=body_data) + if serializer.is_valid(): + pos_session = serializer.create(validated_data=body_data) + pos_session.pos = pos + pos_session.password = password + pos_session.save() + return Response( + {"result": "خوش آمدید", "pos_id": pos.pos_id, "pos_password": password, 'fullname': pos.user.fullname, + 'mobile': pos.user.mobile}, + status=status.HTTP_200_OK) + return Response(serializer.errors) + + def update(self, request, *args, **kwargs): + if 'pos_id' in request.data.keys(): + pos = POSMachine.objects.get( + pos_id=request.data['pos_id']) + timestamp_date = request.data['timestamp_date'] + pos_date = datetime.fromtimestamp(timestamp_date) + request.data.pop('timestamp_date') + pos.last_check = pos_date + pos.save() + else: + pos = POSMachine.objects.get( + key=request.data['pos_key']) + request.data.pop('pos_key') + serializer = self.serializer_class(pos) + serializer.update(instance=pos, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class POSDeviceSessionForInspectionViewSet(viewsets.ModelViewSet): + queryset = POSDeviceSession.objects.all() + permission_classes = [AllowAny] + serializer_class = POSDeviceSessionForInspectionSerializer + + def list(self, request, *args, **kwargs): + pos_devices = POSDeviceSession.objects.filter(trash=False, lng__gt=0, lot__gt=0).order_by('id').select_related( + 'pos') + serializer = self.serializer_class(pos_devices, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + pos_session = POSDeviceSession.objects.get(key=request.GET['session_key'], trash=False) + pos_session.trash = True + pos_session.save() + + return Response({"result": "موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class PosDeviceVersionViewSet(viewsets.ModelViewSet): + queryset = PosDeviceVersion.objects.all() + permission_classes = [AllowAny] + serializer_class = PosDeviceVersionSerializer + + def create(self, request, *args, **kwargs): + if 'provider' not in request.data.keys() or request.data['provider'] == "": + return Response({"result": "invalid input"}, status=status.HTTP_403_FORBIDDEN) + + else: + company = PosCompany.objects.get(en_name=request.data['provider']) + request.data.pop('provider') + if 'code' not in request.data.keys() or request.data['code'] == "": + return Response({"result": "invalid input"}, status=status.HTTP_403_FORBIDDEN) + pos_version = PosDeviceVersion.objects.filter(company=company, code=request.data['code']).first() + if pos_version: + serializer = self.serializer_class(pos_version) + serializer.update(instance=pos_version, validated_data=request.data) + else: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_version = serializer.create(validated_data=request.data) + pos_version.company = company + pos_version.save() + return Response({"result": "done!"}, status=status.HTTP_200_OK) + + +class ColdHouseViewSet(viewsets.ModelViewSet): + queryset = ColdHouse.objects.all() + permission_classes = [AllowAny] + serializer_class = ColdHouseSerializer + + def create(self, request, *args, **kwargs): + steward = None + kill_house = None + if 'steward_key' in request.data.keys(): + steward = Guilds.objects.get(key=request.data['steward_key'], trash=False) + request.data.pop('steward_key') + else: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key'], trash=False) + request.data.pop('kill_house_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + cold_house = serializer.create(validated_data=request.data) + if steward: + cold_house.steward = steward + else: + cold_house.kill_house = kill_house + cold_house.save() + serializer = self.serializer_class(cold_house) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if 'total' in request.GET: + cold_houses = ColdHouse.objects.all() + serializer = self.serializer_class(cold_houses, many=True) + else: + if request.GET['role'] == 'KillHouse': + if 'dashboard' in request.GET: + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + serializer = ColdHouseSerializer(cold_house) + + + elif 'allocation' in request.GET: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + cold_house = ColdHouse.objects.filter(trash=False).order_by('kill_house').exclude( + kill_house=kill_house) + + serializer = ColdHouseSerializer(cold_house, many=True) + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + cold_house = ColdHouse.objects.filter(trash=False).order_by('kill_house') + + # cold_house = ColdHouse.objects.filter( + # Q(kill_house=kill_house) | Q(steward__isnull=False), trash=False).order_by( + # 'kill_house') + serializer = ColdHouseSerializer(cold_house, many=True) + else: + # live_stock_support = LiveStockSupport.objects.get(user=user, trash=False) + cold_house = ColdHouse.objects.filter(live_stock_support__isnull=False, trash=False).first() + serializer = ColdHouseSerializer(cold_house) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + cold_house = ColdHouse.objects.get(key=request.data['cold_house_key'], trash=False) + request.data.pop('cold_house_key') + serializer = self.serializer_class(cold_house) + serializer.update(instance=cold_house, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalColdHouseDashboardForRolesViewSet(viewsets.ModelViewSet): + queryset = ColdHouse.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ColdHouseSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + cold_houses = ColdHouse.objects.filter(kill_house=kill_house, trash=False) + else: + steward = Guilds.objects.get(user=user, trash=False) + cold_houses = ColdHouse.objects.filter(steward=steward, trash=False) + + total_input_weight = cold_houses.aggregate(total=Sum('total_input_weight'))[ + 'total'] or 0 + total_allocated_weight = cold_houses.aggregate(total=Sum('total_allocated_weight'))[ + 'total'] or 0 + total_remain_weight = cold_houses.aggregate(total=Sum('total_remain_weight'))[ + 'total'] or 0 + + result = { + "total_cold_houses": len(cold_houses), + "total_input_weight": total_input_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class ColdHouseForProvinceViewSet(viewsets.ModelViewSet): + queryset = ColdHouse.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ColdHouseSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = ColdHouseFilterSet + filterset_fields = [ + 'name', + 'province', + 'city', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + ] + + def list(self, request, *args, **kwargs): + type = request.GET.get('type') + if type == 'KillHouse': + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + cold_houses = ColdHouse.objects.filter(kill_house=kill_house, trash=False).order_by('id') + else: + steward = Guilds.objects.get(key=request.GET['steward_key'], trash=False) + cold_houses = ColdHouse.objects.filter(steward=steward, trash=False).order_by('id') + + if 'search' in request.GET: + cold_houses_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=cold_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=cold_houses) + cold_houses_list = ps.filter() + cold_houses = [] if len(cold_houses_list) == 0 else cold_houses_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(cold_houses) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(cold_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ColdHouseTotalDashboardViewSet(viewsets.ModelViewSet): + queryset = ColdHouse.objects.all() + permission_classes = [AllowAny] + serializer_class = ColdHouseSerializer + + def list(self, request, *args, **kwargs): + cold_houses = ColdHouse.objects.filter(trash=False) + kill_house_cold_houses = cold_houses.filter(kill_house__isnull=False) + steward_cold_houses = cold_houses.filter(steward__isnull=False) + total_input_weight = cold_houses.aggregate( + total=Sum('total_input_weight'))['total'] or 0 + + total_allocated_weight = cold_houses.aggregate( + total=Sum('total_allocated_weight'))['total'] or 0 + + total_remain_weight = cold_houses.aggregate( + total=Sum('total_remain_weight'))['total'] or 0 + + result = { + "total_cold_houses": len(cold_houses), + "total_kill_house_cold_house": len(kill_house_cold_houses), + "total_steward_cold_house": len(steward_cold_houses), + "total_input_weight": total_input_weight, + "total_allocated_weight": total_allocated_weight, + "total_remain_weight": total_remain_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class ColdHouseDashboardViewSet(viewsets.ModelViewSet): + queryset = ColdHouse.objects.all() + permission_classes = [AllowAny] + serializer_class = ColdHouseSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + cold_house = ColdHouse.objects.get(key=request.GET['cold_house_key'], trash=False) + + # if request.GET['role'] == 'KillHouse': + # # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # # cold_house = ColdHouse.objects.get(kill_house=kill_house, trash=False) + # + # else: + # cold_house = ColdHouse.objects.filter(live_stock_support__isnull=False, trash=False).first() + + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = StewardAllocation.objects.filter(Q(to_cold_house=cold_house) | Q(other_cold_house=cold_house), + trash=False, to_cold_house=cold_house, date__date__gte=date1, + date__date__lte=date2, + receiver_state__in=('pending', 'accepted')) + + + else: + + allocations = StewardAllocation.objects.filter(trash=False, to_cold_house=cold_house, + receiver_state__in=('pending', 'accepted')) + + input_bars = allocations.filter( + Q(kill_house__isnull=False, to_cold_house=cold_house) | Q( + kill_house__isnull=True, other_cold_house=cold_house), + receiver_state='accepted') + output_bars = allocations.filter( + Q(to_steward__isnull=False) | Q(to_guilds__isnull=False) | Q(other_cold_house__isnull=False), + kill_house__isnull=True, to_cold_house=cold_house) + + total_input_bars_weight = input_bars.aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + total_output_bars_weight = output_bars.aggregate( + total=Sum('real_weight_of_carcasses'))['total'] or 0 + + result = { + "total_input_bars": len(input_bars), + "total_input_bars_weight": total_input_bars_weight, + "total_output_bars": len(output_bars), + "total_output_bars_weight": total_output_bars_weight, + } + + return Response(result, status=status.HTTP_200_OK) + + +class CheckColdHouseAllocationsViewSet(viewsets.ModelViewSet): + queryset = ColdHouseAllocations.objects.all() + permission_classes = [AllowAny] + serializer_class = ColdHouseAllocationsSerializer + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + allocation = ColdHouseAllocations.objects.get(key=request.data['allocation_key'], trash=False) + cold_house = ColdHouse.objects.get(key=allocation.cold_house.key, trash=False) + role = request.data['role'] + request.data.pop('allocation_key') + request.data.pop('role') + ware_house = KillHouseWareHouse.objects.get(key=allocation.kill_house_ware_house.key, trash=False) + kill_house_request = KillHouseRequest.objects.get(key=allocation.kill_house_request.key, trash=False) + + if request.data['state'] == 'accepted': + + if request.data['accepted_weight'] > kill_house_request.ware_house_accepted_real_weight or request.data[ + 'accepted_quantity'] > kill_house_request.ware_house_accepted_real_quantity: + return Response({"result": "حجم بار کمتر از مقدار وارد شده است!"}, + status=status.HTTP_403_FORBIDDEN) + + if request.data['accepted_quantity'] > allocation.quantity: + diffrent_quantity = request.data['accepted_quantity'] - allocation.quantity + diffrent_weight = request.data['accepted_weight'] - allocation.weight + if diffrent_quantity > ware_house.remain_total_number_of_carcasses and diffrent_weight > ware_house.remain_total_weight_of_carcasses: + return Response({"result": "موجودی انبار کمتر از مقدار وارد شده است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + allocation.accepted_quantity = request.data['accepted_quantity'] + allocation.accepted_weight = request.data['accepted_weight'] + allocation.save() + ware_house.allocated_total_number_of_carcasses += diffrent_quantity + ware_house.freezing_quantity += diffrent_quantity + ware_house.allocated_total_weight_of_carcasses += diffrent_weight + ware_house.freezing_weight += diffrent_weight + ware_house.save() + else: + diffrent_quantity = allocation.quantity - request.data['accepted_quantity'] + diffrent_weight = allocation.weight - request.data['accepted_weight'] + allocation.accepted_quantity = request.data['accepted_quantity'] + allocation.accepted_weight = request.data['accepted_weight'] + allocation.save() + ware_house.allocated_total_number_of_carcasses -= diffrent_quantity + ware_house.freezing_quantity -= diffrent_quantity + ware_house.allocated_total_weight_of_carcasses -= diffrent_weight + ware_house.freezing_weight -= diffrent_weight + ware_house.save() + cold_house.total_quantity += allocation.accepted_quantity + cold_house.total_weight += allocation.accepted_weight + cold_house.save() + + allocation.reviewer = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()), + } + allocation.save() + serializer = self.serializer_class(allocation) + serializer.update(instance=allocation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + # return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_200_OK) + + +class ColdHouseAllocationsViewSet(viewsets.ModelViewSet): + queryset = ColdHouseAllocations.objects.all() + permission_classes = [AllowAny] + serializer_class = ColdHouseAllocationsSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = ColdHouseAllocationsFilterSet + filterset_fields = [ + 'name', + 'cold_house__live_stock_support__user__first_name', + 'cold_house__live_stock_support__user__last_name', + 'cold_house__live_stock_support__user__fullname', + 'cold_house__live_stock_support__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + ] + + def create(self, request, *args, **kwargs): + now = datetime.now().date() + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + kill_house = KillHouse.objects.get(key=product.kill_house.key, trash=False) + cold_house = ColdHouse.objects.get(key=request.data['cold_house_key'], trash=False) + # kill_house_ware_house = KillHouseWareHouse.objects.get(key=request.data['ware_house_key'], trash=False) + date = datetime.now().date() + # date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + # request.data.pop('date') + request.data.pop('product_key') + request.data.pop('cold_house_key') + # request.data.pop('ware_house_key') + if OperationLimitation.objects.all().first().kill_house_freezing_limitation == True: + + if now != date: + return Response({"result": "به علت مغایرت تاریخ امکان انجماد وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + + # if request.data['weight'] > kill_house_request.ware_house_accepted_real_weight or request.data[ + # 'quantity'] > kill_house_request.ware_house_accepted_real_quantity: + # return Response({"result": "موجودی بار کمتر از مقدار وارد شده است!"}, + # status=status.HTTP_403_FORBIDDEN) + # if request.data['weight'] > kill_house_ware_house.remain_total_weight_of_carcasses or request.data[ + # 'quantity'] > kill_house_ware_house.remain_total_number_of_carcasses: + # return Response({"result": "موجودی انبار کمتر از مقدار وارد شده است!"}, + # status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation = serializer.create(validated_data=request.data) + allocation.cold_house = cold_house + allocation.product = product + allocation.kill_house = kill_house + allocation.date = datetime(year=date.year, month=date.month, day=date.day, hour=10, minute=1, second=1) + allocation.allocation_type = 'governmental' + allocation.real_weight = allocation.weight + allocation.real_quantity = allocation.quantity + allocation.save() + kill_house_cold_house_allocations_product_warehousing(product) + # allocation.kill_house_request = kill_house_request + # allocation.kill_house_ware_house = kill_house_ware_house + # kill_house_ware_house.allocated_total_weight_of_carcasses += request.data['weight'] + # kill_house_ware_house.allocated_total_number_of_carcasses += request.data['quantity'] + # kill_house_ware_house.save() + # kill_house_request.freezing = True + # kill_house_request.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + allocations = ColdHouseAllocations.objects.filter(kill_house=kill_house, + date__date__gte=date1, date__date__lte=date2, + trash=False).order_by('id') + else: + allocations = ColdHouseAllocations.objects.filter(date__date__gte=date1, date__date__lte=date2, + trash=False).order_by('id') + + if 'search' in request.GET: + allocations_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=allocations) + allocations_list = ps.filter() + allocations = [] if len(allocations_list) == 0 else allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + allocation = ColdHouseAllocations.objects.get(key=request.data['allocation_key'], + trash=False) + product = allocation.product + # kill_house_request = KillHouseRequest.objects.get(key=allocation.kill_house_request.key, trash=False) + + if allocation.state != 'pending': + return Response({"result": " به علت تایید تخصیص امکان ویرایش وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + # ware_house = KillHouseWareHouse.objects.get(key=allocation.kill_house_ware_house.key, trash=False) + if request.data['quantity'] > allocation.quantity or request.data['weight'] > allocation.weight: + # diffrent_quantity = request.data['quantity'] - allocation.quantity + # diffrent_weight = request.data['weight'] - allocation.weight + # if request.data['weight'] > kill_house_request.ware_house_accepted_real_weight or request.data[ + # 'quantity'] > kill_house_request.ware_house_accepted_real_quantity: + # return Response({"result": "موجودی بار کمتر از مقدار وارد شده است!"}, + # status=status.HTTP_403_FORBIDDEN) + # if diffrent_quantity > ware_house.remain_total_number_of_carcasses or diffrent_weight > ware_house.remain_total_weight_of_carcasses: + # return Response({"result": "موجودی انبار کمتر از مقدار وارد شده است!"}, + # status=status.HTTP_403_FORBIDDEN) + # else: + allocation.quantity = request.data['quantity'] + allocation.weight = request.data['weight'] + allocation.save() + # ware_house.allocated_total_number_of_carcasses += diffrent_quantity + # ware_house.freezing_quantity += diffrent_quantity + # ware_house.allocated_total_weight_of_carcasses += diffrent_weight + # ware_house.freezing_weight += diffrent_weight + # ware_house.save() + else: + diffrent_quantity = allocation.quantity - request.data['quantity'] + diffrent_weight = allocation.weight - request.data['weight'] + allocation.quantity = request.data['quantity'] + allocation.weight = request.data['weight'] + allocation.save() + # ware_house.allocated_total_number_of_carcasses -= diffrent_quantity + # ware_house.freezing_quantity -= diffrent_quantity + # ware_house.allocated_total_weight_of_carcasses -= diffrent_weight + # ware_house.freezing_weight -= diffrent_weight + # ware_house.save() + + allocation.real_quantity = request.data['quantity'] + allocation.real_weight = request.data['weight'] + allocation.save() + kill_house_cold_house_allocations_product_warehousing(product) + + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + allocation = ColdHouseAllocations.objects.get(key=request.GET["allocation_key"]) + product = allocation.product + if allocation.state != 'pending': + return Response({"result": " به علت تایید تخصیص امکان حذف وجود ندارد!"}, status=status.HTTP_403_FORBIDDEN) + # ware_house = KillHouseWareHouse.objects.get(key=allocation.kill_house_ware_house.key) + # ware_house.allocated_total_number_of_carcasses -= allocation.quantity + # ware_house.allocated_total_weight_of_carcasses -= allocation.weight + # ware_house.freezing_quantity -= allocation.quantity + # ware_house.freezing_weight -= allocation.weight + # ware_house.save() + allocation.trash = True + allocation.save() + kill_house_cold_house_allocations_product_warehousing(product) + + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class OperationLimitationViewset(viewsets.ModelViewSet): + queryset = OperationLimitation.objects.all() + permission_classes = [AllowAny] + serializer_class = OperationLimitationSerializer + + def list(self, request, *args, **kwargs): + operation_limitation = OperationLimitation.objects.filter(trash=False).first() + + serializer = self.serializer_class(operation_limitation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + operation_limitation = OperationLimitation.objects.filter(trash=False).first() + serializer = self.serializer_class(operation_limitation) + serializer.update(instance=operation_limitation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ApprovedPriceViewset(viewsets.ModelViewSet): + queryset = ApprovedPrice.objects.all() + permission_classes = [AllowAny] + serializer_class = ApprovedPriceSerializer + + def list(self, request, *args, **kwargs): + approved_price = ApprovedPrice.objects.filter(trash=False).first() + + serializer = self.serializer_class(approved_price) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + approved_price = ApprovedPrice.objects.filter(trash=False).first() + serializer = self.serializer_class(approved_price) + serializer.update(instance=approved_price, validated_data=request.data) + if request.data['approved'] == False: + price = BroadcastPrice.objects.filter(trash=False).first() + price.allow = False + price.save() + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + free_sale_province.allow = False + free_sale_province.save() + FreeCommitmentThread_Threading = threading.Thread( + target=FreeCommitmentThread, + args=(user.province.name,)) + + FreeCommitmentThread_Threading.start() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class AnnouncementsViewset(viewsets.ModelViewSet): + queryset = Announcements.objects.all() + permission_classes = [AllowAny] + serializer_class = AnnouncementsSerializer + + def list(self, request, *args, **kwargs): + if 'total' in request.GET: + announcement = Announcements.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(announcement, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + announcement = Announcements.objects.get(role=request.GET['role'], trash=False) + + serializer = self.serializer_class(announcement) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + announcement = Announcements.objects.get(key=request.data['key'], trash=False) + serializer = self.serializer_class(announcement) + serializer.update(instance=announcement, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChickenAgeRangeViewset(viewsets.ModelViewSet): + queryset = ChickenAgeRange.objects.all() + permission_classes = [AllowAny] + serializer_class = ChickenAgeRangeSerializer + + def list(self, request, *args, **kwargs): + age_range = ChickenAgeRange.objects.filter(trash=False).first() + + serializer = self.serializer_class(age_range) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + age_range = ChickenAgeRange.objects.filter(trash=False).first() + serializer = self.serializer_class(age_range) + serializer.update(instance=age_range, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TimeRangeViewset(viewsets.ModelViewSet): + queryset = TimeRange.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TimeRangeSerializer + + def list(self, request, *args, **kwargs): + time_range = TimeRange.objects.filter(trash=False).first() + + serializer = self.serializer_class(time_range) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + time_range = TimeRange.objects.filter(trash=False).first() + serializer = self.serializer_class(time_range) + serializer.update(instance=time_range, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class SystemWalletViewset(viewsets.ModelViewSet): + queryset = SystemWallet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SystemWalletSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['type'] == 'self': + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + try: + wallet = SystemWallet.objects.get(kill_house=kill_house, trash=False) + except: + wallet = SystemWallet(kill_house=kill_house) + wallet.save() + + serializer = self.serializer_class(wallet) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PaymentGatewayPercentageViewset(viewsets.ModelViewSet): + queryset = PaymentGatewayPercentage.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PaymentGatewayPercentageSerializer + + def list(self, request, *args, **kwargs): + percentage = PaymentGatewayPercentage.objects.filter(trash=False).first() + + serializer = self.serializer_class(percentage) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + percentage = PaymentGatewayPercentage.objects.filter(trash=False).first() + serializer = self.serializer_class(percentage) + serializer.update(instance=percentage, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalPaymentGatewayPercentageViewset(viewsets.ModelViewSet): + queryset = TotalPaymentGatewayPercentage.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalPaymentGatewayPercentageSerializer + + def list(self, request, *args, **kwargs): + percentage = TotalPaymentGatewayPercentage.objects.filter(trash=False).first() + + serializer = self.serializer_class(percentage) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + percentage = TotalPaymentGatewayPercentage.objects.filter(trash=False).first() + serializer = self.serializer_class(percentage) + serializer.update(instance=percentage, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ShareTypeViewset(viewsets.ModelViewSet): + queryset = ShareType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ShareTypeSerializer + + def create(self, request, *args, **kwargs): + if ShareType.objects.filter(name=request.data['name'], trash=False).exists(): + return Response({"result": "سهامدار وارد شده وجود دارد!"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + share_type = serializer.create(validated_data=request.data) + wage_types = WageType.objects.filter(trash=False) + for wage_type in wage_types: + percentage = PercentageOfWageType( + wage_type=wage_type, + share_type=share_type, + ) + percentage.save() + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +class WageTypeViewset(viewsets.ModelViewSet): + queryset = WageType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WageTypeSerializer + + def list(self, request, *args, **kwargs): + wage_types = WageType.objects.filter(trash=False).order_by('id') + + serializer = self.serializer_class(wage_types, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + wage_type = WageType.objects.get(key=request.data['key'], trash=False) + percentages = request.data['percentages'] + request.data.pop('percentages') + for percentage in percentages: + wage_percentage = PercentageOfWageType.objects.get(share_type__name=percentage['name'], wage_type=wage_type, + trash=False) + wage_percentage.percent = percentage['percent'] + wage_percentage.save() + serializer = self.serializer_class(wage_type) + serializer.update(instance=wage_type, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryOutProvinceWageTypeViewset(viewsets.ModelViewSet): + queryset = WageType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WageTypeForPoultryOutProvinceRequestSerializer + + def list(self, request, *args, **kwargs): + wage_type = WageType.objects.get(en_name='poultry-sell-out-province', trash=False) + serializer = self.serializer_class(wage_type) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PercentageOfWageTypeViewset(viewsets.ModelViewSet): + queryset = PercentageOfWageType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PercentageOfWageTypeSerializer + + +class SubSectorPercentageOfWageTypeViewset(viewsets.ModelViewSet): + queryset = SubSectorPercentageOfWageType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SubSectorPercentageOfWageTypeSerializer + + def list(self, request, *args, **kwargs): + if request.GET['type'] == 'city': + + sub_sector_wage_type = SubSectorPercentageOfWageType.objects.filter(city=True, trash=False).order_by('id') + else: + sub_sector_wage_type = SubSectorPercentageOfWageType.objects.filter(trash=False).order_by('id') + + serializer = self.serializer_class(sub_sector_wage_type, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + sub_sector_wage_type = SubSectorPercentageOfWageType.objects.get(key=request.data['sub_sector_wage_type_key'], + trash=False) + request.data.pop('sub_sector_wage_type_key') + serializer = self.serializer_class(sub_sector_wage_type) + serializer.update(instance=sub_sector_wage_type, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalWageInformationViewset(viewsets.ModelViewSet): + queryset = TotalWageInformation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalWageInformationSerializer + + def list(self, request, *args, **kwargs): + try: + total_wage = TotalWageInformation.objects.get(trash=False) + except: + total_wage = TotalWageInformation() + total_wage.save() + + serializer = self.serializer_class(total_wage, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ParentCompanyTotalWageInformationViewset(viewsets.ModelViewSet): + queryset = TotalWageInformation.objects.all() + permission_classes = [AllowAny] + serializer_class = ParentCompanyTotalWageInformationSerializer + + def list(self, request, *args, **kwargs): + try: + total_wage = TotalWageInformation.objects.get(trash=False) + except: + total_wage = TotalWageInformation() + total_wage.save() + + serializer = self.serializer_class(total_wage, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class InternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = InternalTransactionSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_fullname', + 'payer_mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name', + 'user__mobile', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'parent_kill_house__name', + 'parent_kill_house__kill_house_operator__user__fullname', + 'parent_kill_house__kill_house_operator__user__first_name', + 'parent_kill_house__kill_house_operator__user__last_name', + 'parent_kill_house__kill_house_operator__user__mobile', + + ] + + def create(self, request, *args, **kwargs): + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + parent_kill_house = kill_house + if kill_house.killer == True and kill_house.type == 'exclusive': + percentage = KillHousePercentage.objects.filter(kill_house=kill_house, trash=False).first() + parent_kill_house = percentage.kill_house_for_killer if percentage else kill_house + image = request.data['image'] + request.data.pop('image') + request.data.pop('kill_house_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + transaction = serializer.create(validated_data=request.data) + transaction.payer_type = 'kill_house' + transaction.status = 'completed' + transaction.kill_house = kill_house + transaction.parent_kill_house = parent_kill_house + transaction.payer_fullname = kill_house.kill_house_operator.user.fullname + transaction.payer_mobile = kill_house.kill_house_operator.user.mobile + transaction.date = datetime.now() + if image != "": + transaction.image = send_image_to_server(image) + + transaction.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + transactions_list = [] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + # chain_company = ChainCompany.objects.get(key=request.GET['chain_company_key'], trash=False) + + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + else: + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('id') + + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + else: + chain_company = ChainCompany.objects.get(key=request.GET['chain_company_key'], trash=False) + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('-date') + + else: + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + else: + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).order_by('id') + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + # chain_company = ChainCompany.objects.get(key=request.GET['chain_company_key'], trash=False) + + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + status='completed', + trash=False).order_by('-date') + + else: + if 'kill_house_key' in request.GET: + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + union_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + company_share__gt=0, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + guilds_share__gt=0, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('id') + + else: + transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + status='completed', + trash=False).order_by('-date') + + else: + chain_company = ChainCompany.objects.get(key=request.GET['chain_company_key'], trash=False) + if request.GET['role'] == 'ProvinceOperator': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + union_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Company': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + company_share__gt=0, + status='completed', + trash=False).order_by('-date') + elif request.GET['role'] == 'Guilds': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + guilds_share__gt=0, + status='completed', + trash=False).order_by('-date') + + elif request.GET['role'] == 'SuperAdmin': + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + status='completed', + trash=False).exclude(union_share=0, company_share=0, guilds_share=0).order_by('id') + else: + transactions = InternalTransaction.objects.filter( + chain_company=chain_company, + status='completed', + trash=False).order_by('-date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + transaction = InternalTransaction.objects.get(key=request.data['transaction_key'], trash=False) + request.data.pop('transaction_key') + if 'image' in request.data.keys(): + image = request.data['image'] + request.data.pop('image') + + if image != "": + transaction.image = send_image_to_server(image) + transaction.save() + serializer = self.serializer_class(transaction) + serializer.update(instance=transaction, validated_data=request.data) + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + transaction = InternalTransaction.objects.get(key=request.GET['transaction_key'], trash=False) + transaction.trash = True + transaction.save() + + return Response({"result": "موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class PoultryRequestInternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryOutRequestInternalTransactionSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_fullname', + 'payer_mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name', + 'user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'out_province_poultry_request_buyer__user__fullname', + 'out_province_poultry_request_buyer__user__first_name', + 'out_province_poultry_request_buyer__user__last_name', + 'out_province_poultry_request_buyer__user__mobile', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + transactions_list = [] + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['type'] == 'poultry': + transactions = InternalTransaction.objects.filter( + payer_type='poultry', + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + else: + transactions = InternalTransaction.objects.filter( + payer_type='buyer', + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TotalDashboardPoultryRequestInternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryOutRequestInternalTransactionSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = InternalTransaction.objects.filter(Q(payer_type='poultry') | Q(payer_type='buyer'), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('date') + poultry_transactions = transactions.filter(payer_type='poultry') + buyer_transactions = transactions.filter(payer_type='buyer') + total_transactions_amount = transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + poultries = len(poultry_transactions.values_list('poultry', flat=True).distinct()) + buyers = len(buyer_transactions.values_list('out_province_poultry_request_buyer', flat=True).distinct()) + poultry_transactions_total_amount = poultry_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + buyer_transactions_total_amount = buyer_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + transaction_info_dict = { + "total_number_of_transactions": len(transactions), + "total_amount_of_transactions": total_transactions_amount, + "total_number_of_payers": poultries + buyers, + "total_number_of_poultries": poultries, + "total_amount_of_poultries": poultry_transactions_total_amount, + "total_number_of_buyers": buyers, + "total_amount_of_buyers": buyer_transactions_total_amount, + } + return Response(transaction_info_dict, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_gate_way_payer_info(request): + first_char = request.GET['user_gate_way_id'][0] + if len(request.GET['user_gate_way_id']) > 7: + user_gate_way_id = request.GET['user_gate_way_id'][1:7] + order_code = request.GET['user_gate_way_id'][7:] + else: + user_gate_way_id = request.GET['user_gate_way_id'][1:] + order_code = None + if first_char == 'p': + role = 'Poultry' + elif first_char == 'b': + role = 'Buyer' + elif first_char == 'k': + role = 'KillHouse' + else: + role = 'ChainCompany' + + try: + user = SystemUserProfile.objects.get(user_gate_way_id=user_gate_way_id, trash=False) + except: + return Response({"result": "توکن کاربر معتبر نمیباشد!"}, status=status.HTTP_403_FORBIDDEN) + + if role == 'Poultry': + total_unpaid_wage = 0 + # poultry = Poultry.objects.get(user=user, trash=False) + if order_code is not None: + poultry_requests = PoultryRequest.objects.filter(order_code=order_code, poultry__user=user, + payer_type='poultry', + out_province_request_cancel=False, out=True, has_wage=True, + province_state='accepted', wage_pay=False, trash=False) + else: + poultry_requests = PoultryRequest.objects.filter(poultry__user=user, payer_type='poultry', + out_province_request_cancel=False, out=True, has_wage=True, + province_state='accepted', wage_pay=False, trash=False) + + total_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_unpaid_wage += poultry_requests.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + return Response( + { + "role": role, + "user_key": user.key, + "poultry": None, + "order_code": [order_code], + "fullname": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "number_of_requests": len(poultry_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_amount": total_unpaid_wage, + }, + status=status.HTTP_200_OK + + ) + + elif role == 'Buyer': + total_unpaid_wage = 0 + now = datetime.now().date() + buyer = OutProvincePoultryRequestBuyer.objects.get(user=user, trash=False) + poultry_requests = PoultryRequest.objects.filter(out_province_poultry_request_buyer=buyer, payer_type='buyer', + out_province_request_cancel=False, + send_date__date=now, + out=True, has_wage=True, + province_state='accepted', wage_pay=False, trash=False) + total_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + total_unpaid_wage += poultry_requests.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + order_codes = poultry_requests.values_list('order_code', flat=True) + return Response( + { + "role": role, + "user_key": user.key, + "order_code": order_codes, + "fullname": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "number_of_requests": len(poultry_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_amount": total_unpaid_wage + }, + status=status.HTTP_200_OK + + ) + elif role == 'KillHouse': + total_unpaid_wage = 0 + total_paid_wage = 0 + real_free_sale_wage = 0 + kill_house_kill_requests_wage = 0 + # wage_type = WageType.objects.filter(en_name='province-kill-request').first() + # total_check_wage = wage_type.amount + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + total_unpaid_wage = get_finance_info(kill_house)['total_price'] + + slaughter_transactions = InternalTransaction.objects.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return Response( + { + "role": role, + "user_key": user.key, + "name": kill_house.name, + "fullname": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "total_amount": total_unpaid_wage - (total_paid_wage + kill_house.off) + }, + status=status.HTTP_200_OK + + ) + else: + total_unpaid_wage = 0 + total_paid_wage = 0 + chain_company = ChainCompany.objects.get(user=user, trash=False) + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, state='accepted', + trash=False) + chain_allocations_total_wage = chain_allocations.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_unpaid_wage += chain_allocations_total_wage + chain_company_transactions = InternalTransaction.objects.filter(chain_company=chain_company, + status='completed', trash=False) + total_paid_wage += chain_company_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + return Response( + { + "role": role, + "user_key": user.key, + "name": chain_company.name, + "fullname": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "total_amount": total_unpaid_wage - total_paid_wage + }, + status=status.HTTP_200_OK + + ) + + # if 'order_code' in request.GET: + # poultry_request = PoultryRequest.objects.get(order_code=request.GET['order_code'], trash=False) + # role = 'Poultry' + # fullname = poultry_request.poultry.user.fullname if poultry_request.payer_type == 'poultry' else \ + # poultry_request.buyer['firstName'] + " " + poultry_request.buyer[ + # 'lastName'] + # return Response( + # { + # "role": role, + # "order_code": poultry_request.order_code, + # "poultry": poultry_request.poultry.unit_name, + # "fullname": fullname, + # "mobile": poultry_request.poultry.user.mobile, + # "city": poultry_request.poultry.user.city.name, + # "province": poultry_request.poultry.user.province.name, + # "total_amount": poultry_request.total_wage_amount + # }, + # status=status.HTTP_200_OK + # + # ) + # else: + # + # total_unpaid_wage = 0 + # total_paid_wage = 0 + # role = None + # try: + # user = SystemUserProfile.objects.get(user_gate_way_id=request.GET['user_gate_way_id'], trash=False) + # except: + # return Response({"result": "توکن کاربر معتبر نمیباشد!"}, status=status.HTTP_403_FORBIDDEN) + # + # kill_house_role = Group.objects.get(name='KillHouse') + # if kill_house_role in user.role.all(): + # role = 'KillHouse' + # kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, + # state__in=('pending', 'accepted'), trash=False, + # return_to_province=False, + # first_car_allocated_quantity=0, + # archive_wage=False, + # ) + # kill_house_requests = KillHouseRequest.objects.filter( + # Q(Q(killer=kill_house) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) & Q(killhouse_user=kill_house)) | Q( + # Q(killer__isnull=True) | Q(killer=kill_house)), + # # killhouse_user=kill_house, + # archive_wage=False, + # trash=False + # ) + # + # kill_house_requests = kill_house_requests.filter(Q(killer=kill_house) | Q(killhouse_user=kill_house)) + # + # free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, archive_wage=False, + # trash=False) + # + # total_unpaid_wage += province_kill_requests.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage += free_bars.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage += \ + # kill_house_requests.aggregate(total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + # 'total'] or 0 + # slaughter_transactions = InternalTransaction.objects.filter( + # kill_house=kill_house, status='completed', + # trash=False) + # + # total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + # 'total'] or 0 + # + # return Response( + # { + # "role": role, + # "user_key": user.key, + # "name": kill_house.name, + # "fullname": user.fullname, + # "mobile": user.mobile, + # "city": user.city.name, + # "province": user.province.name, + # "total_amount": total_unpaid_wage - total_paid_wage + # }, + # status=status.HTTP_200_OK + # + # ) + # else: + # role = 'ChainCompany' + # chain_company = ChainCompany.objects.get(user=user, trash=False) + # chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, state='accepted', + # trash=False) + # chain_allocations_total_wage = chain_allocations.aggregate(total=Sum('total_wage_amount'))[ + # 'total'] or 0 + # total_unpaid_wage += chain_allocations_total_wage + # chain_company_transactions = InternalTransaction.objects.filter(chain_company=chain_company, + # status='completed', trash=False) + # total_paid_wage += chain_company_transactions.aggregate(total=Sum('amount'))[ + # 'total'] or 0 + # + # return Response( + # { + # "role": role, + # "user_key": user.key, + # "name": chain_company.name, + # "fullname": user.fullname, + # "mobile": user.mobile, + # "city": user.city.name, + # "province": user.province.name, + # "total_amount": total_unpaid_wage - total_paid_wage + # }, + # status=status.HTTP_200_OK + # + # ) + + +class TotalInternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = InternalTransactionSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_fullname', + 'payer_mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name', + 'user__mobile', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'parent_kill_house__name', + 'parent_kill_house__kill_house_operator__user__fullname', + 'parent_kill_house__kill_house_operator__user__first_name', + 'parent_kill_house__kill_house_operator__user__last_name', + 'parent_kill_house__kill_house_operator__user__mobile' + + ] + + def list(self, request, *args, **kwargs): + transactions_list = [] + # todo: موقت دکتر گفته بزارمش روی کشتارگاه ها + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', payer_type='kill_house', + trash=False).order_by('-date') + else: + transactions = InternalTransaction.objects.filter( + status='completed', payer_type='kill_house', + trash=False).order_by('-date') + + # if request.GET['role'] == 'ProvinceOperator': + # transactions = transactions.filter(union_share__gt=0) + # elif request.GET['role'] == 'Company': + # transactions = transactions.filter(company_share__gt=0) + # elif request.GET['role'] == 'Guilds': + # transactions = transactions.filter(guilds_share__gt=0) + # elif request.GET['role'] == 'SuperAdmin': + # transactions = transactions.filter().exclude(guilds_share=0, company_share=0, union_share=0) + # else: + # pass + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ParentCompanyTotalInternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [AllowAny] + serializer_class = InternalTransactionSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + 'payer_fullname', + 'payer_mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name', + 'user__mobile', + 'kill_house__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'parent_kill_house__name', + 'parent_kill_house__kill_house_operator__user__fullname', + 'parent_kill_house__kill_house_operator__user__first_name', + 'parent_kill_house__kill_house_operator__user__last_name', + 'parent_kill_house__kill_house_operator__user__mobile' + + ] + + def list(self, request, *args, **kwargs): + transactions_list = [] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('-date') + else: + transactions = InternalTransaction.objects.filter( + status='completed', + trash=False).order_by('-date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PayersInternalTransactionViewset(viewsets.ModelViewSet): + queryset = InternalTransaction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = InternalTransactionSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = InternalTransactionFilterSet + filterset_fields = [ + 'saleReferenceId', + 'refId', + 'orderId', + 'cardHolderPan', + + ] + + def list(self, request, *args, **kwargs): + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(user=request.user) + transactions_list = [] + transactions = InternalTransaction.objects.filter( + trash=False).order_by('id') + if request.GET['type'] == 'success': + + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + transactions = transactions.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='completed', + ) + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + + transactions = transactions.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + ) + + if request.GET['type'] == 'failed': + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + transactions = transactions.filter( + Q(kill_house=kill_house) | Q(parent_kill_house=kill_house), + date__date__gte=date1, + date__date__lte=date2, + status='failed', + ) + + elif request.GET['role'] == 'ChainCompany': + chain_company = ChainCompany.objects.get(user=user, trash=False) + + transactions = transactions.filter( + chain_company=chain_company, + date__date__gte=date1, + date__date__lte=date2, + status='failed', + ) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityLivestockViewSet(viewsets.ModelViewSet): + queryset = CityLivestock.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityLivestockSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + city_livestock = user.city_livestock_user.all() + + # send to serializer + serializer = self.serializer_class(city_livestock[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class FinalApprovalOutProvinceViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityLivestockSerializer + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.now().date() + poultry_requests = PoultryRequest.objects.filter(trash=False, out_province_request_cancel=False, out=True, + send_date__date=now, province_state='pending', + final_state='pending', state_process='pending') + poultry = SystemUserProfile.objects.filter( + key__in=poultry_requests.filter(payer_type='poultry', sms=False).values_list('poultry__user__key', + flat=True)).values_list('id', + flat=True) + buyer = SystemUserProfile.objects.filter( + key__in=poultry_requests.filter(payer_type='buyer', sms=False).values_list( + 'out_province_poultry_request_buyer__user__key', + flat=True)).values_list('id', flat=True) + poultry_requests_for_sms = poultry_requests.filter(payer_type='poultry').values_list('id', flat=True).distinct() + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + if wage_type and wage_type.status == True: + sms = threading.Thread(target=send_sms_for_final_approval_out_province_threading, + args=(list(buyer), list(poultry_requests_for_sms))) + sms.start() + for poultry_request in poultry_requests: + # if poultry_request.has_wage == False: + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if hatching.left_over >= poultry_request.quantity: + hatching.out_province_killed_weight += int(poultry_request.quantity * poultry_request.Index_weight) + hatching.out_province_killed_quantity += poultry_request.quantity + hatching.save() + else: + different_quantity = poultry_request.quantity - hatching.left_over + hatching.out_province_killed_weight += int(hatching.left_over * poultry_request.Index_weight) + hatching.out_province_killed_quantity += hatching.left_over + hatching.extra_killed_quantity += different_quantity + hatching.save() + url = f'https://rasadyar.net/pay/{base_url_for_sms_report}' + if poultry_request.payer_type == 'poultry': + poultry_request.payment_link = f'{url}/p{poultry_request.poultry.user.user_gate_way_id}{poultry_request.order_code}' + else: + poultry_request.payment_link = f'{url}/b{poultry_request.out_province_poultry_request_buyer.user.user_gate_way_id}' + poultry_request.final_state = 'archive' + poultry_request.province_state = 'accepted' + poultry_request.state_process = 'accepted' + poultry_request.agent = { + "role": None, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.now()) + } + poultry_request.hatching_left_over = poultry_request.hatching.left_over + + poultry_request.save() + + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_201_CREATED) + + +class ImprovingLivestockViewSet(viewsets.ModelViewSet): + queryset = ImprovingLivestock.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ImprovingLivestockSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + # get operator profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + # get operator object + improving_livestock = user.improving_livestock_user.all() + + # send to serializer + serializer = self.serializer_class(improving_livestock[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ReportSubmissionTimeViewset(viewsets.ModelViewSet): + queryset = ReportSubmissionTime.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ReportSubmissionTimeSerializer + + def list(self, request, *args, **kwargs): + report_submission = ReportSubmissionTime.objects.filter(trash=False).first() + serializer = self.serializer_class(report_submission) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + report_submission = ReportSubmissionTime.objects.filter(trash=False).first() + serializer = self.serializer_class(report_submission) + serializer.update(instance=report_submission, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ReportsViewset(viewsets.ModelViewSet): + queryset = Reports.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ReportsSerializer + + def list(self, request, *args, **kwargs): + reports = Reports.objects.filter(trash=False, active=False).order_by('id') + serializer = self.serializer_class(reports, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ReportsUsersViewset(viewsets.ModelViewSet): + queryset = ReportsUsers.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ReportsUsersSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = ReportsUsersFilterSet + filterset_fields = [ + 'firstname', + 'lastname', + 'fullname', + 'mobile', + 'position', + 'city', + + ] + + def create(self, request, *args, **kwargs): + if ReportsUsers.objects.filter(mobile=request.data['mobile']).exists(): + return Response({"result": "این کاربر قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + user = serializer.create(validated_data=request.data) + reports = Reports.objects.filter(active=True, trash=False) + if reports: + for report in reports: + user_report = UserReports( + user=user, + report=report + ) + user_report.save() + report.active = True + report.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + users_list = [] + reports_users = ReportsUsers.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=reports_users + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=reports_users) + users_list = ps.filter() + reports_users = [] if len(users_list) == 0 else users_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(reports_users) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(reports_users, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + reports_user = ReportsUsers.objects.get(key=request.data['user_key'], trash=False) + request.data.pop('user_key') + if 'mobile' in request.data.keys() and request.data['mobile'] != reports_user.mobile: + if ReportsUsers.objects.filter(mobile=request.data['mobile']).exists(): + return Response({"result": "این کاربر قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(reports_user) + serializer.update(instance=reports_user, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class UserReportsViewset(viewsets.ModelViewSet): + queryset = UserReports.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = UserReportsSerializer + + def create(self, request, *args, **kwargs): + reports = Reports.objects.filter(key__in=request.data['reports_list']) + reports_users = ReportsUsers.objects.filter(trash=False).order_by('id') + + for report in reports: + for user in reports_users: + user_report = UserReports( + user=user, + report=report + ) + user_report.save() + report.active = True + report.save() + + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + if 'user_report_key' in request.data.keys(): + user_report = UserReports.objects.get(key=request.data['user_report_key'], trash=False) + request.data.pop('user_report_key') + serializer = self.serializer_class(user_report) + serializer.update(instance=user_report, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + report = Reports.objects.get(key=request.data['report_key'], trash=False) + user_reports = UserReports.objects.filter(report=report) + if not user_reports: + return Response({"result": "گزارشی ثبت نشده"}, status=status.HTTP_403_FORBIDDEN) + for user_report in user_reports: + user_report.active = request.data['active'] + user_report.save() + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +class MovingTextDashboardStatusViewset(viewsets.ModelViewSet): + queryset = MovingTextDashboardStatus.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = MovingTextDashboardStatusSerializer + + def list(self, request, *args, **kwargs): + moving_text_dashboard = MovingTextDashboardStatus.objects.filter(trash=False).first() + serializer = self.serializer_class(moving_text_dashboard) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + moving_text_dashboard = MovingTextDashboardStatus.objects.filter(trash=False).first() + serializer = self.serializer_class(moving_text_dashboard) + serializer.update(instance=moving_text_dashboard, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class MovingTextViewset(viewsets.ModelViewSet): + queryset = MovingText.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = MovingTextSerializer + pagination_class = CustomPagination + + def create(self, request, *args, **kwargs): + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + moving_text = serializer.create(validated_data=request.data) + roles = MovingTextRole.objects.filter(trash=False) + if roles: + for role in roles: + moving_text_with_role = MovingTextWithRole( + moving_text=moving_text, + role=role + ) + moving_text_with_role.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + if 'dashboard' in request.GET: + role = SystemUserProfile.objects.get(user=request.user, trash=False).role.all().values_list('name', + flat=True) + moving_text_id = MovingTextWithRole.objects.filter(trash=False, active=True, + role__role__in=role).values_list('moving_text', + flat=True) + moving_text = MovingText.objects.filter(id__in=moving_text_id, trash=False).order_by('id') + serializer = MovingTextForDashboardSerializer(moving_text, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + else: + moving_text = MovingText.objects.filter(trash=False).order_by('id') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(moving_text) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(moving_text, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + moving_text = MovingText.objects.get(trash=False, key=request.data['moving_text_key']) + request.data.pop('moving_text_key') + serializer = self.serializer_class(moving_text) + serializer.update(instance=moving_text, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class MovingTextWithRoleViewset(viewsets.ModelViewSet): + queryset = MovingTextWithRole.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = MovingTextWithRoleSerializer + + def update(self, request, pk=None, *args, **kwargs): + moving_text_role = MovingTextWithRole.objects.get(trash=False, key=request.data['moving_text_role_key']) + request.data.pop('moving_text_role_key') + serializer = self.serializer_class(moving_text_role) + serializer.update(instance=moving_text_role, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class NewProductViewset(viewsets.ModelViewSet): + queryset = NewProduct.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = NewProductSerializer + + def create(self, request, *args, **kwargs): + parent = None + if 'parent_key' in request.data.keys(): + if request.data['parent_key'] is not None: + parent = NewProduct.objects.get(key=request.data['parent_key']) + request.data.pop('parent_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + product = serializer.create(validated_data=request.data) + if parent is not None: + product.parent = parent + product.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + products = NewProduct.objects.filter(trash=False) + serializer = self.serializer_class(products, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class RolesProductsViewset(viewsets.ModelViewSet): + queryset = RolesProducts.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = RolesProductsSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + + elif request.GET['role'] in ['Guild', 'Steward']: + products = RolesProducts.objects.filter(guild__user=user, guild__active=True, trash=False) + + else: + products = RolesProducts.objects.filter(trash=False) + serializer = self.serializer_class(products, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosRolesProductsViewset(viewsets.ModelViewSet): + queryset = RolesProducts.objects.all() + permission_classes = [AllowAny] + serializer_class = PosRolesProductsSerializer + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + if pos.kill_house: + products = RolesProducts.objects.filter(kill_house=pos.kill_house, trash=False) + else: + products = RolesProducts.objects.filter(guild=pos.guild, trash=False) + + serializer = self.serializer_class(products, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + request.data.pop('product_key') + serializer = self.serializer_class(product) + serializer.update(instance=product, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosPosOtherProductsViewset(viewsets.ModelViewSet): + queryset = OtherProducts.objects.all() + permission_classes = [AllowAny] + serializer_class = PosOtherProductsSerializer + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + if pos.kill_house: + products = OtherProducts.objects.filter(kill_house=pos.kill_house, trash=False) + else: + products = OtherProducts.objects.filter(guild=pos.guild, trash=False) + + serializer = self.serializer_class(products, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + image = None + kill_house = None + guild = None + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + if 'image' in request.data.keys(): + image = request.data['image'] + request.data.pop('image') + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + if pos.kill_house: + kill_house = KillHouse.objects.get(key=pos.kill_house.key, trash=False) + else: + guild = Guilds.objects.get(key=pos.guild.key, trash=False) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + product = serializer.create(validated_data=request.data) + if image: + product.image = send_image_to_server(image) + if kill_house: + product.kill_house = kill_house + else: + product.guild = guild + + product.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + image = None + try: + product = OtherProducts.objects.get(trash=False, key=request.data['product_key']) + request.data.pop('product_key') + except: + return Response({"result": "محصول مورد نظر یافت نشد!"}, status=status.HTTP_200_OK) + + if 'image' in request.data.keys(): + image = request.data['image'] + request.data.pop('image') + product.image = send_image_to_server(image) + serializer = self.serializer_class(product) + serializer.update(instance=product, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + product = OtherProducts.objects.get(trash=False, key=request.GET["product_key"]) + product.trash = True + product.save() + return Response({"result": "با موفقیت حذف شد."}, status=status.HTTP_200_OK) + + +class CombinedPosProductsViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = CombinedPosProductSerializer + + def get_queryset(self, pos_id, version): + pos = POSMachine.objects.get(pos_id=pos_id, trash=False) + if pos.kill_house: + roles_products = RolesProducts.objects.filter(kill_house=pos.kill_house, trash=False) + other_products = OtherProducts.objects.filter(kill_house=pos.kill_house, trash=False) + elif pos.guild: + roles_products = RolesProducts.objects.filter(guild=pos.guild, trash=False) + other_products = OtherProducts.objects.filter(guild=pos.guild, trash=False) + else: + if int(version) <= 217: + live_stock_products = LiveStockRolseProduct.objects.filter(cooperative=pos.cooperative, + parent_product__name='سبوس', trash=False) + else: + live_stock_products = LiveStockRolseProduct.objects.filter(cooperative=pos.cooperative, trash=False) + return list(live_stock_products) + + return list(roles_products) + list(other_products) + + def list(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + version = request.headers.get('device-version') + queryset = self.get_queryset(validation_device, version) + serializer = self.get_serializer(queryset, many=True, context={'validation_device': validation_device}) + return Response(serializer.data, status=status.HTTP_200_OK) +class NewCombinedPosProductsViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = NewCombinedPosProductSerializer + + def get_queryset(self, pos, version,role): + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=pos.owner).first() + roles_products = RolesProducts.objects.filter(kill_house=kill_house, trash=False) + other_products = OtherProducts.objects.filter(kill_house=kill_house, trash=False) + + elif role == 'Steward': + steward = Steward.objects.filter(user=pos.owner).first() + roles_products = RolesProducts.objects.filter(steward=steward, trash=False) + other_products = OtherProducts.objects.filter(steward=steward, trash=False) + elif role == 'Guilds': + guild = Guilds.objects.filter(user=pos.owner).first() + roles_products = RolesProducts.objects.filter(guild=guild, trash=False) + other_products = OtherProducts.objects.filter(guild=guild, trash=False) + else: + if int(version) <= 217: + live_stock_products = LiveStockRolseProduct.objects.filter(cooperative=pos.cooperative, + parent_product__name='سبوس', trash=False) + else: + live_stock_products = LiveStockRolseProduct.objects.filter(cooperative=pos.cooperative, trash=False) + return list(live_stock_products) + + return list(roles_products) + list(other_products) + + def list(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_pos() + version = request.headers.get('device-version') + role = request.headers.get('device-role') + queryset = self.get_queryset(validation_device, version,role) + serializer = self.get_serializer(queryset, many=True, context={'validation_device': validation_device}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class AdminXViewSet(viewsets.ModelViewSet): + queryset = AdminX.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AdminXSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + super_admin = user.admin_x_user.all() + + serializer = self.serializer_class(super_admin[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class SupporterViewSet(viewsets.ModelViewSet): + queryset = Supporter.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SupporterSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + super_admin = SystemUserProfile.objects.get(user=request.user, trash=False).supporter_user.first() + + serializer = self.serializer_class(super_admin) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ZarinPalAccountsViewset(viewsets.ModelViewSet): + queryset = ZarinPalAccounts.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ZarinPalAccountsSerializer + + def list(self, request, *args, **kwargs): + zarinpal_accounts = ZarinPalAccounts.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(zarinpal_accounts, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + zarinpal_account = ZarinPalAccounts.objects.get(trash=False, key=request.data['account_key']) + request.data.pop('account_key') + serializer = self.serializer_class(zarinpal_account) + serializer.update(instance=zarinpal_account, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryExportViewset(viewsets.ModelViewSet): + queryset = PoultryExport.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryExportSerializer + + def list(self, request, *args, **kwargs): + poultry_export = PoultryExport.objects.filter(trash=False).first() + serializer = self.serializer_class(poultry_export) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + poultry_export = PoultryExport.objects.filter(trash=False).first() + serializer = self.serializer_class(poultry_export) + serializer.update(instance=poultry_export, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryOutProvinceRequestViewset(viewsets.ModelViewSet): + queryset = PoultryOutProvinceRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryOutProvinceRequestSerializer + + def list(self, request, *args, **kwargs): + poultry_out_province = PoultryOutProvinceRequest.objects.filter(trash=False).first() + serializer = self.serializer_class(poultry_out_province) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + poultry_out_province = PoultryOutProvinceRequest.objects.filter(trash=False).first() + serializer = self.serializer_class(poultry_out_province) + serializer.update(instance=poultry_out_province, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +def pos_machine_to_dict(pos): + return { + "pos_id": pos.pos_id, + "receiver_number": pos.receiver_number, + "terminal_number": pos.terminal_number, + "Lat": pos.Lat, + "Long": pos.Long, + "pos-company": pos.pos_company.en_name, + } + + +def get_pos_details(pos_machines): + return [pos_machine_to_dict(pos) for pos in pos_machines] + + +def get_role_user_details(role_type, user, name, pos_details): + return { + "type": role_type, + "user-key": user.user_gate_way_id, + "fullname": user.fullname, + "firstname": user.first_name, + "lastname": user.last_name, + "mobile": user.mobile, + "name": name, + "pos-list": pos_details, + } + + +@api_view(['GET']) +@permission_classes([AllowAny]) +def Rolesusers(request): + pos_id = request.query_params.get('pos_id') + role_type = request.query_params.get('type', 'all').lower() + user_key = request.query_params.get('user_key') + + pos_machines = POSMachine.objects.filter(trash=False).select_related('pos_company') + + # If pos_id is provided + if pos_id: + try: + pos_machine = POSMachine.objects.filter(pos_id=pos_id) \ + .select_related('pos_company', 'kill_house', 'guild', 'steward', 'dispenser') \ + .get() + except POSMachine.DoesNotExist: + return Response({"message": "POSMachine not found"}, status=404) + + pos_details = pos_machine_to_dict(pos_machine) + if pos_machine.kill_house: + owner = pos_machine.kill_house.kill_house_operator.user + type_match = "kill-house" + name = pos_machine.kill_house.name + elif pos_machine.guild: + owner = pos_machine.guild.user + type_match = "guilds" + name = pos_machine.guild.guilds_name + elif pos_machine.dispenser: + owner = pos_machine.dispenser.user + type_match = "dispenser" + name = pos_machine.dispenser.user.fullname + elif pos_machine.steward: + owner = pos_machine.steward + type_match = "steward" + name = pos_machine.steward.fullname + else: + return Response({"message": "POSMachine has no related owner"}, status=404) + + if user_key and owner.user_gate_way_id != user_key: + return Response({"message": "User does not match POSMachine owner"}, status=404) + + if role_type != 'all' and role_type != type_match: + return Response({"message": "Type does not match"}, status=404) + + return Response(get_role_user_details(type_match, owner, name, [pos_details])) + + # If no pos_id, handle filtering by type and user_key + kill_house_filters = {} + filters = {} + if user_key: + try: + user_profile = SystemUserProfile.objects.get(user_gate_way_id=user_key) + kill_house_filters['kill_house_operator__user'] = user_profile + filters['user'] = user_profile + except SystemUserProfile.DoesNotExist: + return Response({"message": "User not found"}, status=404) + + roles_users_list = [] + + if role_type in ['all', 'kill-house']: + kill_houses = KillHouse.objects.filter( + out_province=False, trash=False, **kill_house_filters + ).select_related('kill_house_operator__user') \ + .prefetch_related(Prefetch('kill_house_pos', queryset=pos_machines)) \ + .only('kill_house_operator__user__fullname', 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name', 'kill_house_operator__user__mobile', 'name') + + for kh in kill_houses: + if role_type in ['all', 'kill-house']: + roles_users_list.append( + get_role_user_details("KillHouse", kh.kill_house_operator.user, kh.name, + get_pos_details(kh.kill_house_pos.all())) + ) + + if role_type in ['all', 'guilds', 'steward']: + guilds_stewards = Guilds.objects.filter( + trash=False, **filters + ).select_related('user') \ + .prefetch_related(Prefetch('guild_pos', queryset=pos_machines)) \ + .only('user__fullname', 'user__first_name', 'user__last_name', 'user__mobile', 'guilds_name') + + for gs in guilds_stewards: + if role_type in ['all', 'guilds']: + roles_users_list.append( + get_role_user_details("Guilds", gs.user, gs.guilds_name, get_pos_details(gs.guild_pos.all())) + ) + + if role_type in ['all', 'dispenser']: + dispensers = Dispenser.objects.filter( + trash=False, **filters + ).select_related('user') \ + .prefetch_related(Prefetch('dispenser_pos', queryset=pos_machines)) \ + .only('user__fullname', 'user__first_name', 'user__last_name', 'user__mobile') + + for disp in dispensers: + if role_type in ['all', 'dispenser']: + roles_users_list.append( + get_role_user_details("Dispenser", disp.user, disp.user.fullname, + get_pos_details(disp.dispenser_pos.all())) + ) + + if not roles_users_list: + return Response({"message": "Not found"}, status=404) + + return Response(roles_users_list) + + +class VetFarmAggregatePermissionViewset(viewsets.ModelViewSet): + queryset = VetFarmAggregatePermission.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetFarmAggregatePermissionSerializer + + def list(self, request, *args, **kwargs): + aggregate_permission = VetFarmAggregatePermission.objects.filter(trash=False).first() + serializer = self.serializer_class(aggregate_permission) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + aggregate_permission = VetFarmAggregatePermission.objects.filter(trash=False).first() + serializer = self.serializer_class(aggregate_permission) + serializer.update(instance=aggregate_permission, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseBarLimitationViewset(viewsets.ModelViewSet): + queryset = KillHouseBarLimitation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseBarLimitationSerializer + + def list(self, request, *args, **kwargs): + bar_limitation = KillHouseBarLimitation.objects.filter(trash=False).first() + serializer = self.serializer_class(bar_limitation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + bar_limitation = KillHouseBarLimitation.objects.filter(trash=False).first() + serializer = self.serializer_class(bar_limitation) + serializer.update(instance=bar_limitation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHouseDistributionManagementStewardGuildViewset(viewsets.ModelViewSet): + queryset = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHouseDistributionManagementStewardGuildSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = KillHouseFilterSet + filterset_fields = [ + 'name', + 'kill_house_operator__user__fullname', + 'kill_house_operator__user__first_name', + 'kill_house_operator__user__last_name', + 'kill_house_operator__user__mobile', + + ] + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + if role in ('CityOperator', 'CityJahad', 'CityCommerce', 'CitySupervisor', 'CityGuild'): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_houses = KillHouse.objects.filter(address__city=user.city, trash=False, out_province=False).order_by( + 'id') + else: + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + kill_house_list = [] + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=kill_houses + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=kill_houses) + kill_house_list = ps.filter() + kill_houses = [] if len(kill_house_list) == 0 else kill_house_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_houses) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(kill_houses, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardDistributionManagementGuildViewset(viewsets.ModelViewSet): + queryset = Guilds.objects.filter(trash=False, steward=True).order_by('id') + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardDistributionManagementGuildSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsFilterSet + + def list(self, request, *args, **kwargs): + stewards = Guilds.objects.filter(trash=False, steward=True).order_by('id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + stewards = stewards.filter( + self.build_query(value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(stewards.distinct()) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = GuildsSerializer(stewards.distinct(), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def build_query(self, value): + from django.db.models import Q + query = Q() + for field in self.filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query + + +class OutOfProvinceSellingCarcassesPermissionViewset(viewsets.ModelViewSet): + queryset = OutOfProvinceSellingCarcassesPermission.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = OutOfProvinceSellingCarcassesPermissionSerializer + + def list(self, request, *args, **kwargs): + permission = OutOfProvinceSellingCarcassesPermission.objects.filter(trash=False).first() + serializer = self.serializer_class(permission) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + permission = OutOfProvinceSellingCarcassesPermission.objects.filter(trash=False).first() + serializer = self.serializer_class(permission) + serializer.update(instance=permission, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class BaseOutProvinceCarcassesBuyerViewSet(viewsets.ModelViewSet): + queryset = BaseOutProvinceCarcassesBuyer.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = BaseOutProvinceCarcassesBuyerSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = BaseOutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + 'city', + 'province', + + ] + + def list(self, request, *args, **kwargs): + buyer_list = [] + if 'state' in request.GET: + buyers = BaseOutProvinceCarcassesBuyer.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=buyers + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=buyers) + buyer_list = ps.filter() + buyers = [] if len(buyer_list) == 0 else buyer_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(buyers) + if page is not None: + serializer = BaseOutProvinceCarcassesBuyerFordispensersSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + elif 'mobile' in request.GET: + buyer = BaseOutProvinceCarcassesBuyer.objects.filter(mobile=request.GET['mobile'], trash=False) + if buyer: + serializer = self.get_serializer(buyer.first()) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + return Response({"result": "خریداری یافت نشد!"}, status=status.HTTP_404_NOT_FOUND) + + + else: + buyers = BaseOutProvinceCarcassesBuyer.objects.filter(active=True, trash=False).order_by('id') + serializer = self.get_serializer(buyers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class OutProvinceCarcassesBuyerViewSet(viewsets.ModelViewSet): + LEGAL_DOCUMENT_ENDPOINT = "https://pay.rasadyar.net/national-documents" + + queryset = OutProvinceCarcassesBuyer.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = OutProvinceCarcassesBuyerrSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + + def _fetch_legal_person_payload(self, info_value: str): + info_value = info_value or self.request.data.get('info_value') + if not info_value: + return None + try: + response = requests.get( + self.LEGAL_DOCUMENT_ENDPOINT, + params={'info': info_value, 'type': 'unit'}, + ) + if response.status_code == 200: + return response.json() + except: + return None + + def _normalize_branch_list(self, value): + if value in (None, ''): + return value + if isinstance(value, str): + return value + try: + return json.dumps(value, ensure_ascii=False) + except (TypeError, ValueError): + return str(value) + + def _apply_legal_person_payload(self, base_buyer, payload, is_real_person): + base_buyer.isRealPerson = is_real_person + if not payload: + return None + base_buyer.status = payload.get('status', False) + base_buyer.statusCode = payload.get('statusCode') + base_buyer.apiLogId = payload.get('apiLogId') + + data = payload.get('data') or {} + base_buyer.legalPersonInfoDtoId = data.get('legalPersonInfoDtoId') + base_buyer.parentLegalPersonId = data.get('parentLegalPersonId') + base_buyer.successful = data.get('successful', False) + base_buyer.message = data.get('message') + base_buyer.name = data.get('name') + base_buyer.nationalCode = data.get('nationalCode') + base_buyer.postCode = data.get('postCode') + base_buyer.address = data.get('address') + base_buyer.legalPersonType = data.get('legalPersonType') + base_buyer.registerNumber = data.get('registerNumber') + base_buyer.registerUnit = data.get('registerUnit') + base_buyer.registerDate = data.get('registerDate') + base_buyer.registerDateUnix = data.get('registerDateUnix') + base_buyer.residency = data.get('residency') + base_buyer.state = data.get('state') + base_buyer.isSettle = data.get('isSettle', False) + base_buyer.settleDate = data.get('settleDate') + base_buyer.isBreakUp = data.get('isBreakUp', False) + base_buyer.breakUpdate = data.get('breakUpdate') + base_buyer.isBranch = data.get('isBranch', False) + base_buyer.branchList = self._normalize_branch_list(data.get('branchList')) + base_buyer.establishmentDate = data.get('establishmentDate') + base_buyer.isDbResult = data.get('isDbResult', False) + base_buyer.serviceType = data.get('serviceType') + + parent = data.get('parentLegalPerson') or {} + base_buyer.parentLegalPersonInfoDtoId = parent.get('legalPersonInfoDtoId') + base_buyer.parentLegalPersonParentId = parent.get('parentLegalPersonId') + base_buyer.parentLegalPersonSuccessful = parent.get('successful', False) + base_buyer.parentLegalPersonMessage = parent.get('message') + base_buyer.parentLegalPersonName = parent.get('name') + base_buyer.parentLegalPersonNationalCode = parent.get('nationalCode') + base_buyer.parentLegalPersonPostCode = parent.get('postCode') + base_buyer.parentLegalPersonAddress = parent.get('address') + base_buyer.parentLegalPersonType = parent.get('legalPersonType') + base_buyer.parentLegalPersonRegisterNumber = parent.get('registerNumber') + base_buyer.parentLegalPersonRegisterUnit = parent.get('registerUnit') + base_buyer.parentLegalPersonRegisterDate = parent.get('registerDate') + base_buyer.parentLegalPersonRegisterDateUnix = parent.get('registerDateUnix') + base_buyer.parentLegalPersonResidency = parent.get('residency') + base_buyer.parentLegalPersonState = parent.get('state') + base_buyer.parentLegalPersonIsSettle = parent.get('isSettle', False) + base_buyer.parentLegalPersonSettleDate = parent.get('settleDate') + base_buyer.parentLegalPersonIsBreakUp = parent.get('isBreakUp', False) + base_buyer.parentLegalPersonBreakUpdate = parent.get('breakUpdate') + base_buyer.parentLegalPersonIsBranch = parent.get('isBranch', False) + base_buyer.parentLegalPersonBranchList = self._normalize_branch_list(parent.get('branchList')) + base_buyer.parentLegalPersonEstablishmentDate = parent.get('establishmentDate') + base_buyer.parentLegalPersonIsDbResult = parent.get('isDbResult', False) + base_buyer.parentLegalPersonServiceType = parent.get('serviceType') + + def create(self, request, *args, **kwargs): + role = request.data.pop('role', None) + operator_user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.data.get('info_value'): + if BaseOutProvinceCarcassesBuyer.objects.filter(trash=False, + nationalCode=request.data.get('info_value')).exists(): + return Response({"result": "کاربر وجود دارد! "}, status=status.HTTP_403_FORBIDDEN) + if role: + steward = Guilds.objects.get(user=operator_user, active=True, trash=False) + + + else: + kill_house = KillHouse.objects.filter(kill_house_operator__user=operator_user, trash=False).first() + + if SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).exists(): + system_profile = SystemUserProfile.objects.get(mobile=request.data['mobile'], trash=False) + else: + password = "123456" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code in (200, 400): + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=operator_user.city, + province=operator_user.province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است! "}, status=status.HTTP_403_FORBIDDEN) + + base_buyer = BaseOutProvinceCarcassesBuyer.objects.filter(trash=False, user=system_profile) + if base_buyer: + base_buyer = base_buyer.first() + else: + base_buyer = BaseOutProvinceCarcassesBuyer( + user=system_profile, + ) + base_buyer.first_name = request.data['first_name'] + base_buyer.last_name = request.data['last_name'] + base_buyer.mobile = request.data['mobile'] + base_buyer.unit_name = request.data['unit_name'] + base_buyer.city = request.data['city'] + base_buyer.province = request.data['province'] + base_buyer.national_id = request.data['national_id'] + + if 'isRealPerson' in request.data: + is_real_person_value = request.data.get('isRealPerson') + if isinstance(is_real_person_value, bool): + is_real_person = is_real_person_value + else: + is_real_person = str(is_real_person_value).strip().lower() in ( + 'true', '1', 'yes', 'y', 'on', 'real', 'حقیقی' + ) + legal_info_value = ( + request.data.get('info_value') + or request.data.get('legalNationalCode') + or request.data.get('legal_national_code') + or request.data.get('national_id') + ) + legal_payload = self._fetch_legal_person_payload(legal_info_value) + self._apply_legal_person_payload(base_buyer, legal_payload, is_real_person) + base_buyer.save() + if role: + if OutProvinceCarcassesBuyer.objects.filter(buyer=base_buyer, steward=steward).exists(): + return Response({"result": "خریدار قبلا برای مباشر ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + else: + if OutProvinceCarcassesBuyer.objects.filter(buyer=base_buyer, Kill_house=kill_house).exists(): + return Response({"result": "خریدار قبلا برای کشتارگاه ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + if 'info_value' in request.data: + request.data.pop('info_value') + if 'isRealPerson' in request.data: + request.data.pop('isRealPerson') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + buyer = serializer.create(validated_data=request.data) + if role: + buyer.steward = steward + + else: + buyer.Kill_house = kill_house + + buyer.buyer = base_buyer + buyer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + buyer_list = [] + if 'state' in request.GET: + if request.GET['role'] == "KillHouse": + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=kill_house, trash=False).order_by('id') + + elif request.GET['role'] == "Steward": + steward = Guilds.objects.get(user=user, active=True, trash=False) + + buyers = OutProvinceCarcassesBuyer.objects.filter(steward=steward, trash=False).order_by('id') + else: + buyers = OutProvinceCarcassesBuyer.objects.filter(trash=False).order_by('id') + + buyer_type = request.GET.get('type') + if buyer_type: + buyer_type = str(buyer_type).strip().lower() + if buyer_type == 'real': + buyers = buyers.filter(buyer__isRealPerson=True) + elif buyer_type == 'legal': + buyers = buyers.filter(buyer__isRealPerson=False) + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=buyers + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=buyers) + buyer_list = ps.filter() + buyers = [] if len(buyer_list) == 0 else buyer_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(buyers) + if page is not None: + serializer = OutProvinceCarcassesBuyerForBuyerRequestSerializer(page, many=True, + context={'request': request}) + return self.get_paginated_response(serializer.data) + else: + if request.GET['role'] == "KillHouse": + + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house__kill_house_operator__user=user, + active=True, trash=False).order_by('id') + elif request.GET['role'] == "Steward": + + buyers = OutProvinceCarcassesBuyer.objects.filter(steward__user=user, + active=True, trash=False).order_by('id') + else: + buyers = OutProvinceCarcassesBuyer.objects.filter(active=True, trash=False).order_by('id') + + buyer_type = request.GET.get('type') + if buyer_type: + buyer_type = str(buyer_type).strip().lower() + if buyer_type == 'real': + buyers = buyers.filter(buyer__isRealPerson=True) + elif buyer_type == 'legal': + buyers = buyers.filter(buyer__isRealPerson=False) + + serializer = OutProvinceCarcassesBuyerForChoosingBuyerSerializer(buyers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + buyer = OutProvinceCarcassesBuyer.objects.get(key=request.data['buyer_key'], trash=False) + + if 'mobile' in request.data.keys(): + base_buyer = buyer.buyer + system_user_profile = base_buyer.user if base_buyer else None + + if system_user_profile: + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exclude( + id=system_user_profile.id).exists(): + return Response( + {"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN + ) + + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + buyer.mobile = second_mobile_number + buyer.save() + if base_buyer: + base_buyer.mobile = second_mobile_number + base_buyer.save() + + request.data.pop('mobile') + + request.data.pop('buyer_key') + serializer = self.serializer_class(buyer) + serializer.update(instance=buyer, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + buyer = OutProvinceCarcassesBuyer.objects.get(key=request.GET["buyer_key"], trash=False) + buyer.trash = True + buyer.save() + return Response({"result": "با موفقیت حذف شد."}, status=status.HTTP_200_OK) + + +class PosOutProvinceCarcassesBuyerViewSet(viewsets.ModelViewSet): + queryset = OutProvinceCarcassesBuyer.objects.all() + permission_classes = [AllowAny] + serializer_class = OutProvinceCarcassesBuyerrSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = OutProvinceCarcassesBuyerFilterSet + filterset_fields = [ + 'mobile', + 'first_name', + 'last_name', + 'fullname', + 'unit_name', + + ] + + def list(self, request, *args, **kwargs): + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + buyers = OutProvinceCarcassesBuyer.objects.filter(Kill_house=pos.kill_house, + active=True, trash=False).order_by('id') + serializer = OutProvinceCarcassesBuyerForChoosingBuyerSerializer(buyers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProductPricingTypeViewset(viewsets.ModelViewSet): + queryset = ProductPricingType.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProductPricingTypeSerializer + + def list(self, request, *args, **kwargs): + pricing_type = ProductPricingType.objects.filter(trash=False).first() + serializer = self.serializer_class(pricing_type) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + pricing_type = ProductPricingType.objects.filter(trash=False).first() + serializer = self.serializer_class(pricing_type) + serializer.update(instance=pricing_type, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class KillHousePricePermissionViewset(viewsets.ModelViewSet): + queryset = KillHousePricePermission.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = KillHousePricePermissionSerializer + + def list(self, request, *args, **kwargs): + kill_house_permission = KillHousePricePermission.objects.filter(trash=False).first() + serializer = self.serializer_class(kill_house_permission) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + kill_house_permission = KillHousePricePermission.objects.filter(trash=False).first() + serializer = self.serializer_class(kill_house_permission) + serializer.update(instance=kill_house_permission, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class AutomaticDirectBuyingPermissionViewSet(viewsets.ModelViewSet): + queryset = AutomaticDirectBuyingPermission.objects.all() + permission_classes = [AllowAny] + serializer_class = AutomaticDirectBuyingPermissionSerializer + + def list(self, request, *args, **kwargs): + query = self.queryset.first() + ser_data = self.serializer_class(query) + return Response(ser_data.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + query = self.queryset.first() + ser_data = self.serializer_class(query) + ser_data.update(instance=query, validated_data=request.data) + return Response(ser_data.data, status=status.HTTP_200_OK) + + +class PosMachineTransactionViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + permission_classes = [AllowAny] + serializer_class = PosMachineTransactionsSerializer + + def create(self, request, *args, **kwargs): + # timestamp_date = request.data['timestamp_date'] + # transaction_date = datetime.fromtimestamp(timestamp_date) + try: + product = RolesProducts.objects.get(key=request.data['product_key']) + except: + return Response({"result": "محصول موجود نمی باشد!"}, status=status.HTTP_403_FORBIDDEN) + pos = POSMachine.objects.get(pos_id=request.data['pos-id']) + # request.data.pop('timestamp_date') + request.data.pop('product_key') + request.data.pop('pos-id') + + try: + pos_transaction = PosMachineTransactions.objects.get(check_id=request.data['check_id']) + serializer = self.serializer_class(pos_transaction) + serializer.update(instance=pos_transaction, validated_data=request.data) + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + return Response(serializer.data, status=status.HTTP_200_OK) + + + except: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_transaction = serializer.create(validated_data=request.data) + # pos_transaction.date = transaction_date + pos_transaction.product = product + pos_transaction.pos = pos + pos_transaction.save() + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def update(self, request, *args, **kwargs): + # timestamp_date = request.data['timestamp_date'] + # transaction_date = datetime.fromtimestamp(timestamp_date) + + try: + product = RolesProducts.objects.get(key=request.data['product_key']) + except: + return Response({"result": "محصول موجود نمی باشد!"}, status=status.HTTP_403_FORBIDDEN) + + pos = POSMachine.objects.get(pos_id=request.data['pos-id']) + # request.data.pop('timestamp_date') + request.data.pop('product_key') + request.data.pop('pos-id') + + try: + pos_transaction = PosMachineTransactions.objects.get(check_id=request.data['check_id']) + serializer = self.serializer_class(pos_transaction) + serializer.update(instance=pos_transaction, validated_data=request.data) + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + return Response(serializer.data, status=status.HTTP_200_OK) + + + except: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_transaction = serializer.create(validated_data=request.data) + # pos_transaction.date = transaction_date + pos_transaction.product = product + pos_transaction.pos = pos + pos_transaction.save() + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class NewPosMachineTransactionViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + permission_classes = [AllowAny] + serializer_class = PosMachineTransactionsSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'mobile', + 'natcode', + 'fullname', + ] + + def create(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + try: + pos_transaction = PosMachineTransactions.objects.filter(check_id=request.data['check_id']).first() + if pos_transaction: + paid = pos_transaction.paid + request.data.pop('products') + + serializer = self.serializer_class(pos_transaction) + serializer.update(instance=pos_transaction, validated_data=request.data) + if not paid and pos_transaction.paid: + + if not pos_transaction.live_stock: + + product_transaction = ProductsTransactions.objects.filter(transaction=pos_transaction, + trash=False, + product__isnull=False).first() + if product_transaction: + pos_allocation_weight_for_product(product_transaction.product) + else: + product_transaction = ProductsTransactions.objects.filter(transaction=pos_transaction, + trash=False, + live_stack_products__isnull=False).first() + if product_transaction: + cooperative_warehousing(product_transaction.live_stack_products) + rancher_warehousing(pos_transaction) + + else: + products = request.data['products'] + request.data.pop('products') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_transaction = serializer.create(validated_data=request.data) + pos_transaction.pos = pos + if pos.kill_house: + pos_transaction.kill_house = pos.kill_house + elif pos.guild: + pos_transaction.guild = pos.guild + pos_transaction.date = datetime.now() + pos_transaction.save() + for product in products: + product_transaction = ProductsTransactions( + transaction=pos_transaction, + cur_price=product['cur_price'], + cur_weight=product['cur_qty'], + price=product['price'], + name=product['name'], + image=product['image'], + unit=product['unit'], + targetunit=product['targetunit'], + price_approved=product['price_approved'], + ) + if product['product_type'] == 'roles_product': + roles_product = RolesProducts.objects.get(key=product['key']) + product_transaction.product = roles_product + elif product['product_type'] == 'other_product': + other_product = OtherProducts.objects.get(key=product['key']) + product_transaction.other_product = other_product + elif product['product_type'] == 'stock_product': + pos_transaction.live_stock = True + pos_transaction.save() + live_stock_product = LiveStockRolseProduct.objects.get(key=product['key']) + product_transaction.live_stack_products = live_stock_product + product_transaction.save() + if pos_transaction.paid: + if pos_transaction.live_stock == False: + product_transaction = ProductsTransactions.objects.filter(transaction=pos_transaction, + trash=False, + product__isnull=False).first() + if product_transaction: + pos_allocation_weight_for_product(product_transaction.product) + else: + product_transaction = ProductsTransactions.objects.filter(transaction=pos_transaction, + trash=False, + live_stack_products__isnull=False).first() + if product_transaction: + cooperative_warehousing(product_transaction.live_stack_products) + rancher_warehousing(pos_transaction) + + chat_ids = list( + User_Bale.objects.filter(trash=False, super_admin=True).values_list('chat_id', + flat=True).distinct()) + if pos_transaction.pos: + chat_id_list = chat_ids + list( + User_Bale.objects.filter(rasadyar_user=pos_transaction.pos.user, trash=False).values_list( + 'chat_id', + flat=True).distinct()) + else: + chat_id_list = [] + send_transaction(pos_transaction, chat_id_list) + return Response(serializer.data, status=status.HTTP_200_OK) + except Exception as e: + error_message = str(e) + error_title = e.__class__.__name__ + error_traceback = traceback.format_exc() + print(error_message) + print(error_title) + print(error_traceback) + + return Response( + { + "result": "خطای سرور داخلی رخ داده است. لطفا بعدا تلاش کنید.", + "error_message": error_message, + "error_title": error_title, + "error_traceback": error_traceback, + }, + status=status.HTTP_500_INTERNAL_SERVER_ERROR + ) + + def update(self, request, *args, **kwargs): + # timestamp_date = request.data['timestamp_date'] + # transaction_date = datetime.fromtimestamp(timestamp_date) + + try: + product = RolesProducts.objects.get(key=request.data['product_key']) + except: + return Response({"result": "محصول موجود نمی باشد!"}, status=status.HTTP_403_FORBIDDEN) + + pos = POSMachine.objects.get(pos_id=request.data['pos-id']) + # request.data.pop('timestamp_date') + request.data.pop('product_key') + request.data.pop('pos-id') + + try: + pos_transaction = PosMachineTransactions.objects.get(check_id=request.data['check_id']) + serializer = self.serializer_class(pos_transaction) + serializer.update(instance=pos_transaction, validated_data=request.data) + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + return Response(serializer.data, status=status.HTTP_200_OK) + + + except: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_transaction = serializer.create(validated_data=request.data) + # pos_transaction.date = transaction_date + pos_transaction.product = product + pos_transaction.pos = pos + pos_transaction.save() + if pos_transaction.paid: + pos_allocation_weight_for_product(product) + + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + filters = {} + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + price_type = request.GET.get('price_type') + paid = request.GET.get('paid') + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + filters['trash'] = False + filters['pos'] = pos + + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + if price_type: + filters['price_type__in'] = price_type.split(',') + + if paid: + filters['paid'] = True if paid == 'true' else False + + transactions = PosMachineTransactions.objects.filter(**filters).order_by('-date') + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = NewPosMachineTransactionsSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = NewPosMachineTransactionsSerializer(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockTransactionViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PosMachineTransactionsSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'mobile', + 'natcode', + 'fullname', + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + state = request.GET.get('state') + filters = {} + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + "sheep_concentrate": "کنسانتره گوسفندی", + "high_cow_concentrate": "کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate": "کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate": "کنسانتره گوساله پرواری", + } + product = products[request.GET.get('name')] + if state: + if state == 'paid': + filters['paid'] = True + elif state == 'unpaid': + filters['paid'] = False + else: + pass + + cooperative_key = request.GET.get('cooperative_key') + if role in ('LiveStockProvinceJahad', 'Union'): + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + + else: + transactions = PosMachineTransactions.objects.filter(trash=False, live_stock=True).order_by('-date') + + + elif cooperative_key: + cooperative = Cooperative.objects.get(key=cooperative_key) + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + else: + + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).order_by('-date') + + + + else: + cooperative = Cooperative.objects.get(user=user) + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).order_by('-date') + + else: + + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).order_by('-date') + + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + transactions = transactions.filter(**filters).order_by('-date') + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = PosMachineTransactionsForLiveStockSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = PosMachineTransactionsForLiveStockSerializer(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class LiveStockTransactionDashboeardViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + serializer_class = PosMachineTransactionsSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'mobile', + 'natcode', + 'fullname', + ] + + def list(self, request, *args, **kwargs): + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + state = request.GET.get('state') + filters = {} + if state: + if state == 'paid': + filters['paid'] = True + elif state == 'unpaid': + filters['paid'] = False + else: + pass + + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + "sheep_concentrate": "کنسانتره گوسفندی", + "high_cow_concentrate": "کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate": "کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate": "کنسانتره گوساله پرواری", + } + product = products[request.GET.get('name')] + + cooperative_key = request.GET.get('cooperative_key') + if role in ('LiveStockProvinceJahad', 'Union'): + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + + + else: + + transactions = PosMachineTransactions.objects.filter(trash=False, paid=True, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + + + elif cooperative_key: + cooperative = Cooperative.objects.get(key=cooperative_key) + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + + else: + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + + + + else: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + cooperative = Cooperative.objects.get(user=user) + + if product: + product_transactions = ProductsTransactions.objects.filter( + live_stack_products__parent_product__name=product, live_stack_products__cooperative=cooperative, + trash=False).values_list('transaction__id', + flat=True) + transactions = PosMachineTransactions.objects.filter(id__in=product_transactions, trash=False, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + else: + transactions = PosMachineTransactions.objects.filter(pos__cooperative=cooperative, trash=False, + live_stock=True).prefetch_related( + 'transaction_products_transactions').only('id', 'additional', 'date').order_by('-date') + + if date1 and date2: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + transactions = transactions.filter(**filters).order_by('-date') + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + + weights_by_transaction = defaultdict(int) + product_weights = ProductsTransactions.objects.filter( + trash=False, + live_stack_products__isnull=False, + transaction__in=transactions + ).values( + 'transaction_id' + ).annotate( + total_weight=Sum('cur_weight') + ) + + for item in product_weights: + weights_by_transaction[item['transaction_id']] = item['total_weight'] or 0 + + price = transactions.aggregate(total=Sum('price'))[ + 'total'] or 0 + total_cooperative_price = 0 + total_union_price = 0 + total_company_price = 0 + cur_heavy = 0 + cur_light = 0 + weight = 0 + for transaction in transactions: + total_weight = weights_by_transaction.get(transaction.id, 0) + additional_data = json.loads(transaction.additional) + for share in additional_data.get('shares', []): + share_price = int(share.get('price', 0)) + if share.get('name') == 'union': + total_union_price += share_price * total_weight + else: + total_company_price += share_price * total_weight + total_cooperative_price += additional_data.get('cooperative_price', 0) + cur_heavy += additional_data.get('cur_heavy', 0) + cur_light += additional_data.get('cur_light', 0) + weight += total_weight + + dict_result = { + 'lenTransaction': len(transactions), + 'price': price, + 'totalCooperativePrice': total_cooperative_price, + 'totalUnionPrice': total_union_price, + 'totalCompanyPrice': total_company_price, + 'curHeavy': cur_heavy, + 'curLight': cur_light, + 'curWeight': weight, + } + + return Response(dict_result, status=status.HTTP_200_OK) + + +class PosAllocationTransactionsViewSet(viewsets.ModelViewSet): + queryset = PosAllocationTransactions.objects.all() + permission_classes = [AllowAny] + serializer_class = PosAllocationTransactionsSerializer + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + paid = request.GET.get('paid') + if date1: + filters = { + 'date__date__gte': date1, + 'date__date__lte': date2, + 'trash': False, + } + else: + filters = { + 'trash': False, + } + if paid: + filters['paid'] = paid + + transactions = PosAllocationTransactions.objects.filter(**filters).order_by('-date') + if 'page_size' in request.GET: + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + timestamp_date = request.data['timestamp_date'] + transaction_date = datetime.fromtimestamp(timestamp_date) + pos = POSMachine.objects.get(pos_id=request.data['pos-id']) + allocation = StewardAllocation.objects.get(key=request.data['allocation_key']) + request.data.pop('timestamp_date') + request.data.pop('allocation_key') + request.data.pop('pos-id') + + try: + allocation_transaction = PosAllocationTransactions.objects.get(check_id=request.data['check_id']) + serializer = self.serializer_class(allocation_transaction) + serializer.update(instance=allocation_transaction, validated_data=request.data) + if allocation_transaction.paid: + allocation_calculate_price(allocation) + return Response(serializer.data, status=status.HTTP_200_OK) + + + except: + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + allocation_transaction = serializer.create(validated_data=request.data) + allocation_transaction.date = transaction_date + allocation_transaction.pos = pos + allocation_transaction.allocation = allocation + allocation_transaction.save() + if allocation_transaction.paid: + allocation_calculate_price(allocation) + return Response(serializer.data, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +class BroadcastPriceViewset(viewsets.ModelViewSet): + queryset = BroadcastPrice.objects.all() + permission_classes = [AllowAny] + serializer_class = BroadcastPriceSerializer + + def list(self, request, *args, **kwargs): + price = BroadcastPrice.objects.filter(trash=False).first() + + serializer = self.serializer_class(price) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + kill_house_price = 0 + steward_price = 0 + guild_price = 0 + price = BroadcastPrice.objects.filter(trash=False).first() + # approved_price = ApprovedPrice.objects.filter(trash=False).first() + # if request.data['active'] == True: + # if approved_price.approved == False: + # return Response({"result":"ابتدا در استان قیمت مصوب مرغ زنده رو در استان فعال کنید !"},status=status.HTTP_403_FORBIDDEN) + parent_product = NewProduct.objects.get(trash=False) + parent_product.approved_price_status = request.data['active'] + if 'kill_house_price' in request.data.keys(): + parent_product.approved_price = int(request.data['kill_house_price']) + kill_house_price = int(request.data['kill_house_price']) + steward_price = int(request.data['steward_price']) + guild_price = int(request.data['guild_price']) + parent_product.save() + roles_products_thread = threading.Thread(target=change_roles_products_state, + args=( + request.data['active'], kill_house_price, steward_price, + guild_price)) + + roles_products_thread.start() + + serializer = self.serializer_class(price) + serializer.update(instance=price, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class NewPosBroadcastPriceViewset(viewsets.ModelViewSet): + queryset = BroadcastPrice.objects.all() + permission_classes = [AllowAny] + serializer_class = BroadcastPriceSerializer + + def list(self, request, *args, **kwargs): + price = BroadcastPrice.objects.filter(trash=False).first() + allow = AllowRegisterCodeForStewardAllocation.objects.filter(trash=False).first() + steward_free_sale = AllowRegisterCodeForStewardFreeSaleBarInformation.objects.filter(trash=False).first() + kill_free_sale = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False).first() + + result = { + "active": price.active, + "kill_house_price": int(price.kill_house_price), + "steward_price": int(price.steward_price), + "guild_price": int(price.guild_price), + "kill_house_in_province_allocation_register_code": allow.active, + "steward_in_province_allocation_register_code": allow.active, + "kill_house_free_sale_register_code": kill_free_sale.active, + "steward_free_sale_register_code": steward_free_sale.active, + } + + return Response(result, status=status.HTTP_200_OK) + + +class OutProvinceSaleLimitationViewset(viewsets.ModelViewSet): + queryset = OutProvinceSaleLimitation.objects.all() + permission_classes = [AllowAny] + serializer_class = OutProvinceSaleLimitationSerializer + + def list(self, request, *args, **kwargs): + limitation = OutProvinceSaleLimitation.objects.filter(trash=False).first() + + serializer = self.serializer_class(limitation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + limitation = BroadcastPrice.objects.filter(trash=False).first() + serializer = self.serializer_class(limitation) + serializer.update(instance=limitation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosBroadcastPriceViewset(viewsets.ModelViewSet): + queryset = BroadcastPrice.objects.all() + permission_classes = [AllowAny] + serializer_class = BroadcastPriceSerializer + + def list(self, request, *args, **kwargs): + price = BroadcastPrice.objects.filter(trash=False).first() + type = request.GET.get('type') + if type: + if type in ('KillHouse_Steward', 'KillHouse_Guild'): + price_amount = price.kill_house_price + approved_price_status = False if price.active == False else True + + elif type in ( + 'KillHouse_KillHouse', 'Steward_Steward', 'Steward_KillHouse', 'Guild_KillHouse', 'Guild_Guild', + 'Guild_Steward'): + price_amount = price.guild_price + approved_price_status = False + + else: + price_amount = price.steward_price + approved_price_status = False if price.active == False else True + else: + price_amount = price.guild_price + approved_price_status = False + + result = { + "price": int(price_amount), + # "approved_price_status": approved_price_status, + "approved_price_status": False, + } + + return Response(result, status=status.HTTP_200_OK) + + +class ParentCompanyViewSet(viewsets.ModelViewSet): + queryset = ParentCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ParentCompanySerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + parent_company = SystemUserProfile.objects.get(user=request.user, trash=False).parent_company_user.first() + + serializer = self.serializer_class(parent_company) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityGuildViewSet(viewsets.ModelViewSet): + queryset = CityGuild.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityGuildSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + city_guild = SystemUserProfile.objects.get(user=request.user, trash=False).city_guild_user.first() + + serializer = self.serializer_class(city_guild) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityGuildForSubSectorViewSet(viewsets.ModelViewSet): + queryset = CityGuild.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityGuildForSubSectorSerializer + + def list(self, request, *args, **kwargs): + city_guilds = CityGuild.objects.filter(trash=False) + serializer = self.serializer_class(city_guilds, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityGuildForSubSectorTransactionsViewSet(viewsets.ModelViewSet): + queryset = CityGuild.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityGuildForSubsectorTransactionSerializer + + def list(self, request, *args, **kwargs): + city_guilds = CityGuild.objects.filter(trash=False) + serializer = self.serializer_class(city_guilds, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CityGuildWageDashboardViewSet(viewsets.ModelViewSet): + queryset = CityGuild.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CityGuildSerializer + + def list(self, request, *args, **kwargs): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__isnull=False, calculate_status=True, + temporary_trash=False, temporary_deleted=False, + receiver_state='accepted', date__date__gte=date1, + date__date__lte=date2) + transactions = PosMachineTransactions.objects.filter(paid=True, trash=False, date__date__gte=date1, + date__date__lte=date2) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild__isnull=False, + date__date__gte=date1, date__date__lte=date2) + else: + allocations = StewardAllocation.objects.filter(trash=False, to_guilds__isnull=False, calculate_status=True, + temporary_trash=False, temporary_deleted=False, + receiver_state='accepted') + transactions = PosMachineTransactions.objects.filter(paid=True, trash=False) + sub_transactions = SubSectorTransactions.objects.filter(trash=False, city_guild__isnull=False) + allocations_weight = allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + transactions_weight = transactions.aggregate(total=Sum('weight'))[ + 'total'] or 0 + transactions_weight = transactions_weight / 1000 if transactions_weight > 0 else 0 + total_wage = transactions_weight * (province_live_wage_amount * other_province_kill_request_percent) + + sub_transactions_amount = sub_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + remain_wage = total_wage - sub_transactions_amount + + result = { + "buy_weight": allocations_weight, + "sell_weight": transactions_weight, + "total_wage": total_wage, + "guild_deposit": sub_transactions_amount, + "remain_wage": remain_wage + } + + return Response(result, status=status.HTTP_200_OK) + + +class TotalCitySubSectorWageDashboardViewSet(viewsets.ModelViewSet): + queryset = ProvinceOperator.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceOperatorSerializer + + def list(self, request, *args, **kwargs): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, poultry__in=poultries, + temporary_deleted=False, send_date__date__gte=date1, + send_date__date__lte=date2) + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted', acceptor_date__date__gte=date1, + acceptor_date__date__lte=date2) + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2) + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, poultry__in=poultries, + temporary_deleted=False) + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False) + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + hatching_list1 = hatchings.filter( + pk__in=province_kill_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list2 = hatchings.filter( + pk__in=kill_house_requests.values_list('province_request__poultry_request__hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', flat=True) + hatching_list3 = hatchings.filter(pk__in=poultry_requests.values_list('hatching', flat=True), + poultry__in=poultries, killed_quantity__gt=0, trash=False).values_list('id', + flat=True) + total_hatching_list = chain(hatching_list1, hatching_list2, hatching_list3) + hatchings = hatchings.filter(pk__in=total_hatching_list) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + else: + date1 = None + date2 = None + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses, date1, date2) + # return Response(total_pure_province_carcasses_weight) + internal_total_pure_province_carcasses_weight = ( + ( + total_pure_province_carcasses_weight / total_province_carcasses_weight) if total_province_carcasses_weight > 0 else 0) * total_province_carcasses_weight + external_total_pure_province_carcasses_weight = total_province_carcasses_weight - internal_total_pure_province_carcasses_weight + + total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = poultry_requests.filter(hatching__id__in=hatching_list3) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + + union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_free_sell_carcasses_wage + hatching_killing_percent = (( + out_province_poultry_request_quantity + total_province_live_quantity) / hatching_quantity if hatching_quantity > 0 else 0) * 100 + + city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request + city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request + city_out_province_sell_carcasses = union_free_sell_carcasses_wage * city_percent_out_sell_carcasses + city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_sell_carcasses + + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + city_total_remain_wage_amount = city_total_wage - city_deposit + + result = { + "wage_counting_type": wage_counting_type, + "poultries": len(poultries), + "hatchings": len(hatchings), + "hatchings_quantity": hatching_quantity, + "total_province_kill_requests_quantity": total_province_live_quantity, + "total_province_kill_requests_weight": total_province_live_weight, + "total_province_kill_requests_total_carcasses_weight": total_province_carcasses_weight, + "total_province_kill_requests_carcasses_weight": internal_total_pure_province_carcasses_weight, + "total_out_selling_province_carcasses_weight": external_total_pure_province_carcasses_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "total_killed_quantity": out_province_poultry_request_quantity + total_province_live_quantity, + "hatching_killing_percent": hatching_killing_percent, + "out_province_poultry_request_amount": union_out_province_poultry_request_amount, + "total_pure_province_carcasses_price": union_province_kill_request_wage, + "union_total_out_selling_province_carcasses_price": union_free_sell_carcasses_wage, + "union_total_wage": union_total_wage, + "city_total_wage": city_total_wage, + "city_deposit": city_deposit, + "city_total_remain_wage_amount": city_total_remain_wage_amount, + } + + return Response(result, status=status.HTTP_200_OK) + + +# class TotalCitySubSectortransactionDashboardViewSet(viewsets.ModelViewSet): +# queryset = ProvinceOperator.objects.all() +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = ProvinceOperatorSerializer +# +# def list(self, request, *args, **kwargs): +# total_wage_type = WageType.objects.filter(trash=False) +# province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount +# city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( +# percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 +# city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( +# percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 +# city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( +# percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 +# +# percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) +# union_province_kill_request_percent = percentages_wage_type.filter(wage_type__en_name='province-kill-request', +# share_type__en_name='union').first().percent / 100 +# kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') +# poultries = Poultry.objects.filter(trash=False).order_by('id') +# hatchings = PoultryHatching.objects.filter(poultry__in=poultries, trash=False).order_by('poultry') +# +# poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), +# province_state__in=('pending', 'accepted'), out=True, +# out_province_request_cancel=False, temporary_trash=False, +# temporary_deleted=False, hatching__in=hatchings) +# +# union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ +# 'total'] or 0 +# +# province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, +# archive_wage=False, +# state__in=('pending', 'accepted'), +# temporary_trash=False, temporary_deleted=False, +# province_request__poultry_request__hatching__in=hatchings) +# +# total_province_kill_requests_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ +# 'total'] or 0 +# total_province_live_weight = total_province_kill_requests_weight +# +# kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter(kill_house__in=kill_houses, +# archive_wage=False, +# calculate_status=True, +# trash=False) +# kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter( +# kill_house__in=kill_houses, +# archive_wage=False, +# calculate_status=True, +# trash=False) +# total_out_selling_province_carcasses_weight = \ +# kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 +# union_total_out_selling_province_carcasses_price = \ +# kill_house_free_sale_bar_info.aggregate(total=Sum('union_share'))['total'] or 0 +# +# total_province_carcasses_weight = total_province_live_weight * 0.75 +# total_out_carcasses_buying_for_pure_province_carcasses_weight = \ +# kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 +# out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( +# total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 +# total_pure_province_carcasses_weight = total_province_carcasses_weight - out_selling_out_carcasses_buying_difference +# +# total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_amount +# union_province_kill_request_wage = int( +# total_pure_province_carcasses_price * union_province_kill_request_percent) +# union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_total_out_selling_province_carcasses_price +# +# city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request +# city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request +# city_out_province_out_sell_carcasses_price = union_total_out_selling_province_carcasses_price * city_percent_out_sell_carcasses +# city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_out_sell_carcasses_price +# city_operator_deposit = SubSectorTransactions.objects.filter(trash=False) +# city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 +# city_total_remain_wage_amount = city_total_wage - city_deposit +# +# result = { +# "wage_counting_type": wage_counting_type, +# "city_out_province_poultry_request": city_out_province_poultry_request, +# "city_province_kill_request_wage": city_province_kill_request_wage, +# "city_out_province_out_sell_carcasses_wage": city_out_province_out_sell_carcasses_price, +# "union_total_wage": union_total_wage, +# "city_total_wage": city_total_wage, +# "city_deposit": city_deposit, +# "city_total_remain_wage_amount": city_total_remain_wage_amount, +# } +# +# return Response(result, status=status.HTTP_200_OK) +class TotalCitySubSectortransactionDashboardViewSet(viewsets.ModelViewSet): + queryset = ProvinceOperator.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProvinceOperatorSerializer + + def list(self, request, *args, **kwargs): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcesses_weight_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0).order_by('id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + trash=False, calculate_status=True + ) + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_province_live_quantity += kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + total_province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + + total_province_carcasses_weight = total_province_live_weight * 0.75 + + total_pure_province_carcasses_weight = total_province_carcasses_weight - get_difference_carcasses_weight( + kill_houses) + + # return Response(total_pure_province_carcasses_weight) + internal_total_pure_province_carcasses_weight = ( + total_pure_province_carcasses_weight / total_province_carcasses_weight) * total_province_carcasses_weight + external_total_pure_province_carcasses_weight = total_province_carcasses_weight - internal_total_pure_province_carcasses_weight + + total_pure_province_carcasses_price = internal_total_pure_province_carcasses_weight * province_live_wage_amount + total_out_selling_province_carcasses_price = external_total_pure_province_carcasses_weight * free_sell_carcesses_weight_amount + + poultries = Poultry.objects.filter(trash=False, city_operator__isnull=False).order_by('id') + hatchings = PoultryHatching.objects.filter(poultry__in=poultries, killed_quantity__gt=0, trash=False).order_by( + 'poultry') + + hatching_quantity = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + has_wage=True, wage_pay=True, + temporary_deleted=False, hatching__in=hatchings) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + union_out_province_poultry_request_amount = poultry_requests.aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + union_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='union').first().percent / 100 + + union_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='union').first().percent / 100 + union_province_kill_request_wage = total_pure_province_carcasses_price * union_province_kill_request_percent + union_free_sell_carcasses_wage = total_out_selling_province_carcasses_price * union_free_sell_carcasses_percent + + city_percent_province_kill_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='province-kill-request').first().percent / 100 + city_percent_out_poultry_request = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='poultry-sell-out-province').first().percent / 100 + city_percent_out_sell_carcasses = SubSectorPercentageOfWageType.objects.filter( + percentage_of_wage_type__wage_type__en_name='carcasse-sell').first().percent / 100 + + union_total_wage = union_province_kill_request_wage + union_out_province_poultry_request_amount + union_free_sell_carcasses_wage + hatching_killing_percent = (( + out_province_poultry_request_quantity + total_province_live_quantity) / hatching_quantity) * 100 + + city_province_kill_request_wage = union_province_kill_request_wage * city_percent_province_kill_request + city_out_province_poultry_request = union_out_province_poultry_request_amount * city_percent_out_poultry_request + city_out_province_sell_carcasses = union_free_sell_carcasses_wage * city_percent_out_sell_carcasses + city_total_wage = city_province_kill_request_wage + city_out_province_poultry_request + city_out_province_sell_carcasses + city_operator_deposit = SubSectorTransactions.objects.filter(trash=False) + city_deposit = city_operator_deposit.aggregate(total=Sum('amount'))['total'] or 0 + city_total_remain_wage_amount = city_total_wage - city_deposit + + result = { + "wage_counting_type": wage_counting_type, + "city_out_province_poultry_request": city_out_province_poultry_request, + "city_province_kill_request_wage": city_province_kill_request_wage, + "city_out_province_out_sell_carcasses_wage": city_out_province_sell_carcasses, + "union_total_wage": union_total_wage, + "city_total_wage": city_total_wage, + "city_deposit": city_deposit, + "city_total_remain_wage_amount": city_total_remain_wage_amount, + } + + return Response(result, status=status.HTTP_200_OK) + + +class SubSectorTransactionsViewSet(viewsets.ModelViewSet): + queryset = SubSectorTransactions.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = SubSectorTransactionsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = SubSectorTransactionsFilterSet + filterset_fields = [ + 'city_operator__user__first_name', + 'city_operator__user__last_name', + 'city_operator__user__fullname', + 'city_operator__user__mobile', + 'city_operator__user__city__name', + 'from_account', + 'to_account', + + ] + + def create(self, request, *args, **kwargs): + operator = None + vet = None + guild = None + role_type = request.data['role_type'] + if role_type == 'vet': + vet = Vet.objects.get(key=request.data['role_key'], trash=False) + + elif role_type == 'guild': + guild = CityGuild.objects.get(key=request.data['role_key'], trash=False) + else: + operator = CityOperator.objects.get(key=request.data['role_key'], trash=False) + request.data.pop('role_type') + request.data.pop('role_key') + image = request.data['image'] + request.data.pop('image') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + transaction = serializer.create(validated_data=request.data) + transaction.image = send_image_to_server(image) + if operator: + transaction.city_operator = operator + + elif guild: + transaction.city_guild = guild + + else: + transaction.vet = vet + + transaction.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + role_type = request.GET['type'] + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_operator__isnull=False, + trash=False).order_by('-date') + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + vet__isnull=False, + trash=False).order_by('-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(date__date__gte=date1, + date__date__lte=date2, + city_guild__isnull=False, + trash=False).order_by('-date') + + + else: + if role_type == 'city': + operator_transactions = SubSectorTransactions.objects.filter(city_operator__isnull=False, + trash=False).order_by('-date') + + elif role_type == 'vet': + operator_transactions = SubSectorTransactions.objects.filter(vet__isnull=False, trash=False).order_by( + '-date') + else: + operator_transactions = SubSectorTransactions.objects.filter(city_guild__isnull=False, + trash=False).order_by('-date') + + if 'search' in request.GET: + operator_transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=operator_transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=operator_transactions) + operator_transactions_list = ps.filter() + operator_transactions = [] if len(operator_transactions_list) == 0 else operator_transactions_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(operator_transactions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(operator_transactions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + transaction = SubSectorTransactions.objects.get(key=request.data['transaction_key'], trash=False) + if 'image' in request.data.keys(): + if request.data['image'] != None or request.data['image'] != "": + transaction.image = send_image_to_server(request.data['image']) + transaction.save() + + request.data.pop('image') + request.data.pop('transaction_key') + serializer = self.serializer_class(transaction) + serializer.update(instance=transaction, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + transaction = SubSectorTransactions.objects.get(key=request.GET["transaction_key"], trash=False) + transaction.trash = True + transaction.save() + return Response({"result": "با موفقیت حذف شد."}, status=status.HTTP_200_OK) + + +class PosSegmentationViewSet(viewsets.ModelViewSet): + queryset = PosSegmentation.objects.all() + permission_classes = [AllowAny] + serializer_class = PosSegmentationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosSegmentationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name' + ] + + def create(self, request, *args, **kwargs): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + guild = Guilds.objects.get(id=pos.guild.id, trash=False) + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + request.data.pop('product_key') + if product.total_remain_weight < request.data['weight']: + return Response({"result": "موجودی انبار کمتر از وزن وارد شده است!"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + segmentation = serializer.create(validated_data=request.data) + segmentation.guild = guild + segmentation.product = product + segmentation.date = datetime.now() + segmentation.save() + guild_steward_product_segmentation(product) + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device, trash=False) + segmentations = PosSegmentation.objects.filter(guild=pos.guild, + date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('-date') + + if 'search' in request.GET and 'value' in request.GET: + segmentation_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=segmentations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=segmentations) + segmentation_list = ps.filter() + segmentations = [] if len(segmentation_list) == 0 else segmentation_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(segmentations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(segmentations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.data['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت ویرایش به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(segmentation) + serializer.update(instance=segmentation, validated_data=request.data) + guild_steward_product_segmentation(segmentation.product) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.GET['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت حذف به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + product = segmentation.product + segmentation.trash = True + segmentation.save() + guild_steward_product_segmentation(product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class NewPosSegmentationViewSet(viewsets.ModelViewSet): + queryset = PosSegmentation.objects.all() + permission_classes = [AllowAny] + serializer_class = PosSegmentationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosSegmentationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name' + ] + + def create(self, request, *args, **kwargs): + + pos = POSMachine.objects.get(pos_id=request.data['pos-id'], trash=False) + guild = None + kill_house = None + quota = None + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + if pos.guild: + guild = product.guild + else: + kill_house = product.kill_house + quota = request.data['quota'] + to_guild = None + if 'guild_key' in request.data.keys(): + to_guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + + request.data.pop('product_key') + if kill_house: + kill_house_total_input_warehouse_governmental_weight = kill_house.total_input_warehouse_governmental_weight + kill_house_total_input_warehouse_free_weight = kill_house.total_input_warehouse_free_weight + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + segmentation_sale_type = request.data['sale_type'] + if kill_house.governmental_selling_permission: + if segmentation_sale_type == 'free': + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_segmentation_governmental_weight > 0: + if kill_house.total_segmentation_governmental_weight + request.data[ + 'weight'] > kill_house.total_commitment_segmentation_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_segmentation_free_weight > 0: + if kill_house.total_segmentation_free_weight + request.data[ + 'weight'] > kill_house.total_commitment_segmentation_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not guild.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if guild.total_input_warehouse_governmental_weight < ( + guild.total_selling_warehouse_governmental_weight + request.data['weight']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if guild.total_input_warehouse_free_weight < ( + guild.total_selling_warehouse_free_weight + request.data['weight']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + segmentation_sale_type = request.data['sale_type'] + if guild.governmental_selling_permission: + if segmentation_sale_type == 'free': + if not guild.free_sale_form_governmental_quota: + if guild.total_commitment_selling_in_province_governmental_weight > guild.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if guild.total_commitment_selling_in_province_governmental_weight > guild.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if guild.total_commitment_segmentation_governmental_weight > 0: + if guild.total_segmentation_governmental_weight + request.data[ + 'weight'] > guild.total_commitment_segmentation_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if guild.free_selling_permission: + if guild.total_commitment_selling_in_province_free_weight > guild.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if guild.total_commitment_segmentation_free_weight > 0: + if guild.total_segmentation_free_weight + request.data[ + 'weight'] > guild.total_commitment_segmentation_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if product.total_remain_weight < request.data['weight']: + return Response({"result": "موجودی انبار کمتر از وزن وارد شده است!"}, status=status.HTTP_403_FORBIDDEN) + + now_time = datetime.now().time() + + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('production_date') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + segmentation = serializer.create(validated_data=request.data) + if guild: + segmentation.guild = guild + else: + + segmentation.kill_house = kill_house + if to_guild: + segmentation.to_guild = to_guild + + segmentation.product = product + segmentation.date = datetime.now() + segmentation.production_date = production_date + segmentation.save() + guild_steward_product_segmentation(product) + + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + pos = POSMachine.objects.get(pos_id=request.GET['pos-id'], trash=False) + if role: + + if date1: + + if role == 'KillHouse': + segmentations = PosSegmentation.objects.filter(kill_house=pos.kill_house, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + segmentations = PosSegmentation.objects.filter(guild=pos.guild, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + if role == 'KillHouse': + segmentations = PosSegmentation.objects.filter(kill_house=pos.kill_house, + trash=False) + else: + segmentations = PosSegmentation.objects.filter(guild=pos.guild, + trash=False) + else: + segmentations = PosSegmentation.objects.filter(trash=False) + + if 'search' in request.GET and 'value' in request.GET: + segmentation_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=segmentations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=segmentations) + segmentation_list = ps.filter() + segmentations = [] if len(segmentation_list) == 0 else segmentation_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(segmentations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(segmentations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.data['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت ویرایش به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + if segmentation.kill_house: + if segmentation.quota == 'governmental': + if segmentation.kill_house.total_input_warehouse_governmental_weight < ( + (segmentation.kill_house.total_selling_warehouse_governmental_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if segmentation.kill_house.total_input_warehouse_free_weight < ( + (segmentation.kill_house.total_selling_warehouse_free_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if segmentation.quota == 'governmental': + if segmentation.guild.total_input_warehouse_governmental_weight < ( + (segmentation.guild.total_selling_warehouse_governmental_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if segmentation.guild.total_input_warehouse_free_weight < ( + (segmentation.guild.total_selling_warehouse_free_weight - segmentation.weight) + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(segmentation) + serializer.update(instance=segmentation, validated_data=request.data) + guild_steward_product_segmentation(segmentation.product) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.GET['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت حذف به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + product = segmentation.product + segmentation.trash = True + segmentation.save() + # if segmentation.guild: + guild_steward_product_segmentation(product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class AppSegmentationViewSet(viewsets.ModelViewSet): + queryset = PosSegmentation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = AppSegmentationSerializer + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosSegmentationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name', + 'to_guild__user__first_name', + 'to_guild__user__last_name', + 'to_guild__user__fullname', + 'to_guild__user__mobile', + 'to_guild__guilds_name' + ] + + def create(self, request, *args, **kwargs): + guild = None + kill_house = None + quota = None + dispenser = request.data.pop('dispenser',None) + representative = request.data.pop('representative',None) + product = RolesProducts.objects.get(key=request.data['product_key'], trash=False) + if product.guild: + guild = product.guild + else: + kill_house = product.kill_house + quota = request.data['quota'] + to_guild = None + if 'guild_key' in request.data.keys(): + to_guild = Guilds.objects.get(key=request.data['guild_key'], trash=False) + request.data.pop('guild_key') + + request.data.pop('product_key') + if kill_house: + kill_house_total_input_warehouse_governmental_weight = kill_house.total_input_warehouse_governmental_weight + kill_house_total_input_warehouse_free_weight = kill_house.total_input_warehouse_free_weight + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not kill_house.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if kill_house.total_input_warehouse_governmental_weight < ( + kill_house.total_selling_warehouse_governmental_weight + request.data['weight']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_input_warehouse_free_weight < ( + kill_house.total_selling_warehouse_free_weight + request.data['weight']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + segmentation_sale_type = request.data['sale_type'] + if kill_house.governmental_selling_permission: + if segmentation_sale_type == 'free': + if not kill_house.free_sale_form_governmental_quota: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if kill_house.total_commitment_selling_in_province_governmental_weight > kill_house.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if kill_house.total_commitment_segmentation_governmental_weight > 0: + if kill_house.total_segmentation_governmental_weight + request.data[ + 'weight'] > kill_house.total_commitment_segmentation_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if kill_house.free_selling_permission: + if kill_house.total_commitment_selling_in_province_free_weight > kill_house.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if kill_house.total_commitment_segmentation_free_weight > 0: + if kill_house.total_segmentation_free_weight + request.data[ + 'weight'] > kill_house.total_commitment_segmentation_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if request.data['sale_type'] == 'free': + quota = request.data['quota'] + if quota == 'governmental': + if not guild.free_sale_form_governmental_quota: + return Response({"result": "مجاز به فروش آزاد از انبار دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if quota == 'governmental': + if guild.total_input_warehouse_governmental_weight < ( + guild.total_selling_warehouse_governmental_weight + request.data['weight']): + return Response({"result": "مجاز به فروش دولتی بیشتر از ورودی دولتی انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if guild.total_input_warehouse_free_weight < ( + guild.total_selling_warehouse_free_weight + request.data['weight']): + return Response({"result": "مجاز به فروش آزاد بیشتر از ورودی آزاد انبار نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + if quota == 'governmental': + segmentation_sale_type = request.data['sale_type'] + if guild.governmental_selling_permission: + if segmentation_sale_type == 'free': + if not guild.free_sale_form_governmental_quota: + if guild.total_commitment_selling_in_province_governmental_weight > guild.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if guild.total_commitment_selling_in_province_governmental_weight > guild.total_selling_in_province_governmental_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش دولتی نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + if guild.total_commitment_segmentation_governmental_weight > 0: + if guild.total_segmentation_governmental_weight + request.data[ + 'weight'] > guild.total_commitment_segmentation_governmental_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if guild.free_selling_permission: + if guild.total_commitment_selling_in_province_free_weight > guild.total_selling_in_province_free_weight: + return Response({"result": "ابتدا تعهد داخل استان رو تکمیل کنید!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "مجاز به فروش آزاد نمیباشید!"}, status=status.HTTP_403_FORBIDDEN) + + if guild.total_commitment_segmentation_free_weight > 0: + if guild.total_segmentation_free_weight + request.data[ + 'weight'] > guild.total_commitment_segmentation_free_weight: + return Response({"result": "به دلیل بیشتر از وزن تعهد مجاز به فروش دولتی نمیباشید!"}, + status=status.HTTP_403_FORBIDDEN) + + if product.total_remain_weight < request.data['weight']: + return Response({"result": "موجودی انبار کمتر از وزن وارد شده است!"}, status=status.HTTP_403_FORBIDDEN) + + now_time = datetime.now().time() + + production_date = datetime.strptime(str(request.data['production_date']), '%Y-%m-%d').date() + production_date = datetime(year=production_date.year, month=production_date.month, day=production_date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('production_date') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + segmentation = serializer.create(validated_data=request.data) + if guild: + segmentation.guild = guild + else: + + segmentation.kill_house = kill_house + if to_guild: + segmentation.to_guild = to_guild + + segmentation.product = product + segmentation.date = datetime.now() + segmentation.production_date = production_date + segmentation.dispenser = dispenser if dispenser else None + segmentation.representative = representative if representative else None + segmentation.save() + guild_steward_product_segmentation(product) + + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + steward_key = request.GET.get('steward_key') + user = SystemUserProfile.objects.get(user=request.user) + if role: + if steward_key: + if steward_key == 'all': + if role in ['CityJahad']: + segmentations = PosSegmentation.objects.filter(guild__isnull=False, guild__user__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + segmentations = PosSegmentation.objects.filter(guild__isnull=False, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + guild = Guilds.objects.get(key=steward_key, trash=False) + if role in ['CityJahad']: + segmentations = PosSegmentation.objects.filter(guild=guild, guild__user__city=user.city, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + + segmentations = PosSegmentation.objects.filter(guild=guild, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user).first() + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + guild = Guilds.objects.get(user=user, active=True, trash=False) + segmentations = PosSegmentation.objects.filter(guild=guild, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + else: + guild = Guilds.objects.get(user=user, active=True, trash=False) + segmentations = PosSegmentation.objects.filter(guild=guild, + date__date__gte=date1, + date__date__lte=date2, + trash=False) + + if 'search' in request.GET and 'value' in request.GET: + segmentation_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=segmentations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=segmentations) + segmentation_list = ps.filter() + segmentations = [] if len(segmentation_list) == 0 else segmentation_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(segmentations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(segmentations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.data['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت ویرایش به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + if segmentation.kill_house: + if segmentation.quota == 'governmental': + if segmentation.kill_house.total_input_warehouse_governmental_weight < ( + (segmentation.kill_house.total_selling_warehouse_governmental_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if segmentation.kill_house.total_input_warehouse_free_weight < ( + (segmentation.kill_house.total_selling_warehouse_free_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + + else: + if segmentation.quota == 'governmental': + if segmentation.guild.total_input_warehouse_governmental_weight < ( + (segmentation.guild.total_selling_warehouse_governmental_weight - segmentation.weight) + + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده دولتی می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if segmentation.guild.total_input_warehouse_free_weight < ( + (segmentation.guild.total_selling_warehouse_free_weight - segmentation.weight) + request.data[ + 'weight']): + return Response({"result": "وزن وارد شده بیشتر از باقی مانده آزاد می باشد!"}, + status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(segmentation) + serializer.update(instance=segmentation, validated_data=request.data) + guild_steward_product_segmentation(segmentation.product) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + now = datetime.now().date() + segmentation = PosSegmentation.objects.get(key=request.GET['key']) + if now != segmentation.date.date(): + return Response({"result": "مهلت حذف به اتمام رسیده است !"}, status=status.HTTP_403_FORBIDDEN) + product = segmentation.product + segmentation.trash = True + segmentation.save() + # if segmentation.guild: + guild_steward_product_segmentation(product) + + return Response({"result": "بار با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class SegmentationDashboardViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + filterset_class = PosSegmentationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name', + 'to_guild__user__first_name', + 'to_guild__user__last_name', + 'to_guild__user__fullname', + 'to_guild__user__mobile', + 'to_guild__guilds_name' + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + steward_key = request.GET.get('steward_key') + user = SystemUserProfile.objects.get(user=request.user) + if role: + if role == 'KillHouse': + filters = {'trash': False, 'kill_house__kill_house_operator__user': user} + else: + if steward_key: + if steward_key == 'all': + filters = {'trash': False, 'guild__isnull': False} + else: + filters = {'trash': False, 'guild__key': steward_key} + + else: + filters = {'trash': False, 'guild__user': user} + + + else: + filters = {'trash': False, 'guild__user': user} + if date1: + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + segmentations = PosSegmentation.objects.filter(**filters) + if 'search' in request.GET and 'value' in request.GET: + segmentation_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=segmentations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=segmentations) + segmentation_list = ps.filter() + segmentations = [] if len(segmentation_list) == 0 else segmentation_list + + segmentations_aggregates = segmentations.aggregate( + total_count=Count('id'), + total_self_count=Count('id', filter=Q(to_guild__isnull=True)), + total_other_count=Count('id', filter=Q(to_guild__isnull=False)), + total_weight=Sum('weight'), + total_self_weight=Sum('weight', filter=Q(to_guild__isnull=True)), + total_other_weight=Sum('weight', filter=Q(to_guild__isnull=False)), + + ) + + result = { + "total_count": segmentations_aggregates['total_count'] or 0, + "total_weight": segmentations_aggregates['total_weight'] or 0, + "total_self_count": segmentations_aggregates['total_self_count'] or 0, + "total_self_weight": segmentations_aggregates['total_self_weight'] or 0, + "total_other_count": segmentations_aggregates['total_other_count'] or 0, + "total_other_weight": segmentations_aggregates['total_other_weight'] or 0 + + } + return Response(result, status=status.HTTP_200_OK) + + +class GuildsForPosMachineTransactionsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + serializer_class = GuildsPosMachineForTransactionsNewSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = GuildsForPostationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name' + ] + + # def get_filtered_guilds(self, request): + # if 'date1' in request.GET and 'date2' in request.GET: + # date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + # date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + # + # guilds = Guilds.objects.filter( + # id__in=PosMachineTransactions.objects.filter( + # trash=False, + # date__date__gte=date1, + # date__date__lte=date2, + # pos__guild__isnull=False, + # paid=True + # ).values_list('pos__guild__id', flat=True).distinct() + # ).annotate( + # transaction_count=Count( + # 'guild_pos__roles_products_pos_transactions', + # filter=Q(guild_pos__roles_products_pos_transactions__trash=False) & + # Q(guild_pos__roles_products_pos_transactions__paid=True) + # ) + # ).order_by('-transaction_count') + # + # else: + # guilds = Guilds.objects.annotate( + # transaction_count=Count( + # 'guild_pos__roles_products_pos_transactions', + # filter=Q(guild_pos__roles_products_pos_transactions__trash=False) & + # Q(guild_pos__roles_products_pos_transactions__paid=True) + # ) + # ).order_by('-transaction_count') + # + # return guilds + + def get_filtered_guilds(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + + if date1 and date2: + date1 = datetime.strptime(date1, '%Y-%m-%d').date() + date2 = datetime.strptime(date2, '%Y-%m-%d').date() + + guilds = Guilds.objects.filter( + Q( + id__in=PosMachineTransactions.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + pos__guild__isnull=False, + paid=True + ).values_list('pos__guild__id', flat=True) + ) | + Q( + id__in=StewardAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + to_guilds__isnull=False, + to_cold_house__isnull=True, + temporary_trash=False, + trash=False, + calculate_status=True + ).values_list('to_guilds__id', flat=True) + ) + ).annotate( + transaction_count=Count( + 'guild_pos__roles_products_pos_transactions', + filter=Q( + guild_pos__roles_products_pos_transactions__trash=False, + guild_pos__roles_products_pos_transactions__paid=True, + guild_pos__roles_products_pos_transactions__date__date__gte=date1, + guild_pos__roles_products_pos_transactions__date__date__lte=date2 + ), + distinct=True + ) + ).order_by('-transaction_count') + + else: + guilds = Guilds.objects.filter( + Q( + id__in=PosMachineTransactions.objects.filter( + trash=False, + paid=True, + pos__guild__isnull=False + ).values_list('pos__guild__id', flat=True) + ) | + Q( + id__in=StewardAllocation.objects.filter( + to_guilds__isnull=False, + to_cold_house__isnull=True, + temporary_trash=False, + trash=False, + calculate_status=True + ).values_list('to_guilds__id', flat=True) + ) + ).annotate( + transaction_count=Count( + 'guild_pos__roles_products_pos_transactions', + filter=Q( + guild_pos__roles_products_pos_transactions__trash=False, + guild_pos__roles_products_pos_transactions__paid=True + ), + distinct=True + ) + ).order_by('-transaction_count') + + return guilds + + def apply_search_filter(self, request, guilds): + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + return guilds + + def list(self, request, *args, **kwargs): + guilds = self.get_filtered_guilds(request) + guilds = self.apply_search_filter(request, guilds) + + serializer = self.serializer_class(guilds, many=True, context={'request': request}) + data = serializer.data + + data = sorted(data, key=lambda x: x['transaction']['total_carcasses_weight'], reverse=True) + + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(data) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(data) + + return Response(data, status=status.HTTP_200_OK) + + +# class GuildsForPosMachineTransactionsViewSet(viewsets.ModelViewSet): +# queryset = Guilds.objects.all() +# serializer_class = GuildsPosMachineForTransactionsNewSerializer +# permission_classes = [TokenHasReadWriteScope] +# filter_backends = [DjangoFilterBackend] +# pagination_class = CustomPagination +# filterset_class = GuildsForPostationFilterSet +# filterset_fields = [ +# 'guild__user__first_name', +# 'guild__user__last_name', +# 'guild__user__fullname', +# 'guild__user__mobile', +# 'guild__guilds_name' +# ] +# +# def _get_date_range(self, request): +# d1 = request.GET.get('date1') +# d2 = request.GET.get('date2') +# if d1 and d2: +# try: +# date1 = datetime.strptime(d1, '%Y-%m-%d').date() +# date2 = datetime.strptime(d2, '%Y-%m-%d').date() +# return date1, date2 +# except ValueError: +# return None, None +# return None, None +# +# def get_filtered_guild_ids(self, request): +# date1, date2 = self._get_date_range(request) +# +# if date1 and date2: +# pos_qs = PosMachineTransactions.objects.filter( +# trash=False, +# date__date__gte=date1, +# date__date__lte=date2, +# pos__guild__isnull=False, +# paid=True +# ).values_list('pos__guild__id', flat=True) +# alloc_qs = StewardAllocation.objects.filter( +# date__date__gte=date1, +# date__date__lte=date2, +# to_guilds__isnull=False, +# to_cold_house__isnull=True, +# temporary_trash=False, +# trash=False, +# receiver_state='accepted', +# calculate_status=True +# ).values_list('to_guilds__id', flat=True) +# else: +# pos_qs = PosMachineTransactions.objects.filter( +# trash=False, paid=True, pos__guild__isnull=False +# ).values_list('pos__guild__id', flat=True) +# alloc_qs = StewardAllocation.objects.filter( +# to_guilds__isnull=False, +# to_cold_house__isnull=True, +# temporary_trash=False, +# trash=False, +# receiver_state='accepted', +# calculate_status=True +# ).values_list('to_guilds__id', flat=True) +# +# guild_ids_from_related = set(pos_qs) | set(alloc_qs) +# guilds_base = Guilds.objects.filter(id__in=guild_ids_from_related).order_by('id') +# +# if request.GET.get('search') == 'filter' and request.GET.get('value') not in ["", "undefined", None]: +# value = request.GET.get('value') +# for f in self.filterset_fields: +# query = QueryDict(f'{f}__contains={value}') +# qs = self.filterset_class(data=query, queryset=guilds_base).qs +# if qs.exists(): +# guilds_base = qs +# break +# +# return list(guilds_base.values_list('id', flat=True)), guilds_base +# +# def list(self, request, *args, **kwargs): +# guild_ids, guilds_qs_for_pagination = self.get_filtered_guild_ids(request) +# guild_id_set = set(guild_ids) +# +# date1, date2 = self._get_date_range(request) +# +# pos_filter = Q(trash=False, paid=True, pos__guild__id__in=guild_ids, pos__guild__isnull=False) +# if date1 and date2: +# pos_filter &= Q(date__date__gte=date1, date__date__lte=date2) +# pos_values = PosMachineTransactions.objects.filter(pos_filter).values( +# 'pos__guild__id', 'price', 'weight' +# ) +# +# seg_filter = Q(trash=False, guild__id__in=guild_ids) +# if date1 and date2: +# seg_filter &= Q(date__date__gte=date1, date__date__lte=date2) +# seg_values = PosSegmentation.objects.filter(seg_filter).values('guild__id', 'weight') +# +# alloc_filter = Q(trash=False, calculate_status=True, to_guilds__isnull=False, +# receiver_state='accepted', to_cold_house__isnull=True, temporary_trash=False) +# if date1 and date2: +# alloc_filter &= Q(date__date__gte=date1, date__date__lte=date2) +# alloc_values = StewardAllocation.objects.filter(alloc_filter).values('to_guilds__id', 'real_weight_of_carcasses') +# +# product_values = RolesProducts.objects.filter(trash=False, guild__id__in=guild_ids).values( +# 'guild__id', 'name', 'total_remain_weight' +# ).order_by('guild__id') +# +# agg = {gid: { +# "len_transaction": 0, +# "total_price": 0, +# "pos_weight": 0, +# "pos_segmentation_weight": 0, +# "allocation_carcass_weight": 0, +# "product": None, +# "total_remain_weight": 0, +# } for gid in guild_ids} +# +# for p in pos_values: +# gid = p.get('pos__guild__id') +# if gid in guild_id_set: +# agg_g = agg[gid] +# agg_g['len_transaction'] += 1 +# agg_g['total_price'] += p.get('price') or 0 +# agg_g['pos_weight'] += p.get('weight') or 0 +# +# for s in seg_values: +# gid = s.get('guild__id') +# if gid in guild_id_set: +# agg[gid]['pos_segmentation_weight'] += s.get('weight') or 0 +# +# for a in alloc_values: +# gid = a.get('to_guilds__id') +# if gid in guild_id_set: +# agg[gid]['allocation_carcass_weight'] += a.get('real_weight_of_carcasses') or 0 +# +# seen_products = set() +# for pr in product_values: +# gid = pr.get('guild__id') +# if gid in guild_id_set and gid not in seen_products: +# agg[gid]['product'] = pr.get('name') or '-' +# agg[gid]['total_remain_weight'] = pr.get('total_remain_weight') or 0 +# seen_products.add(gid) +# +# precomputed = {} +# for gid, v in agg.items(): +# pos_weight_kg = round((v['pos_weight'] or 0) / 1000, 1) +# seg_weight_kg = round((v['pos_segmentation_weight'] or 0) / 1000, 1) +# total_carcasses = v['allocation_carcass_weight'] or 0 +# +# precomputed[gid] = { +# "len_transaction": v['len_transaction'], +# "total_price": v['total_price'], +# "real_allocated_weight": round(pos_weight_kg + seg_weight_kg, 1), +# "product": v['product'] or '-', +# "total_carcasses_weight": total_carcasses, +# "total_remain_weight": v['total_remain_weight'] or 0, +# } +# +# page = self.paginate_queryset(guilds_qs_for_pagination) +# to_serialize = page if page is not None else guilds_qs_for_pagination +# context = {'request': request, 'precomputed_transactions': precomputed} +# serializer = self.get_serializer(to_serialize, many=True, context=context) +# +# if page is not None: +# return self.get_paginated_response(serializer.data) +# return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosMachineTransactionsForInsPectionViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + serializer_class = PosMachineTransactionsForInspectionSerializer + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'pos__guild__user__first_name', + 'pos__guild__user__last_name', + 'pos__guild__user__fullname', + 'pos__guild__user__mobile', + 'pos__guild__guilds_name' + ] + + def list(self, request, *args, **kwargs): + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = PosMachineTransactions.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, pos__key=request.GET['pos_key'], + paid=True) + else: + transactions = PosMachineTransactions.objects.filter(trash=False, pos__key=request.GET['pos_key'], + paid=True) + + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = self.serializer_class(transactions, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class DetailsOfGuildsForPosMachineTransactionsViewSet(viewsets.ModelViewSet): + queryset = PosMachineTransactions.objects.all() + serializer_class = PosMachineTransactionsForInspectionSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = PosMachineTransactionsFilterSet + filterset_fields = [ + 'pos__guild__user__first_name', + 'pos__guild__user__last_name', + 'pos__guild__user__fullname', + 'pos__guild__user__mobile', + 'pos__guild__guilds_name' + ] + + def list(self, request, *args, **kwargs): + guild = Guilds.objects.get(key=request.GET['key']) + if 'date1' in request.GET: + date1 = datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + transactions = PosMachineTransactions.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, pos__guild=guild, + paid=True).order_by('-date') + else: + transactions = PosMachineTransactions.objects.filter(trash=False, pos__guild=guild, + paid=True).order_by('-date') + + if 'search' in request.GET and 'value' in request.GET: + transactions_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=transactions + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=transactions) + transactions_list = ps.filter() + transactions = [] if len(transactions_list) == 0 else transactions_list + if 'page' in request.GET: + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(transactions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = self.serializer_class(transactions, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class DashboardOfGuildsForPosMachineTransactionsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + serializer_class = GuildsPosMachineForTransactionsSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + pagination_class = CustomPagination + filterset_class = GuildsForPostationFilterSet + filterset_fields = [ + 'guild__user__first_name', + 'guild__user__last_name', + 'guild__user__fullname', + 'guild__user__mobile', + 'guild__guilds_name' + ] + + def get_filtered_guilds(self, request): + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + guilds = Guilds.objects.filter( + id__in=PosMachineTransactions.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + pos__guild__isnull=False, + paid=True + ).values_list('pos__guild__id', flat=True).distinct() + ) + else: + guilds = Guilds.objects.filter( + trash=False + ) + + return guilds + + def apply_search_filter(self, request, guilds): + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + guilds = guilds.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + return guilds + + def list(self, request, *args, **kwargs): + guilds = self.get_filtered_guilds(request) + guilds = self.apply_search_filter(request, guilds) + pos = PosMachineTransactions.objects.filter(trash=False, pos__guild__in=guilds, paid=True) + total_price = pos.aggregate(total=Sum('price'))[ + 'total'] or 0 + + result = { + 'lenGuild': len(guilds), + "totalPrice": total_price, + "lenPosTransaction": len(pos), + } + + return Response(result, status=status.HTTP_200_OK) + + +class CooperativeWarehouseDashboardViewSet(viewsets.ModelViewSet): + queryset = Cooperative.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CooperativeForAllocationsReportSerializer + filterset_class = CooperativeFilterSet + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + cooperatives = cooperatives.filter( + build_query(self.filterset_class.Meta.fields, search) + ) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + page = self.paginate_queryset(cooperatives) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + serializer = self.serializer_class(cooperatives, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DashboardForCooperativeWarehouseViewSet(viewsets.ModelViewSet): + queryset = Cooperative.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CooperativeForAllocationsReportSerializer + filterset_class = CooperativeFilterSet + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + cooperatives = Cooperative.objects.filter(trash=False).order_by('id') + value = request.GET.get('value') + search = request.GET.get('search') + products = { + "bran": "سبوس", + "barley": "جو", + "soy": "سویا", + "corn": "ذرت", + "sheep_concentrate": "کنسانتره گوسفندی", + "high_cow_concentrate": "کنسانتره گاو شیری پرتولید", + "medium_cow_concentrate": "کنسانتره گاو شیری متوسط", + "fattening_calf_concentrate": "کنسانتره گوساله پرواری", + } + name = products[request.GET.get('name')] + if value and search == 'filter': + if search != 'undefined' and search.strip(): + cooperatives = cooperatives.filter( + build_query(self.filterset_class.Meta.fields, search) + ) + cooperative_roles = LiveStockRolseProduct.objects.filter(cooperative__in=cooperatives, + parent_product__name=name) + product_transactions = ProductsTransactions.objects.filter(live_stack_products__in=cooperative_roles, + transaction__paid=True) + transactions = PosMachineTransactions.objects.filter( + pk__in=product_transactions.values_list('transaction', flat=True), trash=False) + transactions_amount = product_transactions.aggregate( + total=Sum('total_price') + )['total'] or 0 + + total_transactions_weight = product_transactions.aggregate( + total=Sum('cur_weight') + )['total'] or 0 + total_weight = cooperative_roles.aggregate( + total=Sum('total_weight') + )['total'] or 0 + total_receipt_weight = cooperative_roles.aggregate( + total=Sum('total_receipt_weight') + )['total'] or 0 + total_weight = cooperative_roles.aggregate( + total=Sum('total_weight') + )['total'] or 0 + total_remain_weight = cooperative_roles.aggregate( + total=Sum('total_remain_weight') + )['total'] or 0 + total_allocated_weight = cooperative_roles.aggregate( + total=Sum('total_allocated_weight') + )['total'] or 0 + result_dict = { + "totalTransactionsPrice": transactions_amount, + "totalTransactionsWeight": total_transactions_weight, + "transactions": len(transactions), + "totalWeight": total_weight, + "totalReceiptWeight": total_receipt_weight, + "totalAllocatedWeight": total_allocated_weight, + "totalRemainWeight": total_remain_weight, + } + return Response(result_dict, status=status.HTTP_200_OK) + + +class PriceConfirmationViewset(viewsets.ModelViewSet): + queryset = PriceConfirmation.objects.all() + permission_classes = [AllowAny] + serializer_class = PriceConfirmationSerializer + + def list(self, request, *args, **kwargs): + price_confirmation = PriceConfirmation.objects.filter(trash=False).first() + + serializer = self.serializer_class(price_confirmation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + price_confirmation = PriceConfirmation.objects.filter(trash=False).first() + serializer = self.serializer_class(price_confirmation) + serializer.update(instance=price_confirmation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CompanyBeneficiaryAccountViewset(viewsets.ModelViewSet): + queryset = CompanyBeneficiaryAccount.objects.all() + permission_classes = [AllowAny] + serializer_class = CompanyBeneficiaryAccountSerializer + + def create(self, request, *args, **kwargs): + # accounts = CompanyBeneficiaryAccount.objects.filter(trash=False) + # percents = accounts.aggregate(total=Sum('percent'))['total'] or 0 + # if request.data['percent'] + percents > 100: + # return Response({"result": " مجموع درصد ها نباید از 100 بیشتر شود !"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + account = serializer.create(validated_data=request.data) + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + accounts = CompanyBeneficiaryAccount.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(accounts, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + account = CompanyBeneficiaryAccount.objects.get(key=request.data['account_key']) + request.data.pop('account_key') + if 'percent' in request.data: + percent = request.data['percent'] + accounts = CompanyBeneficiaryAccount.objects.filter(trash=False).exclude(id=account.id) + percents = accounts.aggregate(total=Sum('percent'))['total'] or 0 + # if percent + percents > 100: + # return Response({"result": " مجموع درصد ها نباید از 100 بیشتر شود !"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(account) + serializer.update(instance=account, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + account = CompanyBeneficiaryAccount.objects.get(key=request.GET['account_key']) + account.trash = True + account.save() + return Response({"result": " با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +from django.db.models.expressions import RawSQL, Subquery + +from django.db.models.fields import IntegerField, BooleanField, TextField + + +def filter_json_text_field(*args, **kwargs): + queryset = PosMachineTransactions.objects.filter( + ~Q(additional=''), + additional__isnull=False, + additional__regex=r'^\s*{' + ) + + for i in range(0, len(args), 2): + if i + 1 >= len(args): + break + + key = args[i] + value = args[i + 1] + + if isinstance(value, bool): + field_type = BooleanField() + elif isinstance(value, int): + field_type = IntegerField() + else: + field_type = TextField() + + annotation_name = f'json_{key}' + queryset = queryset.annotate(**{ + annotation_name: RawSQL( + """ + jsonb_extract_path_text(additional::jsonb, %s) + """, + [key] + ) + }).annotate( + **{f'cast_{key}': Cast(F(annotation_name), field_type)} + ).filter(**{f'cast_{key}': value}) + + return queryset.filter(**kwargs) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_T(request): + results = filter_json_text_field( + 'cur_heavy', 2, + 'isTaavoni', True, + 'ownerNatcode', '4060603546' + ) + + return Response(results.count()) + + +class ReportPosDeviceSessionViewSet(viewsets.ModelViewSet): + queryset = POSDeviceSession.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = POSDeviceSessionForCompanySerializer + pagination_class = CustomPagination + filterset_class = POSDeviceSessionForCompanyFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.filter(trash=False, user=request.user).first() + company = request.GET.get('company') + role_check = request.GET['role'] + filters = {"trash": False} + if role_check in ('AdminX', 'SuperAdmin', 'Jahad', 'GuildRoom'): + if company and company is not None: + filters['key'] = request.GET['company'] + + else: + filters['user'] = user + pos_company = PosCompany.objects.filter(**filters) + + pos = POSMachine.objects.filter(pos_company__in=pos_company, trash=False).annotate( + session_count=Count('pos_device_session', filter=Q(pos_device_session__trash=False)) + ).filter(session_count__gt=0) + pos_sessions = POSDeviceSession.objects.filter(pos__in=pos, trash=False) + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + pos_sessions = pos_sessions.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + page = self.paginate_queryset(pos_sessions) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = POSDeviceSessionForCompanySerializer(pos_sessions, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ProteinGuildViewSet(viewsets.ModelViewSet): + queryset = ProteinGuild.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ProteinGuildSerializer + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + guild = user.protein_guild_user.all() + serializer = self.serializer_class(guild[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([TokenHasReadWriteScope]) +def get_all_pos_company(request): + pos_company = PosCompany.objects.filter(trash=False).order_by('id') + ser_data = PosCompanySerializer(pos_company, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def get_all_pos_version(request): + pos_version = PosDeviceVersion.objects.filter(trash=False).order_by('-code').values_list('code', + flat=True).distinct() + pos_company = PosCompany.objects.all().order_by('en_name') + ser_data = PosCompanyForPosVersionSerializer(pos_company, many=True) + result_dict = { + 'pos_version': pos_version, + 'company': ser_data.data + } + return Response(result_dict, 200) + + +class GetOnePosVersionViewSet(viewsets.ModelViewSet): + queryset = PosDeviceVersion.objects.all() + serializer_class = PosDeviceVersionForOneCompanySerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + pos_version = PosDeviceVersion.objects.filter(trash=False, code=int(request.GET['code'])).order_by( + 'company__en_name') + ser_data = self.serializer_class(pos_version, many=True) + + return Response(ser_data.data, 200) + + def update(self, request, *args, **kwargs): + key = request.data.pop('key') + query = self.queryset.get(key=key) + serializer = self.serializer_class(query) + serializer.update(instance=query, validated_data=request.data) + return Response(serializer.data, 200) + + def create(self, request, *args, **kwargs): + company_id = request.data.pop('id', None) + if company_id: + company = PosCompany.objects.get(id=int(company_id)) + + else: + company = PosCompany.objects.filter(trash=False, en_name='Unknown').first() + + if self.queryset.filter(trash=False, company=company, code=int(request.data['code'])).exists(): + return Response({"result": f'برای {company.name} نسخه {request.data["code"]} قبلا ثبت شده است.'}) # noqa + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + pos_device_version = serializer.create(validated_data=request.data) + pos_device_version.company = company + pos_device_version.save() + return Response({"result": f"با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +class CommonlyUsedViewSet(viewsets.ModelViewSet): + queryset = CommonlyUsed.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = CommonlyUsedSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = CommonlyUsedFilterSet + filterset_fields = [ + 'kill_house__name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'guild__guilds_name', + 'guild__user__last_name', + 'guild__user__first_name', + 'guild__user__fullname', + 'guild__user__mobile', + + ] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.data.pop('role') + guilds = Guilds.objects.filter(key__in=request.data.pop('guild_key_list'), trash=False) + + serializer = self.serializer_class(data=request.data) + if not serializer.is_valid(): + return Response(serializer.errors) + + validated_data = serializer.validated_data + if role == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + + commonly_used_instances = [ + CommonlyUsed( + **validated_data, + kill_house=kill_house, + guild=guild + ) + for guild in guilds + ] + + else: + steward = Guilds.objects.get(user=user, steward=True, trash=False) + + commonly_used_instances = [ + CommonlyUsed( + **validated_data, + steward=steward, + guild=guild + ) + for guild in guilds + ] + + CommonlyUsed.objects.bulk_create(commonly_used_instances) + + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_201_CREATED) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + role = request.GET.get('role') + today = datetime.now().date() + allocations = None + commonly_used = None + + if role == 'KillHouse': + kill_house = KillHouse.objects.filter( + kill_house_operator__user=user, trash=False + ).first() + + allocations = StewardAllocation.objects.filter( + Q(to_steward__isnull=False) | Q(to_guilds__isnull=False), + kill_house=kill_house, + date__date=today + ) + + filter_args = {'kill_house': kill_house, 'trash': False} + + else: + steward = Guilds.objects.get( + user=user, steward=True, trash=False + ) + + allocations = StewardAllocation.objects.filter( + Q(to_steward__isnull=False) | Q(to_guilds__isnull=False), + steward=steward, + date__date=today + ) + + filter_args = {'steward': steward, 'trash': False} + + excluded_guild_ids = allocations.filter(to_guilds__isnull=False).values_list('to_guilds', flat=True) + excluded_steward_ids = allocations.filter(to_steward__isnull=False).values_list('to_steward', flat=True) + + commonly_used = CommonlyUsed.objects.filter(**filter_args).exclude( + Q(guild__in=excluded_guild_ids) | Q(guild__in=excluded_steward_ids) + ) + + if 'search' in request.GET: + commonly_used_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=commonly_used + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=commonly_used) + commonly_used_list = ps.filter() + commonly_used = [] if len(commonly_used_list) == 0 else commonly_used_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(commonly_used) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(commonly_used, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + commonly_used = CommonlyUsed.objects.get(key=request.GET["commonly_used_key"], trash=False) + commonly_used.trash = True + commonly_used.save() + return Response({"result": "با موفقیت حذف شد."}, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def get_all_guilds(request): + steward = Guilds.objects.filter(trash=False, steward=True).select_related('user').only('key', + 'guilds_name', + 'user__mobile', + 'user__fullname') \ + .order_by('id') + ser_data = GetAllGuildsSerializer(steward, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class PercentageDropLimitationViewset(viewsets.ModelViewSet): + queryset = PercentageDropLimitation.objects.all() + permission_classes = [AllowAny] + serializer_class = PercentageDropLimitationSerializer + + def list(self, request, *args, **kwargs): + drop_limitation = PercentageDropLimitation.objects.filter(trash=False).first() + + serializer = self.serializer_class(drop_limitation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + drop_limitation = PercentageDropLimitation.objects.filter(trash=False).first() + serializer = self.serializer_class(drop_limitation) + serializer.update(instance=drop_limitation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class UploadImageLimitationViewset(viewsets.ModelViewSet): + queryset = UploadImageLimitation.objects.all() + permission_classes = [AllowAny] + serializer_class = UploadImageLimitationSerializer + + def list(self, request, *args, **kwargs): + image_limitation = UploadImageLimitation.objects.filter(trash=False).first() + + serializer = self.serializer_class(image_limitation) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + image_limitation = UploadImageLimitation.objects.filter(trash=False).first() + serializer = self.serializer_class(image_limitation) + serializer.update(instance=image_limitation, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ApkInfoViewset(viewsets.ModelViewSet): + queryset = ApkInfo.objects.all() + permission_classes = [AllowAny] + serializer_class = ApkInfoSerializer + + def list(self, request, *args, **kwargs): + apk = ApkInfo.objects.filter(trash=False).first() + + serializer = self.serializer_class(apk) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + apk = ApkInfo.objects.filter(trash=False).first() + serializer = self.serializer_class(apk) + serializer.update(instance=apk, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class DirectBuyingVerificationViewset(viewsets.ModelViewSet): + queryset = DirectBuyingVerification.objects.filter(trash=False) + permission_classes = [AllowAny] + serializer_class = DirectBuyingVerificationSerializer + + def get_object(self): + instance, created = DirectBuyingVerification.objects.get_or_create( + trash=False) + return instance + + def list(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class FinePermissionViewset(viewsets.ModelViewSet): + queryset = FinePermission.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = FinePermissionSerializer + + def list(self, request, *args, **kwargs): + fines = FinePermission.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(fines, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + fine = FinePermission.objects.get(trash=False, key=request.data['key']) + serializer = self.serializer_class(fine) + serializer.update(instance=fine, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ShowMarketRequestViewset(viewsets.ModelViewSet): + queryset = ShowMarketRequest.objects.filter(trash=False) + permission_classes = [AllowAny] + serializer_class = ShowMarketRequestSerializer + + def get_object(self): + instance, created = ShowMarketRequest.objects.get_or_create( + trash=False) + return instance + + def list(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class IndexWeightCategoryViewSet(viewsets.ModelViewSet): + queryset = IndexWeightCategory.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = IndexWeightCategorySerializer + + def list(self, request, *args, **kwargs): + index_weight = IndexWeightCategory.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(index_weight, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + index_weight = IndexWeightCategory.objects.get(trash=False, key=request.data['key']) + serializer = self.serializer_class(index_weight) + serializer.update(instance=index_weight, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class GetAllPoultryForPoultryScienceViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + poultry_science = PoultryScience.objects.filter(trash=False, poultry__isnull=False).values_list('poultry__id', + flat=True).distinct() + + poultry = Poultry.objects.filter(trash=False).exclude(id__in=poultry_science).select_related('user', + 'address').order_by( + 'id') + serializer = GetAllPoultryForPoultryScienceSerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryScienceViewSet(viewsets.ModelViewSet): + queryset = PoultryScience.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryScienceSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryScienceFilterSet + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_science = user.poultry_science_user.all() + serializer = self.serializer_class(poultry_science[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + query = self.queryset.get(id=request.data['poultry_science_id']) + query.poultry.set(request.data['poultry']) + return Response({'result': 'باموفقیت انجام شد.'}, status=status.HTTP_200_OK) + + def list(self, request, *args, **kwargs): + query = self.queryset + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + query = query.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(query) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryScienceReportViewSet(viewsets.ModelViewSet): + queryset = PoultryScienceReport.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryScienceReportSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryScienceReportFilterSet + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + query = self.queryset.order_by('-id') + role = request.GET['role'] + + if role == 'PoultryScience': + query = query.filter(poultry_science__user=user) + + elif role == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + hatching_ids = PoultryHatching.objects.filter( + poultry__in=poultries + ).values_list('id', flat=True) + query = query.filter(hatching__id__in=hatching_ids) + + elif role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + hatching_ids = PoultryHatching.objects.filter( + poultry__city_operator=city_operator.unit_name + ).values_list('id', flat=True) + query = query.filter(hatching__id__in=hatching_ids) + + elif role == 'CityJahad': + hatching_ids = PoultryHatching.objects.filter( + poultry__address__city=user.city + ).values_list('id', flat=True) + query = query.filter(hatching__id__in=hatching_ids) + + elif role == 'CityPoultry': + hatching_ids = PoultryHatching.objects.filter( + poultry__address__city=user.city + ).values_list('id', flat=True) + query = query.filter(hatching__id__in=hatching_ids) + + else: + query = query.filter(user=user) + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + query = query.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(query) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = get_object_or_404(SystemUserProfile, user=request.user, trash=False) + poultry_science = PoultryScience.objects.filter(trash=False, user=user).first() + + # if poultry_science: + # if not poultry_science.poultry.exists(): + # return Response( + # {"result": "برای این کارشناس مرغداری ثبت نشده است!"}, + # status=status.HTTP_403_FORBIDDEN + # ) + + hatching_id = request.data.get("hatching_id") + hatching = PoultryHatching.objects.filter(trash=False, id=hatching_id).first() + # if self.queryset.filter(hatching=hatching).exists(): + # return Response( + # {"result": "برای این واحد قبلا گزارش ثبت شده است!"}, + # status=status.HTTP_403_FORBIDDEN + # ) + if not hatching: + return Response( + {"result": "جوجه‌ریزی وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN + ) + + # دریافت JSON از request + report_json = request.data.get('json') or request.data.get('report_information') + if isinstance(report_json, str): + try: + report_json = json.loads(report_json) + except json.JSONDecodeError: + report_json = None + + poultry_science_report = PoultryScienceReport( + hatching=hatching, + poultry_science=poultry_science or None, + user=user, + reporter_fullname=user.fullname, + reporter_mobile=user.mobile, + reporter_role=request.data.get('role'), + date=datetime.now(), + lat=request.data.get('lat', None), + log=request.data.get('log', None), + report_information=report_json, + chicken_age=hatching.chicken_age, + ) + + # files = request.FILES.getlist("file") + # if not files: + # single_file = request.FILES.get("file") + # if single_file: + # files = [single_file] + # if files: + # poultry_science_report.image = [ + # send_image_to_server_for_poultry_science(f, f.name) for f in files + # ] + + poultry_science_report.save() + + ser_data = self.serializer_class(poultry_science_report) + return Response(ser_data.data, status=status.HTTP_201_CREATED) + + +class PoultryAndHatchingForPoultryScience(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + + def get(self, request): + type_page = request.GET.get('type') + hatching_has_report = request.GET.get('report') + role = request.GET.get('role') + user = get_object_or_404(SystemUserProfile, user=request.user, trash=False) + poultry_science = PoultryScience.objects.filter(trash=False, user=user).first() + if poultry_science: + poultry = poultry_science.poultry.filter(trash=False) + hatching = PoultryHatching.objects.filter( + state='pending', + allow_hatching='pending', + archive=False, + trash=False, + poultry__in=poultry + ).order_by('-date', 'poultry') + else: + hatching = PoultryHatching.objects.filter( + state='pending', + allow_hatching='pending', + archive=False, + trash=False, + ).order_by('-date', 'poultry') + + if type_page == 'farm': + + poultry = poultry_science.poultry.filter(trash=False) + page_size = request.query_params.get('page_size') + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry) + if page is not None: + serializer = PoultryDetailForPoultryScienceSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = PoultryDetailForPoultryScienceSerializer(poultry, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + elif type_page == 'hatching': + if hatching_has_report: + hatching = hatching.exclude( + id__in=PoultryScienceReport.objects.filter(trash=False).values_list('hatching__id', + flat=True).distinct()) + if role == 'PoultryScience': + poultry_science = PoultryScience.objects.filter(user=user, trash=False) + allowed_poultry_ids = poultry_science.values_list('poultry', flat=True).distinct() + hatching = hatching.filter(poultry__in=allowed_poultry_ids) + + elif role == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + hatching = hatching.filter( + poultry__in=poultries + ) + elif role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + hatching = hatching.filter( + poultry__city_operator=city_operator.unit_name + ) + elif role == 'CityJahad': + city_jahad = CityJahad.objects.get(user=user, trash=False) + hatching = hatching.filter( + poultry__address__city=city_jahad.address.city + ) + elif role == 'CityPoultry': + city_poultry = CityPoultry.objects.get(user=user, trash=False) + hatching = hatching.filter( + poultry__address__city=city_poultry.city + ) + else: + hatching = hatching + + page_size = request.query_params.get('page_size') + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(hatching) + if page is not None: + serializer = PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + ser_data = PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer(hatching, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + else: + hatching_aggregate = hatching.aggregate( + total_quantity=Sum('quantity'), + total_left_over=Sum('left_over'), + total_losses=Sum('losses'), + total_killed_quantity=Sum('killed_quantity'), + ) + poultry_count = hatching.values_list('poultry', flat=True).distinct() + result = { + "farm_count": poultry_count.count(), + "hatching_count": hatching.count(), + "hatching_quantity": hatching_aggregate['total_quantity'] or 0, + "hatching_left_over": hatching_aggregate['total_left_over'] or 0, + "hatching_losses": hatching_aggregate['total_losses'] or 0, + "hatching_killed_quantity": hatching_aggregate['total_killed_quantity'] or 0, + "hatching_max_age": hatching.order_by( + '-chicken_age').first().chicken_age if hatching.exists() else None, + "hatching_min_age": hatching.order_by('chicken_age').first().chicken_age if hatching.exists() else None, + } + return Response(result, status=status.HTTP_200_OK) + + +class AllowRegisterCodeForGuildsViewSet(viewsets.ModelViewSet): + queryset = AllowRegisterCodeForGuilds.objects.filter(trash=False) + serializer_class = AllowRegisterCodeForGuildsSerializer + permission_classes = [TokenHasReadWriteScope] + + +class StewardAppLoginViewSet(viewsets.ModelViewSet): + queryset = StewardAppLogin.objects.filter(trash=False) + serializer_class = StewardAppLoginSerializer + permission_classes = [AllowAny] + + def create(self, request, *args, **kwargs): + steward = Guilds.objects.get(user__mobile=request.data['mobile'], trash=False) + request.data.pop('mobile') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + login = serializer.create(validated_data=request.data) + login.steward = steward + login.save() + return Response({"result": f"با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +class GuildsGeneralConfigsViewSet(viewsets.ModelViewSet): + queryset = GuildsGeneralConfigs.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsGeneralConfigsSerializer + + def list(self, request, *args, **kwargs): + configs = GuildsGeneralConfigs.objects.filter(trash=False).first() + serializer = self.serializer_class(configs) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + stewards = Guilds.objects.filter(trash=False, steward=True).order_by('id') + configs = GuildsGeneralConfigs.objects.filter(trash=False).first() + serializer = self.serializer_class(configs, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + update_data = serializer.validated_data + fields_to_update = [] + for field in update_data.keys(): + if hasattr(Guilds, field): + fields_to_update.append(field) + for steward in stewards: + setattr(steward, field, update_data[field]) + + if fields_to_update: + Guilds.objects.bulk_update(stewards, fields_to_update) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class GuildsForGeneralConfigsViewSet(viewsets.ModelViewSet): + queryset = Guilds.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = GuildsForGeneralConfigsSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsForGeneralConfigsFilterSet + + def list(self, request, *args, **kwargs): + stewards = Guilds.objects.filter(trash=False, steward=True).order_by('id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + stewards = stewards.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(stewards) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(stewards, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + steward = Guilds.objects.get(key=request.data['key']) + serializer = self.serializer_class(steward) + serializer.update(instance=steward, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class StewardSalesInformationViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(user=user, steward=True, active=True, trash=False) + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, warehouse=True) + + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q( + to_steward=steward), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) + + output_steward_allocations = guild_steward_allocations.filter(Q(guilds=steward) | Q(steward=steward)) + input_steward_allocations = guild_steward_allocations.filter( + Q(to_guilds=steward) | Q(to_steward=steward)) + + steward_free_bar_informations = StewardFreeBarInformation.objects.filter(steward=steward, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( + steward=steward, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + + segmentations = PosSegmentation.objects.filter(guild=steward, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False, + warehouse=True) + + total_input_allocations_governmental_weight = \ + input_steward_allocations.filter(receiver_state='accepted', quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_input_allocations_free_weight = \ + input_steward_allocations.filter(receiver_state='accepted', quota='free').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_input_free_bar_carcasses_weight = \ + steward_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_steward_free_sale_bar_carcasses_weight = \ + steward_free_Sale_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_steward_free_sale_bar_carcasses_governmental_weight = \ + steward_free_Sale_bar_informations.filter(quota='governmental').aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_house_free_sale_bar_carcasses_free_weight = \ + steward_free_Sale_bar_informations.filter(quota='free').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_in_province_allocations_weight = \ + output_steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_in_province_allocations_governmental_weight = \ + output_steward_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_steward_in_province_allocations_free_weight = \ + output_steward_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + pos_allocated_weight_info = transactions.aggregate( + pos_allocated_weight=Sum('cur_weight'), + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + pos_allocated_weight = pos_allocated_weight_info['pos_allocated_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + + total_governmental_input_weight = total_input_allocations_governmental_weight + total_free_input_weight = total_input_allocations_free_weight + total_input_free_bar_carcasses_weight + total_governmental_output_weight = total_steward_free_sale_bar_carcasses_governmental_weight + segmentations_governmental_weight + total_steward_in_province_allocations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output_weight = total_steward_house_free_sale_bar_carcasses_free_weight + total_steward_in_province_allocations_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - archives_free_weight + + result = { + + "total_governmental_input_weight": int(total_governmental_input_weight), + "total_free_input_weight": int(total_free_input_weight), + "total_governmental_output_weight": int(total_governmental_output_weight), + "total_free_output_weight": int(total_free_output_weight), + "total_governmental_remain_weight": int(total_governmental_remain_weight), + "total_free_remain_weight": int(total_free_remain_weight), + "total_steward_free_sale_bar_carcasses_weight": int(total_steward_free_sale_bar_carcasses_weight), + "total_steward_in_province_allocations_weight": int(total_steward_in_province_allocations_weight), + "segmentations_weight": int(segmentations_weight), + "total_selling_in_province_governmental_weight": steward.total_selling_in_province_governmental_weight, + "total_selling_in_province_free_weight": steward.total_selling_in_province_free_weight, + "total_commitment_selling_in_province_governmental_weight": steward.total_commitment_selling_in_province_governmental_weight, + "total_commitment_selling_in_province_governmental_remain_weight": steward.total_commitment_selling_in_province_governmental_remain_weight, + "total_commitment_selling_in_province_free_weight": steward.total_commitment_selling_in_province_free_weight, + "total_commitment_selling_in_province_free_remain_weight": steward.total_commitment_selling_in_province_free_remain_weight, + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "pos_governmental_allocated_weight": int(pos_governmental_allocated_weight / 1000), + "pos_free_allocated_weight": int(pos_free_allocated_weight / 1000), + "archives_governmental_weight": archives_governmental_weight, + "archives_free_weight": archives_free_weight, + + } + + return Response(result, status=200) + + +class ReturnStewardAllocationViewSet(viewsets.ModelViewSet): + queryset = StewardAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = StewardAllocationSerializer + + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + allocation = StewardAllocation.objects.get(key=request.data['key']) + quota = allocation.quota + if allocation.kill_house: + if quota == 'governmental': + if allocation.kill_house.total_remain_warehouse_governmental_weight < allocation.real_weight_of_carcasses: + return Response({"result": "باقیمانده وزن دولتی کمتر از تخصیص برگشت داده شده است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + if allocation.kill_house.total_remain_warehouse_free_weight < allocation.real_weight_of_carcasses: + return Response({"result": "باقیمانده وزن آزاد کمتر از تخصیص برگشت داده شده است!"}, + status=status.HTTP_403_FORBIDDEN) + allocation.trash = False + allocation.return_trash = True + allocation.returner_trash = user.fullname + allocation.return_trash_date = datetime.now() + allocation.save() + if allocation.seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(allocation.product) + else: + guild_steward_allocations_product_warehousing(allocation.product) + return Response({"result": "با موفقیت انجام شد!"}, status=status.HTTP_200_OK) + + +class StewardRequestViewSet(viewsets.ModelViewSet): + queryset = StewardRequest.objects.filter(trash=False) + serializer_class = StewardRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(key=request.data['key']) + + request.data.pop('key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + steward_request = serializer.create(validated_data=request.data) + steward_request.steward = steward + steward_request.registerer = user.fullname + steward_request.registerer_mobile = user.mobile + steward_request.save() + return Response({"result": f"با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + +class RestrictionCarcassDistributionViewSet(viewsets.ModelViewSet): + queryset = RestrictionCarcassDistribution.objects.filter(trash=False).order_by('id') + serializer_class = RestrictionCarcassDistributionSerializer + permission_classes = [TokenHasReadWriteScope] + + +class AllowRegisterCodeForKillHouseFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False) + serializer_class = AllowRegisterCodeForKillHouseFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + def get_queryset(self): + return AllowRegisterCodeForKillHouseFreeSaleBarInformation.objects.filter(trash=False) + + def list(self, request, *args, **kwargs): + instance = self.get_queryset().first() + serializer = self.get_serializer(instance) + return Response(serializer.data) + + +class AllowRegisterCodeForStewardFreeSaleBarInformationViewSet(viewsets.ModelViewSet): + queryset = AllowRegisterCodeForStewardFreeSaleBarInformation.objects.filter(trash=False) + serializer_class = AllowRegisterCodeForStewardFreeSaleBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + def get_queryset(self): + return AllowRegisterCodeForStewardFreeSaleBarInformation.objects.filter(trash=False) + + def list(self, request, *args, **kwargs): + instance = self.get_queryset().first() + serializer = self.get_serializer(instance) + return Response(serializer.data) + + +class LimitationForDirectPurchaseAndBarInformationViewSet(viewsets.ModelViewSet): + queryset = LimitationForDirectPurchaseAndBarInformation.objects.filter(trash=False) + serializer_class = LimitationForDirectPurchaseAndBarInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + def get_queryset(self): + return LimitationForDirectPurchaseAndBarInformation.objects.filter(trash=False) + + def list(self, request, *args, **kwargs): + instance = self.get_queryset().first() + serializer = self.get_serializer(instance) + return Response(serializer.data) + + +class PosSalesInformationViewSet(APIView): + permission_classes = [AllowAny] + + def kill_house_info(self, kill_house): + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False) + pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + pos_governmental_allocated_weight = transactions.filter(price_approved=True).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + pos_free_allocated_weight = transactions.filter(price_approved=False).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False, warehouse=True) + + kill_house_requests = KillHouseRequest.objects.filter( + input_warehouse=kill_house, + temporary_trash=False, + temporary_deleted=False, + trash=False, calculate_status=True, warehouse=True) + + kill_house_free_bar_informations = KillHouseFreeBarInformation.objects.filter(input_warehouse=kill_house, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, + warehouse=True).exclude( + entered_message='ورود به انبار مجازی') + kill_house_free_Sale_bar_informations = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False, + temporary_trash=False, + temporary_deleted=False, + calculate_status=True, warehouse=True) + kill_house_allocations = StewardAllocation.objects.filter(kill_house=kill_house, trash=False, + receiver_state__in=('pending', 'accepted'), + temporary_trash=False, + temporary_deleted=False, + to_cold_house__isnull=True, + calculate_status=True, warehouse=True) + + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, trash=False, warehouse=True) + cold_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, + to_cold_house__isnull=False, + receiver_state__in=('accepted', 'pending'), + trash=False, warehouse=True) + total_entered_kill_house_requests_carcasses_governmental_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=False).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + total_entered_kill_house_requests_carcasses_free_weight = \ + kill_house_requests.filter(ware_house_confirmation=True, + province_request__poultry_request__free_sale_in_province=True).aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + total_entered_kill_house_free_bar_carcasses_weight = \ + kill_house_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_governmental_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_free_sale__bar_carcasses_free_weight = \ + kill_house_free_Sale_bar_informations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_kill_house_allocations_governmental_weight = \ + kill_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_kill_house_allocations_free_weight = \ + kill_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + + cold_house_allocations_governmental_weight = \ + cold_house_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + cold_house_allocations_free_weight = \ + cold_house_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_governmental_input_weight = total_entered_kill_house_requests_carcasses_governmental_weight + total_free_input_weight = total_entered_kill_house_requests_carcasses_free_weight + total_entered_kill_house_free_bar_carcasses_weight + total_governmental_output_weight = total_kill_house_free_sale__bar_carcasses_governmental_weight + segmentations_governmental_weight + total_kill_house_allocations_governmental_weight + cold_house_allocations_governmental_weight + int( + (pos_governmental_allocated_weight / 1000)) + total_free_output_weight = total_kill_house_free_sale__bar_carcasses_free_weight + total_kill_house_allocations_free_weight + segmentations_free_weight + cold_house_allocations_free_weight + int( + pos_free_allocated_weight / 1000) + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - archives_free_weight + result = { + + "total_governmental_input_weight": int(total_governmental_input_weight), + "total_free_input_weight": int(total_free_input_weight), + "total_governmental_output_weight": int(total_governmental_output_weight), + "total_free_output_weight": int(total_free_output_weight), + "total_governmental_remain_weight": int(total_governmental_remain_weight), + "total_free_remain_weight": int(total_free_remain_weight), + "segmentations_weight": int(segmentations_weight), + "total_output": int(total_governmental_output_weight + total_free_output_weight), + "total_input": int(total_governmental_input_weight + total_free_input_weight), + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "archives_governmental_weight": archives_governmental_weight, + "archives_free_weight": archives_free_weight, + + } + + return result + + def guild_steward_info(self, steward): + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, trash=False) + pos_allocated_weight = transactions.aggregate(total=Sum('cur_weight'))['total'] or 0 + pos_governmental_allocated_weight = transactions.filter(price_approved=True).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + pos_free_allocated_weight = transactions.filter(price_approved=False).aggregate(total=Sum('cur_weight'))[ + 'total'] or 0 + + archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, warehouse=True) + + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q( + to_steward=steward), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) + + output_steward_allocations = guild_steward_allocations.filter(Q(guilds=steward) | Q(steward=steward)) + input_steward_allocations = guild_steward_allocations.filter( + Q(to_guilds=steward) | Q(to_steward=steward)) + + steward_free_bar_informations = StewardFreeBarInformation.objects.filter(steward=steward, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( + steward=steward, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + + segmentations = PosSegmentation.objects.filter(guild=steward, trash=False, warehouse=True) + + total_input_allocations_governmental_weight = \ + input_steward_allocations.filter(receiver_state='accepted', quota='governmental').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_input_allocations_free_weight = \ + input_steward_allocations.filter(receiver_state='accepted', quota='free').aggregate( + total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_input_free_bar_carcasses_weight = \ + steward_free_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_steward_free_sale_bar_carcasses_weight = \ + steward_free_Sale_bar_informations.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_steward_free_sale_bar_carcasses_governmental_weight = \ + steward_free_Sale_bar_informations.filter(quota='governmental').aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_house_free_sale_bar_carcasses_free_weight = \ + steward_free_Sale_bar_informations.filter(quota='free').aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_in_province_allocations_weight = \ + output_steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + total_steward_in_province_allocations_governmental_weight = \ + output_steward_allocations.filter(quota='governmental').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + total_steward_in_province_allocations_free_weight = \ + output_steward_allocations.filter(quota='free').aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentations_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_governmental_weight = \ + segmentations.filter(quota='governmental').aggregate(total=Sum('weight'))[ + 'total'] or 0 + segmentations_free_weight = \ + segmentations.filter(quota='free').aggregate(total=Sum('weight'))[ + 'total'] or 0 + + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_governmental_input_weight = total_input_allocations_governmental_weight + total_free_input_weight = total_input_allocations_free_weight + total_input_free_bar_carcasses_weight + total_governmental_output_weight = total_steward_free_sale_bar_carcasses_governmental_weight + segmentations_governmental_weight + total_steward_in_province_allocations_governmental_weight + int( + (pos_governmental_allocated_weight / 1000)) + total_free_output_weight = total_steward_house_free_sale_bar_carcasses_free_weight + total_steward_in_province_allocations_free_weight + segmentations_free_weight + int( + (pos_free_allocated_weight / 1000)) + total_governmental_remain_weight = ( + total_governmental_input_weight - total_governmental_output_weight) - archives_governmental_weight + total_free_remain_weight = (total_free_input_weight - total_free_output_weight) - archives_free_weight + + result = { + + "total_governmental_input_weight": int(total_governmental_input_weight), + "total_free_input_weight": int(total_free_input_weight), + "total_governmental_output_weight": int(total_governmental_output_weight), + "total_free_output_weight": int(total_free_output_weight), + "total_governmental_remain_weight": int(total_governmental_remain_weight), + "total_free_remain_weight": int(total_free_remain_weight), + "segmentations_weight": int(segmentations_weight), + "total_output": int(total_governmental_output_weight + total_free_output_weight), + "total_input": int(total_governmental_input_weight + total_free_input_weight), + "pos_allocated_weight": int(pos_allocated_weight / 1000), + "archives_governmental_weight": archives_governmental_weight, + "archives_free_weight": archives_free_weight, + + } + + return result + + def get(self, request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + if pos.kill_house: + result = self.kill_house_info(pos.kill_house) + else: + + result = self.guild_steward_info(pos.guild) + + return Response(result, status=status.HTTP_200_OK) + + +class PosColdHouseViewSet(APIView): + permission_classes = [AllowAny] + serializer_class = ColdHouseSerializer + + def get(self, request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + + cold_house = ColdHouse.objects.filter(trash=False).order_by('kill_house') + + serializer = ColdHouseSerializer(cold_house, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PosRemainWeightViewSet(APIView): + permission_classes = [AllowAny] + + def kill_house_info(self, kill_house): + + today = datetime.now().date() + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + days = (two_days_ago, yesterday, today) + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False, date__date__gte=two_days_ago, + date__date__lte=today) + + kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, + kill_request__recive_date__date__gte=two_days_ago, + kill_request__recive_date__date__lte=today, + ware_house_confirmation=True, trash=False, + calculate_status=True, warehouse=True) + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(trash=False, + calculate_status=True, warehouse=True, + date__date__gte=two_days_ago, + date__date__lte=today, + input_warehouse=kill_house) \ + .exclude(entered_message='ورود به انبار مجازی') + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, + receiver_state__in=('pending', 'accepted'), production_date__date__gte=two_days_ago, + production_date__date__lte=today) + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + production_date__date__gte=two_days_ago, + production_date__date__lte=today, + trash=False, + calculate_status=True, + warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, production_date__date__gte=two_days_ago, + production_date__date__lte=today, trash=False, + warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date__gte=two_days_ago, + transaction__date__date__lte=today, trash=False, + warehouse=True) + + governmental_list = [] + free_list = [] + final_dict = {} + + for day in days: + kill_house_requests_info = kill_house_requests.aggregate( + total_kill_house_request_governmental_weight=Sum('ware_house_accepted_real_weight', filter=Q( + province_request__poultry_request__free_sale_in_province=False, + kill_request__recive_date__date=day)), + total_kill_house_request_free_weight=Sum('ware_house_accepted_real_weight', filter=Q( + province_request__poultry_request__free_sale_in_province=True, + kill_request__recive_date__date=day)), + + ) + + kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( + total_kill_house_free_buying_bars_weight=Sum('weight_of_carcasses', filter=Q(date__date=day))) + + kill_house_allocations_info = kill_house_allocations.aggregate( + total_kill_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental', + production_date__date=day)), + total_kill_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)), + + ) + + kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( + total_kill_house_free_sale_bars_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental', + production_date__date=day)), + total_kill_house_free_sale_bars_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)), + + ) + + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental', production_date__date=day)), + segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), + + ) + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True, transaction__date__date=day)), + pos_free_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=False, transaction__date__date=day)), + + ) + + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental', date__date=day)), + archives_free_weight=Sum('weight', + filter=Q(quota='free', date__date=day)), + + ) + + total_kill_house_request_governmental_weight = kill_house_requests_info[ + 'total_kill_house_request_governmental_weight'] or 0 + total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 + total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ + 'total_kill_house_free_buying_bars_weight'] or 0 + total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_governmental_weight'] or 0 + total_kill_house_allocations_free_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_free_weight'] or 0 + total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_governmental_weight'] or 0 + total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + total_governmental_input = total_kill_house_request_governmental_weight + total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight + total_governmental_output = total_kill_house_allocations_governmental_weight + total_kill_house_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output = total_kill_house_allocations_free_weight + total_kill_house_free_sale_bars_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + governmental_data = { + 'day': jdatetime.date.fromgregorian(date=day).strftime('%Y-%m-%d'), + 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, + } + free_data = { + 'day': jdatetime.date.fromgregorian(date=day).strftime('%Y-%m-%d'), + 'amount': (total_free_input - total_free_output) - archives_free_weight, + } + + governmental_list.append(governmental_data) + free_list.append(free_data) + final_dict['governmental'] = governmental_list + final_dict['free'] = free_list + return final_dict + + def guild_steward_info(self, steward): + today = datetime.now().date() + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + days = (two_days_ago, yesterday, today) + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, warehouse=True, + date__date__gte=two_days_ago, date__date__lte=today) + + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q( + to_steward=steward), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) + + output_steward_allocations = guild_steward_allocations.filter(Q(guilds=steward) | Q(steward=steward), + production_date__date__gte=two_days_ago, + production_date__date__lte=today, ) + input_steward_allocations = guild_steward_allocations.filter( + Q(to_guilds=steward) | Q(to_steward=steward), date__date__gte=two_days_ago, date__date__lte=today, ) + + steward_free_bar_informations = StewardFreeBarInformation.objects.filter(steward=steward, + date__date__gte=two_days_ago, + date__date__lte=today, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( + steward=steward, + production_date__date__gte=two_days_ago, + production_date__date__lte=today, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + + segmentations = PosSegmentation.objects.filter(guild=steward, production_date__date__gte=two_days_ago, + production_date__date__lte=today, trash=False, warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date__gte=two_days_ago, + transaction__date__date__lte=today, trash=False, + warehouse=True) + + governmental_list = [] + free_list = [] + final_dict = {} + + for day in days: + input_steward_allocations_info = input_steward_allocations.aggregate( + total_input_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', + quota='governmental', date__date=day)), + total_input_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', quota='free', + date__date=day)) + ) + output_steward_allocations_info = output_steward_allocations.aggregate( + total_output_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental', + production_date__date=day)), + total_output_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)) + + ) + steward_free_bar_info = steward_free_bar_informations.aggregate( + total_free_bar_weight=Sum('weight_of_carcasses', filter=Q(date__date=day)), + + ) + + steward_free_Sale_bar_info = steward_free_Sale_bar_informations.aggregate( + total_free_Sale_bar_governmental_weight=Sum('weight_of_carcasses', + filter=Q(quota='governmental', production_date__date=day)), + total_free_Sale_bar_free_weight=Sum('weight_of_carcasses', + filter=Q(quota='free', production_date__date=day)) + + ) + + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental', production_date__date=day)), + segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), + + ) + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True, transaction__date__date=day)), + pos_free_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=False, transaction__date__date=day)), + + ) + + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental', date__date=day)), + archives_free_weight=Sum('weight', + filter=Q(quota='free', date__date=day)), + + ) + + total_input_steward_allocations_governmental_weight = input_steward_allocations_info[ + 'total_input_allocations_governmental_weight'] or 0 + total_input_steward_allocations_free_weight = input_steward_allocations_info[ + 'total_input_allocations_free_weight'] or 0 + total_steward_free_buying_bars_weight = steward_free_bar_info[ + 'total_free_bar_weight'] or 0 + total_output_steward_allocations_governmental_weight = output_steward_allocations_info[ + 'total_output_allocations_governmental_weight'] or 0 + total_output_steward_allocations_free_weight = output_steward_allocations_info[ + 'total_output_allocations_free_weight'] or 0 + total_steward_free_sale_bars_governmental_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_governmental_weight'] or 0 + total_steward_free_sale_bars_free_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + total_governmental_input = total_input_steward_allocations_governmental_weight + total_free_input = total_input_steward_allocations_free_weight + total_steward_free_buying_bars_weight + total_governmental_output = total_output_steward_allocations_governmental_weight + total_steward_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output = total_output_steward_allocations_free_weight + total_steward_free_sale_bars_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + governmental_data = { + 'day': jdatetime.date.fromgregorian(date=day).strftime('%Y-%m-%d'), + 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, + } + free_data = { + 'day': jdatetime.date.fromgregorian(date=day).strftime('%Y-%m-%d'), + 'amount': (total_free_input - total_free_output) - archives_free_weight, + } + + governmental_list.append(governmental_data) + free_list.append(free_data) + final_dict['governmental'] = governmental_list + final_dict['free'] = free_list + return final_dict + + def get(self, request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + + if pos.kill_house: + final_dict = self.kill_house_info(pos.kill_house) + else: + final_dict = self.guild_steward_info(pos.guild) + + return Response(final_dict, status=status.HTTP_200_OK) + + +class PosRemainWeightWithDateViewSet(APIView): + permission_classes = [AllowAny] + + def kill_house_info(self, kill_house, date): + + product = RolesProducts.objects.filter(kill_house=kill_house, trash=False, name='مرغ گرم').first() + + kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, + kill_request__recive_date__date=date, + ware_house_confirmation=True, trash=False, + calculate_status=True, warehouse=True) + kill_house_free_buying_bars = KillHouseFreeBarInformation.objects.filter(trash=False, + calculate_status=True, warehouse=True, + date__date=date, + input_warehouse=kill_house) \ + .exclude(entered_message='ورود به انبار مجازی') + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, + receiver_state__in=('pending', 'accepted'), production_date__date=date) + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + production_date__date=date, + trash=False, + calculate_status=True, + warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, production_date__date=date, trash=False, + warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date=date, trash=False, warehouse=True) + archives = WarehouseArchive.objects.filter(kill_house=kill_house, trash=False, warehouse=True, date__date=date) + + final_dict = {} + + kill_house_requests_info = kill_house_requests.aggregate( + total_kill_house_request_governmental_weight=Sum('ware_house_accepted_real_weight', filter=Q( + province_request__poultry_request__free_sale_in_province=False)), + total_kill_house_request_free_weight=Sum('ware_house_accepted_real_weight', filter=Q( + province_request__poultry_request__free_sale_in_province=True)), + + ) + + kill_house_free_buying_bars_info = kill_house_free_buying_bars.aggregate( + total_kill_house_free_buying_bars_weight=Sum('weight_of_carcasses')) + + kill_house_allocations_info = kill_house_allocations.aggregate( + total_kill_house_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + + ) + + kill_house_free_sale_bars_info = kill_house_free_sale_bars.aggregate( + total_kill_house_free_sale_bars_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_kill_house_free_sale_bars_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')), + + ) + + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + segmentations_free_weight=Sum('weight', filter=Q(quota='free')), + + ) + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_kill_house_request_governmental_weight = kill_house_requests_info[ + 'total_kill_house_request_governmental_weight'] or 0 + total_kill_house_request_free_weight = kill_house_requests_info['total_kill_house_request_free_weight'] or 0 + total_kill_house_free_buying_bars_weight = kill_house_free_buying_bars_info[ + 'total_kill_house_free_buying_bars_weight'] or 0 + total_kill_house_allocations_governmental_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_governmental_weight'] or 0 + total_kill_house_allocations_free_weight = kill_house_allocations_info[ + 'total_kill_house_allocations_free_weight'] or 0 + total_kill_house_free_sale_bars_governmental_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_governmental_weight'] or 0 + total_kill_house_free_sale_bars_free_weight = kill_house_free_sale_bars_info[ + 'total_kill_house_free_sale_bars_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + total_governmental_input = total_kill_house_request_governmental_weight + total_free_input = total_kill_house_request_free_weight + total_kill_house_free_buying_bars_weight + total_governmental_output = total_kill_house_allocations_governmental_weight + total_kill_house_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output = total_kill_house_allocations_free_weight + total_kill_house_free_sale_bars_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + date = datetime.strptime(date, '%Y-%m-%d').date() + + governmental_data = { + 'day': jdatetime.date.fromgregorian(date=date).strftime('%Y-%m-%d'), + 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, + } + free_data = { + 'day': jdatetime.date.fromgregorian(date=date).strftime('%Y-%m-%d'), + 'amount': (total_free_input - total_free_output) - archives_free_weight, + } + + final_dict['governmental'] = governmental_data + final_dict['free'] = free_data + return final_dict + + def guild_steward_info(self, steward, date): + + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + guild_steward_allocations = StewardAllocation.objects.filter( + Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q( + to_steward=steward), + trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) + + output_steward_allocations = guild_steward_allocations.filter(Q(guilds=steward) | Q(steward=steward), + production_date__date=date) + input_steward_allocations = guild_steward_allocations.filter( + Q(to_guilds=steward) | Q(to_steward=steward), date__date=date) + + steward_free_bar_informations = StewardFreeBarInformation.objects.filter(steward=steward, + date__date=date, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( + steward=steward, + production_date__date=date, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True) + + segmentations = PosSegmentation.objects.filter(guild=steward, production_date__date=date, trash=False, + warehouse=True) + transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, + transaction__date__date=date, trash=False, warehouse=True) + archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, + date__date=date, + warehouse=True) + + final_dict = {} + + input_steward_allocations_info = input_steward_allocations.aggregate( + total_input_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', + quota='governmental')), + total_input_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(receiver_state='accepted', quota='free')) + ) + output_steward_allocations_info = output_steward_allocations.aggregate( + total_output_allocations_governmental_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='governmental')), + total_output_allocations_free_weight=Sum('real_weight_of_carcasses', + filter=Q(quota='free')) + + ) + steward_free_bar_info = steward_free_bar_informations.aggregate( + total_free_bar_weight=Sum('weight_of_carcasses'), + + ) + + steward_free_Sale_bar_info = steward_free_Sale_bar_informations.aggregate( + total_free_Sale_bar_governmental_weight=Sum('weight_of_carcasses', + filter=Q(quota='governmental')), + total_free_Sale_bar_free_weight=Sum('weight_of_carcasses', filter=Q(quota='free')) + + ) + + segmentations_info = segmentations.aggregate( + segmentations_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + segmentations_free_weight=Sum('weight', filter=Q(quota='free')), + + ) + pos_allocated_weight_info = transactions.aggregate( + pos_governmental_allocated_weight=Sum('cur_weight', + filter=Q(price_approved=True)), + pos_free_allocated_weight=Sum('cur_weight', filter=Q(price_approved=False)), + + ) + archives_info = archives.aggregate( + archives_governmental_weight=Sum('weight', + filter=Q(quota='governmental')), + archives_free_weight=Sum('weight', + filter=Q(quota='free')), + + ) + archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 + archives_free_weight = archives_info['archives_free_weight'] or 0 + + total_input_steward_allocations_governmental_weight = input_steward_allocations_info[ + 'total_input_allocations_governmental_weight'] or 0 + total_input_steward_allocations_free_weight = input_steward_allocations_info[ + 'total_input_allocations_free_weight'] or 0 + total_steward_free_buying_bars_weight = steward_free_bar_info[ + 'total_free_bar_weight'] or 0 + total_output_steward_allocations_governmental_weight = output_steward_allocations_info[ + 'total_output_allocations_governmental_weight'] or 0 + total_output_steward_allocations_free_weight = output_steward_allocations_info[ + 'total_output_allocations_free_weight'] or 0 + total_steward_free_sale_bars_governmental_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_governmental_weight'] or 0 + total_steward_free_sale_bars_free_weight = steward_free_Sale_bar_info[ + 'total_free_Sale_bar_free_weight'] or 0 + segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 + segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 + pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 + pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 + total_governmental_input = total_input_steward_allocations_governmental_weight + total_free_input = total_input_steward_allocations_free_weight + total_steward_free_buying_bars_weight + total_governmental_output = total_output_steward_allocations_governmental_weight + total_steward_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( + pos_governmental_allocated_weight / 1000) + total_free_output = total_output_steward_allocations_free_weight + total_steward_free_sale_bars_free_weight + segmentations_free_weight + int( + pos_free_allocated_weight / 1000) + date = datetime.strptime(date, '%Y-%m-%d').date() + governmental_data = { + 'day': jdatetime.date.fromgregorian(date=date).strftime('%Y-%m-%d'), + 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, + } + free_data = { + 'day': jdatetime.date.fromgregorian(date=date).strftime('%Y-%m-%d'), + 'amount': (total_free_input - total_free_output) - archives_free_weight, + } + + final_dict['governmental'] = governmental_data + final_dict['free'] = free_data + return final_dict + + def get(self, request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + pos = POSMachine.objects.get(pos_id=validation_device) + date = request.GET.get('date') + + if pos.kill_house: + final_dict = self.kill_house_info(pos.kill_house, date) + else: + final_dict = self.guild_steward_info(pos.guild, date) + + return Response(final_dict, status=status.HTTP_200_OK) + + +# class StewardRemainWeightViewSet(APIView): +# permission_classes = [TokenHasReadWriteScope] +# +# def get(self, request): +# user = SystemUserProfile.objects.get(user=request.user, trash=False) +# steward = Guilds.objects.get(user=user, trash=False) +# product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() +# today = datetime.now().date() +# yesterday = today - timedelta(days=1) +# two_days_ago = yesterday - timedelta(days=1) +# days = (two_days_ago, yesterday, today) +# archives = WarehouseArchive.objects.filter(Q(steward=steward) | Q(guild=steward), trash=False, +# date__date__gte=two_days_ago, date__date__lte=today) +# +# guild_steward_allocations = StewardAllocation.objects.filter( +# Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q( +# to_steward=steward), +# trash=False, calculate_status=True, warehouse=True, steward_warehouse=True) +# +# output_steward_allocations = guild_steward_allocations.filter(Q(guilds=steward) | Q(steward=steward), +# production_date__date__gte=two_days_ago, +# production_date__date__lte=today, ) +# input_steward_allocations = guild_steward_allocations.filter( +# Q(to_guilds=steward) | Q(to_steward=steward), date__date__gte=two_days_ago, date__date__lte=today, ) +# +# steward_free_bar_informations = StewardFreeBarInformation.objects.filter(steward=steward, +# date__date__gte=two_days_ago, +# date__date__lte=today, +# trash=False, +# temporary_trash=False, +# temporary_deleted=False, +# warehouse=True) +# steward_free_Sale_bar_informations = StewardFreeSaleBarInformation.objects.filter( +# steward=steward, +# production_date__date__gte=two_days_ago, +# production_date__date__lte=today, +# trash=False, +# temporary_trash=False, +# temporary_deleted=False, +# warehouse=True) +# +# segmentations = PosSegmentation.objects.filter(guild=steward, production_date__date__gte=two_days_ago, +# production_date__date__lte=today, trash=False, warehouse=True) +# transactions = ProductsTransactions.objects.filter(product=product, transaction__paid=True, +# transaction__date__date__gte=two_days_ago, +# transaction__date__date__lte=today, trash=False, +# warehouse=True) +# +# governmental_list = [] +# free_list = [] +# final_dict = {} +# +# for day in days: +# input_steward_allocations_info = input_steward_allocations.aggregate( +# total_input_allocations_governmental_weight=Sum('real_weight_of_carcasses', +# filter=Q(receiver_state='accepted', +# quota='governmental', date__date=day)), +# total_input_allocations_free_weight=Sum('real_weight_of_carcasses', +# filter=Q(receiver_state='accepted', quota='free', +# date__date=day)) +# ) +# output_steward_allocations_info = output_steward_allocations.aggregate( +# total_output_allocations_governmental_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='governmental', +# production_date__date=day)), +# total_output_allocations_free_weight=Sum('real_weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day)) +# +# ) +# steward_free_bar_info = steward_free_bar_informations.aggregate( +# total_free_bar_weight=Sum('weight_of_carcasses', filter=Q(date__date=day)), +# +# ) +# +# steward_free_Sale_bar_info = steward_free_Sale_bar_informations.aggregate( +# total_free_Sale_bar_governmental_weight=Sum('weight_of_carcasses', +# filter=Q(quota='governmental', production_date__date=day)), +# total_free_Sale_bar_free_weight=Sum('weight_of_carcasses', +# filter=Q(quota='free', production_date__date=day)) +# +# ) +# +# segmentations_info = segmentations.aggregate( +# segmentations_governmental_weight=Sum('weight', +# filter=Q(quota='governmental', production_date__date=day)), +# segmentations_free_weight=Sum('weight', filter=Q(quota='free', production_date__date=day)), +# +# ) +# pos_allocated_weight_info = transactions.aggregate( +# pos_governmental_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=True, transaction__date__date=day)), +# pos_free_allocated_weight=Sum('cur_weight', +# filter=Q(price_approved=False, transaction__date__date=day)), +# +# ) +# archives_info = archives.aggregate( +# archives_governmental_weight=Sum('weight', +# filter=Q(quota='governmental', date__date=day)), +# archives_free_weight=Sum('weight', +# filter=Q(quota='free', date__date=day)), +# +# ) +# +# total_input_steward_allocations_governmental_weight = input_steward_allocations_info[ +# 'total_input_allocations_governmental_weight'] or 0 +# total_input_steward_allocations_free_weight = input_steward_allocations_info[ +# 'total_input_allocations_free_weight'] or 0 +# total_steward_free_buying_bars_weight = steward_free_bar_info[ +# 'total_free_bar_weight'] or 0 +# total_output_steward_allocations_governmental_weight = output_steward_allocations_info[ +# 'total_output_allocations_governmental_weight'] or 0 +# total_output_steward_allocations_free_weight = output_steward_allocations_info[ +# 'total_output_allocations_free_weight'] or 0 +# total_steward_free_sale_bars_governmental_weight = steward_free_Sale_bar_info[ +# 'total_free_Sale_bar_governmental_weight'] or 0 +# total_steward_free_sale_bars_free_weight = steward_free_Sale_bar_info[ +# 'total_free_Sale_bar_free_weight'] or 0 +# segmentations_governmental_weight = segmentations_info['segmentations_governmental_weight'] or 0 +# segmentations_free_weight = segmentations_info['segmentations_free_weight'] or 0 +# pos_governmental_allocated_weight = pos_allocated_weight_info['pos_governmental_allocated_weight'] or 0 +# pos_free_allocated_weight = pos_allocated_weight_info['pos_free_allocated_weight'] or 0 +# archives_governmental_weight = archives_info['archives_governmental_weight'] or 0 +# archives_free_weight = archives_info['archives_free_weight'] or 0 +# total_governmental_input = total_input_steward_allocations_governmental_weight +# total_free_input = total_input_steward_allocations_free_weight + total_steward_free_buying_bars_weight +# total_governmental_output = total_output_steward_allocations_governmental_weight + total_steward_free_sale_bars_governmental_weight + segmentations_governmental_weight + int( +# pos_governmental_allocated_weight / 1000) +# total_free_output = total_output_steward_allocations_free_weight + total_steward_free_sale_bars_free_weight + segmentations_free_weight + int( +# pos_free_allocated_weight / 1000) +# governmental_data = { +# 'day': day, +# 'amount': (total_governmental_input - total_governmental_output) - archives_governmental_weight, +# } +# free_data = { +# 'day': day, +# 'amount': (total_free_input - total_free_output) - archives_free_weight, +# } +# +# governmental_list.append(governmental_data) +# free_list.append(free_data) +# final_dict['governmental'] = governmental_list +# final_dict['free'] = free_list +# +# return Response(final_dict, status=status.HTTP_200_OK) + +class StewardRemainWeightViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + steward = Guilds.objects.get(user=user, active=True, trash=False) + product = RolesProducts.objects.filter(guild=steward, trash=False, name='مرغ گرم').first() + target_date = request.GET.get('date') + today = datetime.now().date() if not target_date else datetime.strptime(target_date, "%Y-%m-%d").date() + month_ago = today - timedelta(days=30) + yesterday = today - timedelta(days=1) + two_days_ago = yesterday - timedelta(days=1) + + days = [month_ago + timedelta(days=i) for i in range(31)] + target_days = {two_days_ago, yesterday, today} + + archives_vals = list(WarehouseArchive.objects.filter( + Q(steward=steward) | Q(guild=steward), + trash=False, + date__date__gte=month_ago, + date__date__lte=today, + warehouse=True, + ).values('date__date', 'quota', 'weight')) + + # allocations_vals = list(StewardAllocation.objects.filter( + # Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q(to_steward=steward), + # trash=False, + # calculate_status=True, + # warehouse=True, + # steward_warehouse=True + # ).values('production_date__date', 'date__date', 'quota', 'real_weight_of_carcasses', 'receiver_state')) + + allocations_vals = StewardAllocation.objects.filter( + Q(guilds=steward) | Q(to_guilds=steward) | Q(steward=steward) | Q(to_steward=steward), + trash=False, + calculate_status=True, + warehouse=True, + production_date__isnull=False, + steward_warehouse=True + ) + input_allocations_vals = allocations_vals.filter(Q(to_guilds=steward,to_steward__isnull=True) | Q(to_steward=steward,to_guilds__isnull=True),receiver_state='accepted').values('production_date__date', 'date__date', 'quota', 'real_weight_of_carcasses', 'receiver_state') + output_allocations_vals = allocations_vals.filter(Q(guilds=steward,steward__isnull=True) | Q(steward=steward,guilds__isnull=True),receiver_state__in=('accepted','pending')).values('production_date__date', 'date__date', 'quota', 'real_weight_of_carcasses', 'receiver_state') + + + free_bar_vals = list(StewardFreeBarInformation.objects.filter( + steward=steward, + date__date__gte=month_ago, + date__date__lte=today, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True + ).values('date__date', 'weight_of_carcasses')) + + free_sale_vals = list(StewardFreeSaleBarInformation.objects.filter( + steward=steward, + production_date__date__gte=month_ago, + production_date__date__lte=today, + trash=False, + temporary_trash=False, + temporary_deleted=False, + warehouse=True + ).values('production_date__date', 'quota', 'weight_of_carcasses')) + + seg_vals = list(PosSegmentation.objects.filter( + guild=steward, + production_date__date__gte=month_ago, + production_date__date__lte=today, + trash=False, + warehouse=True + ).values('production_date__date', 'quota', 'weight')) + + pos_vals = list(ProductsTransactions.objects.filter( + product=product, + transaction__paid=True, + transaction__date__date__gte=month_ago, + transaction__date__date__lte=today, + trash=False, + warehouse=True + ).values('transaction__date__date', 'price_approved', 'cur_weight')) + + archives_daily = {} + for a in archives_vals: + d = a['date__date'] + q = a['quota'] + w = a['weight'] or 0 + if d not in archives_daily: + archives_daily[d] = {'governmental': 0, 'free': 0} + archives_daily[d][q] += w + + input_alloc_daily = {} + output_alloc_daily = {} + # for a in allocations_vals: + # date_field = 'date__date' if a['receiver_state'] == 'accepted' else 'production_date__date' + # w = a['real_weight_of_carcasses'] or 0 + # q = a['quota'] + # if a['receiver_state'] == 'accepted': # input + # if a[date_field] not in input_alloc_daily: + # input_alloc_daily[a[date_field]] = {'governmental': 0, 'free': 0} + # input_alloc_daily[a[date_field]][q] += w + # print(w) + # else: # output + # if a[date_field] not in output_alloc_daily: + # output_alloc_daily[a[date_field]] = {'governmental': 0, 'free': 0} + # output_alloc_daily[a[date_field]][q] += w + for a in input_allocations_vals: + date_field = 'date__date' + w = a['real_weight_of_carcasses'] or 0 + q = a['quota'] + if a[date_field] not in input_alloc_daily: + input_alloc_daily[a[date_field]] = {'governmental': 0, 'free': 0} + input_alloc_daily[a[date_field]][q] += w + + + for a in output_allocations_vals: + date_field = 'production_date__date' + w = a['real_weight_of_carcasses'] or 0 + q = a['quota'] + if a[date_field] not in output_alloc_daily: + output_alloc_daily[a[date_field]] = {'governmental': 0, 'free': 0} + output_alloc_daily[a[date_field]][q] += w + + + free_bar_daily = {} + for f in free_bar_vals: + d = f['date__date'] + free_bar_daily[d] = free_bar_daily.get(d, 0) + (f['weight_of_carcasses'] or 0) + + free_sale_daily = {} + for f in free_sale_vals: + d = f['production_date__date'] + q = f['quota'] + w = f['weight_of_carcasses'] or 0 + if d not in free_sale_daily: + free_sale_daily[d] = {'governmental': 0, 'free': 0} + free_sale_daily[d][q] += w + + seg_daily = {} + for s in seg_vals: + d = s['production_date__date'] + q = s['quota'] + w = s['weight'] or 0 + if d not in seg_daily: + seg_daily[d] = {'governmental': 0, 'free': 0} + seg_daily[d][q] += w + + pos_daily = {} + for p in pos_vals: + d = p['transaction__date__date'] + w = p['cur_weight'] or 0 + if d not in pos_daily: + pos_daily[d] = {'governmental': 0, 'free': 0} + if p['price_approved']: + pos_daily[d]['governmental'] += w + else: + pos_daily[d]['free'] += w + + governmental_list = [] + free_list = [] + + for day in days: + gov_in = input_alloc_daily.get(day, {}).get('governmental', 0) + free_in = input_alloc_daily.get(day, {}).get('free', 0) + free_bar_daily.get(day, 0) + + gov_out = ( + output_alloc_daily.get(day, {}).get('governmental', 0) + + free_sale_daily.get(day, {}).get('governmental', 0) + + seg_daily.get(day, {}).get('governmental', 0) + + (pos_daily.get(day, {}).get('governmental', 0) // 1000) + ) + + free_out = ( + output_alloc_daily.get(day, {}).get('free', 0) + + free_sale_daily.get(day, {}).get('free', 0) + + seg_daily.get(day, {}).get('free', 0) + + (pos_daily.get(day, {}).get('free', 0) // 1000) + ) + + governmental_list.append({ + 'day': day, + 'governmental': gov_in, + 'amount': (gov_in - gov_out) - archives_daily.get(day, {}).get('governmental', 0) if ( + gov_in - gov_out) - archives_daily.get( + day, {}).get('governmental', 0) > 0 else 0, + 'active': day in target_days + }) + + free_list.append({ + 'day': day, + 'amount': (free_in - free_out) - archives_daily.get(day, {}).get('free', 0) if ( + free_in - free_out) - archives_daily.get( + day, {}).get('free', 0) > 0 else 0, + 'active': day in target_days + }) + + return Response({ + 'governmental': governmental_list, + 'free': free_list + }, status=status.HTTP_200_OK) + + +class TotalStewardRemainWeightViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalStewardRemainWeightSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsForPostationFilterSet + filterset_fields = [ + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'guilds_name' + ] + + def get(self, request): + owner_type = request.GET.get('owner_type') + guild_steward_filters = {'trash': False, 'total_remain_warehouse_weight__gt': 0, 'active': True} + guild_steward_filters['steward'] = True if owner_type == 'steward' else False + guild_steward = Guilds.objects.filter(**guild_steward_filters).order_by('id') + + if 'search' in request.GET: + guild_steward_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=guild_steward + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=guild_steward) + guild_steward_list = ps.filter() + guild_steward = [] if len( + guild_steward_list) == 0 else guild_steward_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guild_steward) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(guild_steward, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# class TotalStewardRemainWeightViewSet(GenericAPIView): +# permission_classes = [TokenHasReadWriteScope] +# serializer_class = TotalStewardRemainWeightSerializer +# pagination_class = CustomPagination +# filter_backends = [DjangoFilterBackend] +# filterset_class = GuildsForPostationFilterSet +# filterset_fields = [ +# 'user__first_name', +# 'user__last_name', +# 'user__fullname', +# 'user__mobile', +# 'guilds_name' +# ] +# +# def get(self, request): +# from collections import defaultdict +# from datetime import datetime, timedelta +# +# owner_type = request.GET.get('owner_type') +# filters = {'trash': False, 'total_remain_warehouse_weight__gt': 0, 'steward': owner_type == 'steward'} +# guilds = Guilds.objects.filter(**filters).order_by('id') +# +# if request.GET.get('search') == 'filter' and request.GET.get('value') not in ["", "undefined"]: +# value = request.GET['value'] +# for f in self.filterset_fields: +# query = QueryDict(f'{f}__contains={value}') +# qs = self.filterset_class(data=query, queryset=guilds).qs +# if qs.exists(): +# guilds = qs +# break +# +# guild_ids = list(guilds.values_list('id', flat=True)) +# if not guild_ids: +# return Response([]) +# +# allocations = StewardAllocation.objects.filter( +# Q(guilds_id__in=guild_ids) | Q(to_guilds_id__in=guild_ids) | +# Q(steward_id__in=guild_ids) | Q(to_steward_id__in=guild_ids), +# trash=False, calculate_status=True, warehouse=True, steward_warehouse=True +# ).values('guilds_id', 'to_guilds_id', 'steward_id', 'to_steward_id', 'quota', 'receiver_state', +# 'real_weight_of_carcasses', 'date', 'production_date') +# +# free_bars = StewardFreeBarInformation.objects.filter( +# steward_id__in=guild_ids, trash=False, temporary_trash=False, temporary_deleted=False, warehouse=True +# ).values('steward_id', 'date', 'weight_of_carcasses') +# +# free_sales = StewardFreeSaleBarInformation.objects.filter( +# steward_id__in=guild_ids, trash=False, temporary_trash=False, temporary_deleted=False, warehouse=True +# ).values('steward_id', 'production_date', 'quota', 'weight_of_carcasses') +# +# segmentations = PosSegmentation.objects.filter( +# guild_id__in=guild_ids, trash=False, warehouse=True +# ).values('guild_id', 'production_date', 'quota', 'weight') +# +# archives = WarehouseArchive.objects.filter( +# Q(guild_id__in=guild_ids) | Q(steward_id__in=guild_ids), trash=False +# ).values('guild_id', 'steward_id', 'date', 'quota', 'weight') +# +# data = defaultdict(lambda: defaultdict(lambda: {'gov': 0, 'free': 0})) +# today = datetime.now().date() +# exclude_days = {today, today - timedelta(days=1), today - timedelta(days=2)} +# +# def add(gid, day, gov, free): +# if not gid or not day or day in exclude_days: +# return +# data[gid][day]['gov'] += gov +# data[gid][day]['free'] += free +# +# for a in allocations: +# for gid in [a['guilds_id'], a['to_guilds_id'], a['steward_id'], a['to_steward_id']]: +# if not gid or gid not in guild_ids: +# continue +# quota = a['quota'] +# val = a['real_weight_of_carcasses'] or 0 +# if a['receiver_state'] == 'accepted' and a['date']: +# add(gid, a['date'], val if quota == 'governmental' else 0, val if quota == 'free' else 0) +# if a['production_date']: +# add(gid, a['production_date'], -val if quota == 'governmental' else 0, -val if quota == 'free' else 0) +# +# for b in free_bars: +# add(b['steward_id'], b['date'], 0, b['weight_of_carcasses'] or 0) +# +# for s in free_sales: +# val = s['weight_of_carcasses'] or 0 +# add(s['steward_id'], s['production_date'], -val if s['quota'] == 'governmental' else 0, -val if s['quota'] == 'free' else 0) +# +# for seg in segmentations: +# val = seg['weight'] or 0 +# add(seg['guild_id'], seg['production_date'], -val if seg['quota'] == 'governmental' else 0, -val if seg['quota'] == 'free' else 0) +# +# for arc in archives: +# gid = arc['guild_id'] or arc['steward_id'] +# val = arc['weight'] or 0 +# add(gid, arc['date'], -val if arc['quota'] == 'governmental' else 0, -val if arc['quota'] == 'free' else 0) +# +# precomputed = {} +# for gid, days in data.items(): +# gov_by_day = defaultdict(float) +# free_by_day = defaultdict(float) +# for d, v in days.items(): +# if v['gov'] > 0: +# gov_by_day[d.strftime('%Y-%m-%d')] += v['gov'] +# if v['free'] > 0: +# free_by_day[d.strftime('%Y-%m-%d')] += v['free'] +# +# precomputed[gid] = { +# 'governmental': [{'day': day, 'amount': amt} for day, amt in sorted(gov_by_day.items())], +# 'free': [{'day': day, 'amount': amt} for day, amt in sorted(free_by_day.items())], +# } +# +# page_size = request.query_params.get('page_size') +# if page_size: +# self.pagination_class.page_size = int(page_size) +# +# page = self.paginate_queryset(guilds) +# context = {'precomputed_data': precomputed} +# serializer = self.get_serializer(page or guilds, many=True, context=context) +# +# if page: +# return self.get_paginated_response(serializer.data) +# return Response(serializer.data, status=status.HTTP_200_OK) + +class WarehouseArchiveViewSet(viewsets.ModelViewSet): + queryset = WarehouseArchive.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = WarehouseArchiveSerializer + pagination_class = CustomPagination + filterset_class = WarehouseArchiveFilterSet + + def create(self, request, *args, **kwargs): + now = datetime.now() + now_time = now.time() + role = request.data.get('role') + image = request.data.get('image') + owner_key = request.data['owner_key'] + archive_type = request.data['archive_type'] + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date = datetime.strptime(str(request.data['date']), '%Y-%m-%d').date() + date = datetime(year=date.year, month=date.month, + day=date.day, + hour=now_time.hour, + minute=now_time.minute, + second=now_time.second) + request.data.pop('date') + request.data.pop('owner_key') + request.data.pop('archive_type') + request.data.pop('role') + if 'image' in request.data.keys(): + request.data.pop('image') + if archive_type == 'kill_house': + kill_house = KillHouse.objects.get(key=owner_key) + else: + guild_steward = Guilds.objects.get(key=owner_key) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + archive = serializer.create(validated_data=request.data) + archive.date = date + + if archive_type == 'kill_house': + archive.kill_house = kill_house + elif archive_type == 'steward': + archive.steward = guild_steward + else: + archive.guild = guild_steward + + if image: + archive.image = send_image_to_server(image) + archive.registerer = user.fullname + archive.registerer_mobile = user.mobile + archive.registerer_role = role + archive.save() + if archive.kill_house: + kill_house_archive_warehousing(archive.kill_house) + elif archive.steward: + guild_steward_archive_warehousing(archive.steward) + + else: + guild_steward_archive_warehousing(archive.guild) + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + role = request.GET.get('role') + archive_type = request.GET.get('archive_type') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + filters = {"trash": False} + if date1: + filters['create_date__date__gte'] = date1 + filters['create_date__date__lte'] = date2 + if archive_type == 'kill_house': + filters['kill_house__isnull'] = False + elif archive_type == 'steward': + filters['steward__isnull'] = False + + elif archive_type == 'guild': + filters['guild__isnull'] = False + else: + filters['kill_house__isnull'] = False + + archives = WarehouseArchive.objects.filter(**filters) + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + archives = archives.filter( + build_query(self.filterset_class.Meta.fields, value) + ) + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + page = self.paginate_queryset(archives) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = POSDeviceSessionForCompanySerializer(archives, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + archive = WarehouseArchive.objects.get(key=request.GET['key']) + archive.trash = True + archive.save() + if archive.kill_house: + kill_house_archive_warehousing(archive.kill_house) + elif archive.steward: + guild_steward_archive_warehousing(archive.steward) + + else: + guild_steward_archive_warehousing(archive.guild) + return Response({"result": " با موفقیت حذف شد !"}, status=status.HTTP_200_OK) + + +class SmsRecipientViewSet(viewsets.ModelViewSet): + queryset = SmsRecipient.objects.all() + serializer_class = SmsRecipientSerializer + permission_classes = [TokenHasReadWriteScope] + + +def persian_date_to_datetime(persian_date_str): + """ + تبدیل تاریخ فارسی (مثل ۱۴۰۰/۰۵/۲۱) به datetime + """ + if not persian_date_str: + return None + + try: + # تبدیل اعداد فارسی به انگلیسی + persian_numbers = '۰۱۲۳۴۵۶۷۸۹' + english_numbers = '0123456789' + translation_table = str.maketrans(persian_numbers, english_numbers) + english_date = persian_date_str.translate(translation_table) + + # جدا کردن سال، ماه، روز + parts = english_date.split('/') + if len(parts) != 3: + return None + + year = int(parts[0]) + month = int(parts[1]) + day = int(parts[2]) + + # استفاده از تابع موجود برای تبدیل + from panel.convert_date import convert_to_miladi + return convert_to_miladi(year=year, month=month, day=day) + except: + return None + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +def create_or_update_guild_by_national_id(request): + if 'file' not in request.FILES: + return Response({"result": "فایل اکسل الزامی است"}, status=status.HTTP_400_BAD_REQUEST) + + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + + failed_records = [] + success_count = 0 + update_count = 0 + + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + national_id = str(row[0]) if row[0] else None + if not national_id: + continue + + try: + try: + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=person" + ) + person_data = person_response.json() + if not person_data.get('status'): + failed_records.append({"national_id": national_id, "reason": "اطلاعات شخص یافت نشد"}) + continue + person_info = person_data.get('data', {}) + except Exception as e: + failed_records.append({"national_id": national_id, "reason": f"خطا در دریافت اطلاعات شخصی: {str(e)}"}) + continue + + try: + guild_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=guild" + ) + guild_data = guild_response.json() + if not guild_data.get('status') or not guild_data.get('data'): + failed_records.append({"national_id": national_id, "reason": "اطلاعات صنفی یافت نشد"}) + continue + + guild_list = guild_data.get('data', []) + guild_info = None + + for guild in guild_list: + license_status_value = guild.get('licenseStatus', '') + if license_status_value and 'فعال' in license_status_value: + guild_info = guild + break + + if not guild_info: + failed_records.append({"national_id": national_id, + "reason": "هیچ پروانه کسب فعالی برای این کد ملی یافت نشد (تمام پروانه‌ها ابطال شده‌اند)"}) + continue + + guild_layer_two = guild_info.get('layerTwo', {}) + except Exception as e: + failed_records.append({"national_id": national_id, "reason": f"خطا در دریافت اطلاعات صنفی: {str(e)}"}) + continue + + first_name = person_info.get('firstName') + last_name = person_info.get('lastName') + father_name = person_info.get('fatherName') + gender = person_info.get('gender') + identity_no = person_info.get('identityNo') + is_alive = person_info.get('isLive', True) + birth_date = person_info.get('birthDate') + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + city_name = guild_info.get('city') + address_text = guild_info.get('address') + postal_code = guild_layer_two.get('postalcode') + license_number = guild_info.get('licenseNumber') + license_expire_date = guild_info.get('licenseExpireDate') + license_issue_date = guild_layer_two.get('licenseIssueDate') + license_type = guild_info.get('licenseType') + license_status = guild_info.get('licenseStatus') + type_activity_name = guild_info.get('isicname') + mobile = guild_layer_two.get('mobilenumber') + company_name = guild_layer_two.get('corporationName') + company_identifier = guild_layer_two.get('nationalId') + union_name = guild_layer_two.get('unionName') + phone_number = guild_layer_two.get('phonenumber') + + def parse_yes_no(val): + if not val: + return False + return str(val).strip() == 'بله' + + has_partner = parse_yes_no(guild_layer_two.get('hasPartner')) + steward = parse_yes_no(guild_layer_two.get('hasSteward')) + is_foreign_national = parse_yes_no(guild_layer_two.get('isForeigner')) + + try: + group = Group.objects.get(name__exact="Guilds") + except Group.DoesNotExist: + failed_records.append({"national_id": national_id, "reason": "گروه Guilds یافت نشد"}) + continue + + def _normalize_fa_ar(text): + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + if not city: + failed_records.append({"national_id": national_id, "reason": f"شهر '{city_name}' یافت نشد"}) + continue + + province = city.province + + existing_guild = Guilds.objects.filter(user__national_id=national_id, trash=False) + + system_profile = SystemUserProfile.objects.filter(national_id=national_id, trash=False) + + if not system_profile: + if not mobile: + failed_records.append( + {"national_id": national_id, "reason": "شماره موبایل در اطلاعات صنفی یافت نشد"}) + continue + + password = "00100" + data = { + "username": mobile, + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + " " + last_name, + user=user, + base_order=base_id, + password=password, + national_id=national_id, + national_code=identity_no, + city=city, + province=province, + father_name=father_name, + gender=gender, + birthday=birthday_str, + is_alive=is_alive + ) + system_profile.save() + else: + failed_records.append({"national_id": national_id, "reason": "در ثبت کاربر مشکلی بوجود آمده است"}) + continue + + else: + system_profile.national_id = national_id + system_profile.national_code = identity_no + system_profile.father_name = father_name + system_profile.gender = gender + system_profile.birthday = birthday_str + system_profile.is_alive = is_alive + system_profile.save() + + address = SystemAddress(city=city, province=province, address=address_text, + postal_code=postal_code) + address.save() + system_profile.role.add(group) + + if not existing_guild: + wallet = Wallet() + wallet.save() + else: + wallet = existing_guild.wallet + + role = request.data.get('role', 'ProvinceOperator') + + type_activity = TypeActivity.objects.filter(title__icontains=type_activity_name, trash=False).first() + if not type_activity: + type_activity = TypeActivity.objects.filter(trash=False).first() + + area_activity = AreaActivity.objects.filter(trash=False).first() + + if existing_guild: + try: + guilds = existing_guild + guilds.guilds_name = guild_info.get('title', '') + guilds.license_number = license_number + guilds.license_type = license_type + guilds.license_status = license_status + guilds.is_foreign_national = is_foreign_national + guilds.has_partner = has_partner + guilds.has_inquiry = True + guilds.steward = steward + guilds.company_name = company_name + guilds.company_identifier = company_identifier + guilds.user = system_profile + guilds.registerar_fullname = 'سیستمی' + guilds.registerar_mobile = '09000000000' + guilds.registerar_role = role + guilds.address = address + guilds.wallet = wallet + guilds.type_activity = type_activity.title if type_activity else type_activity_name + guilds.area_activity = area_activity.title if area_activity else '' + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.phone_number = phone_number + guilds.union_name = union_name + + if license_issue_date: + converted_date = persian_date_to_datetime(license_issue_date) + if converted_date: + guilds.license_issue_date = converted_date + + if license_expire_date: + converted_date = persian_date_to_datetime(license_expire_date) + if converted_date: + guilds.license_expire_date = converted_date + + guilds.save() + update_count += 1 + except Exception as e: + failed_records.append({"national_id": national_id, "reason": f"خطا در آپدیت: {str(e)}"}) + continue + + else: + try: + guilds = Guilds( + guilds_name=guild_info.get('title', ''), + license_number=license_number, + license_type=license_type, + license_status=license_status, + is_foreign_national=is_foreign_national, + has_partner=has_partner, + has_inquiry=True, + steward=steward, + company_name=company_name, + phone_number=phone_number, + union_name=union_name, + company_identifier=company_identifier, + user=system_profile, + registerar_fullname='سیستمی', + registerar_mobile='09000000000', + registerar_role=role, + address=address, + wallet=wallet, + type_activity=type_activity.title if type_activity else type_activity_name, + area_activity=area_activity.title if area_activity else '', + province_accept_state='pending', + guild_type_activity=type_activity, + guild_area_activity=area_activity, + ) + + if license_issue_date: + converted_date = persian_date_to_datetime(license_issue_date) + if converted_date: + guilds.license_issue_date = converted_date + + if license_expire_date: + converted_date = persian_date_to_datetime(license_expire_date) + if converted_date: + guilds.license_expire_date = converted_date + + guilds.save() + + parent_product = NewProduct.objects.all().first() + price = BroadcastPrice.objects.filter(trash=False).first() + + if parent_product and price: + approved_price = price.steward_price if guilds.steward else price.guild_price + approved_type = price.active if approved_price > 0 else False + + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + + if role == 'KillHouse': + try: + user = SystemUserProfile.objects.get(user=request.user) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).order_by( + 'id').first() + if kill_house: + guilds.kill_house_centers_allocation = [ + {"label": kill_house.name, "value": str(kill_house.key)}] + guilds.province_accept_state = 'pending' + guilds.kill_house_register = True + guilds.save() + + if guilds.steward == True: + guilds.steward_kill_house.add(kill_house) + else: + guilds.kill_house.add(kill_house) + except: + pass + + elif role == 'Guilds': + try: + user = SystemUserProfile.objects.get(user=request.user) + steward = Steward.objects.get(guilds__user=user, trash=False) + + guilds.centers_allocation = [ + {"label": steward.guilds.user.fullname, "value": str(steward.key)}] + guilds.province_accept_state = 'pending' + guilds.steward_register = True + guilds.save() + except: + pass + + elif role == 'PosCompany': + guilds.province_accept_state = 'pending' + guilds.pos_company_register = True + guilds.save() + + success_count += 1 + + except Exception as e: + failed_records.append({"national_id": national_id, "reason": f"خطا در ساخت: {str(e)}"}) + continue + + except Exception as e: + failed_records.append({"national_id": national_id, "reason": f"خطای کلی: {str(e)}"}) + continue + + return Response({ + "result": "پردازش کامل شد", + "success_count": success_count, + "update_count": update_count, + "failed_count": len(failed_records), + "failed_records": failed_records + }, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +def update_guild_by_national_id(request): + national_id = request.data.get('national_id') + has_inquery = request.data.get('has_inquiry') + update_flag = request.data.get('update_flag') + mobile = request.data.get('mobile') + steward = request.data.get('steward', False) + active_register_code = request.data.get('active_register_code', False) + + first_name = request.data.get('firstName') + last_name = request.data.get('lastName') + father_name = request.data.get('fatherName') + gender = request.data.get('gender') + identity_no = request.data.get('identityNo') + is_alive = request.data.get('isLive', True) + birth_date = request.data.get('birthDate') + + city_name = request.data.get('city') + address_text = request.data.get('address') + postal_code = request.data.get('postalcode') + license_number = request.data.get('licenseNumber') + license_expire_date = request.data.get('licenseExpireDate') + license_issue_date = request.data.get('licenseIssueDate') + license_type = request.data.get('licenseType') + license_status = request.data.get('licenseStatus') + type_activity_name = request.data.get('isicname') + mobilenumber = request.data.get('mobilenumber') + company_name = request.data.get('corporationName') + company_identifier = request.data.get('nationalId') + union_name = request.data.get('unionName') + phone = request.data.get('phonenumber') + has_partner_val = request.data.get('hasPartner') + is_foreigner_val = request.data.get('isForeigner') + title = request.data.get('title', '') + + try: + user = SystemUserProfile.objects.get(tras=False, user=request.user) + registerar_fullname = user.fullname + registerar_mobile = user.mobile + except: + registerar_fullname = 'سیستمی' + registerar_mobile = '09000000000' + + if not national_id: + return Response({"result": "کد ملی الزامی است"}, status=status.HTTP_400_BAD_REQUEST) + + try: + if not mobile: + mobile = mobilenumber + + if not mobile: + return Response({"result": "شماره موبایل الزامی است"}, + status=status.HTTP_400_BAD_REQUEST) + + try: + if birth_date: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + else: + birthday_str = None + except: + birthday_str = None + + def parse_yes_no(val): + if isinstance(val, bool): + return val + if isinstance(val, str): + x = False if val == 'خیر' else True + return x + return bool(val) + + has_partner = parse_yes_no(has_partner_val) + is_foreign_national = parse_yes_no(is_foreigner_val) + + def _normalize_fa_ar(text): + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + if not city: + return Response({"result": f"شهر '{city_name}' یافت نشد"}, status=status.HTTP_404_NOT_FOUND) + + province = city.province + + system_profile = SystemUserProfile.objects.filter(Q(national_id=national_id) | Q(mobile=mobile), + trash=False).first() + if not system_profile: + if not mobile: + return Response({"result": "شماره موبایل الزامی است"}, + status=status.HTTP_400_BAD_REQUEST) + + password = "123456" + data = { + "username": mobile, + "password": password, + "api_key": PROJECT_API_KEY + } + + try: + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name) + user.save() + + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + " " + last_name, + user=user, + base_order=base_id, + password=password, + national_id=national_id, + national_code=identity_no, + city=city, + province=province, + father_name=father_name, + gender=gender, + birthday=birthday_str, + is_alive=is_alive + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + return Response({"result": f"خطا در ثبت کاربر: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + has_killhouse = system_profile.role.filter(name='KillHouse').exists() + if has_killhouse: + if request.GET.get('role') == 'AdminX': + if system_profile.national_id == national_id: + return Response({"result": "کد ملی به نام {} ثبت شده است!".format(system_profile.fullname)}, + status=status.HTTP_403_FORBIDDEN) + elif system_profile.mobile == mobile: + return Response( + {"result": "شماره موبایل به نام {} ثبت شده است!".format(system_profile.fullname)}, + status=status.HTTP_403_FORBIDDEN) + return Response({"result": "کاربر قبلا در سامانه ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + + if mobile and system_profile.mobile != mobile: + if not has_killhouse: + first_mobile_number = system_profile.mobile + second_mobile_number = mobile + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + user = User.objects.get(id=system_profile.user.id) + user.username = second_mobile_number + user.save() + system_profile.mobile = second_mobile_number + system_profile.save() + else: + return Response({"result": "شماره همراه قبلا در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "شماره همراه قبلا در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + system_profile.first_name = first_name + system_profile.last_name = last_name + system_profile.fullname = first_name + " " + last_name + system_profile.national_id = national_id + system_profile.national_code = identity_no + system_profile.father_name = father_name + system_profile.gender = gender + system_profile.birthday = birthday_str + system_profile.is_alive = is_alive + system_profile.city = city + system_profile.province = province + system_profile.save() + + address = SystemAddress(city=city, province=province, address=address_text, postal_code=postal_code) + address.save() + + existing_guild = Guilds.objects.filter(user__national_id=national_id, trash=False, active=True).first() + + if not existing_guild: + wallet = Wallet() + wallet.save() + else: + wallet = existing_guild.wallet + + type_activity = TypeActivity.objects.filter(title__icontains=type_activity_name, trash=False).first() + if not type_activity: + type_activity = TypeActivity.objects.filter(trash=False).first() + + area_activity = AreaActivity.objects.filter(trash=False).first() + + if existing_guild: + try: + guilds = existing_guild + guilds.guilds_name = title + guilds.license_number = license_number + guilds.license_type = license_type + guilds.license_status = license_status + guilds.is_foreign_national = is_foreign_national + guilds.has_partner = has_partner + guilds.has_inquiry = has_inquery + guilds.steward = steward + guilds.company_name = company_name + guilds.company_identifier = company_identifier + guilds.user = system_profile + guilds.registerar_fullname = registerar_fullname + guilds.registerar_mobile = registerar_mobile + guilds.address = address + guilds.wallet = wallet + guilds.type_activity = type_activity.title if type_activity else type_activity_name + guilds.area_activity = area_activity.title if area_activity else '' + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.union_name = union_name + guilds.phone_number = phone + guilds.active = True + + if license_issue_date: + converted_date = persian_date_to_datetime(license_issue_date) + if converted_date: + guilds.license_issue_date = converted_date + + if license_expire_date: + converted_date = persian_date_to_datetime(license_expire_date) + if converted_date: + guilds.license_expire_date = converted_date + + guilds.save() + + guilds_group = Group.objects.get(name__exact="Guilds") + steward_group = Group.objects.get(name__exact="Steward") + + role_changed = False + if steward: + if system_profile.role.filter(name='Guilds').exists(): + role_changed = True + try: + req = requests.post( + url=ARTA_URL_REMOVE_USER_ROLE, + data={"mobile": system_profile.mobile, "role": "Guilds"}, + verify=False + ) + if req.status_code == 200 or req.status_code == 400: + system_profile.role.remove(guilds_group) + except: + pass + if not system_profile.role.filter(name='Steward').exists(): + system_profile.role.add(steward_group) + else: + if system_profile.role.filter(name='Steward').exists(): + role_changed = True + try: + req = requests.post( + url=ARTA_URL_REMOVE_USER_ROLE, + data={"mobile": system_profile.mobile, "role": "Steward"}, + verify=False + ) + if req.status_code == 200 or req.status_code == 400: + system_profile.role.remove(steward_group) + except: + pass + if not system_profile.role.filter(name='Guilds').exists(): + system_profile.role.add(guilds_group) + + # اگر نقش عوض شد، StewardAllocation ها را به‌روزرسانی کن + if role_changed: + update_steward_allocations_on_role_change(system_profile, guilds, steward) + + if active_register_code: + number = random.randint(10000, 99000) + guilds.register_code = number + guilds.active_register_code = True + guilds.register_date_register_code = datetime.now() + guilds.save() + + try: + send_sms_for_guild(guilds) + except: + pass + + ser_data = GuildsSerializer(guilds).data + return Response(ser_data, status=status.HTTP_200_OK) + + except Exception as e: + return Response({"result": f"خطا در به‌روزرسانی صنف: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + if request.GET.get('role') in ('AdminX', 'SuperAdmin'): + province_accept = 'accepted' + else: + province_accept = 'pending' + has_killhouse = system_profile.role.filter(name='KillHouse').exists() + if has_killhouse: + return Response({"result": "کاربر قبلا در سامانه ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + try: + guilds = Guilds( + guilds_name=title, + license_number=license_number, + license_type=license_type, + license_status=license_status, + is_foreign_national=is_foreign_national, + has_partner=has_partner, + has_inquiry=has_inquery, + steward=steward, + company_name=company_name, + company_identifier=company_identifier, + user=system_profile, + registerar_fullname=registerar_fullname, + registerar_mobile=registerar_mobile, + address=address, + wallet=wallet, + type_activity=type_activity.title if type_activity else type_activity_name, + area_activity=area_activity.title if area_activity else '', + province_accept_state=province_accept, + guild_type_activity=type_activity, + guild_area_activity=area_activity, + union_name=union_name, + phone_number=phone, + active=True, + ) + + if license_issue_date: + converted_date = persian_date_to_datetime(license_issue_date) + if converted_date: + guilds.license_issue_date = converted_date + + if license_expire_date: + converted_date = persian_date_to_datetime(license_expire_date) + if converted_date: + guilds.license_expire_date = converted_date + + guilds.save() + + guilds_group = Group.objects.get(name__exact="Guilds") + steward_group = Group.objects.get(name__exact="Steward") + + role_changed = False + if steward: + if system_profile.role.filter(name='Guilds').exists(): + role_changed = True + try: + req = requests.post( + url=ARTA_URL_REMOVE_USER_ROLE, + data={"mobile": system_profile.mobile, "role": "Guilds"}, + verify=False + ) + if req.status_code == 200: + system_profile.role.remove(guilds_group) + except: + pass + if not system_profile.role.filter(name='Steward').exists(): + system_profile.role.add(steward_group) + else: + if system_profile.role.filter(name='Steward').exists(): + role_changed = True + try: + req = requests.post( + url=ARTA_URL_REMOVE_USER_ROLE, + data={"mobile": system_profile.mobile, "role": "Steward"}, + verify=False + ) + if req.status_code == 200: + system_profile.role.remove(steward_group) + except: + pass + if not system_profile.role.filter(name='Guilds').exists(): + system_profile.role.add(guilds_group) + + # اگر نقش عوض شد، StewardAllocation ها را به‌روزرسانی کن + if role_changed: + update_steward_allocations_on_role_change(system_profile, guilds, steward) + + parent_product = NewProduct.objects.all().first() + price = BroadcastPrice.objects.filter(trash=False).first() + + if parent_product and price: + approved_price = price.steward_price if guilds.steward else price.guild_price + approved_type = price.active if approved_price > 0 else False + + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + if active_register_code: + number = random.randint(10000, 99000) + guilds.register_code = number + guilds.active_register_code = True + guilds.register_date_register_code = datetime.now() + guilds.save() + + try: + send_sms_for_guild(guilds) + except: + pass + ser_data = GuildsSerializer(guilds).data + return Response(ser_data, status=status.HTTP_201_CREATED) + + except Exception as e: + return Response({"result": f"خطا در ایجاد صنف: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + except Exception as e: + return Response({"result": f"خطای کلی: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +def register_legal_guild(request): + first_name = request.data.get('first_name') + last_name = request.data.get('last_name') + national_id = request.data.get('national_id') + province_name = request.data.get('province') + address_text = request.data.get('address') + unit_name = request.data.get('unit_name') + mobile = request.data.get('mobile') + city_name = request.data.get('city') + + if not national_id: + return Response({"result": "کد ملی الزامی است"}, status=status.HTTP_400_BAD_REQUEST) + + if not mobile: + return Response({"result": "شماره موبایل الزامی است"}, + status=status.HTTP_400_BAD_REQUEST) + + if not unit_name: + return Response({"result": "نام واحد الزامی است"}, + status=status.HTTP_400_BAD_REQUEST) + + try: + user = SystemUserProfile.objects.get(tras=False, user=request.user) + registerar_fullname = user.fullname + registerar_mobile = user.mobile + except: + registerar_fullname = 'سیستمی' + registerar_mobile = '09000000000' + + try: + # جستجوی شهر + if base_url_for_sms_report == 'ha': + city = City.objects.filter(name__icontains='همدان', trash=False).first() + elif base_url_for_sms_report == 'ku': + city = City.objects.filter(name__icontains='کردستان', trash=False).first() + elif base_url_for_sms_report == 'ma': + city = City.objects.filter(name__icontains='مرکزی', trash=False).first() + else: + city = City.objects.filter(name__icontains='تست', trash=False).first() + province = city.province + + system_profile = SystemUserProfile.objects.filter(Q(national_id=national_id) | Q(mobile=mobile), + trash=False).first() + if not system_profile: + password = "123456" + data = { + "username": mobile, + "password": password, + "api_key": PROJECT_API_KEY + } + + try: + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=mobile, first_name=first_name, last_name=last_name) + user.save() + + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + + system_profile = SystemUserProfile( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=first_name + " " + last_name, + user=user, + base_order=base_id, + password=password, + national_id=national_id, + city=city, + province=province, + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + return Response({"result": f"خطا در ثبت کاربر: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + has_killhouse = system_profile.role.filter(name='KillHouse').exists() + if has_killhouse: + if request.GET.get('role') == 'AdminX': + if system_profile.national_id == national_id: + return Response({"result": "کد ملی به نام {} ثبت شده است!".format(system_profile.fullname)}, + status=status.HTTP_403_FORBIDDEN) + elif system_profile.mobile == mobile: + return Response( + {"result": "شماره موبایل به نام {} ثبت شده است!".format(system_profile.fullname)}, + status=status.HTTP_403_FORBIDDEN) + return Response({"result": "کاربر قبلا در سامانه ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + + if mobile and system_profile.mobile != mobile: + if not has_killhouse: + first_mobile_number = system_profile.mobile + second_mobile_number = mobile + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + user = User.objects.get(id=system_profile.user.id) + user.username = second_mobile_number + user.save() + system_profile.mobile = second_mobile_number + system_profile.save() + else: + return Response({"result": "شماره همراه قبلا در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + else: + return Response({"result": "شماره همراه قبلا در سامانه ثبت شده است!"}, + status=status.HTTP_403_FORBIDDEN) + + system_profile.first_name = first_name + system_profile.last_name = last_name + system_profile.fullname = first_name + " " + last_name + system_profile.national_id = national_id + system_profile.city = city + system_profile.province = province + system_profile.save() + + address = SystemAddress(city=city, province=province, address=address_text) + address.save() + + existing_guild = Guilds.objects.filter(user__national_id=national_id, trash=False, active=True, + is_real_person=False).first() + + if not existing_guild: + wallet = Wallet() + wallet.save() + else: + wallet = existing_guild.wallet + + type_activity = TypeActivity.objects.filter(trash=False, key=request.data.get('type_activity')).first() + area_activity = AreaActivity.objects.filter(trash=False).first() + + if existing_guild: + try: + guilds = existing_guild + guilds.guilds_name = unit_name + guilds.license_number = national_id + guilds.user = system_profile + guilds.registerar_fullname = registerar_fullname + guilds.registerar_mobile = registerar_mobile + guilds.address = address + guilds.wallet = wallet + guilds.type_activity = type_activity.title if type_activity else '' + guilds.area_activity = area_activity.title if area_activity else '' + guilds.guild_type_activity = type_activity + guilds.guild_area_activity = area_activity + guilds.city_name = city_name + guilds.province_name = province_name + guilds.active = True + guilds.is_real_person = False + guilds.save() + + guilds_group = Group.objects.get(name__exact="Guilds") + if not system_profile.role.filter(name='Guilds').exists(): + system_profile.role.add(guilds_group) + + ser_data = GuildsSerializer(guilds).data + return Response(ser_data, status=status.HTTP_200_OK) + + except Exception as e: + return Response({"result": f"خطا در به‌روزرسانی صنف: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + else: + if request.GET.get('role') in ('AdminX', 'SuperAdmin'): + province_accept = 'accepted' + else: + province_accept = 'pending' + has_killhouse = system_profile.role.filter(name='KillHouse').exists() + if has_killhouse: + return Response({"result": "کاربر قبلا در سامانه ثبت شده است!"}, status=status.HTTP_403_FORBIDDEN) + try: + guilds = Guilds( + guilds_name=unit_name, + license_number=national_id, # استفاده از national_id به عنوان شماره صنف + user=system_profile, + registerar_fullname=registerar_fullname, + registerar_mobile=registerar_mobile, + address=address, + wallet=wallet, + type_activity=type_activity.title if type_activity else '', + area_activity=area_activity.title if area_activity else '', + province_accept_state=province_accept, + guild_type_activity=type_activity, + guild_area_activity=area_activity, + city_name=city_name, + province_name=province_name, + active=True, + is_real_person=False, + ) + + guilds.save() + + guilds_group = Group.objects.get(name__exact="Guilds") + if not system_profile.role.filter(name='Guilds').exists(): + system_profile.role.add(guilds_group) + + parent_product = NewProduct.objects.all().first() + price = BroadcastPrice.objects.filter(trash=False).first() + + if parent_product and price: + approved_price = price.guild_price + approved_type = price.active if approved_price > 0 else False + + product = RolesProducts( + parent_product=parent_product, + guild=guilds, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + + ser_data = GuildsSerializer(guilds).data + return Response(ser_data, status=status.HTTP_201_CREATED) + + except Exception as e: + return Response({"result": f"خطا در ایجاد صنف: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + except Exception as e: + return Response({"result": f"خطای کلی: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +class TotalGuildStewardWarehouseArchiveDashboardViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalGuildStewardWarehouseArchiveDashboardSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = GuildsForArchiveFilterSet + filterset_fields = [ + 'guilds_name', + 'user__mobile', + 'user__fullname', + 'user__first_name', + 'user__last_name' + + ] + + def get(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + owner_type = request.GET.get('owner_type') + if owner_type == 'steward': + archives_filters = {"trash": False, "steward__isnull": False} + else: + archives_filters = {"trash": False, "guild__isnull": False} + + if date1: + archives_filters['create_date__date__gte'] = date1 + archives_filters['create_date__date__lte'] = date2 + + archives = WarehouseArchive.objects.filter(**archives_filters) + + if owner_type == 'steward': + guilds = Guilds.objects.filter(id__in=archives.values_list('steward__id', flat=True), trash=False) + else: + guilds = Guilds.objects.filter(id__in=archives.values_list('guild__id', flat=True), trash=False) + + if 'search' in request.GET: + guilds_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=guilds + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=guilds) + guilds_list = ps.filter() + guilds = [] if len( + guilds_list) == 0 else guilds_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(guilds) + if page is not None: + serializer = self.get_serializer(page, many=True, + context={'date1': date1, 'date2': date2, 'owner_type': owner_type}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(guilds, many=True, + context={'date1': date1, 'date2': date2, 'owner_type': owner_type}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class MarketDailyLimitationViewset(viewsets.ModelViewSet): + queryset = MarketDailyLimitation.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = MarketDailyLimitationSerializer + + def get_object(self): + instance, created = MarketDailyLimitation.objects.get_or_create( + trash=False) + return instance + + def list(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + instance = self.get_object() + data = request.data.copy() + data.update({ + "register_fullname": user.fullname, + "register_mobile": user.mobile, + }) + serializer = self.get_serializer(instance, data=data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + + +class HatchingArchivePercentViewset(viewsets.ModelViewSet): + queryset = HatchingArchivePercent.objects.filter(trash=False) + permission_classes = [TokenHasReadWriteScope] + serializer_class = HatchingArchivePercentSerializer + + def get_object(self): + instance, created = HatchingArchivePercent.objects.get_or_create( + trash=False) + return instance + + def list(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=True) + serializer.is_valid(raise_exception=True) + serializer.save() + return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_steward_allocation_role_mismatch(request): + fixed_count = 0 + problems = [] + + steward_guilds = Guilds.objects.filter(steward=True, trash=False, active=True) + + for guild in steward_guilds: + wrong_allocations = StewardAllocation.objects.filter( + (Q(guilds=guild) | Q(to_guilds=guild)), + trash=False + ) + + for allocation in wrong_allocations: + if allocation.to_cold_house or allocation.other_cold_house: + continue + + if allocation.guilds == guild: + allocation.steward = guild + allocation.guilds = None + elif allocation.to_guilds == guild: + allocation.to_steward = guild + allocation.to_guilds = None + + if allocation.to_cold_house or allocation.other_cold_house: + pass + elif allocation.to_steward: + if allocation.steward: + allocation.type = 'steward_steward' + elif allocation.kill_house: + allocation.type = 'killhouse_steward' + elif allocation.to_guilds: + if allocation.steward: + allocation.type = 'steward_guild' + elif allocation.kill_house: + allocation.type = 'killhouse_guild' + + allocation.save() + fixed_count += 1 + + problems.append({ + 'guild_id': guild.id, + 'guild_name': guild.guilds_name, + 'guild_user_mobile': guild.user.mobile if guild.user else None, + 'guild_user_fullname': guild.user.fullname if guild.user else None, + 'allocation_id': allocation.id, + 'allocation_key': str(allocation.key) if allocation.key else None, + 'fixed': True + }) + + normal_guilds = Guilds.objects.filter(steward=False, trash=False, active=True) + + for guild in normal_guilds: + wrong_allocations = StewardAllocation.objects.filter( + (Q(steward=guild) | Q(to_steward=guild)), + trash=False + ) + + for allocation in wrong_allocations: + if allocation.to_cold_house or allocation.other_cold_house: + continue + + if allocation.steward == guild: + allocation.guilds = guild + allocation.steward = None + elif allocation.to_steward == guild: + allocation.to_guilds = guild + allocation.to_steward = None + + if allocation.to_cold_house or allocation.other_cold_house: + pass + elif allocation.to_steward: + if allocation.steward: + allocation.type = 'steward_steward' + elif allocation.kill_house: + allocation.type = 'killhouse_steward' + elif allocation.to_guilds: + if allocation.steward: + allocation.type = 'steward_guild' + elif allocation.kill_house: + allocation.type = 'killhouse_guild' + + allocation.save() + fixed_count += 1 + + problems.append({ + 'guild_id': guild.id, + 'guild_name': guild.guilds_name, + 'guild_user_mobile': guild.user.mobile if guild.user else None, + 'guild_user_fullname': guild.user.fullname if guild.user else None, + 'allocation_id': allocation.id, + 'allocation_key': str(allocation.key) if allocation.key else None, + 'fixed': True + }) + + return Response({ + 'result': 'اصلاح کامل شد', + 'total_fixed': fixed_count, + 'fixed_allocations': problems + }, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def get_dispenser_user_info(request): + national_code = request.GET.get('national_code') + if not national_code: + return Response({'result': 'ورود کد ملی الزامیست!'}, status=status.HTTP_403_FORBIDDEN) + if Dispenser.objects.filter(trash=False, user__national_id=national_code).exists(): + return Response({'result': 'این توزیع کننده قبلا ثبت شده!'}, status=status.HTTP_403_FORBIDDEN) + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=person" + ) + person_data = person_response.json() + return Response(person_data, status=status.HTTP_200_OK) diff --git a/panel/ReportingPanel/__init__.py b/panel/ReportingPanel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/ReportingPanel/excel_output.py b/panel/ReportingPanel/excel_output.py new file mode 100644 index 0000000..190b2f0 --- /dev/null +++ b/panel/ReportingPanel/excel_output.py @@ -0,0 +1,174 @@ +# if 'excel_export' in request.GET: +# options = [ +# 'مرغدار', +# 'شهر', +# 'استان', +# 'کد پستی', +# 'موبایل', +# 'تاریخ تولد', +# 'کد ملی', +# 'کد اکونومی', +# 'کد سیستمی', +# 'کد اپیدمیلوژیک', +# 'کد یکتا', +# 'ظرفیت کل', +# 'شماره مجوز', +# 'شماره گواهی بهداشتی', +# 'تعداد درخواست ها', +# 'تاریخ جوجه ریزی', +# 'تعداد جوجه ریزی', +# 'تعاونی', +# 'سفارشات', +# 'تعداد درخواست مرغدار', +# 'تاریخ درخواست', +# 'نوع مرغ', +# 'وزن جفت مرغ', +# 'تاییدیه شهرستان', +# 'اپراتور شهرستان', +# 'تاییدیه استان', +# 'اپراتور استان', +# 'موبایل اپراتور شهرستان', +# 'موبایل اپراتور استان', +# 'تاریخ تاییدیه شهرستان', +# 'تاریخ تاییدیه استان', +# 'کد سفارش', +# 'سن جوجه ها', +# 'وزن کل', +# 'قیمت کل', +# 'کارمزد', +# 'بارکد فاکتور', +# 'تاریخ فاکتور', +# 'نام مقصد پرداختی', +# 'شماره کارت مقصد پرداختی', +# 'شماره شبا مقصد پرداختی', +# ] +# excel_options = request.GET['excel_export'].split(',') +# if request.GET['excel_export'] == "": +# excel_options = options +# data_list = [] +# orders = [] +# for x in range(len(serializer.data)): +# nested_data_list = {} +# nested_data_list['مرغدار'] = serializer.data[x]['user']['fullname'] +# nested_data_list['مرغدار2'] = serializer.data[x]['id'] +# nested_data_list['شهر'] = serializer.data[x]['user']['address']['city'] +# nested_data_list['استان'] = serializer.data[x]['user']['address']['province'] +# nested_data_list['کد پستی'] = serializer.data[x]['user']['address']['postal_code'] +# nested_data_list['موبایل'] = serializer.data[x]['user']['mobile'] +# nested_data_list['تاریخ تولد'] = serializer.data[x]['user']['birthday'] +# nested_data_list['کد ملی'] = serializer.data[x]['user']['natinal_id'] +# nested_data_list['کد اکونومی'] = serializer.data[x]['user']['economic_code'] +# nested_data_list['کد سیستمی'] = serializer.data[x]['user']['system_code'] +# nested_data_list['کد اپیدمیلوژیک'] = serializer.data[x]['user']['epidemiological_code'] +# nested_data_list['کد یکتا'] = serializer.data[x]['user']['breeding_unique_id'] +# nested_data_list['ظرفیت کل'] = serializer.data[x]['user']['total_capacity'] +# nested_data_list['شماره مجوز'] = serializer.data[x]['user']['licence_number'] +# nested_data_list['شماره گواهی بهداشتی'] = serializer.data[x]['user'][ +# 'health_certificate_number'] +# nested_data_list['تعداد درخواست ها'] = serializer.data[x]['user']['number_of_requests'] +# nested_data_list['تاریخ جوجه ریزی'] = serializer.data[x]['user']['incubation_date'] +# nested_data_list['تعداد جوجه ریزی'] = serializer.data[x]['user']['number_of_incubators'] +# nested_data_list['تعاونی'] = serializer.data[x]['user']['cooperative'] +# if 'kill_house_assinment' in serializer.data[x].keys(): +# if len(serializer.data[x]['kill_house_assinment']['bars']) != 0: +# for i in serializer.data[x]['kill_house_assinment']['bars']: +# if 'poultry_net_weight' in i.keys(): +# poultry_net_weight = i['poultry_net_weight'] +# else: +# poultry_net_weight = "" +# if 'poultry_state' in i.keys(): +# state = i['poultry_state'] +# else: +# state = "" +# barcode = i['barcode'] +# kill_house_name = i['kill_house_name'] +# quantity = i['quantity'] +# date = i['date'] +# time = i['time'] +# name = i['car_info']['name'] +# car_quantity = i['car_info']['quantity'] +# pelak = i['car_info']['pelak'] +# driver_name = i['car_info']['driver_name'] +# order_string = "بارکد سفارش : {0}\n نام کشتارگاه : {1} \n تعداد : {2} \n تاریخ " \ +# ": {3} \n زمان : {4} \n مدل ماشین : {5} \n ظرفیت ماشین : {6} \n " \ +# "پلاک : {7} \n نام راننده : {8} \n وزن خالص : {9} \n وضعیت : {9} \n".format( +# barcode, +# kill_house_name, +# quantity, +# date, +# time, +# name, +# car_quantity, +# pelak, +# driver_name, +# poultry_net_weight, +# state, +# ) +# orders.append(order_string) +# nested_data_list['سفارشات'] = "".join(orders) +# nested_data_list['تعداد درخواست مرغدار'] = serializer.data[x]['quantity'] +# nested_data_list['تاریخ درخواست'] = serializer.data[x]['send_date'] +# nested_data_list['نوع مرغ'] = serializer.data[x]['chicken_breed'] +# nested_data_list['وزن جفت مرغ'] = serializer.data[x]['Index_weight'] +# nested_data_list['تاییدیه شهرستان'] = serializer.data[x]['state']['city_state'] +# nested_data_list['اپراتور شهرستان'] = serializer.data[x]['state']['city_operator'] +# nested_data_list['تاییدیه استان'] = serializer.data[x]['state']['province_state'] +# nested_data_list['اپراتور استان'] = serializer.data[x]['state']['province_operator'] +# nested_data_list['موبایل اپراتور شهرستان'] = serializer.data[x]['state']['city_operator_mobile'] +# if 'province_operator_mobile' in serializer.data[x]['state'].keys(): +# nested_data_list['موبایل اپراتور استان'] = serializer.data[x]['state'][ +# 'province_operator_mobile'] +# if 'city_operator_date_time_accepted' in serializer.data[x]['state'].keys(): +# nested_data_list['تاریخ تاییدیه شهرستان'] = serializer.data[x]['state'][ +# 'city_operator_date_time_accepted'] +# if 'province_operator_date_time_accepted' in serializer.data[x]['state'].keys(): +# nested_data_list['تاریخ تاییدیه استان'] = serializer.data[x]['state'][ +# 'province_operator_date_time_accepted'] +# nested_data_list['کد سفارش'] = serializer.data[x]['order_code'] +# nested_data_list['سن جوجه ها'] = serializer.data[x]['chicken_age'] +# if 'province_to_killhouse_factor' in serializer.data[x].keys(): +# nested_data_list['وزن کل'] = serializer.data[x]['province_to_killhouse_factor'][ +# 'total_weight'] +# nested_data_list['قیمت کل'] = serializer.data[x]['province_to_killhouse_factor'][ +# 'total_price'] +# nested_data_list['کارمزد'] = serializer.data[x]['province_to_killhouse_factor'][ +# 'factor_fee'] +# nested_data_list['بارکد فاکتور'] = serializer.data[x]['province_to_killhouse_factor'][ +# 'factor_bar_code'] +# nested_data_list['تاریخ فاکتور'] = serializer.data[x]['province_to_killhouse_factor'][ +# 'factor_date'] +# nested_data_list['نام مقصد پرداختی'] = \ +# serializer.data[x]['province_to_killhouse_factor']['bank']['bank_info'] +# nested_data_list['شماره کارت مقصد پرداختی'] = \ +# serializer.data[x]['province_to_killhouse_factor']['bank']['bank_card'] +# nested_data_list['شماره شبا مقصد پرداختی'] = \ +# serializer.data[x]['province_to_killhouse_factor']['bank']['bank_shaba'] +# data_list.append( +# nested_data_list, +# ) +# output = BytesIO() +# workbook = xlsxwriter.Workbook(output) +# worksheet = workbook.add_worksheet() +# for count in range(len(excel_options)): +# worksheet.write(0, count, excel_options[count]) +# +# for item in range(len(data_list)): +# for x in range(len(excel_options)): +# if excel_options[x] in data_list[item].keys(): +# worksheet.write(item + 1, x, data_list[item][excel_options[x]]) +# else: +# worksheet.write(item + 1, x, " ") +# workbook.close() +# output.seek(0) +# +# # create a response +# response = HttpResponse(content_type='application/vnd.ms-excel') +# +# # tell the browser what the file is named +# response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"' +# +# # put the spreadsheet data into the response +# response.write(output.getvalue()) +# +# # return the response +# return response diff --git a/panel/ReportingPanel/filterset.py b/panel/ReportingPanel/filterset.py new file mode 100644 index 0000000..b14caf0 --- /dev/null +++ b/panel/ReportingPanel/filterset.py @@ -0,0 +1,61 @@ +from url_filter.filtersets import ModelFilterSet + +from authentication.models import SystemUserProfile +from panel.models import ( + PoultryRequest, + KillHouseRequest, + CityOperatorCheckRequest, + ProvinceCheckOperatorRequest, + VetCheckRequest, + VetFarm, + KillHouseVet, + PoultryHatching, Poultry +) + + +class UserProfileFilterSet(ModelFilterSet): + class Meta(object): + model = SystemUserProfile + + +class PoultryFilterSet(ModelFilterSet): + class Meta(object): + model = Poultry + + +class PoultryRequestFilterSet(ModelFilterSet): + class Meta(object): + model = PoultryRequest + + +class KillHouseRequestFilterSet(ModelFilterSet): + class Meta(object): + model = KillHouseRequest + + +class CityOperatorCheckFilterSet(ModelFilterSet): + class Meta(object): + model = CityOperatorCheckRequest + + +class ProvinceOperatorCheckFilterSet(ModelFilterSet): + class Meta(object): + model = ProvinceCheckOperatorRequest + + +class VetOperatorCheckFilterSet(ModelFilterSet): + class Meta(object): + model = VetCheckRequest + + +class PoultryHatchingFilterSet(ModelFilterSet): + class Meta(object): + model = PoultryHatching + +class ProfileFilterSet(ModelFilterSet): + class Meta(object): + model = SystemUserProfile + +class ManagementVetFarmFilterSet(ModelFilterSet): + class Meta(object): + model = VetFarm diff --git a/panel/ReportingPanel/helper.py b/panel/ReportingPanel/helper.py new file mode 100644 index 0000000..d1b0e04 --- /dev/null +++ b/panel/ReportingPanel/helper.py @@ -0,0 +1,173 @@ + +poultry_request_fields = [ + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__national_id', + 'poultry__user__national_code', + 'poultry__address__province__name', + 'poultry__address__city__name', + 'poultry__natinal_id', + 'poultry__unit_name', + 'poultry__gis_code', + 'poultry__operating_licence_capacity', + 'poultry__number_of_halls', + 'poultry__person_type', + 'poultry__economic_code', + 'poultry__system_code', + 'poultry__epidemiological_code', + 'poultry__total_capacity', + 'poultry__licence_number', + 'poultry__health_certificate_number', + 'poultry__number_of_requests', + 'poultry__hatching_date', + 'hatching__quantity', + 'hatching__chicken_breed', + 'poultry__last_party_date', + 'poultry__number_of_incubators', + 'poultry__herd_age_by_day', + 'poultry__herd_age_by_week', + 'poultry__number_of_party', + 'poultry__communication_type', + 'poultry__cooperative', + 'poultry__date_of_register', + 'poultry__unit_status', + 'poultry__samasat_user_code', + 'poultry__incubation_date', + 'poultry__address__breeding_unique_id', + 'order_code', + 'quantity', + 'chicken_breed', + 'Index_weight', + 'user__address__postal_code', + 'user__company' + + # 'bar_code', +] + +user_fields = [ + 'mobile', + 'fullname', + 'first_name', + 'last_name', + 'province__name', + 'city__name', + 'national_code', + 'national_id', +] + +city_operator_fields = [ + 'city_operator_system__user__mobile', + 'city_operator_system__user__fullname', + 'city_operator_system__user__first_name', + 'city_operator_system__user__last_name', + 'city_operator_system__user__national_code', + 'city_operator_system__user__national_id', +] + +province_operator_fields = [ + 'province_operator_system__user__mobile', + 'province_operator_system__user__fullname', + 'province_operator_system__user__first_name', + 'province_operator_system__user__last_name', + 'province_operator_system__user__national_code', + 'province_operator_system__user__national_id', +] + +kill_house_operator_fields = [ + 'killhouse_user__userprofile__mobile', + 'killhouse_user__userprofile__fullname', + 'killhouse_user__userprofile__first_name', + 'killhouse_user__userprofile__last_name', + 'killhouse_user__userprofile__national_code', + 'killhouse_user__userprofile__national_id', + 'killhouse_user__name', + 'killhouse_user__phone', + 'killhouse_user__capacity', + 'capacity', + 'quantity', + 'bar_code', +] + +vet_operator_fields = [ + 'vet__user__mobile', + 'vet__user__fullname', + 'vet__user__first_name', + 'vet__user__last_name', + 'vet__user__national_code', + 'vet__user__national_id', +] + +poultry_hatching_fields = [ + 'quantity', + 'losses', + 'left_over', + 'hall', + 'chicken_breed', + 'period', + 'state' +] + +# new + +poultry_filterset_fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__city__name', + 'user__province_name', + 'unit_name', + 'gis_code', + 'operating_licence_capacity', + 'number_of_halls', + 'economic_code', + 'system_code', + 'epidemiological_code', + 'total_capacity', + 'licence_number', + 'health_certificate_number', +] + +poultry_hatching_filterset_fields = [ + 'quantity', + 'losses', + 'left_over', + 'hall', + 'chicken_breed', + 'period', + 'state' +] + +poultry_request_new_fields = [ + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__national_id', + 'poultry__user__national_code', + 'poultry__address__province__name', + 'poultry__address__city__name', + 'poultry__unit_name', + 'order_code', + 'quantity', + 'chicken_breed', + 'Index_weight', + + # 'bar_code', +] + +kill_house_request_filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__user__city__name', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + +] + + + diff --git a/panel/ReportingPanel/models.py b/panel/ReportingPanel/models.py new file mode 100644 index 0000000..e6b0dce --- /dev/null +++ b/panel/ReportingPanel/models.py @@ -0,0 +1,10 @@ +from authentication.models import BaseModel +from django.db import models + + +class SearchFields(BaseModel): + type = models.CharField(max_length=100, null=True) + field_name = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(SearchFields, self).save(*args, **kwargs) diff --git a/panel/ReportingPanel/serializer.py b/panel/ReportingPanel/serializer.py new file mode 100644 index 0000000..8bc4dbc --- /dev/null +++ b/panel/ReportingPanel/serializer.py @@ -0,0 +1,1873 @@ +import datetime + +from django.db.models import Q, Sum, F + +from rest_framework import serializers + +from deposit_percent import wage_percent, carcases_sell +from panel.models import ReportingFieldRoleLimitation, ProvinceKillRequest, KillHousePercentage, \ + KillHouseRequest, KillHouseFreeBarInformation, InternalTransaction, ChainAllocation, KillHouse, WageType, \ + PercentageOfWageType, KillHouseFreeSaleBarInformation, IranProvinces, IranCities, AgeNotificationPoultry, \ + CookieSamasat, HatchingLossManagement +from authentication.serializers import GroupSerializer +from .models import SearchFields + + +# class ReportingPanelSerializer(serializers.ModelSerializer): +# class Meta: +# model = PoultryRequest + + +class ReportingFieldLimitationSerializer(serializers.ModelSerializer): + role_name = GroupSerializer(required=False) + + class Meta: + model = ReportingFieldRoleLimitation + fields = [ + 'role_name', + 'fields' + ] + + def create(self, validated_data): + return ReportingFieldRoleLimitation.objects.create(**validated_data) + + +class SearchFieldsSerializer(serializers.ModelSerializer): + class Meta: + model = SearchFields + fields = ['type', 'field_name'] + + +class HatchingLossManagementSerializer(serializers.ModelSerializer): + class Meta: + model = HatchingLossManagement + fields = [ + 'id', + 'include_total_disease_losses', + 'include_total_flock_destruction', + 'include_total_normal_flock_losses', + 'include_total_force_majeure_losses', + 'include_total_fire_losses' + ] + read_only_fields = ['id'] + + +class DetailsGeneraWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['id', 'info'] + + def get_info(self, obj): + real_free_sale_wage = 0 + union_real_free_sale_wage = 0 + company_real_free_sale_wage = 0 + guilds_real_free_sale_wage = 0 + other_real_free_sale_wage = 0 + total_check_wage = 0 + union_wage_percent = 0 + company_wage_percent = 0 + guilds_wage_percent = 0 + other_wage_percent = 0 + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False) + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_wage = free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False) + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_wage = free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + union_free_sales = free_sales.filter(union_share__gt=0, trash=False) + union_free_sales_weight = union_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + union_free_sales_wage = union_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + company_free_sales = free_sales.filter(company_share__gt=0, trash=False) + company_free_sales_weight = company_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + company_free_sales_wage = company_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + guilds_free_sales = free_sales.filter(guilds_share__gt=0, trash=False) + guilds_free_sales_weight = guilds_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + guilds_free_sales_wage = guilds_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + other_free_sales = free_sales.filter(other_share__gt=0, trash=False) + other_free_sales_weight = other_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + other_free_sales_wage = other_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + if carcases_sell == True: + real_free_sale_wage = (free_sales_weight * total_check_wage) - free_sales_wage if (free_sales_weight * total_check_wage) - free_sales_wage > 0 else 0 + + union_real_free_sale_wage = (union_free_sales_weight * union_wage_percent) - union_free_sales_wage if (union_free_sales_weight * union_wage_percent) - union_free_sales_wage > 0 else 0 + + company_real_free_sale_wage = (company_free_sales_weight * company_wage_percent) - company_free_sales_wage if (company_free_sales_weight * company_wage_percent) - company_free_sales_wage > 0 else 0 + + + guilds_real_free_sale_wage = (guilds_free_sales_weight * guilds_wage_percent) - guilds_free_sales_wage if (guilds_free_sales_weight * guilds_wage_percent) - guilds_free_sales_wage > 0 else 0 + + other_real_free_sale_wage = (other_free_sales_weight * other_wage_percent) - other_free_sales_wage if (other_free_sales_weight * other_wage_percent) - other_free_sales_wage > 0 else 0 + + if obj.killer == True: + killer = True + else: + killer = False + if obj.killer == True and obj.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=obj, trash=False) + killer_type = f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif obj.killer == True and obj.type == 'public': + killer_type = 'کشتارکن عمومی' + else: + killer_type = 'کشتارگاه' + role = self.context.get('request').GET['role'] + + if self.context.get('request').GET['date1'] != 'null': + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).exclude(union_share=0, company_share=0, + guilds_share=0).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=obj) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) | Q(killer=obj)), + archive_wage=False, + trash=False, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).select_related('province_kill_request').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity', 'accepted_real_quantity') + + kill_house_requests = kill_house_requests.filter(Q(killer=obj) | Q(killhouse_user=obj)).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, kill_house=obj, + archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + + slaughter_transactions = InternalTransaction.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house=obj, status='completed', + trash=False).only('union_share', + 'company_share', + 'guilds_share', 'amount') + + else: + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=obj, + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ).exclude(union_share=0, company_share=0, + guilds_share=0).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killer=obj) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) & Q(killhouse_user=obj)) | Q( + Q(killer__isnull=True) | Q(killer=obj)), + archive_wage=False, + trash=False + ).select_related('province_kill_request').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity', 'accepted_real_quantity') + kill_house_requests = kill_house_requests.filter(Q(killer=obj) | Q(killhouse_user=obj)).select_related( + 'province_kill_request').only( + 'accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(kill_house=obj, archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house=obj, status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_wage_amount'))[ + 'total'] or 0 + if wage_percent > 0: + province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + freezing_province_kill_request_total_wage = \ + freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + kill_house_reqest_total_wage = \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + if wage_percent > 0: + kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + freezing_kill_house_reqest_total_wage = \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage = free_bars_carcases_total_wage + kill_house_reqest_total_wage + \ + freezing_kill_house_reqest_total_wage + province_kill_requests_total_wage + \ + freezing_province_kill_request_total_wage + free_bars_live_total_wage + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + union_province_kill_request_total_wage = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + union_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + union_province_kill_request_kill_house_requests_total_wage -= union_province_kill_request_kill_house_requests_total_wage * wage_percent + union_province_kill_request_total_wage += union_province_kill_request_kill_house_requests_total_wage + + freezing_union_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + union_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + union_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage = \ + slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_total_wage = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + if wage_percent > 0: + company_province_kill_request_total_wage -= company_province_kill_request_total_wage * wage_percent + company_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + company_province_kill_request_kill_house_requests_total_wage -= company_province_kill_request_kill_house_requests_total_wage * wage_percent + + company_province_kill_request_total_wage += company_province_kill_request_kill_house_requests_total_wage + freezing_company_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + + company_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + + company_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage = \ + slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_total_wage = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + if wage_percent > 0: + guilds_province_kill_request_total_wage -= guilds_province_kill_request_total_wage * wage_percent + + guilds_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + + if wage_percent > 0: + guilds_province_kill_request_kill_house_requests_total_wage -= guilds_province_kill_request_kill_house_requests_total_wage * wage_percent + + guilds_province_kill_request_total_wage += guilds_province_kill_request_kill_house_requests_total_wage + freezing_guilds_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + + guilds_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage = \ + slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + accepted_real_weight = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + if wage_percent > 0: + accepted_real_weight -= accepted_real_weight * wage_percent + total_killed_weights = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + total_killed_weights -= total_killed_weights * wage_percent + total_killed_quantitys = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + accepted_real_quantity = \ + kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + + guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_total_wage = \ + province_kill_requests.filter(other_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('other_share'))[ + 'total'] or 0 + if wage_percent > 0: + other_province_kill_request_total_wage -= other_province_kill_request_total_wage * wage_percent + + other_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__other_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__other_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + other_province_kill_request_kill_house_requests_total_wage -= other_province_kill_request_kill_house_requests_total_wage * wage_percent + other_province_kill_request_total_wage += other_province_kill_request_kill_house_requests_total_wage + freezing_other_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + freezing_other_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__other_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__other_share_percent') / 100)))[ + 'total'] or 0 + + other_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + other_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + other_total_paid_wage = \ + slaughter_transactions.filter(other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + other_total_wage = other_province_kill_request_total_wage + freezing_other_province_kill_request_total_wage + other_kill_house_free_live_bar_total_wage + other_kill_house_free_carcases_bar_total_wage + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + not_paied = total_wage - total_paid_wage + values_list3 = { + "type": killer_type, + "killer": killer, + "kill_house_name": obj.name, + "fullname": obj.kill_house_operator.user.fullname, + "mobile": obj.kill_house_operator.user.mobile, + "city": obj.kill_house_operator.user.city.name, + "len_province_kill_requests": len(province_kill_requests), + "total_killed_quantity": total_killed_quantitys, + "total_killed_weight": total_killed_weights, + "len_kill_house_requests": len(kill_house_requests), + "accepted_real_quantity": accepted_real_quantity, + "accepted_real_weight": accepted_real_weight, + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) > 0 else 0, + "union_total_unpaid_wage": union_total_unpaid_wage, + "union_total_paid_wage": union_total_paid_wage, + } + + if role == 'ProvinceOperator': + pass + elif role == 'AdminX': + values_list3.update({ + "off": obj.off, + "len_slaughter_transactions": len(slaughter_transactions), + "total_wage": total_wage - real_free_sale_wage if (total_wage - real_free_sale_wage) > 0 else 0 , + "company_total_wage": company_total_wage - company_real_free_sale_wage if (company_total_wage - company_real_free_sale_wage) > 0 else 0, + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) >0 else 0, + "guilds_total_wage": guilds_total_wage - guilds_real_free_sale_wage if (guilds_total_wage - guilds_real_free_sale_wage) > 0 else 0, + "other_total_wage": other_total_wage - other_real_free_sale_wage if (other_total_wage - other_real_free_sale_wage) > 0 else 0, + "not_paied": not_paied - obj.off, + "company_total_unpaid_wage": company_total_unpaid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + "other_total_unpaid_wage": other_total_unpaid_wage, + "total_paid_wage": total_paid_wage, + "union_total_paid_wage": union_total_paid_wage, + "company_total_paid_wage": company_total_paid_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "other_total_paid_wage": other_total_paid_wage, + }) + else: + values_list3.update({ + "off": obj.off, + "total_wage": total_wage - real_free_sale_wage if (total_wage - real_free_sale_wage) > 0 else 0 , + "company_total_wage": company_total_wage - company_real_free_sale_wage if (company_total_wage - company_real_free_sale_wage) > 0 else 0, + "len_slaughter_transactions": len(slaughter_transactions), + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) >0 else 0, + "guilds_total_wage": guilds_total_wage - guilds_real_free_sale_wage if (guilds_total_wage - guilds_real_free_sale_wage) > 0 else 0, + # "not_paied": not_paied - other_total_unpaid_wage, + "not_paied": not_paied - obj.off, + "company_total_unpaid_wage": company_total_unpaid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + "total_paid_wage": total_paid_wage , + "company_total_paid_wage": company_total_paid_wage, + "union_total_paid_wage": union_total_paid_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + }) + + return values_list3 + + +class DashboardDetailsGeneraWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['id', 'info'] + + def get_info(self, obj): + role = self.context.get('request').GET['role'] + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + union_total_paid_wage = 0 + + union_chain_allocation_total_wage = 0 + + company_total_paid_wage = 0 + + company_chain_allocation_total_wage = 0 + + guilds_total_paid_wage = 0 + + guilds_chain_allocation_total_wage = 0 + + other_total_weight = 0 + other_total_wage = 0 + other_total_paid_wage = 0 + other_chain_allocation_total_wage = 0 + + other_chain_allocation_total_weight = 0 + real_free_sale_wage = 0 + union_real_free_sale_wage = 0 + company_real_free_sale_wage = 0 + guilds_real_free_sale_wage = 0 + other_real_free_sale_wage = 0 + total_check_wage = 0 + union_wage_percent = 0 + company_wage_percent = 0 + guilds_wage_percent = 0 + other_wage_percent = 0 + wage_type = WageType.objects.filter(en_name='province-kill-request').first() + total_check_wage = wage_type.amount + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + union_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name == 'company': + company_wage_percent = percentage_wage_type.percent / 100 + + elif percentage_wage_type.share_type.en_name == 'guilds': + guilds_wage_percent = percentage_wage_type.percent / 100 + elif percentage_wage_type.share_type.en_name in ['city', 'wallet']: + pass + else: + other_wage_percent = percentage_wage_type.percent / 100 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False) + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_wage = free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + free_sales = KillHouseFreeSaleBarInformation.objects.filter(trash=False) + free_sales_weight = free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + free_sales_wage = free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + union_free_sales = free_sales.filter(union_share__gt=0, trash=False) + union_free_sales_weight = union_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + union_free_sales_wage = union_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + company_free_sales = free_sales.filter(company_share__gt=0, trash=False) + company_free_sales_weight = company_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + company_free_sales_wage = company_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + guilds_free_sales = free_sales.filter(guilds_share__gt=0, trash=False) + guilds_free_sales_weight = guilds_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + guilds_free_sales_wage = guilds_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + other_free_sales = free_sales.filter(other_share__gt=0, trash=False) + other_free_sales_weight = other_free_sales.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + + other_free_sales_wage = other_free_sales.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + if carcases_sell == True: + real_free_sale_wage = (free_sales_weight * total_check_wage) - free_sales_wage if (free_sales_weight * total_check_wage) - free_sales_wage > 0 else 0 + + union_real_free_sale_wage = (union_free_sales_weight * union_wage_percent) - union_free_sales_wage if (union_free_sales_weight * union_wage_percent) - union_free_sales_wage > 0 else 0 + + company_real_free_sale_wage = (company_free_sales_weight * company_wage_percent) - company_free_sales_wage if (company_free_sales_weight * company_wage_percent) - company_free_sales_wage > 0 else 0 + + + guilds_real_free_sale_wage = (guilds_free_sales_weight * guilds_wage_percent) - guilds_free_sales_wage if (guilds_free_sales_weight * guilds_wage_percent) - guilds_free_sales_wage > 0 else 0 + + other_real_free_sale_wage = (other_free_sales_weight * other_wage_percent) - other_free_sales_wage if (other_free_sales_weight * other_wage_percent) - other_free_sales_wage > 0 else 0 + + + if self.context.get('request').GET['date1'] != 'null': + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).exclude(union_share=0, company_share=0, + guilds_share=0).only('total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + archive_wage=False, + trash=False, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).select_related('province_kill_request').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity').select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity', + 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + + slaughter_transactions = InternalTransaction.objects.filter(date__date__gte=date1, + date__date__lte=date2, + status='completed', kill_house__isnull=False, + trash=False).only('union_share', + 'company_share', + 'guilds_share', 'amount') + + + else: + province_kill_requests = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), + trash=False, + return_to_province=False, + first_car_allocated_quantity=0, + archive_wage=False, + ).exclude(union_share=0, company_share=0, + guilds_share=0).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity') + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'guilds_share', 'total_wage_amount', + 'total_killed_quantity') + + kill_house_requests = KillHouseRequest.objects.filter( + archive_wage=False, + trash=False + ).select_related('province_kill_request').only( + 'accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity').only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', + 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', + 'accepted_real_quantity', + 'accepted_real_quantity') + + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True).select_related( + 'province_kill_request').only('accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity') + + free_bars = KillHouseFreeBarInformation.objects.filter(archive_wage=False, + trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount') + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + 'total_wage_amount' + ) + slaughter_transactions = InternalTransaction.objects.filter( + kill_house__isnull=False, status='completed', + trash=False).only('union_share', 'company_share', 'guilds_share', 'amount') + + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_wage_amount'))[ + 'total'] or 0 + if wage_percent > 0: + province_kill_requests_total_wage -= province_kill_requests_total_wage * wage_percent + freezing_province_kill_request_total_wage = \ + freezing_province_kill_requests.aggregate(total=Sum('total_wage_amount'))['total'] or 0 + + total_wage += province_kill_requests_total_wage + freezing_province_kill_request_total_wage + province_kill_requests_total_weight = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + if wage_percent > 0: + province_kill_requests_total_weight -= province_kill_requests_total_weight * wage_percent + freezing_province_kill_request_total_weight = \ + freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_weight += province_kill_requests_total_weight + freezing_province_kill_request_total_weight + kill_house_reqest_total_wage = \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + if wage_percent > 0: + kill_house_reqest_total_wage -= kill_house_reqest_total_wage * wage_percent + freezing_kill_house_reqest_total_wage = \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + total_wage += kill_house_reqest_total_wage + freezing_kill_house_reqest_total_wage + + kill_house_reqest_total_weight = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + kill_house_reqest_total_weight -= kill_house_reqest_total_weight * wage_percent + freezing_kill_house_reqest_total_weight = \ + freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + total_weight += kill_house_reqest_total_weight + freezing_kill_house_reqest_total_weight + + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_live_total_wage + free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_weight += free_bars_live_total_weight + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum('total_wage_amount'))[ + 'total'] or 0 + total_wage += free_bars_carcases_total_wage + free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_weight += free_bars_carcases_total_weight + + total_paid_wage += slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + union_province_kill_request_total_weight = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + if wage_percent > 0: + union_province_kill_request_total_weight -= union_province_kill_request_total_weight * wage_percent + freezing_union_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + union_province_kill_request_kill_house_requests_total_weight = \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + if wage_percent > 0: + union_province_kill_request_kill_house_requests_total_weight -= union_province_kill_request_kill_house_requests_total_weight * wage_percent + union_province_kill_request_total_weight += union_province_kill_request_kill_house_requests_total_weight + + freezing_union_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + union_province_kill_request_total_wage = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + if wage_percent > 0: + union_province_kill_request_total_wage -= union_province_kill_request_total_wage * wage_percent + + union_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + union_province_kill_request_kill_house_requests_total_wage -= union_province_kill_request_kill_house_requests_total_wage * wage_percent + union_province_kill_request_total_wage += union_province_kill_request_kill_house_requests_total_wage + + freezing_union_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + union_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + union_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_chain_allocation_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_total_weight = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + company_province_kill_request_total_weight -= company_province_kill_request_total_weight * wage_percent + + company_province_kill_request_kill_house_requests_total_weight = \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + if wage_percent > 0: + company_province_kill_request_kill_house_requests_total_weight -= company_province_kill_request_kill_house_requests_total_weight * wage_percent + company_province_kill_request_total_weight += company_province_kill_request_kill_house_requests_total_weight + freezing_company_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + company_province_kill_request_total_wage = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + if wage_percent > 0: + company_province_kill_request_total_wage -= company_province_kill_request_total_wage * wage_percent + + company_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + company_province_kill_request_kill_house_requests_total_wage -= company_province_kill_request_kill_house_requests_total_wage * wage_percent + company_province_kill_request_total_wage += company_province_kill_request_kill_house_requests_total_wage + freezing_company_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + + company_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + + company_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_chain_allocation_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_total_weight = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + if wage_percent > 0: + guilds_province_kill_request_total_weight -= guilds_province_kill_request_total_weight * wage_percent + + guilds_province_kill_request_kil_house_requests_total_weight = \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + guilds_province_kill_request_kil_house_requests_total_weight -= guilds_province_kill_request_kil_house_requests_total_weight * wage_percent + + guilds_province_kill_request_total_weight += guilds_province_kill_request_kil_house_requests_total_weight + + freezing_guilds_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + guilds_province_kill_request_total_wage = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + if wage_percent > 0: + guilds_province_kill_request_total_wage -= guilds_province_kill_request_total_wage * wage_percent + guilds_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + guilds_province_kill_request_kill_house_requests_total_wage -= guilds_province_kill_request_kill_house_requests_total_wage * wage_percent + guilds_province_kill_request_total_wage += guilds_province_kill_request_kill_house_requests_total_wage + freezing_guilds_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + + guilds_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + accepted_real_weight = \ + kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_killed_weights = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + total_killed_quantitys = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + accepted_real_quantity = \ + kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + + guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_chain_allocation_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + other_province_kill_request_total_weight = \ + province_kill_requests.filter(other_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + other_province_kill_request_total_weight -= other_province_kill_request_total_weight * wage_percent + + other_province_kill_request_kill_house_requests_total_weight = \ + kill_house_requests.filter(province_kill_request__other_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + if wage_percent > 0: + other_province_kill_request_kill_house_requests_total_weight -= other_province_kill_request_kill_house_requests_total_weight * wage_percent + + other_province_kill_request_total_weight += other_province_kill_request_kill_house_requests_total_weight + + freezing_other_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(other_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_other_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__other_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + other_province_kill_request_total_wage = \ + province_kill_requests.filter(other_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('other_share'))[ + 'total'] or 0 + if wage_percent > 0: + other_province_kill_request_total_wage -= other_province_kill_request_total_wage * wage_percent + + other_province_kill_request_kill_house_requests_total_wage = \ + kill_house_requests.filter(province_kill_request__other_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__other_share_percent') / 100)))[ + 'total'] or 0 + if wage_percent > 0: + other_province_kill_request_kill_house_requests_total_wage -= other_province_kill_request_kill_house_requests_total_wage * wage_percent + other_province_kill_request_total_wage += other_province_kill_request_kill_house_requests_total_wage + freezing_other_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + freezing_other_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__other_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__other_share_percent') / 100)))[ + 'total'] or 0 + other_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', other_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + other_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + other_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', other_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + other_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + other_total_paid_wage += \ + slaughter_transactions.filter(other_share__gt=0).aggregate(total=Sum('other_share'))[ + 'total'] or 0 + + other_total_weight = other_province_kill_request_total_weight + freezing_other_province_kill_request_total_weight + other_chain_allocation_total_weight + other_kill_house_free_live_bar_total_weight + other_kill_house_free_carcases_bar_total_weight + other_total_wage = other_province_kill_request_total_wage + freezing_other_province_kill_request_total_wage + other_chain_allocation_total_wage + other_kill_house_free_live_bar_total_wage + other_kill_house_free_carcases_bar_total_wage + other_total_unpaid_wage = other_total_wage - other_total_paid_wage + kill_houses = KillHouse.objects.filter(trash=False, + id__in=province_kill_requests.values_list('killhouse_user', flat=True)) + total_off = kill_houses.aggregate(total=Sum('off'))[ + 'total'] or 0 + + not_paied = total_wage - total_paid_wage + + if role == 'ProvinceOperator': + values_list3 = { + "len_province_kill_requests": len(province_kill_requests), + "total_killed_quantity": total_killed_quantitys, + "total_killed_weight": total_killed_weights, + "len_kill_house_requests": len(kill_house_requests), + "accepted_real_quantity": accepted_real_quantity, + "accepted_real_weight": accepted_real_weight, + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) > 0 else 0, + "union_total_unpaid_wage": union_total_unpaid_wage, + "union_total_paid_wage": union_total_paid_wage, + + } + return values_list3 + elif role == 'AdminX': + values_list3 = { + "len_province_kill_requests": len(province_kill_requests), + "total_killed_quantity": total_killed_quantitys, + "total_killed_weight": total_killed_weights, + "len_kill_house_requests": len(kill_house_requests), + "accepted_real_quantity": accepted_real_quantity, + "accepted_real_weight": accepted_real_weight, + "len_slaughter_transactions": len(slaughter_transactions), + "total_wage": total_wage - real_free_sale_wage if (total_wage - real_free_sale_wage) > 0 else 0, + "company_total_wage": company_total_wage - company_real_free_sale_wage if (company_total_wage - company_real_free_sale_wage) > 0 else 0 , + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) > 0 else 0, + "guilds_total_wage": guilds_total_wage - guilds_real_free_sale_wage if (guilds_total_wage - guilds_real_free_sale_wage) > 0 else 0, + "other_total_wage": other_total_wage - other_real_free_sale_wage if (other_total_wage - other_real_free_sale_wage) > 0 else 0, + "not_paied": not_paied - total_off, + "company_total_unpaid_wage": company_total_unpaid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + "other_total_unpaid_wage": other_total_unpaid_wage, + "total_paid_wage": total_paid_wage, + "union_total_paid_wage": union_total_paid_wage, + "company_total_paid_wage": company_total_paid_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "other_total_paid_wage": other_total_paid_wage, + "total_off": total_off, + + } + return values_list3 + else: + values_list3 = { + "len_province_kill_requests": len(province_kill_requests), + "total_killed_quantity": total_killed_quantitys, + "total_killed_weight": total_killed_weights, + "len_kill_house_requests": len(kill_house_requests), + "accepted_real_quantity": accepted_real_quantity, + "accepted_real_weight": accepted_real_weight, + "len_slaughter_transactions": len(slaughter_transactions), + "total_wage": total_wage - real_free_sale_wage if (total_wage - real_free_sale_wage) > 0 else 0, + "company_total_wage": company_total_wage - company_real_free_sale_wage if (company_total_wage - company_real_free_sale_wage) > 0 else 0, + "union_total_wage": union_total_wage - union_real_free_sale_wage if (union_total_wage - union_real_free_sale_wage) > 0 else 0, + "guilds_total_wage": guilds_total_wage - guilds_real_free_sale_wage if (guilds_total_wage - guilds_real_free_sale_wage) > 0 else 0, + "not_paied": not_paied - total_off, + "company_total_unpaid_wage": company_total_unpaid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + "total_paid_wage": total_paid_wage, + "union_total_paid_wage": union_total_paid_wage, + "company_total_paid_wage": company_total_paid_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "total_off": total_off, + + } + return values_list3 + + +class NewDetailsGeneraWageSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = KillHouse + fields = ['id', 'info'] + + def get_info(self, obj): + request = self.context.get('request') + date1, date2 = self.parse_dates(request) + role = request.GET.get('role') + + province_kill_requests_filters = self.get_province_kill_requests_filters(obj, date1, date2) + kill_house_requests_filters = self.get_kill_house_requests_filters(obj, date1, date2) + free_bars_filters = self.get_free_bars_filters(obj, date1, date2) + slaughter_transactions_filters = self.get_slaughter_transactions_filters(obj, date1, date2) + province_kill_requests = self.filter_province_kill_requests(province_kill_requests_filters) + kill_house_requests = self.filter_kill_house_requests(kill_house_requests_filters, obj) + free_bars = self.filter_free_bars(free_bars_filters) + slaughter_transactions = self.filter_slaughter_transactions(slaughter_transactions_filters) + + wage_data = self.calculate_wage_data(obj, province_kill_requests, kill_house_requests, free_bars, + slaughter_transactions) + basic_info = self.get_basic_info(obj, province_kill_requests, kill_house_requests, free_bars, + slaughter_transactions, wage_data) + + return self.prepare_info(role, obj, basic_info, slaughter_transactions, wage_data) + + def parse_dates(self, request): + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + + if date1 != 'null' and date2 != 'null': + date1 = datetime.datetime.strptime(date1, '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(date2, '%Y-%m-%d').date() + else: + date1 = date2 = None + return date1, date2 + + def get_province_kill_requests_filters(self, obj, date1, date2): + filters = { + 'killhouse_user': obj, + 'state__in': ('pending', 'accepted'), + 'trash': False, + 'return_to_province': False, + 'first_car_allocated_quantity': 0, + 'archive_wage': False + } + if date1 and date2: + filters.update({ + 'kill_request__recive_date__date__gte': date1, + 'kill_request__recive_date__date__lte': date2, + }) + return filters + + def get_kill_house_requests_filters(self, obj, date1, date2): + filters = Q( + (Q(killer=obj) & Q(killhouse_user=obj)) | + Q(killer__isnull=True, killhouse_user=obj) | + Q(killer__isnull=True) | Q(killer=obj) + ) + filters &= Q(archive_wage=False, trash=False) + if date1 and date2: + filters &= Q(kill_request__recive_date__date__gte=date1) + filters &= Q(kill_request__recive_date__date__lte=date2) + return filters + + def get_free_bars_filters(self, obj, date1, date2): + filters = { + 'kill_house': obj, + 'trash': False, + 'archive_wage': False + } + if date1 and date2: + filters.update({ + 'date__date__gte': date1, + 'date__date__lte': date2, + }) + return filters + + def get_slaughter_transactions_filters(self, obj, date1, date2): + filters = { + 'kill_house': obj, + 'trash': False, + 'status': 'completed', + } + if date1 and date2: + filters.update({ + 'date__date__gte': date1, + 'date__date__lte': date2, + }) + return filters + + def filter_province_kill_requests(self, filters): + return ProvinceKillRequest.objects.filter(**filters).exclude( + union_share=0, company_share=0, guilds_share=0 + ).only( + 'total_killed_weight', 'union_share', 'company_share', + 'guilds_share', 'total_wage_amount', 'total_killed_quantity' + ) + + def filter_kill_house_requests(self, filters, obj): + return KillHouseRequest.objects.filter(filters).select_related( + 'province_kill_request' + ).only( + 'accepted_real_weight', 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent', 'accepted_real_quantity' + ).filter( + Q(killer=obj) | Q(killhouse_user=obj) + ) + + def filter_free_bars(self, filters): + return KillHouseFreeBarInformation.objects.filter(**filters).only( + 'live_weight', 'union_share', 'weight_of_carcasses', + 'company_share', 'guilds_share', 'total_wage_amount' + ) + + def filter_slaughter_transactions(self, filters): + return InternalTransaction.objects.filter(**filters).only( + 'union_share', 'company_share', 'guilds_share', 'amount' + ) + + def calculate_wage_data(self, obj, province_kill_requests, kill_house_requests, free_bars, slaughter_transactions): + def sum_field(queryset, field): + return queryset.aggregate(total=Sum(field))['total'] or 0 + + def calculate_wage(queryset, weight_field, percent_field): + return queryset.aggregate( + total=Sum(F(weight_field) * F(percent_field) / 100) + )['total'] or 0 + + wage_data = { + 'province_kill_requests_total_wage': sum_field(province_kill_requests, 'total_wage_amount'), + 'kill_house_requests_total_wage': sum_field(kill_house_requests, + F('accepted_real_weight') * F('province_kill_request__wage')), + 'free_bars_live_total_wage': sum_field(free_bars.filter(buy_type='live'), 'total_wage_amount'), + 'free_bars_carcases_total_wage': sum_field(free_bars.filter(buy_type='carcass'), 'total_wage_amount'), + 'total_paid_wage': sum_field(slaughter_transactions, 'amount'), + 'union_total_paid_wage': sum_field(slaughter_transactions, 'union_share'), + 'company_total_paid_wage': sum_field(slaughter_transactions, 'company_share'), + 'guilds_total_paid_wage': sum_field(slaughter_transactions, 'guilds_share'), + 'union_total_wage': calculate_wage(kill_house_requests, 'accepted_real_weight', + 'province_kill_request__union_share_percent') + sum_field( + province_kill_requests, 'union_share') + sum_field(free_bars, 'union_share'), + 'company_total_wage': calculate_wage(kill_house_requests, 'accepted_real_weight', + 'province_kill_request__company_share_percent') + sum_field( + province_kill_requests, 'company_share') + sum_field(free_bars, 'company_share'), + 'guilds_total_wage': calculate_wage(kill_house_requests, 'accepted_real_weight', + 'province_kill_request__guilds_share_percent') + sum_field( + province_kill_requests, 'guilds_share') + sum_field(free_bars, 'guilds_share'), + } + + wage_data['total_wage'] = sum(wage_data[key] for key in wage_data if + key in ['province_kill_requests_total_wage', 'kill_house_requests_total_wage', + 'free_bars_live_total_wage', 'free_bars_carcases_total_wage']) + wage_data['not_paied'] = wage_data['total_wage'] - (wage_data['total_paid_wage'] + obj.off) + wage_data['union_total_unpaid_wage'] = wage_data['union_total_wage'] - wage_data['union_total_paid_wage'] + wage_data['company_total_unpaid_wage'] = wage_data['company_total_wage'] - wage_data['company_total_paid_wage'] + wage_data['guilds_total_unpaid_wage'] = wage_data['guilds_total_wage'] - wage_data['guilds_total_paid_wage'] + + return wage_data + + def get_basic_info(self, obj, province_kill_requests, kill_house_requests, free_bars, slaughter_transactions, + wage_data): + def sum_field(queryset, field): + return queryset.aggregate(total=Sum(field))['total'] or 0 + + return { + "type": self.get_killer_type(obj), + "killer": obj.killer, + "kill_house_name": obj.name, + "fullname": obj.kill_house_operator.user.fullname, + "mobile": obj.kill_house_operator.user.mobile, + "city": obj.kill_house_operator.user.city.name, + "len_province_kill_requests": len(province_kill_requests), + "total_killed_quantity": sum_field(province_kill_requests, 'total_killed_quantity'), + "total_killed_weight": sum_field(province_kill_requests, 'total_killed_weight'), + "len_kill_house_requests": len(kill_house_requests), + "len_slaughter_transactions": len(slaughter_transactions), + "accepted_real_quantity": sum_field(kill_house_requests, 'accepted_real_quantity'), + "accepted_real_weight": sum_field(kill_house_requests, 'accepted_real_weight'), + "free_bar_live_quantity": sum_field(free_bars.filter(buy_type='live'), 'quantity'), + "free_bar_live_weight": sum_field(free_bars.filter(buy_type='live'), 'live_weight'), + "free_bar_carcasses_quantity": sum_field(free_bars.filter(buy_type='carcass'), 'number_of_carcasses'), + "free_bar_carcasses_weight": sum_field(free_bars.filter(buy_type='carcass'), 'weight_of_carcasses'), + "union_total_wage": wage_data['union_total_wage'], + "union_total_unpaid_wage": wage_data['union_total_unpaid_wage'], + "union_total_paid_wage": wage_data['total_paid_wage'], + } + + def get_killer_type(self, obj): + if obj.killer: + if obj.type == 'exclusive': + parent = KillHousePercentage.objects.get(kill_house=obj, trash=False) + return f'کشتارکن اختصاصی {parent.kill_house_for_killer.name}' + elif obj.type == 'public': + return 'کشتارکن عمومی' + return 'کشتارگاه' + + def prepare_info(self, role, obj, basic_info, slaughter_transactions, wage_data): + # def sum_field(queryset, field): + # return queryset.aggregate(total=Sum(field))['total'] or 0 + + if role == 'ProvinceOperator': + return basic_info + elif role == 'AdminX': + admin_info = { + "off": obj.off, + # "free_bars_live_weight": sum_field( + # KillHouseFreeBarInformation.objects.filter(kill_house=obj, trash=False, buy_type='live'), + # 'live_weight'), + # "free_bars_carcasses_weight": sum_field( + # KillHouseFreeBarInformation.objects.filter(kill_house=obj, trash=False, buy_type='carcass'), + # 'weight_of_carcasses'), + **wage_data + } + return {**basic_info, **admin_info} + return {} + + +class GenaeralWageSerailizer(serializers.ModelSerializer): + general = serializers.SerializerMethodField('get_general') + + class Meta: + model = ProvinceKillRequest + fields = ['key', 'general'] + + def get_general(self, province_kill_requests): + type = 'total_wage_amount' + share_type = 'amount' + + total_weight = 0 + total_wage = 0 + total_paid_wage = 0 + union_total_paid_wage = 0 + company_total_paid_wage = 0 + guilds_total_paid_wage = 0 + freezing_province_kill_requests = province_kill_requests.filter( + province_request__poultry_request__freezing=True).only('total_killed_weight', 'union_share', + 'company_share', + 'total_killed_weight', 'guilds_share') + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, archive_wage=False).exclude( + province_kill_request__union_share=0, province_kill_request__company_share=0, + province_kill_request__guilds_share=0).only('accepted_real_weight', + 'province_kill_request__union_share_percent', + 'province_kill_request__wage', 'accepted_real_weight', + 'province_kill_request__guilds_share_percent', + 'province_kill_request__company_share_percent') + freezing_kill_house_requests = kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=True) + + chain_allocations = ChainAllocation.objects.filter(trash=False, state='accepted').only('weight', 'union_share', + 'company_share', + 'guilds_share', + ) + free_bars = KillHouseFreeBarInformation.objects.filter(archive_wage=False, trash=False).only('live_weight', + 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + ) + total_slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', + status='completed', + trash=False).only('union_share', + 'company_share', + 'guilds_share') + total_chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', + status='completed', trash=False).only( + 'union_share', 'company_share', 'guilds_share') + + union_province_kill_request_total_weight = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + union_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + union_province_kill_request_total_wage = \ + province_kill_requests.filter(union_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('union_share'))[ + 'total'] or 0 + union_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__union_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + + freezing_union_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + freezing_union_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__union_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__union_share_percent') / 100)))[ + 'total'] or 0 + union_chain_allocation_total_weight = \ + chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + union_chain_allocation_total_wage = \ + chain_allocations.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + union_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + + union_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + union_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + total_slaughter_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_paid_wage += \ + total_chain_company_transactions.filter(union_share__gt=0).aggregate(total=Sum('union_share'))[ + 'total'] or 0 + union_total_weight = union_province_kill_request_total_weight + freezing_union_province_kill_request_total_weight + union_chain_allocation_total_weight + union_kill_house_free_live_bar_total_weight + union_kill_house_free_carcases_bar_total_weight + union_total_wage = union_province_kill_request_total_wage + freezing_union_province_kill_request_total_wage + union_chain_allocation_total_wage + union_kill_house_free_live_bar_total_wage + union_kill_house_free_carcases_bar_total_wage + union_total_unpaid_wage = union_total_wage - union_total_paid_wage + + company_province_kill_request_total_weight = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + company_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + company_province_kill_request_total_wage = \ + province_kill_requests.filter(company_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('company_share'))[ + 'total'] or 0 + company_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__company_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + freezing_company_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__company_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__company_share_percent') / 100)))[ + 'total'] or 0 + company_chain_allocation_total_weight = \ + chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + company_chain_allocation_total_wage = \ + chain_allocations.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + company_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + + company_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + company_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + total_slaughter_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_paid_wage += \ + total_chain_company_transactions.filter(company_share__gt=0).aggregate(total=Sum('company_share'))[ + 'total'] or 0 + company_total_weight = company_province_kill_request_total_weight + freezing_company_province_kill_request_total_weight + company_chain_allocation_total_weight + company_kill_house_free_live_bar_total_weight + company_kill_house_free_carcases_bar_total_weight + company_total_wage = company_province_kill_request_total_wage + freezing_company_province_kill_request_total_wage + company_chain_allocation_total_wage + company_kill_house_free_live_bar_total_wage + company_kill_house_free_carcases_bar_total_wage + company_total_unpaid_wage = company_total_wage - company_total_paid_wage + + guilds_province_kill_request_total_weight = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_weight += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_guilds_province_kill_request_total_weight = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_weight += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage = \ + province_kill_requests.filter(guilds_share__gt=0, + province_request__poultry_request__freezing=False).aggregate( + total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_province_kill_request_total_wage += \ + kill_house_requests.filter(province_kill_request__guilds_share__gt=0, + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage = \ + freezing_province_kill_requests.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + freezing_guilds_province_kill_request_total_wage += \ + freezing_kill_house_requests.filter(province_kill_request__guilds_share__gt=0).aggregate(total=Sum( + F('accepted_real_weight') * F('province_kill_request__wage') * ( + F('province_kill_request__guilds_share_percent') / 100)))[ + 'total'] or 0 + guilds_chain_allocation_total_weight = \ + chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('weight'))[ + 'total'] or 0 + guilds_chain_allocation_total_wage = \ + chain_allocations.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_weight = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + guilds_kill_house_free_live_bar_total_wage = \ + free_bars.filter(buy_type='live', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + + guilds_kill_house_free_carcases_bar_total_weight = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate( + total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + guilds_kill_house_free_carcases_bar_total_wage = \ + free_bars.filter(buy_type='carcass', guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + total_slaughter_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_paid_wage += \ + total_chain_company_transactions.filter(guilds_share__gt=0).aggregate(total=Sum('guilds_share'))[ + 'total'] or 0 + guilds_total_weight = guilds_province_kill_request_total_weight + freezing_guilds_province_kill_request_total_weight + guilds_chain_allocation_total_weight + guilds_kill_house_free_live_bar_total_weight + guilds_kill_house_free_carcases_bar_total_weight + guilds_total_wage = guilds_province_kill_request_total_wage + freezing_guilds_province_kill_request_total_wage + guilds_chain_allocation_total_wage + guilds_kill_house_free_live_bar_total_wage + guilds_kill_house_free_carcases_bar_total_wage + guilds_total_unpaid_wage = guilds_total_wage - guilds_total_paid_wage + + province_kill_requests_total_wage = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum(type))[ + 'total'] or 0 + province_kill_requests_total_wage += \ + kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + + freezing_province_kill_requests_total_wage = freezing_province_kill_requests.aggregate(total=Sum(type))[ + 'total'] or 0 + freezing_province_kill_requests_total_wage += \ + freezing_kill_house_requests.aggregate( + total=Sum(F('accepted_real_weight') * F('province_kill_request__wage')))[ + 'total'] or 0 + + free_bars_live = free_bars.filter(buy_type='live', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + ) + free_bars_carcases = free_bars.filter(buy_type='carcass', trash=False).only('live_weight', 'union_share', + 'weight_of_carcasses', + 'company_share', + 'guilds_share', + ) + + total_wage += province_kill_requests_total_wage + freezing_province_kill_requests_total_wage + + province_kill_requests_total_weight = \ + province_kill_requests.filter(province_request__poultry_request__freezing=False).aggregate( + total=Sum('total_killed_weight'))[ + 'total'] or 0 + province_kill_requests_total_weight += kill_house_requests.filter( + province_kill_request__province_request__poultry_request__freezing=False).aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + freezing_province_kill_requests_total_weight = \ + freezing_province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + freezing_province_kill_requests_total_weight += \ + freezing_kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_weight += province_kill_requests_total_weight + freezing_province_kill_requests_total_weight + + chain_allocations_total_wage = chain_allocations.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += chain_allocations_total_wage + chain_allocations_total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_weight += chain_allocations_total_weight + free_bars_live_total_wage = free_bars_live.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += free_bars_live_total_wage + free_bars_live_total_weight = free_bars_live.aggregate(total=Sum('live_weight'))[ + 'total'] or 0 + total_weight += free_bars_live_total_weight + free_bars_carcases_total_wage = free_bars_carcases.aggregate(total=Sum(type))[ + 'total'] or 0 + total_wage += free_bars_carcases_total_wage + free_bars_carcases_total_weight = free_bars_carcases.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] or 0 + total_weight += free_bars_carcases_total_weight + slaughter_transactions = InternalTransaction.objects.filter(payer_type='kill_house', status='completed', + trash=False) + + total_paid_wage += slaughter_transactions.aggregate(total=Sum(share_type))[ + 'total'] or 0 + chain_company_transactions = InternalTransaction.objects.filter(payer_type='chain_company', + status='completed', trash=False) + total_paid_wage += chain_company_transactions.aggregate(total=Sum(share_type))[ + 'total'] or 0 + + values_list = { + "total_weight": total_weight, + "total_wage": total_wage, + "union_total_wage": union_total_wage, + "company_total_wage": company_total_wage, + "guilds_total_wage": guilds_total_wage, + "total_paid_wage": total_paid_wage, + "union_total_paid_wage": union_total_paid_wage, + "company_total_paid_wage": company_total_paid_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "total_wage - total_paid_wage": total_wage - total_paid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + "company_total_unpaid_wage": company_total_unpaid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + + } + + values_list2 = { + "province_kill_requests_total_weight": province_kill_requests_total_weight, + "province_kill_requests_total_wage": province_kill_requests_total_wage, + "freezing_province_kill_requests_total_weight": freezing_province_kill_requests_total_weight, + "freezing_province_kill_requests_total_wage": freezing_province_kill_requests_total_wage, + "chain_allocations_total_weight": chain_allocations_total_weight, + "chain_allocations_total_wage": chain_allocations_total_wage, + "free_bars_live_total_weight": free_bars_live_total_weight, + "free_bars_live_total_wage": free_bars_live_total_wage, + "free_bars_carcases_total_weight": free_bars_carcases_total_weight, + "free_bars_carcases_total_wage": free_bars_carcases_total_wage, + + } + + values_union = { + "union_province_kill_request_total_weight": union_province_kill_request_total_weight, + "union_province_kill_request_total_wage": union_province_kill_request_total_wage, + "freezing_union_province_kill_request_total_weight": freezing_union_province_kill_request_total_weight, + "freezing_union_province_kill_request_total_wage": freezing_union_province_kill_request_total_wage, + "union_chain_allocation_total_weight": union_chain_allocation_total_weight, + "union_chain_allocation_total_wage": union_chain_allocation_total_wage, + "union_kill_house_free_live_bar_total_weight": union_kill_house_free_live_bar_total_weight, + "union_kill_house_free_live_bar_total_wage": union_kill_house_free_live_bar_total_wage, + "union_kill_house_free_carcases_bar_total_weight": union_kill_house_free_carcases_bar_total_weight, + "union_kill_house_free_carcases_bar_total_wage": union_kill_house_free_carcases_bar_total_wage, + "union_total_wage": union_total_wage, + "union_total_paid_wage": union_total_paid_wage, + "union_total_unpaid_wage": union_total_unpaid_wage, + + } + + values_company = { + "company_province_kill_request_total_weight": company_province_kill_request_total_weight, + "company_province_kill_request_total_wage": company_province_kill_request_total_wage, + "freezing_company_province_kill_request_total_weight": freezing_company_province_kill_request_total_weight, + "freezing_company_province_kill_request_total_wage": freezing_company_province_kill_request_total_wage, + "company_chain_allocation_total_weight": company_chain_allocation_total_weight, + "company_chain_allocation_total_wage": company_chain_allocation_total_wage, + "company_kill_house_free_live_bar_total_weight": company_kill_house_free_live_bar_total_weight, + "company_kill_house_free_live_bar_total_wage": company_kill_house_free_live_bar_total_wage, + "company_kill_house_free_carcases_bar_total_weight": company_kill_house_free_carcases_bar_total_weight, + "company_kill_house_free_carcases_bar_total_wage": company_kill_house_free_carcases_bar_total_wage, + "company_total_wage": company_total_wage, + "company_total_paid_wage": company_total_paid_wage, + "company_total_unpaid_wage": company_total_unpaid_wage, + + } + + values_guild = { + "guilds_province_kill_request_total_weight": guilds_province_kill_request_total_weight, + "guilds_province_kill_request_total_wage": guilds_province_kill_request_total_wage, + "freezing_guilds_province_kill_request_total_weight": freezing_guilds_province_kill_request_total_weight, + "freezing_guilds_province_kill_request_total_wage": freezing_guilds_province_kill_request_total_wage, + "guilds_chain_allocation_total_weight": guilds_chain_allocation_total_weight, + "guilds_chain_allocation_total_wage": guilds_chain_allocation_total_wage, + "guilds_kill_house_free_live_bar_total_weight": guilds_kill_house_free_live_bar_total_weight, + "guilds_kill_house_free_live_bar_total_wage": guilds_kill_house_free_live_bar_total_wage, + "guilds_kill_house_free_carcases_bar_total_weight": guilds_kill_house_free_carcases_bar_total_weight, + "guilds_kill_house_free_carcases_bar_total_wage": guilds_kill_house_free_carcases_bar_total_wage, + "guilds_total_wage": guilds_total_wage, + "guilds_total_paid_wage": guilds_total_paid_wage, + "guilds_total_unpaid_wage": guilds_total_unpaid_wage, + + } + + dict1 = { + "general": values_list, + 'detail': values_list2, + 'union': values_union, + 'company': values_company, + 'guild': values_guild + } + return dict1 + + +class IranProvinceSerializer(serializers.ModelSerializer): + class Meta: + model = IranProvinces + fields = ['id', 'name'] + +class IranCitiesSerializer(serializers.ModelSerializer): + class Meta: + model = IranCities + fields = ['id', 'name'] + + +class AgeNotificationPoultrySerilizer(serializers.ModelSerializer): + class Meta: + model = AgeNotificationPoultry + fields = '__all__' + + +class CookieSamasatSerilizer(serializers.ModelSerializer): + class Meta: + model = CookieSamasat + fields = '__all__' diff --git a/panel/ReportingPanel/views.py b/panel/ReportingPanel/views.py new file mode 100644 index 0000000..40b7b4e --- /dev/null +++ b/panel/ReportingPanel/views.py @@ -0,0 +1,8959 @@ +import datetime +import hashlib +import random +import re +import difflib +from collections import defaultdict, Counter +from datetime import timedelta +from io import BytesIO +import xml.etree.ElementTree as ET + +import jdatetime +import openpyxl +import requests +from bs4 import BeautifulSoup +from dateutil.relativedelta import relativedelta +from django.contrib.auth.models import User, Group +from django.db.models import Q, F, Sum, Avg, Count, Min +from django.http import HttpResponse +from django.http import QueryDict, JsonResponse +from django.views.decorators.csrf import csrf_exempt +from oauth2_provider.contrib.rest_framework.permissions import TokenHasReadWriteScope +from oauth2_provider.models import AccessToken +from openpyxl import Workbook +from openpyxl.styles import Alignment +from requests.adapters import HTTPAdapter +from requests.packages.urllib3.util.ssl_ import create_urllib3_context +from rest_framework import status +from rest_framework import viewsets +from rest_framework.decorators import api_view, permission_classes +from rest_framework.pagination import PageNumberPagination +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from url_filter.integrations.drf import DjangoFilterBackend +from LiveStock.helpers import build_query +from panel.ProvinceOperator.serializers import PoultryScienceReportSerializer +from panel.filterset import PoultryScienceReportFilterSet +from authentication.filterset import ( + SystemUserProfileFilteSet +) +from authentication.models import SystemUserProfile, Province, SystemAddress, City +from authentication.register import ARTA_REGISTER +from authentication.sahandsms.sms import USERNAME_SMS_FINANCIAL, PASSWORD_SMS_FINANCIAL, kill_house_price +from authentication.serializer.serializer import SystemUserProfileSerializer +from authentication.sms_management import send_sms_for_kill_house_not_add_to_inventory, send_sms_for_guild, \ + send_sms_for_guild_for_register, steward_allocation_sms, guild_register_password, guild_register_username, \ + send_sms_for_sale_bar_for_steward, send_sms_for_sale_bar, send_sms_request +from authentication.views import ARTA_URL_CHANGE_MOBILE_NUMBER + +ARTA_URL_CHECK_USER_EXISTS = "https://userbackend.rasadyar.com/api/check_user_exists/" +from general_urls import base_url_for_sms_report +from helper_eata import chat_id_mali, token +from panel.ProvinceOperator.serializers import \ + NewProvinceAutoAllocationSerializer, GuildsSerializer +from panel.ProvinceOperator.helpers import guild_steward_allocations_product_warehousing +from panel.KillHouse.helpers import kill_house_allocations_product_warehousing, kill_house_archive_warehousing +from panel.ReportingPanel.filterset import ( + PoultryRequestFilterSet, + KillHouseRequestFilterSet, + CityOperatorCheckFilterSet, + ProvinceOperatorCheckFilterSet, + VetOperatorCheckFilterSet, + PoultryHatchingFilterSet, PoultryFilterSet, UserProfileFilterSet +) +from panel.ReportingPanel.models import SearchFields +from panel.models import ( + PoultryRequest, + KillHouseRequest, + CityOperatorCheckRequest, + ProvinceCheckOperatorRequest, + VetCheckRequest, + Poultry, + PoultryHatching, ProvinceKillRequest, ProvinceFactorToKillHouse, KillHouseAssignmentInformation, + KillHouseFactorToProvince, PovinceInspector, CityOperator, ProvinceOperator, VetFarm, KillHouseVet, + ProvinceAutoAllocation, KillHouse, IranProvinces, IranCities, AgeNotificationPoultry, CookieSamasat, LastUpdate, + Wallet, KillHouseFreeSaleBarInformation, KillRequest, KillHouseFreeBarInformation, ChickenCommissionPrices, + RolesProducts, ColdHouse, StewardAllocation, ProductsTransactions, PosMachineTransactions, POSMachine, Guilds, + PosSegmentation, + PoultryRequestQuarantineCode, ChainAllocation, ManagementSendSms, StewardFreeSaleBarInformation, POSTransactions, + SmsRecipient, EvacuationHatchingDetail, HatchingLossManagement, ChickenAgeRange, PoultryScience, + PoultryScienceReport, WarehouseArchive +) +from ticket.helper import send_image_to_server_for_poultry_science +from panel.poultry.serializers import ( + PoultryRequestSerializer, + PoultrySerializer, + PoultryHatchingSerializer, PoultryRequestForGeneralCasestatusSerializer, + ChickenCommissionPricesForDashboardSerializer +) +from ticket.models import MessageSupport, TicketSupport +from .helper import ( + poultry_request_fields, + user_fields, + city_operator_fields, + province_operator_fields, + kill_house_operator_fields, + vet_operator_fields, + poultry_hatching_fields, poultry_filterset_fields, poultry_hatching_filterset_fields +) +from .serializer import SearchFieldsSerializer, DetailsGeneraWageSerializer, GenaeralWageSerailizer, \ + DashboardDetailsGeneraWageSerializer, NewDetailsGeneraWageSerializer, IranProvinceSerializer, IranCitiesSerializer, \ + AgeNotificationPoultrySerilizer, CookieSamasatSerilizer, HatchingLossManagementSerializer +from ..KillHouse.helpers import kill_house_allocations_product_warehousing, market_poultry_request_remain_quantity, \ + kill_house_cold_house_allocations, cold_house_warehousing, kill_house_free_buying_product_warehousing, \ + kill_house_free_sale_product_warehousing +from ..ProvinceOperator.helpers import guild_steward_allocations_product_warehousing, \ + guild_steward_free_sale_product_warehousing +from ..admin import PROJECT_API_KEY +from ..convert_date import convert_to_miladi +from ..helper_excel import percent_of_losses, create_value, create_header, create_header_freez, shamsi_date, \ + excel_description, to_locale_str, convert_str_to_date +from ..helper import check_mobile_number +from ..validate_headers import PosDeviceValidator + + +def check_quarantine_code(code): + session = requests.Session() + session.mount('https://', SSLAdapter()) + data = {'gid': str(code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + try: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + if date_match: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + return True + except: + return False + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +class ReportingAllPoultryRequests(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + city_queryset = CityOperatorCheckRequest.objects.all() + province_queryset = ProvinceCheckOperatorRequest.objects.all() + kill_house_queryset = KillHouseRequest.objects.all() + vet_queryset = VetCheckRequest.objects.all() + poultry_hatching_queryset = PoultryHatching.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + kill_house_filter_class = KillHouseRequestFilterSet + city_operator_filter_class = CityOperatorCheckFilterSet + province_operator_filter_class = ProvinceOperatorCheckFilterSet + vet_operator_filter_class = VetOperatorCheckFilterSet + poultry_hatching_filter_class = PoultryHatchingFilterSet + filterset_fields = poultry_request_fields + user_filterset_fields = user_fields + city_operator_filter_fields = city_operator_fields + province_operator_filter_fields = province_operator_fields + kill_house_operator_filter_fields = kill_house_operator_fields + vet_operator_filter_fields = vet_operator_fields + poultry_hatching_filter_fields = poultry_hatching_fields + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + query_val = [] + city_operator_query_val = [] + province_operator_query_val = [] + kill_house_operator_query_val = [] + vet_operator_query_val = [] + poultry_hatching_query_val = [] + user_val = [] + poultry_query_li = [] + hatching_poultry_li = [] + limited_query = [] + city_limited_query = [] + province_limited_query = [] + kill_house_limited_query = [] + vet_limited_query = [] + poultry_hatching_limited_query = [] + limited_dict = {} + province_limited_dict = {} + city_limited_dict = {} + kill_house_limited_dict = {} + vet_limited_dict = {} + poultry_hatching_limited_dict = {} + user_query = [] + user_dict = {} + values_item = [] + total_tons = [] + if 'type' in request.GET: + if request.GET['value'] != "": + if request.GET['type'] == 'filter': + if 'value' in request.GET: + values = request.GET['value'].split(',') + for item in values: + if item != "": + values_item.append(item) + for val in values_item: + if not query_val: + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.filterset_class(data=query, queryset=self.queryset)).filter(): + ps = self.filterset_class(data=query, queryset=self.queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + limited_query.append(query) + + if not city_operator_query_val: + for item in self.city_operator_filter_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if ( + self.city_operator_filter_class(data=query, + queryset=self.city_queryset)).filter(): + ps = self.city_operator_filter_class(data=query, queryset=self.city_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + city_limited_query.append(query) + + if not province_operator_query_val: + for item in self.province_operator_filter_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.city_operator_filter_class(data=query, + queryset=self.province_queryset)).filter(): + ps = self.city_operator_filter_class(data=query, + queryset=self.province_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + province_limited_query.append(query) + + if not kill_house_operator_query_val: + for item in self.kill_house_operator_filter_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.kill_house_filter_class(data=query, + queryset=self.kill_house_queryset)).filter(): + ps = self.kill_house_filter_class(data=query, queryset=self.kill_house_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + kill_house_limited_query.append(query) + + if not vet_operator_query_val: + for item in self.vet_operator_filter_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if ( + self.vet_operator_filter_class(data=query, + queryset=self.vet_queryset)).filter(): + ps = self.vet_operator_filter_class(data=query, queryset=self.vet_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + vet_limited_query.append(query) + + if not poultry_hatching_query_val: + for item in self.poultry_hatching_filter_fields: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.poultry_hatching_filter_class(data=query, + queryset=self.poultry_hatching_queryset)).filter(): + ps = self.poultry_hatching_filter_class(data=query, + queryset=self.poultry_hatching_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + poultry_hatching_limited_query.append(query) + + if not user_val: + for user_item in self.user_filterset_fields: + query = QueryDict('{0}__exact={1}'.format(user_item, val)) + if (SystemUserProfileFilteSet( + data=query, + queryset=SystemUserProfile.objects.all()) + ).filter(): + ps = SystemUserProfileFilteSet( + data=query, + queryset=SystemUserProfile.objects.all() + ) + filtered_poultry_user = ps.filter() + if filtered_poultry_user: + user_query.append(query) + + for i in limited_query: + for key, value in i.items(): + limited_dict[key] = value + if len(values_item) != len(limited_dict): + pass + else: + for i in PoultryRequest.objects.filter(**limited_dict): + query_val.append(i) + + for i in city_limited_query: + for key, value in i.items(): + city_limited_dict[key] = value + if len(values_item) != len(city_limited_dict): + pass + else: + for i in self.city_queryset.filter(**city_limited_dict): + query_val.append(i.poultry_request) + + for i in province_limited_query: + for key, value in i.items(): + province_limited_dict[key] = value + if len(values_item) != len(province_limited_dict): + pass + else: + for i in self.province_queryset.filter(**province_limited_dict): + query_val.append(i.city_request_Poultry.poultry_request) + + for i in kill_house_limited_query: + for key, value in i.items(): + kill_house_limited_dict[key] = value + if len(values_item) != len(kill_house_limited_dict): + pass + else: + for i in self.kill_house_queryset.filter(**kill_house_limited_dict): + query_val.append(i.province_request.city_request_Poultry.poultry_request) + + for i in vet_limited_query: + for key, value in i.items(): + vet_limited_dict[key] = value + if len(values_item) != len(vet_limited_dict): + pass + else: + for i in self.vet_queryset.filter(**vet_limited_dict): + query_val.append( + i.kill_house_request.province_request.city_request_Poultry.poultry_request) + + for i in poultry_hatching_limited_query: + for key, value in i.items(): + poultry_hatching_limited_dict[key] = value + if len(values_item) != len(poultry_hatching_limited_dict): + pass + else: + for i in self.poultry_hatching_queryset.filter(**poultry_hatching_limited_dict): + poultry_query_li.append(i.poultry) + hatching_poultry_li.append(i) + + for i in user_query: + for key, value in i.items(): + user_dict[key] = value + if len(values_item) != len(user_dict): + pass + else: + for i in SystemUserProfile.objects.filter(**user_dict): + user_val.append(i) + + if 'hatching_date' in request.GET: + date_li = [] + query_li = [] + if request.GET['hatching_date'] != "": + date = request.GET['hatching_date'].split(',') + date_split_1 = date[0].split('-') + date_split_2 = date[1].split('-') + main_date_1 = datetime.datetime( + int(date_split_1[0]), + int(date_split_1[1]), + int(date_split_1[2]) + ) + main_date_2 = datetime.datetime( + int(date_split_2[0]), + int(date_split_2[1]), + int(date_split_2[2]) + ) + date_li.append(main_date_1) + date_li.append(main_date_2) + for i in PoultryHatching.objects.all(): + if date_li[0] <= i.date <= date_li[1]: + if i.poultry not in poultry_query_li: + poultry_query_li.append(i.poultry) + + if 'hatching_info' in request.GET: + serializer = PoultryHatchingSerializer(hatching_poultry_li, many=True) + data = {'hatching_info': serializer.data} + return Response(data, status=status.HTTP_200_OK) + + if 'number_of_incubators' in request.GET: + if request.GET['number_of_incubators'] != "": + num = request.GET['number_of_incubators'].split(',') + for i in PoultryHatching.objects.all(): + if int(num[0]) <= int(i.quantity) <= int(num[1]): + if i.poultry not in poultry_query_li: + poultry_query_li.append(i.poultry) + + if 'number_of_requests' in request.GET: + if request.GET['number_of_requests'] != "": + num = request.GET['number_of_requests'].split(',') + for i in Poultry.objects.all(): + if int(num[0]) <= int(i.number_of_requests) <= int(num[1]): + if i not in poultry_query_li: + poultry_query_li.append(i) + + if 'total_capacity' in request.GET: + if request.GET['total_capacity'] != "": + num = request.GET['total_capacity'].split(',') + for i in Poultry.objects.all(): + if int(num[0]) <= int(i.total_capacity) <= int(num[1]): + if i not in poultry_query_li: + poultry_query_li.append(i) + + if 'tons_for_slaughter' in request.GET: + total = 0 + total_li = [] + if request.GET['tons_for_slaughter'] != "": + tons_date = request.GET['tons_for_slaughter'] + date_split = tons_date.split('-') + main_date = (jdatetime.datetime( + int(date_split[0]), int(date_split[1]), + int(date_split[2])).togregorian()) + for item in self.queryset: + if item.send_date.strftime("%Y-%m-%d") == main_date.strftime("%Y-%m-%d"): + total += item.quantity + total_li.append(item) + serializer = self.serializer_class(total_li, many=True) + return Response({'poultry_req': serializer.data, 'total_quantity': total}) + + if 'total_tons_in_date' in request.GET: + if request.GET['total_tons_in_date'] != "": + age_li = [] + total_tons_split = request.GET['total_tons_in_date'].split(',') + total = 0 + splited_date = total_tons_split[0].split('-') + date1 = jdatetime.date( + int(splited_date[0]), + int(splited_date[1]), + int(splited_date[2]) + ).togregorian() + for item in PoultryHatching.objects.all(): + if item.date != None: + date2 = datetime.date( + int(item.date.year), + int(item.date.month), + int(item.date.day), + ) + age = (date1 - date2) + if 48 >= age.days >= int(total_tons_split[1]): + total += item.quantity + total_tons.append(item.poultry) + age_li.append(age.days) + + if 'show' in request.GET: + if request.GET['show'] == 'active': + poultry_req = self.queryset.filter(final_state="pending") + serializer = self.serializer_class(poultry_req, many=True) + return Response({'poultry_req': serializer.data}, status=status.HTTP_200_OK) + if request.GET['show'] == "deactive": + poultry_req = self.queryset.filter(final_state="complete") + serializer = self.serializer_class(poultry_req, many=True) + return Response({'poultry_req': serializer.data}, status=status.HTTP_200_OK) + if request.GET['show'] == "all": + poultry_req = self.queryset + serializer = self.serializer_class(poultry_req, many=True) + return Response({'poultry_req': serializer.data}, status=status.HTTP_200_OK) + + serializer = self.serializer_class(query_val, many=True) + user_serializer = SystemUserProfileSerializer(user_val, many=True) + poultry_serializer = PoultrySerializer(poultry_query_li, many=True) + final_output_data = { + 'poultry_req': serializer.data, + 'poultry': poultry_serializer.data, + 'user_detail': user_serializer.data, + } + return Response(final_output_data, status=status.HTTP_200_OK) + + serializer = PoultryRequestSerializer( + self.queryset.filter(send_date=(datetime.datetime.now() - datetime.timedelta(days=1))), + many=True + ) + data = {'poultry_req': serializer.data} + return Response(data, status=status.HTTP_200_OK) + + +class SearchFieldsViewSet(viewsets.ModelViewSet): + queryset = SearchFields.objects.all() + serializer_class = SearchFieldsSerializer + permission_classes = [TokenHasReadWriteScope] + + +class NewReportingAllPoultryRequests(viewsets.ModelViewSet): + userprofile_queryset = SystemUserProfile.objects.all() + userprofile_serializer_class = SystemUserProfileSerializer + userprofile_filterset_class = UserProfileFilterSet + queryset = Poultry.objects.all() + serializer_class = PoultrySerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryFilterSet + poultry_filterset_f = poultry_filterset_fields + poultry_hatching_queryset = PoultryHatching.objects.all() + poultry_hatching_filter_class = PoultryHatchingFilterSet + poultry_hatching_filterset_f = poultry_hatching_filterset_fields + poultry_hatching_serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + query_val = [] + poultry_hatching_query_val = [] + limited_dict = {} + values_item = [] + limited_query = [] + poultry_hatching_limited_query = [] + poultry_hatching_limited_dict = {} + + if request.GET['type'] == 'filter': + if 'value' in request.GET and request.GET['value'] != "": + values = request.GET['value'].split(',') + for item in values: + if item != "": + values_item.append(item) + for val in values_item: + if not query_val: + for item in self.poultry_filterset_f: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.filterset_class(data=query, queryset=self.queryset)).filter(): + ps = self.filterset_class(data=query, queryset=self.queryset) + filtered_poultry = ps.filter() + if filtered_poultry: + limited_query.append(query) + + if not poultry_hatching_query_val: + for item in self.poultry_hatching_filterset_f: + query = QueryDict('{0}={1}'.format(item, val)) + if (self.poultry_hatching_filter_class(data=query, + queryset=self.poultry_hatching_queryset)).filter(): + ps = self.poultry_hatching_filter_class(data=query, + queryset=self.poultry_hatching_queryset) + filtered_city_operator = ps.filter() + if filtered_city_operator: + poultry_hatching_limited_query.append(query) + for i in limited_query: + for key, value in i.items(): + limited_dict[key] = value + # + # if len(values_item) != len(limited_dict): + # pass + # else: + + if len(limited_dict) > 0: + for i in Poultry.objects.filter(**limited_dict): + query_val.append(i) + for i in poultry_hatching_limited_query: + for key, value in i.items(): + poultry_hatching_limited_dict[key] = value + + # if len(values_item) == len(poultry_hatching_limited_dict): + # pass + # else: + for i in self.poultry_hatching_queryset.filter(**poultry_hatching_limited_dict): + if i.poultry in query_val: + pass + else: + if len(limited_dict) > 0: + pass + else: + query_val.append(i.poultry) + values_item_count = len(values_item) + if values_item_count != len(limited_dict): + if len(poultry_hatching_limited_dict) == 0: + query_val = [] + + if 'double_hatching_date' in request.GET: + date_li = [] + query_li = [] + if request.GET['double_hatching_date'] != "": + date = request.GET['double_hatching_date'].split(',') + date_split_1 = date[0].split('-') + date_split_2 = date[1].split('-') + main_date_1 = datetime.datetime( + int(date_split_1[0]), + int(date_split_1[1]), + int(date_split_1[2]) + ) + main_date_2 = datetime.datetime( + int(date_split_2[0]), + int(date_split_2[1]), + int(date_split_2[2]) + ) + date_li.append(main_date_1) + date_li.append(main_date_2) + for i in PoultryHatching.objects.all(): + if date_li[0].year <= i.date.year and date_li[0].month <= i.date.month and date_li[ + 0].day <= i.date.day and i.date.year <= date_li[1].year and i.date.month <= date_li[ + 1].month and i.date.day <= date_li[1].day: + if i.poultry not in query_val: + query_val.append(i.poultry) + if 'single_hatching_date' in request.GET: + date_li = [] + query_li = [] + if request.GET['single_hatching_date'] != "": + date = request.GET['single_hatching_date'] + date_split = date.split('-') + main_date = datetime.datetime( + int(date_split[0]), + int(date_split[1]), + int(date_split[2]) + ) + date_li.append(main_date) + for i in PoultryHatching.objects.all(): + if date_li[0].year == i.date.year and date_li[0].month == i.date.month and date_li[ + 0].day == i.date.day: + if i.poultry not in query_val: + query_val.append(i.poultry) + if 'double_age' in request.GET: + age = request.GET['double_age'].split(',') + age1 = int(age[0]) + age2 = int(age[1]) + hatching = PoultryHatching.objects.filter(state='pending') + if hatching.count() > 0: + for hatch in hatching: + chicken_age = (datetime.datetime.now() - hatch.date).days + 1 + if age1 <= chicken_age and chicken_age <= age2: + if hatch.poultry in query_val: + pass + else: + query_val.append(hatch.poultry) + if 'single_age' in request.GET: + age = int(request.GET['single_age']) + hatching = PoultryHatching.objects.filter(state='pending') + if hatching.count() > 0: + for hatch in hatching: + chicken_age = (datetime.datetime.now() - hatch.date).days + 1 + if age == chicken_age: + if hatch.poultry in query_val: + pass + else: + query_val.append(hatch.poultry) + + serializer = self.serializer_class(query_val, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ForcastViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user) + from datetime import datetime, timedelta + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d') + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d') + d = request.GET['day'] + days_interval = (date2 - date1).days + hatching_dict = {} + quantity = 0 + poultry_list_id = [] + poultry_list = [] + interal_dict = {} + final_list = [] + hatchs = PoultryHatching.objects.filter(poultry__address__province=user.province, state='pending') + if hatchs.count() > 0: + for i in range(days_interval + 1): + first_date = date1 + timedelta(days=i) + second_date = first_date - timedelta(days=int(d)) + for hatch in hatchs: + if hatch.date.year == second_date.year and hatch.date.month == second_date.month and hatch.date.day == second_date.day: + quantity += hatch.quantity + if hatch.poultry in poultry_list: + pass + else: + poultry_list.append(hatch.poultry) + for p in poultry_list: + interal_dict = { + "name": p.user.fullname, + "mobile": p.user.mobile, + "unitname": p.unit_name, + "province": p.user.province.name, + "city": p.user.city.name, + } + poultry_list_id.append(interal_dict) + + hatching_dict.update({"date": str(first_date), "quantity": quantity, "poultry": poultry_list_id}) + quantity = 0 + final_list.append(hatching_dict) + hatching_dict = {} + poultry_list_id = [] + poultry_list = [] + + return Response(final_list, status=status.HTTP_200_OK) + + +class PoultryReporttViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + poultry_request_list = [] + dates = [] + hatching_list = [] + average_weight_chart_list = [] + quantity = 0 + losses = 0 + poultry_requests = PoultryRequest.objects.filter(poultry__user=user, trash=False).order_by('send_date') + if poultry_requests.count() > 0: + for poultry_request in poultry_requests: + total_amount = 0 + average_weight = 0 + average_fee = 0 + sales_price = 0 + paid_state = None + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + state='accepted').exists(): + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + poultry_request_dict = { + "hatching_period": poultry_request.hatching.period, + "date": poultry_request.send_date.date(), + "hatching_date": poultry_request.hatching.date, + "hatching_chicken_breed": poultry_request.hatching.chicken_breed, + "quantity": poultry_request.quantity, + "age": age, + "weight_of_suffering": 2.5, + "request_id": poultry_request.id, + + } + province_factors = ProvinceFactorToKillHouse.objects.filter( + province_check_req__poultry_request=poultry_request) + if province_factors.count() > 0: + factor_count = province_factors.count() + factor_counter = 0 + paid_state = 'pending' + for factor in province_factors: + if factor.poultry_factor != None: + total_amount += factor.poultry_factor.shares['poultryShareWithProfit'] + if factor.poultry_factor.paid_state == 'paid': + factor_counter += 1 + else: + total_amount += factor.shares['poultryShareWithProfit'] + if factor.paid_state == 'paid': + factor_counter += 1 + average_weight += factor.total_weight + sales_price += factor.factor_fee + average_fee = factor.province_check_req.fee + if factor_count == factor_counter: + paid_state = 'paid' + sales_price = sales_price / factor_count + average_weight = average_weight / factor_count + average_weight_dict = { + "date": poultry_request.send_date.date(), + "weight": average_weight, + } + average_weight_chart_list.append(average_weight_dict) + + poultry_request_dict.update({ + "total_amount": total_amount, + "average_weight": average_weight, + "average_fee": average_fee, + "sales_price": sales_price, + "paid_state": paid_state, + + }) + poultry_request_list.append(poultry_request_dict) + + poultry_hatchings = PoultryHatching.objects.filter(trash=False).order_by('date') + if poultry_hatchings.count() > 0: + for poultry_hatching in poultry_hatchings: + if poultry_hatching.date.date() in dates: + pass + else: + dates.append(poultry_hatching.date.date()) + for date in dates: + hatching = PoultryHatching.objects.filter(date__year=date.year, date__month=date.month, + date__day=date.day) + for hatch in hatching: + quantity += hatch.quantity + losses += hatch.losses + internal_hatching_dict = { + "date": date, + "quantity": quantity, + "losses": losses, + } + hatching_list.append(internal_hatching_dict) + + quantity = 0 + losses = 0 + + final_dict = { + "table": poultry_request_list, + "hatching_chart": hatching_list, + "weight_chart": average_weight_chart_list, + } + + return Response(final_dict, status=status.HTTP_200_OK) + + +# ویوست مربوط به نامه جهاد واستانداری +class PoultryRequestletterReportViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryRequestSerializer + + def list(self, request, *args, **kwargs): + province = Province.objects.get(id=2) + from datetime import datetime + # refresh(request.user.id) + if 'general_report' in request.GET: + date = datetime.strptime(request.GET['date'], '%Y-%m-%d') + poultry_requests_list = [] + poultry_requests_dict = {} + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=province, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day).order_by('send_date') + + if poultry_requests.count() > 0: + for poultry_request in poultry_requests: + poultry_requests_dict.update({ + 'poultry_name': poultry_request.poultry.unit_name, + 'quantity': poultry_request.previous_quantity, + 'weight': poultry_request.Index_weight, + 'age': (poultry_request.send_date.date() - poultry_request.hatching.date.date()).days + 1, + 'confirmed_quantity': poultry_request.quantity, + 'remain_quantity': poultry_request.hatching.left_over, + }) + + poultry_requests_list.append(poultry_requests_dict) + poultry_requests_dict = {} + return Response(poultry_requests_list, status=status.HTTP_200_OK) + + elif 'daily_report' in request.GET: + now = datetime.now().date() + date_list = [] + hatching_list = [] + poultry_request_detail_list = [] + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=province).order_by('-send_date') + if poultry_requests.count() > 0: + for poultry_request in poultry_requests: + if poultry_request.send_date.date() in date_list: + pass + else: + date_list.append(poultry_request.send_date.date()) + for date in date_list: + quantity = 0 + remain_quantity = 0 + province_quantity = 0 + average_weight = 0 + total_poultry_request_quantity = 0 + accepted_request_quantity = 0 + poultry_requests_list = PoultryRequest.objects.filter(poultry__address__province=province, + send_date__year=date.year, + send_date__month=date.month, + send_date__day=date.day) + for internal_poultry_reqs in poultry_requests_list: + if internal_poultry_reqs.hatching in hatching_list: + pass + else: + hatching_list.append(internal_poultry_reqs.hatching) + remain_quantity += internal_poultry_reqs.hatching.left_over + + quantity += internal_poultry_reqs.previous_quantity + average_weight += internal_poultry_reqs.Index_weight + province_quantity += internal_poultry_reqs.quantity + total_poultry_request_quantity += internal_poultry_reqs.quantity + if internal_poultry_reqs.province_state == 'accepted': + accepted_request_quantity += internal_poultry_reqs.quantity + average_weight = round(average_weight / poultry_requests_list.count(), 2) + + poultry_request_detail_list.append({ + 'today': now, + 'date': date, + 'province': province.name, + 'previous_quantity': quantity, + 'index_weight': average_weight, + 'province_quantity': province_quantity, + 'remain_quantity': remain_quantity, + 'country_quantity': 0, + 'total_poultry_request_quantity': total_poultry_request_quantity, + 'accepted_request_quantity': accepted_request_quantity, + + }) + return Response(poultry_request_detail_list, status=status.HTTP_200_OK) + + +class CasestatusViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryRequestSerializer + + def list(self, request, *args, **kwargs): + poultry_request_list = [] + user = SystemUserProfile.objects.get(user=request.user) + date = datetime.datetime.strptime(str(request.GET['date']), '%Y-%m-%d') + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, + poultry__city_operator=city_operator.unit_name, + trash=False).order_by('id') + elif request.GET['role'] in ['VetFarm', 'CityCommerce', 'CityJahad', 'CityPoultry']: + + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, + poultry__address__city=user.city, + trash=False).order_by('id') + else: + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, + poultry__address__province=user.province, + trash=False).order_by('id') + if poultry_requests: + for poultry_request in poultry_requests: + vet_farm = VetFarm.objects.filter(poultry=poultry_request.poultry, trash=False) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + vet_farm_name = vet_farm.vet.user.fullname + vet_farm_mobile = vet_farm.vet.user.mobile + else: + vet_farm_name = None + vet_farm_mobile = None + + poultry_request_dict = {} + poultry_request_dict.update({"poultry": { + "user_fullname": poultry_request.poultry.user.fullname, + "user_mobile": poultry_request.poultry.user.mobile, + "poultry_name": poultry_request.poultry.unit_name, + "poultry_city": poultry_request.poultry.address.city.name, + "poultry_province": poultry_request.poultry.address.province.name, + "poultry_request_quantity": poultry_request.quantity, + "poultry_request_remain_quantity": poultry_request.remain_quantity, + "freezing": poultry_request.freezing, + "chicken_breed": poultry_request.chicken_breed, + "send_date": poultry_request.send_date, + "index_weight": poultry_request.Index_weight, + "vet_farm_name": vet_farm_name, + "vet_farm_mobile": vet_farm_mobile, + + } + + }) + city_operator = CityOperator.objects.filter(key=poultry_request.city_operator.key, trash=False) + if city_operator: + city_operator = city_operator.last() + city_operator_name = city_operator.user.fullname + city_operator_mobile = city_operator.user.mobile + city_operator_province = city_operator.address.province.name + city_operator_city = city_operator.address.city.name + else: + + city_operator_name = None + city_operator_mobile = None + city_operator_province = None + city_operator_city = None + + city = CityOperatorCheckRequest.objects.filter(poultry_request=poultry_request, trash=False) + if city: + city = city.last() + poultry_request_dict['city_state'] = { + "operator_name": city_operator_name, + "operator_mobile": city_operator_mobile, + "operator_province": city_operator_province, + "operator_city": city_operator_city, + "state": city.state, + } + else: + poultry_request_dict['city_state'] = { + "operator_name": city_operator_name, + "operator_mobile": city_operator_mobile, + "operator_province": city_operator_province, + "operator_city": city_operator_city, + "state": 'pending', + } + role = Group.objects.get(name='ProvinceOperator') + province_operator = ProvinceOperator.objects.filter( + address__province__name=poultry_request.poultry.address.province.name, + user__role=role, trash=False) + if province_operator: + province_operator = province_operator.last() + province_operator_name = province_operator.user.fullname + province_operator_mobile = province_operator.user.mobile + province_operator_provinc = province_operator.address.province.name + province_operator_city = province_operator.address.city.name + + else: + province_operator_name = None + province_operator_mobile = None + province_operator_provinc = None + province_operator_city = None + + province = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request, + trash=False) + if province: + province = province.last() + poultry_request_dict['province_state'] = { + "province_operator_name": province_operator_name, + "province_operator_mobile": province_operator_mobile, + "province_operator_provinc": province_operator_provinc, + "province_operator_city": province_operator_city, + "state": province.state, + } + else: + + poultry_request_dict.update({"province_state": { + "province_operator_name": province_operator_name, + "province_operator_mobile": province_operator_mobile, + "province_operator_provinc": province_operator_provinc, + "province_operator_city": province_operator_city, + "state": 'pending', + }}) + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request=poultry_request) + if province_kill_requests: + province_kill_request_list = [] + for province_kill_request in province_kill_requests: + province_kill_request_dict = {} + province_kill_request_dict = { + "state": province_kill_request.state, + "buyer_name": province_kill_request.kill_request.kill_house.name, + "buyer_mobile": province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": province_kill_request.main_quantity, + } + buyer_type = None + if province_kill_request.kill_request.kill_house.killer == False: + buyer_type = 'kill_house' + else: + buyer_type = 'killer' + province_kill_request_dict.update({ + "buyer_type": buyer_type, + }) + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request=province_kill_request) + if kill_house_requests: + kill_house_request_list = [] + for kill_house_request in kill_house_requests: + kill_house_vet = KillHouseVet.objects.filter( + kill_house=kill_house_request.kill_request.kill_house, trash=False) + if kill_house_vet.count() > 0: + kill_house_vet = kill_house_vet.last() + kill_house_vet_name = kill_house_vet.vet.user.fullname + kill_house_vet_mobile = kill_house_vet.vet.user.mobile + else: + kill_house_vet_name = None + kill_house_vet_mobile = None + + kill_house_request_dict = {} + kill_house_request_dict = { + "vet_state": kill_house_request.vet_state, + "kill_house_vet_name": kill_house_vet_name, + "kill_house_vet_mobile": kill_house_vet_mobile, + "driver_name": kill_house_request.add_car.driver.driver_name, + "driver_mobile": kill_house_request.add_car.driver.driver_mobile, + "pelak": kill_house_request.add_car.driver.pelak, + "health_code": kill_house_request.add_car.driver.health_code, + "quantity": kill_house_request.quantity, + "traffic_code": kill_house_request.traffic_code, + "clearance_code": kill_house_request.clearance_code, + "bar_code": kill_house_request.bar_code, + } + bar = KillHouseAssignmentInformation.objects.filter(trash=False, + kill_house_request=kill_house_request) + if bar: + bar = bar.last() + kill_house_request_dict.update({ + "bar": { + "car_weight_without_load": bar.car_weight_without_load, + "car_weight_without_load_image": bar.car_weight_without_load_image, + "car_weight_with_load": bar.car_weight_with_load, + "car_weight_with_load_image": bar.car_weight_with_load_image, + "net_weight": bar.net_weight, + "state": bar.state, + "real_quantity": bar.real_quantity, + "exploited_carcass": bar.exploited_carcass + } + }) + else: + kill_house_request_dict.update({ + "bar": None + }) + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if province_factor: + province_factor = province_factor.last() + kill_house_request_dict.update({"province_factor": { + "total_weight": province_factor.total_weight, + "factor_fee": province_factor.factor_fee, + "total_price": province_factor.total_price, + "paid_state": province_factor.paid_state, + } + + }) + else: + kill_house_request_dict.update({"province_factor": None}) + + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor: + kill_house_factor = kill_house_factor.last() + kill_house_request_dict.update({"kill_house_factor": { + "payment_code": kill_house_factor.payment_code, + "state": kill_house_factor.state, + "factor_image": kill_house_factor.factor_image, + "message": kill_house_factor.message, + } + + }) + else: + kill_house_request_dict.update({"kill_house_factor": None}) + kill_house_request_list.append(kill_house_request_dict) + province_kill_request_dict.update({"kill_house_requests": kill_house_request_list}) + + + else: + province_kill_request_dict.update({"kill_house_requests": None}) + + province_kill_request_list.append(province_kill_request_dict) + poultry_request_dict.update({"province_kill_requests": province_kill_request_list}) + + else: + poultry_request_dict.update({"province_kill_requests": None}) + + province_inspector = PovinceInspector.objects.filter(poultry_request=poultry_request, trash=False) + if province_inspector: + province_inspector = province_inspector.last() + poultry_request_dict.update({"province_inspector": { + "state": province_inspector.state + + }}) + else: + poultry_request_dict.update({"province_inspector": None}) + poultry_request_list.append(poultry_request_dict) + return Response(poultry_request_list, status=status.HTTP_200_OK) + + +class GeneralCasestatusViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryRequestSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'order_code', + ] + + def list(self, request, *args, **kwargs): + poultry_reqs = [] + poultry_requests = [] + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_reqs = PoultryRequest.objects.filter( + poultry__address__province=user.province, + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False + ).order_by('id').select_related('poultry__user') + + elif request.GET['role'] == 'CityCommerce' or request.GET['role'] == 'VetFarm': + poultry_reqs = PoultryRequest.objects.filter( + poultry__address__province=user.province, + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False + ).order_by('id').select_related('poultry__user') + + else: + poultry_reqs = PoultryRequest.objects.filter( + poultry__address__province=user.province, + send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('id').select_related('poultry__user') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_reqs + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_reqs) + poultry_requests = ps.filter() + poultry_reqs = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_reqs) + if page is not None: + serializer = PoultryRequestForGeneralCasestatusSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForGeneralCasestatusSerializer(poultry_reqs, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class HatchingQueryViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching + serializer_class = PoultryHatchingSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + + hatchings = PoultryHatching.objects.filter(trash=False).order_by('-date') + if hatchings: + hatchings_list = [] + quantity = 0 + + for hatching in hatchings: + poultry_requests = PoultryRequest.objects.filter( + hatching=hatching, + trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted') + ) + + quantity_req = sum(poultry_req.quantity for poultry_req in poultry_requests) + quantity += hatching.quantity + + hatching_dict = { + "poultry_name": hatching.poultry.unit_name, + "quantity": hatching.quantity, + "breed": hatching.breed, + "left_over": hatching.left_over, + "date": hatching.date.date(), + "period": hatching.period, + "poultry_request": quantity_req + } + + hatchings_list.append(hatching_dict) + + return Response(hatchings_list) + + +class BuyerRemittance(viewsets.ModelViewSet): + queryset = ProvinceAutoAllocation.objects.all() + permission_classes = [AllowAny] + serializer_class = NewProvinceAutoAllocationSerializer + + def list(self, request, *args, **kwargs): + + if 'allocation_key' in request.GET: + serializer = NewProvinceAutoAllocationSerializer( + ProvinceAutoAllocation.objects.filter(key=request.GET['allocation_key'], trash=False, ).select_related( + 'poultry_request'), many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + elif 'poultry_request_key' in request.GET: + + poultry_request = PoultryRequest.objects.filter(key=request.GET['poultry_request_key']).prefetch_related( + 'poultry_request_auto_quantity_province', + ).last() + + province_auto_allocations = poultry_request.poultry_request_auto_quantity_province.all().select_related( + 'poultry_request', + 'province_kill_request', + 'daily_quota__kill_house__kill_house_operator__user', + 'daily_quota__killer_kill_house__kill_house_operator__user') + poultry_requests_list = [] + kill_house_list = [] + killer_list = [] + for a in province_auto_allocations: + if a.poultry_request not in poultry_requests_list: + poultry_requests_list.append(a.poultry_request) + num1 = 0 + for b in province_auto_allocations: + if b.daily_quota == a.daily_quota: + num1 += b.quantity * b.poultry_request.Index_weight + dict1 = { + "buyer_name": a.daily_quota.kill_house.name, + "weight": num1 + } + if dict1 not in killer_list: + killer_list.append(dict1) + if a.daily_quota.killer_kill_house == None: + for b in province_auto_allocations: + if b.daily_quota == a.daily_quota or b.daily_quota.killer_kill_house == a.daily_quota.kill_house: + num1 += b.quantity * b.poultry_request.Index_weight + dict2 = { + "kill_house_name": a.daily_quota.kill_house.name, + "weight": num1 + } + if dict2 not in kill_house_list: + kill_house_list.append(dict2) + + allocation_list = [] + for allocation in province_auto_allocations: + if allocation.daily_quota.killer_kill_house: + kill_house = allocation.daily_quota.killer_kill_house + else: + kill_house = allocation.daily_quota.kill_house + + allocation_dict = { + "buyer_fullname": allocation.daily_quota.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": allocation.daily_quota.kill_house.kill_house_operator.user.mobile, + "quantity": allocation.quantity, + "kill_house": { + "kill_house_fullname": kill_house.kill_house_operator.user.fullname, + "kill_house_mobile": kill_house.kill_house_operator.user.mobile, + } + } + allocation_list.append(allocation_dict) + internal_poultry_req_dict = { + "poultry_fullname": poultry_request.poultry.user.fullname, + "base_order": poultry_request.poultry.user.base_order, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_quantity": poultry_request.quantity, + "index_weight": poultry_request.Index_weight, + "date": poultry_request.send_date, + "allocations": allocation_list, + } + final_dict = { + "poultry": internal_poultry_req_dict, + "buyer": killer_list, + "kill_house": kill_house_list + } + return Response(final_dict, status=status.HTTP_200_OK) + + elif 'auto_allocation' in request.GET: + + now = datetime.datetime.now().date() + date = datetime.datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + allocations = ProvinceAutoAllocation.objects.filter(trash=False, create_date__date=date).select_related( + 'poultry_request', + 'province_kill_request', + 'daily_quota__kill_house__kill_house_operator__user', + 'daily_quota__killer_kill_house__kill_house_operator__user' + ) + + poultry_requests_list = [] + final_poultry_requests_list = [] + kill_house_list = [] + killer_list = [] + + for a in allocations: + if a.poultry_request not in poultry_requests_list: + poultry_requests_list.append(a.poultry_request) + num1 = 0 + for b in allocations: + if b.daily_quota == a.daily_quota: + num1 += b.quantity * b.poultry_request.Index_weight + dict1 = { + "buyer_name": a.daily_quota.kill_house.name, + "weight": num1 + } + if dict1 not in killer_list: + killer_list.append(dict1) + if a.daily_quota.killer_kill_house == None: + for b in allocations: + if b.daily_quota == a.daily_quota or b.daily_quota.killer_kill_house == a.daily_quota.kill_house: + num1 += b.quantity * b.poultry_request.Index_weight + dict2 = { + "kill_house_name": a.daily_quota.kill_house.name, + "weight": num1 + } + if dict2 not in kill_house_list: + kill_house_list.append(dict2) + + allocation_list = [] + + for poultry_request in poultry_requests_list: + for allocation in allocations: + if allocation.poultry_request != poultry_request: + continue + + kill_house = allocation.daily_quota.killer_kill_house if allocation.daily_quota.killer_kill_house else allocation.daily_quota.kill_house + + allocation_dict = { + "buyer_fullname": allocation.daily_quota.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": allocation.daily_quota.kill_house.kill_house_operator.user.mobile, + "quantity": allocation.quantity, + "kill_house": { + "kill_house_fullname": kill_house.kill_house_operator.user.fullname, + "kill_house_mobile": kill_house.kill_house_operator.user.mobile, + } + } + allocation_list.append(allocation_dict) + + internal_poultry_req_dict = { + "poultry_fullname": poultry_request.poultry.user.fullname, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_quantity": poultry_request.quantity, + "index_weight": poultry_request.Index_weight, + "date": poultry_request.send_date, + "allocations": allocation_list, + } + final_poultry_requests_list.append(internal_poultry_req_dict) + final_dict = { + "poultry": final_poultry_requests_list, + "buyer": killer_list, + "kill_house": kill_house_list, + } + + return Response(final_dict, status=status.HTTP_200_OK) + + elif 'poultry_remittance' in request.GET: + now = datetime.datetime.now().date() + date = datetime.datetime.strptime(str(request.GET['date']), + '%Y-%m-%d').date() if 'date' in request.GET else now + allocations = ProvinceAutoAllocation.objects.filter(trash=False, create_date__date=date).select_related( + 'poultry_request', + 'province_kill_request', + 'daily_quota__kill_house__kill_house_operator__user', + 'daily_quota__killer_kill_house__kill_house_operator__user' + ) + + poultry_requests_list = [] + final_poultry_requests_list = [] + allocation_list = [] + for a in allocations: + if a.poultry_request not in poultry_requests_list: + poultry_requests_list.append(a.poultry_request) + for poultry_request in poultry_requests_list: + for allocation in allocations: + if allocation.poultry_request != poultry_request: + continue + + kill_house = allocation.daily_quota.killer_kill_house if allocation.daily_quota.killer_kill_house else allocation.daily_quota.kill_house + + allocation_dict = { + "buyer_fullname": allocation.daily_quota.kill_house.kill_house_operator.user.fullname, + "buyer_mobile": allocation.daily_quota.kill_house.kill_house_operator.user.mobile, + "quantity": allocation.quantity, + "kill_house": { + "kill_house_fullname": kill_house.kill_house_operator.user.fullname, + "kill_house_mobile": kill_house.kill_house_operator.user.mobile, + } + } + allocation_list.append(allocation_dict) + + internal_poultry_req_dict = { + "poultry_fullname": poultry_request.poultry.user.fullname, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_quantity": poultry_request.quantity, + "date": poultry_request.send_date, + "allocations": allocation_list, + } + final_poultry_requests_list.append(internal_poultry_req_dict) + return Response(final_poultry_requests_list, status=status.HTTP_200_OK) + + elif 'factor_to_province' in request.GET: + factor = ProvinceFactorToKillHouse.objects.get( + key=request.GET['factor_to_province'], paid_state='pending') + # serializer = ProvinceFactorToKillHousePdfSerializer(factor) + # return Response(serializer.data,status=status.HTTP_200_OK) + + economic_code_kill_house = factor.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.kill_house_operator.user.national_code if factor.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.kill_house_operator.user.national_code else None + economic_code_poultry = factor.province_check_req.poultry_request.poultry.user.national_code if factor.province_check_req.poultry_request.poultry.user.national_code else None + dict1 = { + "buyer_name": factor.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.name, + # "economic_code_kill_house":economic_code_kill_house, + # "national_id_kill_house":None, + "serial_number_kill_house": factor.province_check_req.poultry_request.poultry.user.base_order, + "adders_kill_house": factor.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.kill_house_operator.address.address, + # "register_number_kill_house":None, + "postal_code_kill_house": factor.province_check_info.kill_house_assignment.kill_house_request.killhouse_user.kill_house_operator.address.postal_code, + "poultry_name": factor.province_check_req.poultry_request.poultry.unit_name + ' ' + factor.province_check_req.poultry_request.poultry.user.fullname, + # "economic_code_poultry":economic_code_poultry, + # "national_id_poultry":None, + "adders_poultry": factor.province_check_req.poultry_request.poultry.address.address, + # "register_number_poultry":None, + "postal_code_poultry": factor.province_check_req.poultry_request.poultry.address.postal_code, + "factor_bar_code": factor.factor_bar_code, + "amount": factor.total_weight, + "chicken_price": factor.factor_fee, + "total_price": factor.total_price, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class DetailsGeneralWageViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = GenaeralWageSerailizer + queryset = ProvinceKillRequest.objects.filter( + state__in=('pending', 'accepted'), trash=False, archive_wage=False, + first_car_allocated_quantity=0, + return_to_province=False).exclude(union_share=0, company_share=0, guilds_share=0) + + def list(self, request, *args, **kwargs): + ser_general = self.serializer_class(self.queryset).data + return Response(ser_general['general'], status=status.HTTP_200_OK) + + +class DetailsGeneralKillHoseWageViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = DetailsGeneraWageSerializer + # serializer_class = NewDetailsGeneraWageSerializer + queryset = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user', + 'kill_house_operator__user__city').exclude( + out_province=True) + + def list(self, request, *args, **kwargs): + ser_data = self.serializer_class(self.queryset, many=True, context={'request': request}).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class NewDetailsGeneralKillHoseWageViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = NewDetailsGeneraWageSerializer + queryset = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user', + 'kill_house_operator__user__city').exclude( + out_province=True) + + def list(self, request, *args, **kwargs): + ser_data = self.serializer_class(self.queryset, many=True, context={'request': request}).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class DashboardDetailsGeneralKillHoseWageViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = DashboardDetailsGeneraWageSerializer + queryset = KillHouse.objects.filter(trash=False).select_related('kill_house_operator__user', + 'kill_house_operator__user__city').exclude( + out_province=True) + + def list(self, request, *args, **kwargs): + ser_data = self.serializer_class(self.queryset, context={'request': request}).data + return Response(ser_data, status=status.HTTP_200_OK) + + +class DataReportPercentagesViewSet(viewsets.ModelViewSet): + permission_classes = [TokenHasReadWriteScope] + serializer_class = DetailsGeneraWageSerializer + queryset = KillHouseRequest.objects.filter(trash=False).order_by('kill_request__recive_date') + + def list(self, request, *args, **kwargs): + user = request.user + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user__user=user, trash=False) + kill_requests = self.queryset.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + else: + kill_requests = self.queryset + all_list = {} + if request.GET['type'] == 'year': + has_code_list = [] + quarantine_quantity_list = [] + assignment_state_archive_list = [] + accepted_assignment_real_weight_list = [] + hasnt_code_list = [] + difference_bar_list = [] + ware_house_confirmation_list = [] + ware_house_accepted_real_weight_list = [] + weight_year_list = [] + + now = datetime.datetime.now().date() + start_date = now - relativedelta(years=1) # محاسبه تاریخ یک سال پیش + + current_date = start_date + while current_date <= now: + kill_request = kill_requests.filter(kill_request__recive_date__date__month=current_date.month, + kill_request__recive_date__date__year=current_date.year) + has_code_year = len(kill_request.filter(clearance_code__isnull=False)) + quarantine_quantity_year = len(kill_request.filter(quarantine_quantity__isnull=False)) + assignment_state_archive_year = len(kill_request.filter(assignment_state_archive='True')) + accepted_assignment_real_weight = kill_request.aggregate( + total_quantity=Sum('accepted_assignment_real_weight')).get('total_quantity') or 0 + accepted_real_weight = kill_request.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + hasnt_code_year = len(kill_request.filter(clearance_code__isnull=True)) + difference_bar = len(kill_request.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + ware_house_confirmation_year = len(kill_request.filter(ware_house_confirmation=True)) + ware_house_accepted_real_weight = kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get('total_quantity') or 0 + + dict_has_code_year = { + 'date': current_date, + 'percent': round(has_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_quarantine_quantity_year = { + 'date': current_date, + 'percent': round(quarantine_quantity_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_assignment_state_archive_year = { + 'date': current_date, + 'percent': round(assignment_state_archive_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_accepted_assignment_real_weight_year = { + 'date': current_date, + 'percent': round(accepted_assignment_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_hasnt_code_year = { + 'date': current_date, + 'percent': round(hasnt_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_difference_bar_year = { + 'date': current_date, + 'percent': round(difference_bar * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_ware_house_confirmation_year = { + 'date': current_date, + 'percent': round(ware_house_confirmation_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_ware_house_accepted_real_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_assignment_real_weight, + 2) if accepted_assignment_real_weight > 0 else 0 + } + + has_code_list.append(dict_has_code_year) + quarantine_quantity_list.append(dict_quarantine_quantity_year) + assignment_state_archive_list.append(dict_assignment_state_archive_year) + accepted_assignment_real_weight_list.append(dict_accepted_assignment_real_weight_year) + hasnt_code_list.append(dict_hasnt_code_year) + difference_bar_list.append(dict_difference_bar_year) + ware_house_confirmation_list.append(dict_ware_house_confirmation_year) + ware_house_accepted_real_weight_list.append(dict_ware_house_accepted_real_weight_year) + weight_year_list.append(dict_weight_year) + + current_date += relativedelta(months=1) + + all_list['hasCode'] = has_code_list + all_list['quarantineQuantity'] = quarantine_quantity_list + all_list['assignmentStateArchive'] = assignment_state_archive_list + all_list['acceptedAssignmentRealWeight'] = accepted_assignment_real_weight_list + all_list['hasntCode'] = hasnt_code_list + all_list['differenceBar'] = difference_bar_list + all_list['wareHouseConfirmation'] = ware_house_confirmation_list + all_list['wareHouseAcceptedRealWeight'] = ware_house_accepted_real_weight_list + all_list['weightYear'] = weight_year_list + elif request.GET['type'] == 'sixMonths': + has_code_list = [] + quarantine_quantity_list = [] + assignment_state_archive_list = [] + accepted_assignment_real_weight_list = [] + hasnt_code_list = [] + difference_bar_list = [] + ware_house_confirmation_list = [] + ware_house_accepted_real_weight_list = [] + weight_year_list = [] + + now = datetime.datetime.now().date() + start_date = now - relativedelta(months=5) # محاسبه تاریخ شش ماه پیش + + current_date = start_date + while current_date <= now: + kill_request = kill_requests.filter(kill_request__recive_date__date__month=current_date.month, + kill_request__recive_date__date__year=current_date.year) + has_code_year = len(kill_request.filter(clearance_code__isnull=False)) + quarantine_quantity_year = len(kill_request.filter(quarantine_quantity__isnull=False)) + assignment_state_archive_year = len(kill_request.filter(assignment_state_archive='True')) + accepted_assignment_real_weight = kill_request.aggregate( + total_quantity=Sum('accepted_assignment_real_weight')).get('total_quantity') or 0 + accepted_real_weight = kill_request.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + hasnt_code_year = len(kill_request.filter(clearance_code__isnull=True)) + difference_bar = len(kill_request.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + ware_house_confirmation_year = len(kill_request.filter(ware_house_confirmation=True)) + ware_house_accepted_real_weight = kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get('total_quantity') or 0 + + dict_has_code_year = { + 'date': current_date, + 'percent': round(has_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_quarantine_quantity_year = { + 'date': current_date, + 'percent': round(quarantine_quantity_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_assignment_state_archive_year = { + 'date': current_date, + 'percent': round(assignment_state_archive_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_accepted_assignment_real_weight_year = { + 'date': current_date, + 'percent': round(accepted_assignment_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_hasnt_code_year = { + 'date': current_date, + 'percent': round(hasnt_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_difference_bar_year = { + 'date': current_date, + 'percent': round(difference_bar * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_ware_house_confirmation_year = { + 'date': current_date, + 'percent': round(ware_house_confirmation_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_ware_house_accepted_real_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_assignment_real_weight, + 2) if accepted_assignment_real_weight > 0 else 0 + } + + has_code_list.append(dict_has_code_year) + quarantine_quantity_list.append(dict_quarantine_quantity_year) + assignment_state_archive_list.append(dict_assignment_state_archive_year) + accepted_assignment_real_weight_list.append(dict_accepted_assignment_real_weight_year) + hasnt_code_list.append(dict_hasnt_code_year) + difference_bar_list.append(dict_difference_bar_year) + ware_house_confirmation_list.append(dict_ware_house_confirmation_year) + ware_house_accepted_real_weight_list.append(dict_ware_house_accepted_real_weight_year) + weight_year_list.append(dict_weight_year) + + current_date += relativedelta(months=1) + + all_list['hasCode'] = has_code_list + all_list['quarantineQuantity'] = quarantine_quantity_list + all_list['assignmentStateArchive'] = assignment_state_archive_list + all_list['acceptedAssignmentRealWeight'] = accepted_assignment_real_weight_list + all_list['hasntCode'] = hasnt_code_list + all_list['differenceBar'] = difference_bar_list + all_list['wareHouseConfirmation'] = ware_house_confirmation_list + all_list['wareHouseAcceptedRealWeight'] = ware_house_accepted_real_weight_list + all_list['weightYear'] = weight_year_list + elif request.GET['type'] == 'threeMonths': + has_code_list = [] + quarantine_quantity_list = [] + assignment_state_archive_list = [] + accepted_assignment_real_weight_list = [] + hasnt_code_list = [] + difference_bar_list = [] + ware_house_confirmation_list = [] + ware_house_accepted_real_weight_list = [] + weight_year_list = [] + + now = datetime.datetime.now().date() + start_date = now - relativedelta(months=2) # محاسبه تاریخ سه ماه پیش + + current_date = start_date + while current_date <= now: + kill_request = kill_requests.filter(kill_request__recive_date__date__month=current_date.month, + kill_request__recive_date__date__year=current_date.year) + has_code_year = len(kill_request.filter(clearance_code__isnull=False)) + quarantine_quantity_year = len(kill_request.filter(quarantine_quantity__isnull=False)) + assignment_state_archive_year = len(kill_request.filter(assignment_state_archive='True')) + accepted_assignment_real_weight = kill_request.aggregate( + total_quantity=Sum('accepted_assignment_real_weight')).get('total_quantity') or 0 + accepted_real_weight = kill_request.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + hasnt_code_year = len(kill_request.filter(clearance_code__isnull=True)) + difference_bar = len(kill_request.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + ware_house_confirmation_year = len(kill_request.filter(ware_house_confirmation=True)) + ware_house_accepted_real_weight = kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get('total_quantity') or 0 + + dict_has_code_year = { + 'date': current_date, + 'percent': round(has_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_quarantine_quantity_year = { + 'date': current_date, + 'percent': round(quarantine_quantity_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_assignment_state_archive_year = { + 'date': current_date, + 'percent': round(assignment_state_archive_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_accepted_assignment_real_weight_year = { + 'date': current_date, + 'percent': round(accepted_assignment_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_hasnt_code_year = { + 'date': current_date, + 'percent': round(hasnt_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_difference_bar_year = { + 'date': current_date, + 'percent': round(difference_bar * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_ware_house_confirmation_year = { + 'date': current_date, + 'percent': round(ware_house_confirmation_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_ware_house_accepted_real_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_assignment_real_weight, + 2) if accepted_assignment_real_weight > 0 else 0 + } + + has_code_list.append(dict_has_code_year) + quarantine_quantity_list.append(dict_quarantine_quantity_year) + assignment_state_archive_list.append(dict_assignment_state_archive_year) + accepted_assignment_real_weight_list.append(dict_accepted_assignment_real_weight_year) + hasnt_code_list.append(dict_hasnt_code_year) + difference_bar_list.append(dict_difference_bar_year) + ware_house_confirmation_list.append(dict_ware_house_confirmation_year) + ware_house_accepted_real_weight_list.append(dict_ware_house_accepted_real_weight_year) + weight_year_list.append(dict_weight_year) + + current_date += relativedelta(months=1) + + all_list['hasCode'] = has_code_list + all_list['quarantineQuantity'] = quarantine_quantity_list + all_list['assignmentStateArchive'] = assignment_state_archive_list + all_list['acceptedAssignmentRealWeight'] = accepted_assignment_real_weight_list + all_list['hasntCode'] = hasnt_code_list + all_list['differenceBar'] = difference_bar_list + all_list['wareHouseConfirmation'] = ware_house_confirmation_list + all_list['wareHouseAcceptedRealWeight'] = ware_house_accepted_real_weight_list + all_list['weightYear'] = weight_year_list + else: + has_code_list = [] + quarantine_quantity_list = [] + assignment_state_archive_list = [] + accepted_assignment_real_weight_list = [] + hasnt_code_list = [] + difference_bar_list = [] + ware_house_confirmation_list = [] + ware_house_accepted_real_weight_list = [] + weight_year_list = [] + + now = datetime.datetime.now().date() + last_year = now - relativedelta(months=1) # محاسبه تاریخ یک ماه پیش + + current_date = last_year + while current_date <= now: + kill_request = kill_requests.filter(kill_request__recive_date__date=current_date) + has_code_year = len(kill_request.filter(clearance_code__isnull=False)) + quarantine_quantity_year = len(kill_request.filter(quarantine_quantity__isnull=False)) + assignment_state_archive_year = len(kill_request.filter(assignment_state_archive='True')) + accepted_assignment_real_weight = kill_request.aggregate( + total_quantity=Sum('accepted_assignment_real_weight')).get('total_quantity') or 0 + accepted_real_weight = kill_request.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + hasnt_code_year = len(kill_request.filter(clearance_code__isnull=True)) + difference_bar = len(kill_request.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + ware_house_confirmation_year = len(kill_request.filter(ware_house_confirmation=True)) + ware_house_accepted_real_weight = kill_request.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get('total_quantity') or 0 + + dict_has_code_year = { + 'date': current_date, + 'percent': round(has_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_quarantine_quantity_year = { + 'date': current_date, + 'percent': round(quarantine_quantity_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_assignment_state_archive_year = { + 'date': current_date, + 'percent': round(assignment_state_archive_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_accepted_assignment_real_weight_year = { + 'date': current_date, + 'percent': round(accepted_assignment_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_hasnt_code_year = { + 'date': current_date, + 'percent': round(hasnt_code_year * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_difference_bar_year = { + 'date': current_date, + 'percent': round(difference_bar * 100 / len(kill_request), 2) if len(kill_request) > 0 else 0 + } + dict_ware_house_confirmation_year = { + 'date': current_date, + 'percent': round(ware_house_confirmation_year * 100 / len(kill_request), 2) if len( + kill_request) > 0 else 0 + } + dict_ware_house_accepted_real_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_real_weight, + 2) if accepted_real_weight > 0 else 0 + } + dict_weight_year = { + 'date': current_date, + 'percent': round(ware_house_accepted_real_weight * 100 / accepted_assignment_real_weight, + 2) if accepted_assignment_real_weight > 0 else 0 + } + + has_code_list.append(dict_has_code_year) + quarantine_quantity_list.append(dict_quarantine_quantity_year) + assignment_state_archive_list.append(dict_assignment_state_archive_year) + accepted_assignment_real_weight_list.append(dict_accepted_assignment_real_weight_year) + hasnt_code_list.append(dict_hasnt_code_year) + difference_bar_list.append(dict_difference_bar_year) + ware_house_confirmation_list.append(dict_ware_house_confirmation_year) + ware_house_accepted_real_weight_list.append(dict_ware_house_accepted_real_weight_year) + weight_year_list.append(dict_weight_year) + + current_date += relativedelta(days=1) # به روز بعد بروید + + all_list['hasCode'] = has_code_list + all_list['quarantineQuantity'] = quarantine_quantity_list + all_list['assignmentStateArchive'] = assignment_state_archive_list + all_list['acceptedAssignmentRealWeight'] = accepted_assignment_real_weight_list + all_list['hasntCode'] = hasnt_code_list + all_list['differenceBar'] = difference_bar_list + all_list['wareHouseConfirmation'] = ware_house_confirmation_list + all_list['wareHouseAcceptedRealWeight'] = ware_house_accepted_real_weight_list + all_list['weightYear'] = weight_year_list + return Response(all_list) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def check_excel(request): + url = request.GET.get('url') + if not url: + return JsonResponse({'status': 'error', 'message': 'URL parameter is missing'}, status=400) + + try: + r = requests.head(f'https://{base_url_for_sms_report}backend.rasadyar.com/{url}') + return JsonResponse({'status': r.status_code}) + except requests.RequestException as e: + return JsonResponse({'status': 'error', 'message': str(e)}, status=500) + + +class SSLAdapter(HTTPAdapter): + def __init__(self, *args, **kwargs): + self.context = create_urllib3_context() + self.context.options |= 0x4 # OP_LEGACY_SERVER_CONNECT + super().__init__(*args, **kwargs) + + def init_poolmanager(self, *args, **kwargs): + kwargs['ssl_context'] = self.context + return super().init_poolmanager(*args, **kwargs) + + def build_response(self, req, resp): + resp = super().build_response(req, resp) + return resp + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def find_gid_code(request): + date = datetime.datetime.now().date() - datetime.timedelta(days=7) + kill_house_request = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date, trash=False, + quarantine_quantity__isnull=True).only( + 'quarantine_code_state', 'clearance_code', 'quarantine_quantity' + ).order_by('-id') + session = requests.Session() + session.mount('https://', SSLAdapter()) + + for kill in kill_house_request: + if kill.clearance_code is None: + kill.quarantine_code_state = 'noclearance' + else: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + kill.quarantine_code_state = 'notconfirmed' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + else: + table = context.find_all('table') + if table[5:6]: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.quarantine_quantity = int(number) + if kill.quarantine_code_state is not None: + kill.quarantine_code_state = None + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + kill.quarantine_code_state = 'contradiction' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + kill.save() + return HttpResponse('ok') + + +def get_gid(clearance_code): + kill = KillHouseRequest.objects.filter(clearance_code=clearance_code, trash=False).order_by('id') + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kill: + if len(kill) > 1: + for k in kill[1:]: + if k.quarantine_quantity is not None: + k.quarantine_quantity = None + k.quarantine_code_state = 'merge' + k.save() + kill = kill.first() + if kill.quarantine_code_state != 'merge': + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + kill.quarantine_code_state = 'notconfirmed' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + kill.inquiry_date = date.date() + send_date = kill.kill_request.recive_date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.quarantine_quantity = int(number) + if kill.quarantine_code_state is not None: + kill.quarantine_code_state = None + for i in table[4:5]: + rows = i.find_all('tr') + + pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + style='font-family:Tahoma').text.strip() + kill.inquiry_pelak = pelak_txt + td = rows[1].find_all('td')[1] + driver_txt = td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_driver = driver_txt + + for r in rows: + tds = r.find_all('td', colspan="2") + if len(tds) >= 2: + origin_td = tds[0] + origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_origin = origin_text + + destination_td = tds[1] + destination_text = destination_td.find('span', + class_='dynamictxt').text.strip() + kill.inquiry_destination = destination_text + else: + kill.quarantine_code_state = 'contradiction' + kill.quarantine_quantity = None + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + kill.quarantine_code_state = 'contradiction' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + kill.save() + + +def cron_find_gid_code(): + date = datetime.datetime.now().date() - datetime.timedelta(days=7) + kill_house_request = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date, trash=False, + quarantine_quantity__isnull=True, + clearance_code__isnull=False).only( + 'quarantine_code_state', 'clearance_code', 'quarantine_quantity' + ).order_by('-id') + session = requests.Session() + session.mount('https://', SSLAdapter()) + + for kill in kill_house_request: + if kill.quarantine_code_state != 'merge': + if kill.clearance_code is None: + kill.quarantine_code_state = 'noclearance' + else: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + kill.quarantine_code_state = 'notconfirmed' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + kill.inquiry_date = date.date() + send_date = kill.kill_request.recive_date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.quarantine_quantity = int(number) + if kill.quarantine_code_state is not None: + kill.quarantine_code_state = None + for i in table[4:5]: + rows = i.find_all('tr') + + pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + style='font-family:Tahoma').text.strip() + kill.inquiry_pelak = pelak_txt + td = rows[1].find_all('td')[1] + driver_txt = td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_driver = driver_txt + + for r in rows: + tds = r.find_all('td', colspan="2") + if len(tds) >= 2: + origin_td = tds[0] + origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_origin = origin_text + + destination_td = tds[1] + destination_text = destination_td.find('span', + class_='dynamictxt').text.strip() + kill.inquiry_destination = destination_text + else: + kill.quarantine_code_state = 'contradiction' + kill.quarantine_quantity = None + + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + kill.quarantine_code_state = 'contradiction' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + kill.save() + + +class IranProvinceViewSet(viewsets.ModelViewSet): + queryset = IranProvinces.objects.all().order_by('id') + serializer_class = IranProvinceSerializer + permission_classes = [AllowAny] + + +class IranCityViewSet(viewsets.ModelViewSet): + queryset = IranCities.objects.all().order_by('id') + serializer_class = IranCitiesSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + query = self.queryset.filter(province_id__name=request.GET.get('name')) + ser_data = self.serializer_class(query, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + +def fix_image_voilation_hatching(request): + hatchings = PoultryHatching.objects.filter(violation_image__isnull=False) + for h in hatchings: + h.violation_image1 = [h.violation_image] + h.save() + return HttpResponse('ok') + + +def fix_image_voilation_hatching_return(request): + hatchings = PoultryHatching.objects.filter(violation_image1__isnull=False) + for h in hatchings: + h.violation_image = h.violation_image1 + h.save() + return HttpResponse('ok') + + +class AgeNotificationPoultryViewSet(viewsets.ModelViewSet): + queryset = AgeNotificationPoultry.objects.all() + serializer_class = AgeNotificationPoultrySerilizer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + query = self.queryset.filter(trash=False) + ser_data = self.serializer_class(query, many=True).data + return Response(ser_data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + query = self.queryset.get(key=request.data['notif_key']) + request.data.pop('notif_key') + ser_data = self.serializer_class(query) + ser_data.update(instance=query, validated_data=request.data) + return Response(ser_data.data, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + query = self.queryset.get(key=request.GET['notif_key']) + query.trash = True + query.save() + return Response({'result': 'با موفقیت حذف شد.'}, status=status.HTTP_200_OK) + + +def send_sms_for_poultry_from_age_notification(): + notif_poultry = AgeNotificationPoultry.objects.filter(trash=False) + if notif_poultry: + for n in notif_poultry: + poultry_hatchings = PoultryHatching.objects.filter( + archive=False, + allow_hatching='pending', + trash=False, + left_over__gt=(F('quantity') * n.losses_percent) / 100, + chicken_age=n.poultry_age + ).values_list('poultry__user__mobile', flat=True).distinct() + + mobile_numbers = ','.join(poultry_hatchings) + if len(mobile_numbers) > 0: + req = send_sms_request( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/SendPostUrl?username={USERNAME_SMS_FINANCIAL}&password={PASSWORD_SMS_FINANCIAL}&from=30002501&to={mobile_numbers}&message={n.message}") + + +def remove_access_token(): + ARTA_remove_access_token = "https://userbackend.rasadyar.com/api/remove_access_token/" + requests.get( + url=ARTA_remove_access_token, + verify=False + ) + now = datetime.datetime.now() + accesses = AccessToken.objects.filter(created__date__gte=now.date() - timedelta(days=3)) + for access in accesses: + access.expires = now - timedelta(days=2) + access.save() + + +def kill_house_not_add_to_inventory(): + now = datetime.datetime.now().date() - timedelta(days=2) + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).select_related('kill_house_operator__user') + for kill_house in kill_houses: + kill_request = len(KillHouseRequest.objects.filter(Q(killhouse_user=kill_house) | Q(killer=kill_house), + trash=False, ware_house_confirmation=False, + calculate_status=True, + kill_request__recive_date__date__lte=now)) + if kill_request > 0: + send_sms_for_kill_house_not_add_to_inventory(kill_house.kill_house_operator.user.mobile, kill_request) + + +class CookieSamasatViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + queryset = CookieSamasat.objects.first() + serializer_class = CookieSamasatSerilizer + + def list(self, request, *args, **kwargs): + cookie = CookieSamasat.objects.all().first() + if not cookie: + cookie = CookieSamasat( + cookie='-', + table_name='-' + ) + cookie.save() + ser_data = self.serializer_class(cookie).data + return Response(ser_data, status=status.HTTP_200_OK) + + def update(self, request, *args, **kwargs): + query = CookieSamasat.objects.first() + + if base_url_for_sms_report == 'test': + province_list = ['bu', 'ma', 'ha'] + for name in province_list: + requests.put(f"https://{name}backend.rasadyar.com/cookie-samasat/0/", data=request.data) + + serializer = self.serializer_class(query, data=request.data, partial=True) + if serializer.is_valid(): + serializer.save() + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + +# def create_poultry(phone_number,full_name,city,province): +# group = Group.objects.get(name__exact="Poultry") +# hashed_password=None +# password=None +# user = User(username=phone_number, first_name=first_name, last_name=last_name, password=hashed_password) +# user.save() +# base_id = SystemUserProfile.objects.all() +# if base_id.count() > 0: +# base_id = int(base_id.last().base_order) + 1 +# else: +# base_id = 1000 +# system_profile = SystemUserProfile( +# mobile=phone_number, +# first_name=first_name, +# last_name=last_name, +# fullname=first_name + '' + last_name, +# user=user, +# base_order=base_id, +# password=password, +# birthday=str(datetime.datetime.now().date()), +# city=city, +# province=province +# ) +# system_profile.save() +# system_profile.role.add(group) +# wallet = Wallet() +# wallet.save() + +# درست نیست +@api_view(["PUT"]) +@permission_classes([AllowAny]) +@csrf_exempt +def api_update_poultry_hatching(request): + not_find_list = [] + + for data in request.data['Data']: + breeding_uniq_id = data['PartIdCode'] + licence_number = data['RequestCode'] + hatching_quantity = data['BaseHatchingCount'] + poultry_name = data['UnitName'] + losses = data['EvacuationCount'] + health_certificate = data['DesCertId'] + evacuation_details = data.get('EvacuationDetail') or [] + if isinstance(evacuation_details, dict): + evacuation_details = [evacuation_details] + report_type_field_map = { + 'تلفات ناشی از بیماری': 'total_disease_losses', + 'معدوم سازی گله': 'total_flock_destruction', + 'تلفات عادی گله': 'total_normal_flock_losses', + 'تلفات ناشی از عوامل قهری و طبیعی': 'total_force_majeure_losses', + 'تلفات ناشی از آتش سوزی': 'total_fire_losses', + } + evacuation_losses = {} + evacuation_fields = set() + for detail in evacuation_details: + if not isinstance(detail, dict): + continue + report_type = (detail.get('ReportTypeString') or '').strip() + field_name = report_type_field_map.get(report_type) + if not field_name: + continue + try: + good_count = int(detail.get('GoodCount') or 0) + except (TypeError, ValueError): + continue + evacuation_losses[field_name] = evacuation_losses.get(field_name, 0) + good_count + evacuation_fields.add(field_name) + + def apply_evacuation_losses(instance): + for field in evacuation_fields: + setattr(instance, field, evacuation_losses.get(field, 0)) + + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).first() + + if not poultry: + not_find_list.append(breeding_uniq_id) + continue + poultry.unit_name = poultry_name + poultry.save() + hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + if hatch: + period = hatch.last().period + 1 + else: + period = 1 + + hatching_date = data['HatchingDatePersian'].split('/') + date = convert_to_miladi( + year=int(hatching_date[0]), + month=int(hatching_date[1]), + day=int(hatching_date[2]) + ) + + poultry_hatching = hatch.filter(trash=False, archive=False, state='pending', + allow_hatching='pending').order_by('id') + + if not poultry_hatching.exists(): + if not hatch.filter(archive=True, state='complete', + allow_hatching="True", licence_number=licence_number).exists(): + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed='*ترکیبی', + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses, + health_certificate=health_certificate + + ) + apply_evacuation_losses(hatching) + hatching.save() + + else: + previouse_hatching = poultry_hatching.last() + + hatchings = poultry_hatching.filter(licence_number=licence_number) + if not hatchings: + if previouse_hatching.left_over > (previouse_hatching.quantity * percent_of_losses): + previouse_hatching.violation = True + previouse_hatching.save() + + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed='*ترکیبی', + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses, + health_certificate=health_certificate + + ) + apply_evacuation_losses(hatching) + hatching.save() + else: + last_hatchings = hatchings.first() + if last_hatchings.health_certificate is None: + last_hatchings.health_certificate = health_certificate + last_hatchings.date = date + last_hatchings.quantity = hatching_quantity + last_hatchings.losses = losses + apply_evacuation_losses(last_hatchings) + last_hatchings.save() + + update = LastUpdate.objects.first() + update.update_date = datetime.datetime.now() + update.save() + return Response(not_find_list, status=status.HTTP_201_CREATED) + + +@api_view(["PUT"]) +@permission_classes([AllowAny]) +@csrf_exempt +def api_update_chicken_breed(request): + for data in request.data['Data']: + breeding_uniq_id = data['PartIdCode'] + breed = data['PedigreeName'] + health_certificate = data['CertId'] + poultry_hatching = PoultryHatching.objects.filter(Q(poultry__breeding_unique_id=breeding_uniq_id, + health_certificate__isnull=True) | Q( + poultry__breeding_unique_id=breeding_uniq_id, health_certificate__isnull=False, + health_certificate=health_certificate) + , violation=False, trash=False, allow_hatching='pending', + state='pending', + ).order_by( + 'id').last() + + if poultry_hatching: + if poultry_hatching.chicken_breed == '*ترکیبی': + poultry_hatching.chicken_breed = breed + elif poultry_hatching.chicken_breed != breed and poultry_hatching.chicken_breed != '*ترکیبی': + poultry_hatching.chicken_breed = 'ترکیبی' + else: + continue + + poultry_hatching.save() + + return Response({"result": "انجام شد."}, status=status.HTTP_201_CREATED) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def api_update_poultry_hatching_from_rsi(request): + not_find_list = [] + r = requests.get(f'https://rsibackend.rasadyar.com/app/update_hatching/?province={base_url_for_sms_report}') + + for data in r.json(): + breeding_uniq_id = data['PartIdCode'] + licence_number = data['RequestCode'] + hatching_quantity = data['ChickCountSum'] + CertId = data['CertId'] + poultry_name = data.get('UnitName', None) + losses = data.get('Evacuation', 0) + province = data['ProvinceName'] + city = data['CityName'] + PersonTypeName = data['PersonTypeName'] + InteractTypeName = data['InteractTypeName'] + UnionTypeName = data['UnionTypeName'] + date = convert_str_to_date(str(data['Date']), with_datetime=True) + samasat_discharge_percentage = data['samasat_discharge_percentage'] + evacuation_details = data.get('EvacuationDetail') or [] + if isinstance(evacuation_details, dict): + evacuation_details = [evacuation_details] + report_type_field_map = { + 'تلفات ناشی از بیماری': 'total_disease_losses', + 'معدوم سازی گله': 'total_flock_destruction', + 'تلفات عادی گله': 'total_normal_flock_losses', + 'تلفات ناشی از عوامل قهری و طبیعی': 'total_force_majeure_losses', + 'تلفات ناشی از آتش سوزی': 'total_fire_losses', + } + evacuation_detail_fields = [ + 'PartIdCode', + 'RequestId', + 'MoReportId', + 'ReportType', + 'ReportTypeString', + 'ReportDate', + 'ReportDateShamsi', + 'MoReason', + 'MoDate', + 'MoDateShamsi', + 'MoStartDay', + 'MoEndDay', + 'MoReportSubId', + 'ReportStatus', + 'GoodCount', + 'Message', + 'ErrorCode', + 'IsDeleted', + 'RegDate', + 'RegDateShamsi', + 'RegDateShamsiWithTime', + 'RegDateShamsiOnlyTime', + 'ExternalId', + 'StringId', + 'IsPersisted', + 'AllowInsert', + 'AllowUpdate', + 'ModalCss', + 'GridContainerParametersModel', + 'MenuUserAccess', + 'MenuUserAccessId', + 'LogTableName', + 'LogTableAlias', + 'PageTitle', + ] + report_type_fields = set(report_type_field_map.values()) + report_type_field_list = list(report_type_fields) + + def build_unique_key(detail_payload): + external_id = detail_payload.get('ExternalId') + if external_id: + return f"external:{external_id}" + string_id = detail_payload.get('StringId') + if string_id: + return f"string:{string_id}" + return "fallback:" + "|".join( + str(detail_payload.get(key) or '') for key in ('PartIdCode', 'MoReportId', 'ReportType', 'ReportDate')) + + def sync_evacuation_detail_records(hatching_instance): + if not hatching_instance.pk: + return + + def normalize_good_count(value): + if value in (None, ''): + return None + try: + return int(value) + except (TypeError, ValueError): + try: + return int(float(value)) + except (TypeError, ValueError): + return None + + retained_ids = set() + seen_unique_keys = set() + + for detail in evacuation_details: + if not isinstance(detail, dict): + continue + detail_payload = {field: detail.get(field) for field in evacuation_detail_fields} + detail_payload['GoodCount'] = normalize_good_count(detail_payload.get('GoodCount')) + if not any(value not in (None, '') for value in detail_payload.values()): + continue + + unique_key = build_unique_key(detail_payload) + if unique_key in seen_unique_keys: + continue + seen_unique_keys.add(unique_key) + + external_id = detail_payload.get('ExternalId') + string_id = detail_payload.get('StringId') + lookup_kwargs = {'hatching': hatching_instance} + if external_id: + lookup_kwargs['ExternalId'] = external_id + elif string_id: + lookup_kwargs['StringId'] = string_id + else: + lookup_key_fields = ('PartIdCode', 'MoReportId', 'ReportType', 'ReportDate') + lookup_kwargs.update({field: detail_payload.get(field) for field in lookup_key_fields}) + + defaults = detail_payload.copy() + defaults['hatching'] = hatching_instance + + try: + detail_instance, _ = EvacuationHatchingDetail.objects.update_or_create( + defaults=defaults, + **lookup_kwargs + ) + except EvacuationHatchingDetail.MultipleObjectsReturned: + EvacuationHatchingDetail.objects.filter(**lookup_kwargs).delete() + detail_instance, _ = EvacuationHatchingDetail.objects.update_or_create( + defaults=defaults, + **lookup_kwargs + ) + + retained_ids.add(detail_instance.pk) + + if retained_ids: + hatching_instance.evacuation_details.exclude(pk__in=retained_ids).delete() + else: + hatching_instance.evacuation_details.all().delete() + + def apply_evacuation_losses(instance): + totals = {field: 0 for field in report_type_fields} + detail_qs = instance.evacuation_details.filter(trash=False, IsDeleted=False) + for detail in detail_qs: + report_type = (detail.ReportTypeString or '').strip() + field_name = report_type_field_map.get(report_type) + if not field_name: + continue + totals[field_name] += detail.GoodCount or 0 + for field, value in totals.items(): + setattr(instance, field, value) + + hatch = PoultryHatching.objects.filter(trash=False, licence_number=licence_number).order_by('id') + + try: + if not hatch: + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).first() + if not poultry: + first_name = data['poultry']['FirstName'] + last_name = data['poultry']['LastName'] + mobile = data['poultry']['Mobile'] + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).first() + province = Province.objects.filter(trash=False, name__exact=province).first() + city = City.objects.filter(trash=False, name__exact=city).first() + if not system_profile: + + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": '123456', + "national_code": '0', + "role": "Poultry", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + hashed_password = hashlib.sha256(str('123456').encode()).hexdigest() + user = User.objects.filter(username=mobile).first() + if not user: + user = User(username=mobile, first_name=first_name, last_name=last_name, + password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=str(first_name), + last_name=str(last_name), + fullname=str(first_name) + ' ' + str(last_name), + user=user, + base_order=base_id, + password='123456', + birthday=str(datetime.datetime.now().date()), + city=city, + province=province, + ) + system_profile.save() + + else: + not_find_list.append(breeding_uniq_id) + + group = Group.objects.get(name__exact="Poultry") + if not system_profile.role.filter(name="Poultry"): + system_profile.role.add(group) + + wallet = Wallet() + wallet.save() + poultry = Poultry( + user=system_profile, + unit_name=poultry_name, + system_code=data.get('poultry', {}).get('SystemCode', None), + epidemiological_code=data.get('poultry', {}).get('EpidemiologicCode', None), + breeding_unique_id=breeding_uniq_id, + ) + + address = SystemAddress( + province=province, + city=city, + address=city + ) + address.save() + poultry.address = address + poultry.user = system_profile + poultry.wallet = wallet + poultry.save() + + poultry.unit_name = poultry_name + poultry.save() + + hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + if hatch: + period = hatch.last().period + 1 + else: + period = 1 + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed=data["PedigreeName"], + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses, + PersonTypeName=PersonTypeName, + InteractTypeName=InteractTypeName, + UnionTypeName=UnionTypeName, + samasat_discharge_percentage=samasat_discharge_percentage, + CertId=CertId, + predicate_date=date + timedelta( + days=poultry.killing_ave_age) if poultry.killing_ave_age > 1 else None, + + ) + hatching.chicken_age = (datetime.datetime.now().date() - hatching.date.date()).days + 1 + hatching.save() + sync_evacuation_detail_records(hatching) + apply_evacuation_losses(hatching) + if report_type_field_list: + hatching.save(update_fields=report_type_field_list) + else: + hatching.save() + else: + last_hatchings = hatch.first() + last_hatchings.date = date + last_hatchings.quantity = hatching_quantity + last_hatchings.losses = losses + last_hatchings.PersonTypeName = PersonTypeName + last_hatchings.InteractTypeName = InteractTypeName + last_hatchings.UnionTypeName = UnionTypeName + last_hatchings.chicken_age = (datetime.datetime.now().date() - last_hatchings.date.date()).days + 1 + last_hatchings.samasat_discharge_percentage = samasat_discharge_percentage + last_hatchings.predicate_date = date + timedelta( + days=last_hatchings.poultry.killing_ave_age) if last_hatchings.poultry.killing_ave_age > 1 else None + sync_evacuation_detail_records(last_hatchings) + apply_evacuation_losses(last_hatchings) + update_fields = [ + 'date', + 'quantity', + 'losses', + 'PersonTypeName', + 'InteractTypeName', + 'UnionTypeName', + 'chicken_age', + 'samasat_discharge_percentage', + 'predicate_date', + ] + report_type_field_list + last_hatchings.save(update_fields=update_fields) + update = LastUpdate.objects.first() + update.update_date = datetime.datetime.now() + update.save() + except: + not_find_list.append(breeding_uniq_id) + + if not_find_list: + token = "bot291669:9298e675-8b3c-4b8f-a69d-5c89a3f0bdde" + chat_id = '10046800' + url = f'https://eitaayar.ir/api/{token}/sendMessage' + base_message = f'{base_url_for_sms_report}' \ + '\n' + messages = [] + current_message = base_message + new_message_part = ','.join(not_find_list) + if len(current_message) + len(new_message_part) > 4000: # محدودیت تعداد کاراکترها + messages.append(current_message) + current_message = base_message # شروع یک پیام جدید + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + r = requests.post(url, data=data, verify=False) + + return Response(not_find_list, status=status.HTTP_201_CREATED) + + +class HatchingLossManagementViewSet(viewsets.ModelViewSet): + permission_classes = [AllowAny] + serializer_class = HatchingLossManagementSerializer + + def get_queryset(self): + queryset = HatchingLossManagement.objects.filter(trash=False) + if not queryset.exists(): + queryset = HatchingLossManagement.objects.filter( + pk=HatchingLossManagement.objects.create().pk + ) + return queryset + + def get_object(self): + return self.get_queryset().first() + + def list(self, request, *args, **kwargs): + instance = self.get_object() + serializer = self.get_serializer(instance) + return Response( + serializer.data, + status=status.HTTP_200_OK, + ) + + def create(self, request, *args, **kwargs): + return self._update_instance(request, partial=False) + + def update(self, request, *args, **kwargs): + return self._update_instance(request, partial=False) + + def _update_instance(self, request, partial): + instance = self.get_object() + serializer = self.get_serializer(instance, data=request.data, partial=partial) + serializer.is_valid(raise_exception=True) + instance = serializer.save() + self._recalculate_hatchings() + return Response(self.get_serializer(instance).data, status=status.HTTP_200_OK) + + def _recalculate_hatchings(self): + count = 0 + hatchings = PoultryHatching.objects.filter(trash=False, archive=False, allow_hatching='pending') + for hatching in hatchings.iterator(): + hatching.save() + count += 1 + return count + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def update_hatching(request): + r = requests.get(f'https://rsibackend.rasadyar.com/app/update_hatching/?province={base_url_for_sms_report}') + for data in r.json(): + print(data['PartIdCode']) + return Response(r.json()) + + +def cron_update_poultry_hatching_from_rsi(): + not_find_list = [] + r = requests.get(f'https://rsibackend.rasadyar.com/app/update_hatching/?province={base_url_for_sms_report}') + + for data in r.json(): + breeding_uniq_id = data['PartIdCode'] + licence_number = data['RequestCode'] + hatching_quantity = data['ChickCountSum'] + CertId = data['CertId'] + poultry_name = data.get('UnitName', None) + losses = data.get('Evacuation', 0) + province = data['ProvinceName'] + city = data['CityName'] + PersonTypeName = data['PersonTypeName'] + InteractTypeName = data['InteractTypeName'] + UnionTypeName = data['UnionTypeName'] + date = datetime.datetime.strptime(data['Date'], "%Y-%m-%dT%H:%M:%SZ") + samasat_discharge_percentage = data['samasat_discharge_percentage'] + + hatch = PoultryHatching.objects.filter(trash=False, licence_number=licence_number).order_by('id') + + try: + if not hatch: + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=breeding_uniq_id).first() + if not poultry: + first_name = data['poultry']['FirstName'] + last_name = data['poultry']['LastName'] + mobile = data['poultry']['Mobile'] + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).first() + if not system_profile: + + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": '123456', + "national_code": '0', + "role": "Poultry", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + hashed_password = hashlib.sha256(str('123456').encode()).hexdigest() + user = User.objects.filter(username=mobile).first() + if not user: + user = User(username=mobile, first_name=first_name, last_name=last_name, + password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=str(first_name), + last_name=str(last_name), + fullname=str(first_name) + ' ' + str(last_name), + user=user, + base_order=base_id, + password='123456', + birthday=str(datetime.datetime.now().date()), + ) + system_profile.save() + + else: + not_find_list.append(breeding_uniq_id) + + group = Group.objects.get(name__exact="Poultry") + if not system_profile.role.filter(name="Poultry"): + system_profile.role.add(group) + + wallet = Wallet() + wallet.save() + poultry = Poultry( + user=system_profile, + unit_name=poultry_name, + system_code=data.get('poultry', {}).get('SystemCode', None), + epidemiological_code=data.get('poultry', {}).get('EpidemiologicCode', None), + breeding_unique_id=breeding_uniq_id, + ) + province = Province.objects.filter(trash=False, name__exact=province).first() + city = City.objects.filter(trash=False, name__exact=city).first() + address = SystemAddress( + province=province, + city=city, + address=city + ) + address.save() + poultry.address = address + poultry.user = system_profile + poultry.wallet = wallet + poultry.save() + + poultry.unit_name = poultry_name + poultry.save() + + hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + if hatch: + period = hatch.last().period + 1 + else: + period = 1 + hatching = PoultryHatching( + poultry=poultry, + date=date, + quantity=hatching_quantity, + breed=[ + {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + period=period, + chicken_breed=data["PedigreeName"], + hall=1, + left_over=hatching_quantity, + latest_hatching_change={ + "role": "UnitWindow", + "date": str(datetime.datetime.now().date()), + "full_name": "" + }, + licence_number=licence_number, + breeding_unique_id=breeding_uniq_id, + losses=losses, + PersonTypeName=PersonTypeName, + InteractTypeName=InteractTypeName, + UnionTypeName=UnionTypeName, + samasat_discharge_percentage=samasat_discharge_percentage, + CertId=CertId, + predicate_date=date + timedelta( + days=poultry.killing_ave_age) if poultry.killing_ave_age > 1 else None, + + ) + hatching.chicken_age = (datetime.datetime.now().date() - hatching.date.date()).days + 1 + hatching.save() + else: + last_hatchings = hatch.first() + last_hatchings.date = date + last_hatchings.quantity = hatching_quantity + last_hatchings.losses = losses + last_hatchings.PersonTypeName = PersonTypeName + last_hatchings.InteractTypeName = InteractTypeName + last_hatchings.UnionTypeName = UnionTypeName + last_hatchings.chicken_age = (datetime.datetime.now().date() - last_hatchings.date.date()).days + 1 + last_hatchings.samasat_discharge_percentage = samasat_discharge_percentage + last_hatchings.predicate_date = date + timedelta( + days=last_hatchings.poultry.killing_ave_age) if last_hatchings.poultry.killing_ave_age > 1 else None + last_hatchings.save() + update = LastUpdate.objects.first() + update.update_date = datetime.datetime.now() + update.save() + except: + not_find_list.append(breeding_uniq_id) + + # poultry = Poultry.objects.filter(breeding_unique_id=breeding_uniq_id).first() + # try: + # if not poultry: + # first_name = data['poultry']['FirstName'] + # last_name = data['poultry']['LastName'] + # mobile = data['poultry']['Mobile'] + # system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).first() + # if not system_profile: + # + # data = { + # "username": mobile, + # "first_name": first_name, + # "last_name": last_name, + # "password": '123456', + # "national_code": '0', + # "role": "Poultry", + # "api_key": PROJECT_API_KEY + # } + # req = requests.post( + # url=ARTA_REGISTER, + # data=data, + # verify=False + # ) + # + # if req.status_code == 200: + # hashed_password = hashlib.sha256(str('123456').encode()).hexdigest() + # user = User.objects.filter(username=mobile).first() + # if not user: + # user = User(username=mobile, first_name=first_name, last_name=last_name, + # password=hashed_password) + # user.save() + # base_id = SystemUserProfile.objects.all() + # if base_id.count() > 0: + # base_id = int(base_id.last().base_order) + 1 + # else: + # base_id = 1000 + # system_profile = SystemUserProfile( + # mobile=mobile, + # first_name=str(first_name), + # last_name=str(last_name), + # fullname=str(first_name) + ' ' + str(last_name), + # user=user, + # base_order=base_id, + # password='123456', + # birthday=str(datetime.datetime.now().date()), + # ) + # system_profile.save() + # + # else: + # continue + # + # group = Group.objects.get(name__exact="Poultry") + # if not system_profile.role.filter(name="Poultry"): + # system_profile.role.add(group) + # + # wallet = Wallet() + # wallet.save() + # poultry = Poultry( + # user=system_profile, + # unit_name=poultry_name, + # system_code=data.get('poultry', {}).get('SystemCode',None), + # epidemiological_code=data.get('poultry', {}).get('EpidemiologicCode',None), + # breeding_unique_id=breeding_uniq_id, + # ) + # province=Province.objects.filter(trash=False,name__exact=province).first() + # city=City.objects.filter(trash=False,name__exact=city).first() + # address = SystemAddress( + # province=province, + # city=city, + # address=city + # ) + # address.save() + # poultry.address = address + # poultry.user = system_profile + # poultry.wallet = wallet + # poultry.save() + # + # poultry.unit_name = poultry_name + # poultry.save() + # hatch = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + # if hatch: + # period = hatch.last().period + 1 + # else: + # period = 1 + # + # # hatching_date = data['HatchingDatePersian'].split('/') + # date = data['Date'] + # + # poultry_hatching = hatch.filter(trash=False,archive=False, state='pending', + # allow_hatching='pending').order_by('id') + # + # if not poultry_hatching.exists(): + # if not hatch.filter(archive=True, state='complete', + # allow_hatching="True",licence_number=licence_number).exists(): + # hatching = PoultryHatching( + # poultry=poultry, + # date=date, + # quantity=hatching_quantity, + # breed=[ + # {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + # period=period, + # chicken_breed=data["PedigreeName"], + # hall=1, + # left_over=hatching_quantity, + # latest_hatching_change={ + # "role": "UnitWindow", + # "date": str(datetime.datetime.now().date()), + # "full_name": "" + # }, + # licence_number=licence_number, + # breeding_unique_id=breeding_uniq_id, + # losses=losses, + # + # ) + # hatching.save() + # + # else: + # previouse_hatching = poultry_hatching.last() + # + # hatchings = poultry_hatching.filter(licence_number=licence_number) + # if not hatchings: + # if previouse_hatching.left_over > (previouse_hatching.quantity * percent_of_losses): + # previouse_hatching.violation = True + # previouse_hatching.save() + # + # hatching = PoultryHatching( + # poultry=poultry, + # date=date, + # quantity=hatching_quantity, + # breed=[ + # {"breed": 'آرین', "main_quantity": hatching_quantity, "remain_quantity": hatching_quantity}], + # period=period, + # chicken_breed=data["PedigreeName"], + # hall=1, + # left_over=hatching_quantity, + # latest_hatching_change={ + # "role": "UnitWindow", + # "date": str(datetime.datetime.now().date()), + # "full_name": "" + # }, + # licence_number=licence_number, + # breeding_unique_id=breeding_uniq_id, + # losses=losses, + # + # ) + # hatching.save() + # else: + # last_hatchings=hatchings.first() + # # if last_hatchings.health_certificate is None: + # # last_hatchings.health_certificate=health_certificate + # last_hatchings.date = date + # last_hatchings.quantity = hatching_quantity + # last_hatchings.losses = losses + # last_hatchings.save() + # + # update = LastUpdate.objects.first() + # update.update_date = datetime.datetime.now() + # update.save() + # except: + # not_find_list.append(breeding_uniq_id) + if not_find_list: + token = "bot291669:9298e675-8b3c-4b8f-a69d-5c89a3f0bdde" + chat_id = '10046800' + url = f'https://eitaayar.ir/api/{token}/sendMessage' + base_message = f'{base_url_for_sms_report}' \ + '\n' + messages = [] + current_message = base_message + new_message_part = ','.join(not_find_list) + if len(current_message) + len(new_message_part) > 4000: # محدودیت تعداد کاراکترها + messages.append(current_message) + current_message = base_message # شروع یک پیام جدید + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + for message in messages: + data = { + 'chat_id': chat_id, + 'text': message, + } + r = requests.post(url, data=data, verify=False) + + +def fix_bar_without_quarantine(request): + kill_request = KillHouseRequest.objects.filter(trash=False, clearance_code__isnull=False, + quarantine_code_state__isnull=False).only('clearance_code') + print(len(kill_request)) + for kill in kill_request: + get_gid(kill.clearance_code) + return HttpResponse('ok') + + +def get_gid_out_province(id): + kill = KillHouseFreeSaleBarInformation.objects.get(id=id, trash=False) + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kill: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + # kill.quarantine_code_state = 'notconfirmed' + # if kill.quarantine_quantity is not None: + # kill.quarantine_weight_of_carcasses = None + pass + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + send_date = kill.date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + # kill.inquiry_date = date.date() + for i in table[5:6]: + row = i.find_all('tr') + for r in row[0:1]: + + quantity = r.find_all('td')[1] + match = re.search(r'\d+', quantity.text) + + if match: + number = match.group() + kill.quarantine_weight_of_carcasses = int(number) + # if kill.quarantine_code_state is not None: + # kill.quarantine_code_state=None + else: + kill.quarantine_weight_of_carcasses = 0 + # for i in table[4:5]: + # rows = i.find_all('tr') + # + # pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + # style='font-family:Tahoma').text.strip() + # kill.inquiry_pelak=pelak_txt + # td=rows[1].find_all('td')[1] + # driver_txt = td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_driver=driver_txt + # + # for r in rows: + # tds = r.find_all('td', colspan="2") + # if len(tds) >= 2: + # origin_td = tds[0] + # origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_origin=origin_text + # + # destination_td = tds[1] + # destination_text = destination_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_destination=destination_text + + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + # kill.quarantine_code_state = 'contradiction' + if kill.quarantine_weight_of_carcasses > 0: + kill.quarantine_weight_of_carcasses = 0 + kill.save() + + +def get_gid_out_province_cron_job(): + kills = KillHouseFreeSaleBarInformation.objects.filter(quarantine_weight_of_carcasses=0, + clearance_code__isnull=False, trash=False) + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kills: + for kill in kills: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + # kill.quarantine_code_state = 'notconfirmed' + # if kill.quarantine_quantity is not None: + # kill.quarantine_weight_of_carcasses = None + pass + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + # kill.inquiry_date = date.date() + send_date = kill.date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[0:1]: + + quantity = r.find_all('td')[1] + match = re.search(r'\d+', quantity.text) + + if match: + number = match.group() + kill.quarantine_weight_of_carcasses = int(number) + # if kill.quarantine_code_state is not None: + # kill.quarantine_code_state=None + else: + kill.quarantine_weight_of_carcasses = 0 + # for i in table[4:5]: + # rows = i.find_all('tr') + # + # pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + # style='font-family:Tahoma').text.strip() + # kill.inquiry_pelak=pelak_txt + # td=rows[1].find_all('td')[1] + # driver_txt = td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_driver=driver_txt + # + # for r in rows: + # tds = r.find_all('td', colspan="2") + # if len(tds) >= 2: + # origin_td = tds[0] + # origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_origin=origin_text + # + # destination_td = tds[1] + # destination_text = destination_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_destination=destination_text + + # else: + # for table in table: + # p_tags = table.find_all('p') + # for p in p_tags: + # p_text = p.get_text(strip=True) + # if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + # kill.quarantine_code_state = 'contradiction' + # if kill.quarantine_quantity is not None: + # kill.quarantine_quantity = None + kill.save() + + +def get_gid_out_province_manual(request): + kills = KillHouseFreeSaleBarInformation.objects.filter(quarantine_weight_of_carcasses=0, + clearance_code__isnull=False, trash=False) + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kills: + for kill in kills: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + # kill.quarantine_code_state = 'notconfirmed' + # if kill.quarantine_quantity is not None: + # kill.quarantine_weight_of_carcasses = None + pass + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + # kill.inquiry_date = date.date() + send_date = kill.date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[0:1]: + + quantity = r.find_all('td')[1] + match = re.search(r'\d+', quantity.text) + + if match: + number = match.group() + kill.quarantine_weight_of_carcasses = int(number) + # if kill.quarantine_code_state is not None: + # kill.quarantine_code_state=None + else: + kill.quarantine_weight_of_carcasses = 0 + # for i in table[4:5]: + # rows = i.find_all('tr') + # + # pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + # style='font-family:Tahoma').text.strip() + # kill.inquiry_pelak=pelak_txt + # td=rows[1].find_all('td')[1] + # driver_txt = td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_driver=driver_txt + # + # for r in rows: + # tds = r.find_all('td', colspan="2") + # if len(tds) >= 2: + # origin_td = tds[0] + # origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_origin=origin_text + # + # destination_td = tds[1] + # destination_text = destination_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_destination=destination_text + + # else: + # for table in table: + # p_tags = table.find_all('p') + # for p in p_tags: + # p_text = p.get_text(strip=True) + # if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + # kill.quarantine_code_state = 'contradiction' + # if kill.quarantine_quantity is not None: + # kill.quarantine_quantity = None + kill.save() + return HttpResponse(f'تعداد بار :{len(kills)}') + + +def get_gid_poultry_request(poultry_id): + kill = PoultryRequest.objects.filter(id=poultry_id, trash=False).first() + + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kill: + # if kill.quarantine_code_state!='merge': + data = {'gid': str(kill.quarantine_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + kill.quarantine_code_state = 'notconfirmed' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + # kill.inquiry_date = date.date() + send_date = kill.send_date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.quarantine_quantity = int(number) + # if kill.quarantine_code_state is not None: + # kill.quarantine_code_state=None + # for i in table[4:5]: + # rows = i.find_all('tr') + # + # pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + # style='font-family:Tahoma').text.strip() + # kill.inquiry_pelak=pelak_txt + # td=rows[1].find_all('td')[1] + # driver_txt = td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_driver=driver_txt + # + # for r in rows: + # tds = r.find_all('td', colspan="2") + # if len(tds) >= 2: + # origin_td = tds[0] + # origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_origin=origin_text + # + # destination_td = tds[1] + # destination_text = destination_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_destination=destination_text + else: + kill.quarantine_quantity = 0 + + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + # kill.quarantine_code_state = 'contradiction' + if kill.quarantine_quantity > 0: + kill.quarantine_quantity = 0 + kill.save() + + +def get_gid_poultry_request_quarantine_code(poultry_id): + kill = PoultryRequestQuarantineCode.objects.filter(id=poultry_id, trash=False).first() + + session = requests.Session() + session.mount('https://', SSLAdapter()) + if kill: + # if kill.quarantine_code_state!='merge': + data = {'gid': str(kill.quarantine_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + # kill.quarantine_code_state = 'notconfirmed' + # if kill.quarantine_quantity is not None: + # kill.quarantine_quantity = None + if kill.system_quarantine_quantity > 0: + kill.system_quarantine_quantity = 0 + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + # kill.inquiry_date = date.date() + send_date = kill.poultry_request.send_date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.system_quarantine_quantity = int(number) + # if kill.quarantine_code_state is not None: + # kill.quarantine_code_state=None + # for i in table[4:5]: + # rows = i.find_all('tr') + # + # pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + # style='font-family:Tahoma').text.strip() + # kill.inquiry_pelak=pelak_txt + # td=rows[1].find_all('td')[1] + # driver_txt = td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_driver=driver_txt + # + # for r in rows: + # tds = r.find_all('td', colspan="2") + # if len(tds) >= 2: + # origin_td = tds[0] + # origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_origin=origin_text + # + # destination_td = tds[1] + # destination_text = destination_td.find('span', class_='dynamictxt').text.strip() + # kill.inquiry_destination=destination_text + else: + kill.system_quarantine_quantity = 0 + + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + # kill.quarantine_code_state = 'contradiction' + if kill.system_quarantine_quantity > 0: + kill.system_quarantine_quantity = 0 + kill.save() + + +@api_view(["GET"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def dashboard_monitoring_view(request): + now = datetime.datetime.now().date() + yesterday = now - timedelta(days=1) + hatching = PoultryHatching.objects.filter( + state='pending', + archive=False, + allow_hatching='pending', + trash=False + ).only( + 'quantity', + 'killed_quantity', + 'left_over', + 'chicken_age', + 'poultry' + ).select_related('poultry') + + hatching_aggregates = hatching.aggregate( + total_quantity=Sum('quantity'), + total_killed_quantity=Sum('killed_quantity'), + total_left_over=Sum('left_over'), + total_left_over_between_40_75=Sum( + 'left_over', + filter=Q(chicken_age__range=(40, 75)) + ), + + # + total_left_over_lt_35=Sum( + 'left_over', + filter=Q(chicken_age__lt=35) + ), + total_left_over_between_35_40=Sum( + 'left_over', + filter=Q(chicken_age__range=(35, 39)) + ), + total_left_over_between_40_45=Sum( + 'left_over', + filter=Q(chicken_age__range=(40, 44)) + ), + total_left_over_between_45_50=Sum( + 'left_over', + filter=Q(chicken_age__range=(45, 49)) + ), + total_left_over_between_50_55=Sum( + 'left_over', + filter=Q(chicken_age__range=(50, 54)) + ), + total_left_over_between_55_60=Sum( + 'left_over', + filter=Q(chicken_age__range=(55, 59)) + ), + total_left_over_between_60_65=Sum( + 'left_over', + filter=Q(chicken_age__range=(60, 64)) + ), + total_left_over_between_65_70=Sum( + 'left_over', + filter=Q(chicken_age__range=(65, 70)) + ), + total_left_over_gt_70=Sum( + 'left_over', + filter=Q(chicken_age__gt=70) + ), + # + total_killing_ave_age=Avg('poultry__killing_ave_age') + ) + + kill_house_free_bar = KillHouseFreeBarInformation.objects.filter( + trash=False, + archive_wage=False, + date__date__gte=yesterday + ).only( + 'quantity', + 'live_weight', + 'number_of_carcasses', + 'weight_of_carcasses', + 'send_date', + 'type', + 'out' + ) + + kill_house_free_bar_aggregates = kill_house_free_bar.aggregate( + total_quantity_yesterday_live=Sum('quantity', filter=Q(create_date__date=yesterday, buy_type='live')), + total_weight_yesterday_live=Sum('live_weight', filter=Q(create_date__date=yesterday, buy_type='live')), + total_quantity_yesterday_carcass=Sum('number_of_carcasses', + filter=Q(date__date=yesterday, buy_type='carcass')), + total_weight_yesterday_carcass=Sum('weight_of_carcasses', filter=Q(date__date=yesterday, buy_type='carcass')), + + total_quantity_live=Sum('quantity', filter=Q(create_date__date=now, buy_type='live')), + total_weight_live=Sum('live_weight', filter=Q(create_date__date=now, buy_type='live')), + total_quantity_carcass=Sum('number_of_carcasses', + filter=Q(date__date=now, buy_type='carcass')), + total_weight_carcass=Sum('weight_of_carcasses', filter=Q(date__date=now, buy_type='carcass')), + warehouse_total_weight_carcass=Sum('weight_of_carcasses', filter=Q(date__date=now)), + # yesterday + total_quantity_live_yesterday=Sum('quantity', filter=Q(create_date__date=yesterday, buy_type='live')), + total_weight_live_yesterday=Sum('live_weight', filter=Q(create_date__date=yesterday, buy_type='live')), + total_quantity_carcass_yesterday=Sum('number_of_carcasses', + filter=Q(date__date=yesterday, buy_type='carcass')), + total_weight_carcass_yesterday=Sum('weight_of_carcasses', filter=Q(date__date=yesterday, buy_type='carcass')), + + ) + + poultry_request = PoultryRequest.objects.filter( + trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + temporary_trash=False, + temporary_deleted=False, + send_date__date__gte=yesterday + ).only( + 'quantity', + 'Index_weight', + 'send_date' + ) + + poultry_request_aggregates = poultry_request.aggregate( + total_quantity=Sum('quantity', filter=Q(send_date__date=now, direct_buying=False, out=False)), + total_weight=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=now, direct_buying=False, out=False)), + total_direct_buying_quantity=Sum('quantity', filter=Q(send_date__date=now, direct_buying=True)), + total_direct_buying_weight=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=now, direct_buying=True)), + total_quantity_out_yesterday=Sum('quantity', filter=Q(out=True, send_date__date=yesterday)), + poultry_out_province_quantity=Sum('quantity', filter=Q(out=True, send_date__date=now)), + poultry_out_province_weight=Sum(F('quantity') * F('Index_weight'), filter=Q(out=True, send_date__date=now)), + total_killing_ave_weight=Avg('Index_weight', filter=Q(send_date__date=now)), + # yesterday + total_quantity_yesterday=Sum('quantity', filter=Q(send_date__date=yesterday, direct_buying=False, out=False)), + total_weight_yesterday=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=yesterday, direct_buying=False, out=False)), + total_direct_buying_quantity_yesterday=Sum('quantity', filter=Q(send_date__date=yesterday, direct_buying=True)), + total_direct_buying_weight_yesterday=Sum(F('quantity') * F('Index_weight'), + filter=Q(send_date__date=yesterday, direct_buying=True)), + poultry_out_province_quantity_yesterday=Sum('quantity', filter=Q(out=True, send_date__date=yesterday)), + poultry_out_province_weight_yesterday=Sum(F('quantity') * F('Index_weight'), + filter=Q(out=True, send_date__date=yesterday)), + total_killing_ave_weight_yesterday=Avg('Index_weight', filter=Q(send_date__date=now)) + ) + + province_kill_request = ProvinceKillRequest.objects.filter( + trash=False, + archive_wage=False, + return_to_province=False, + state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=yesterday + ).only( + 'total_killed_quantity', + 'total_killed_weight', + 'kill_request__recive_date' + ) + + province_kill_request_aggregates = province_kill_request.aggregate( + total_quantity_yesterday=Sum('total_killed_quantity', filter=Q(kill_request__recive_date__date=yesterday)), + total_weight_yesterday=Sum('total_killed_weight', filter=Q(kill_request__recive_date__date=yesterday)), + total_quantity=Sum('total_killed_quantity', filter=Q(kill_request__recive_date__date=now)), + total_weight_carcass=Sum('total_killed_weight', filter=Q(kill_request__recive_date__date=now)) * 0.75, + province_kill_request_total_weight=Sum('total_killed_weight', filter=Q(kill_request__recive_date__date=now)), + province_kill_request_total_weight_yesterday=Sum('total_killed_weight', + filter=Q(kill_request__recive_date__date=yesterday)) + ) + + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=yesterday, + temporary_trash=False, + temporary_deleted=False + ).select_related('kill_request').only( + 'ware_house_accepted_real_weight', + 'weight_loss', + 'ware_house_confirmation', + 'kill_request__recive_date' + ) + + kill_house_request_aggregates = kill_house_request.aggregate( + total_real_weight=Sum( + 'ware_house_accepted_real_weight', + filter=Q( + kill_request__recive_date__date=yesterday, + ware_house_confirmation=True + ) + ), + total_weight_loss=Avg( + 'weight_loss', + filter=Q(kill_request__recive_date__date=yesterday) + ), + total_quantity=Sum( + 'accepted_real_quantity', + filter=Q(kill_request__recive_date__date=now) + ), + total_quantity_yesterday=Sum( + 'accepted_real_quantity', + filter=Q(kill_request__recive_date__date=yesterday) + ), + total_weight_yesterday=Sum( + 'accepted_real_weight', + filter=Q(kill_request__recive_date__date=yesterday) + ), + total_weight=Sum( + 'accepted_real_weight', + filter=Q(kill_request__recive_date__date=now) + ), + total_real_weight_yesterday=Sum( + 'ware_house_accepted_real_weight', + filter=Q( + kill_request__recive_date__date=yesterday, + ware_house_confirmation=True + ) + ) + ) + + kill_request = KillRequest.objects.filter( + recive_date__date=now, + trash=False, + poultry__isnull=True, + province_state='accepted' + ).only( + 'kill_capacity', + 'recive_date', + 'province_state' + ) + + kill_request_aggregates = kill_request.aggregate( + total_quantity=Sum('kill_capacity'), + ) + + if hatching_aggregates['total_left_over_between_40_75'] and poultry_request_aggregates['total_killing_ave_weight']: + weight_between_forty_seventy_five = int(hatching_aggregates['total_left_over_between_40_75'] * + poultry_request_aggregates['total_killing_ave_weight']) + else: + weight_between_forty_seventy_five = 0 + + enter_warehouse_weight = (kill_house_free_bar_aggregates['warehouse_total_weight_carcass'] or 0) + ( + kill_house_request_aggregates['total_real_weight_yesterday'] or 0) + roles_product = RolesProducts.objects.filter(trash=False) + + roles_product_aggregates = roles_product.aggregate( + total_remain_weight=Sum('total_remain_weight'), + total_out_province_allocated_weight=Sum('out_province_allocated_weight'), + ) + + cold_house = ColdHouse.objects.filter(trash=False).only( + 'total_remain_weight' + ) + + cold_house_aggregates = cold_house.aggregate( + total_freezing_weight=Sum('total_remain_weight') + ) + kill_house_free_sale_bar_aggregates = KillHouseFreeSaleBarInformation.objects.filter( + trash=False + ).aggregate( + total_real_weight_of_carcasses=Sum('real_weight_of_carcasses'), + total_real_weight_of_carcasses_now=Sum('real_weight_of_carcasses', filter=Q(date__date=now)) + ) + steward_allocation = StewardAllocation.objects.filter( + trash=False, + calculate_status=True, + temporary_trash=False, + temporary_deleted=False, + receiver_state__in=('accepted', 'pending') + ).exclude( + seller_type='ColdHouse' + ).only( + 'real_weight_of_carcasses', + 'date' + ) + + steward_allocation_aggregates = steward_allocation.aggregate( + total_real_weight_of_carcasses=Sum('real_weight_of_carcasses'), + total_real_weight_of_carcasses_now=Sum( + 'real_weight_of_carcasses', + filter=Q(date__date=now) + ), + ) + + chicken_price = ChickenCommissionPrices.objects.filter(trash=False, date__date__gte=now - timedelta(7)).order_by( + 'date') + ser_data = ChickenCommissionPricesForDashboardSerializer(chicken_price, many=True) + province_kill_request_weight = province_kill_request_aggregates['province_kill_request_total_weight'] or 0 + province_kill_request_total_weight_yesterday = province_kill_request_aggregates[ + 'province_kill_request_total_weight_yesterday'] or 0 + province_kill_request_weight_yesterday = province_kill_request_aggregates['total_weight_yesterday'] or 0 + bars_live_weight = kill_house_free_bar_aggregates['total_weight_live'] or 0 + total_weight_live_yesterday = kill_house_free_bar_aggregates['total_weight_live_yesterday'] or 0 + bars_carcasses_weight = kill_house_free_bar_aggregates['total_weight_carcass'] or 0 + total_weight_carcass_yesterday = kill_house_free_bar_aggregates['total_weight_carcass_yesterday'] or 0 + bars_yesterday_carcasses_weight = kill_house_free_bar_aggregates['total_weight_yesterday_carcass'] or 0 + bars_yesterday_live_weight = kill_house_free_bar_aggregates['total_weight_yesterday_live'] or 0 + total_loss_weight = int(((province_kill_request_weight + bars_live_weight) * 0.75) + bars_carcasses_weight) + total_loss_weight_yesterday = int(((province_kill_request_total_weight_yesterday + + total_weight_live_yesterday) * 0.75) + total_weight_carcass_yesterday) + total_yesterday_loss_weight = int(((province_kill_request_weight_yesterday + bars_yesterday_live_weight) + * 0.75) + bars_yesterday_carcasses_weight) + + result = { + 'hatching': { + 'quantity': hatching_aggregates['total_quantity'] or 0, + 'killedQuantity': hatching_aggregates['total_killed_quantity'] or 0, + 'leftOver': hatching_aggregates['total_left_over'] or 0, + 'leftOverBetweenFortySeventyFive': hatching_aggregates['total_left_over_between_40_75'] or 0, + 'killingAveAge': int(hatching_aggregates['total_killing_ave_age'] or 0), + 'total_left_over_lt_35': int(hatching_aggregates['total_left_over_lt_35'] or 0), + 'total_left_over_between_35_40': int(hatching_aggregates['total_left_over_between_35_40'] or 0), + 'total_left_over_between_40_45': int(hatching_aggregates['total_left_over_between_40_45'] or 0), + 'total_left_over_between_45_50': int(hatching_aggregates['total_left_over_between_45_50'] or 0), + 'total_left_over_between_50_55': int(hatching_aggregates['total_left_over_between_50_55'] or 0), + 'total_left_over_between_55_60': int(hatching_aggregates['total_left_over_between_55_60'] or 0), + 'total_left_over_between_60_65': int(hatching_aggregates['total_left_over_between_60_65'] or 0), + 'total_left_over_between_65_70': int(hatching_aggregates['total_left_over_between_65_70'] or 0), + 'total_left_over_gt_70': int(hatching_aggregates['total_left_over_gt_70'] or 0), + }, + 'yesterdayKilling': { + 'quantityKillHouseFreeBarLive': kill_house_free_bar_aggregates['total_quantity_yesterday_live'] or 0, + 'weightKillHouseFreeBarLive': kill_house_free_bar_aggregates['total_weight_yesterday_live'] or 0, + 'quantityKillHouseFreeBarCarcass': kill_house_free_bar_aggregates['total_quantity_yesterday_carcass'] or 0, + 'weightKillHouseFreeBarCarcass': kill_house_free_bar_aggregates['total_weight_yesterday_carcass'] or 0, + 'provinceKillRequestQuantity': province_kill_request_aggregates['total_quantity_yesterday'] or 0, + 'provinceKillRequestWeight': province_kill_request_aggregates['total_weight_yesterday'] or 0, + 'outQuantity': poultry_request_aggregates['total_quantity_out_yesterday'] or 0, + # 'weightOfCarcass': kill_house_request_aggregates['total_real_weight'] or 0, + # 'losses': round((kill_house_request_aggregates['total_weight_loss'] or 0),1), + 'weightOfCarcass': total_yesterday_loss_weight, + 'losses': 25, + + }, + 'killing': { + 'quantity': poultry_request_aggregates['total_quantity'] or 0, + 'total_weight': poultry_request_aggregates['total_weight'] or 0, + 'killRequestQuantity': poultry_request_aggregates['total_direct_buying_quantity'] or 0, + 'killRequestWeight': poultry_request_aggregates['total_direct_buying_weight'] or 0, + # 'killRequestQuantity': kill_request_aggregates['total_quantity'] or 0, + 'poultry_out_province_quantity': poultry_request_aggregates['poultry_out_province_quantity'] or 0, + 'poultry_out_province_weight': poultry_request_aggregates['poultry_out_province_weight'] or 0, + 'quantityKillHouseFreeBarLive': kill_house_free_bar_aggregates['total_quantity_live'] or 0, + 'WeightKillHouseFreeBarLive': kill_house_free_bar_aggregates['total_weight_live'] or 0, + 'quantityKillHouseFreeBarCarcass': kill_house_free_bar_aggregates['total_quantity_carcass'] or 0, + 'WeightKillHouseFreeBarCarcass': kill_house_free_bar_aggregates['total_weight_carcass'] or 0, + 'provinceKillRequestQuantity': province_kill_request_aggregates['total_quantity'] or 0, + 'provinceKillRequestWeightCarcass': int( + province_kill_request_aggregates['province_kill_request_total_weight'] or 0), + 'KillHouseRequestQuantity': kill_house_request_aggregates['total_quantity'] or 0, + 'KillHouseRequestWeight': kill_house_request_aggregates['total_weight'] or 0, + 'total_loss_weight': int(total_loss_weight), + + }, + 'killingYesterday': { + 'quantityYesterday': poultry_request_aggregates['total_quantity_yesterday'] or 0, + 'total_weightYesterday': poultry_request_aggregates['total_weight_yesterday'] or 0, + 'killRequestQuantityYesterday': poultry_request_aggregates['total_direct_buying_quantity_yesterday'] or 0, + 'killRequestWeightYesterday': poultry_request_aggregates['total_direct_buying_weight_yesterday'] or 0, + # 'killRequestQuantity': kill_request_aggregates['total_quantity'] or 0, + 'poultry_out_province_quantityYesterday': poultry_request_aggregates[ + 'poultry_out_province_quantity_yesterday'] or 0, + 'poultry_out_province_weightYesterday': poultry_request_aggregates[ + 'poultry_out_province_weight_yesterday'] or 0, + 'quantityKillHouseFreeBarLiveYesterday': kill_house_free_bar_aggregates[ + 'total_quantity_live_yesterday'] or 0, + 'WeightKillHouseFreeBarLiveYesterday': kill_house_free_bar_aggregates['total_weight_live_yesterday'] or 0, + 'quantityKillHouseFreeBarCarcassYesterday': kill_house_free_bar_aggregates[ + 'total_quantity_carcass_yesterday'] or 0, + 'WeightKillHouseFreeBarCarcassYesterday': kill_house_free_bar_aggregates[ + 'total_weight_carcass_yesterday'] or 0, + 'provinceKillRequestQuantityYesterday': province_kill_request_aggregates['total_quantity_yesterday'] or 0, + 'provinceKillRequestWeightCarcassYesterday': int( + province_kill_request_aggregates['province_kill_request_total_weight_yesterday'] or 0), + 'KillHouseRequestQuantityYesterday': kill_house_request_aggregates['total_quantity_yesterday'] or 0, + 'KillHouseRequestWeightYesterday': kill_house_request_aggregates['total_weight_yesterday'] or 0, + 'total_loss_weightYesterday': int(total_loss_weight_yesterday), + + }, + 'inventory': { + 'leftOverBetweenFortySeventyFive': hatching_aggregates['total_left_over_between_40_75'] or 0, + 'weightBetweenFortySeventyFive': weight_between_forty_seventy_five, + 'aveWeight': round((poultry_request_aggregates['total_killing_ave_weight'] or 0), 1), + 'carcassWeight': int(weight_between_forty_seventy_five * 0.75), + + }, + 'warehouseKillHouse': { + 'remainingChickenStock': roles_product_aggregates['total_remain_weight'] or 0, + 'remainingFreezingWeight': cold_house_aggregates['total_freezing_weight'] or 0, + 'outProvinceAllocatedWeight': kill_house_free_sale_bar_aggregates['total_real_weight_of_carcasses'] or 0, + 'allocationWeight': steward_allocation_aggregates['total_real_weight_of_carcasses'] or 0, + + }, + 'warehouseInformation': { + 'enterWarehouseWeight': enter_warehouse_weight, + 'outSellWeight': kill_house_free_sale_bar_aggregates['total_real_weight_of_carcasses_now'] or 0, + 'allocationWeight': steward_allocation_aggregates['total_real_weight_of_carcasses_now'] or 0, + 'leftOverWarehouseWeight': roles_product_aggregates['total_remain_weight'] or 0, + + }, + 'chickenPrice': ser_data.data + } + return Response(result, status=status.HTTP_200_OK) + + +def remove_access_token_manual(request): + ARTA_remove_access_token = "https://userbackend.rasadyar.com/api/remove_access_token/" + requests.get( + url=ARTA_remove_access_token, + verify=False + ) + now = datetime.datetime.now() + accesses = AccessToken.objects.filter(created__date__gte=now.date() - timedelta(days=3)) + for access in accesses: + access.expires = now - timedelta(days=2) + access.save() + return HttpResponse('ok') + + +def find_gid_code_manual(request): + kill_house_request = KillHouseRequest.objects.filter(trash=False, clearance_code__isnull=False, + quarantine_quantity__isnull=True).only( + 'quarantine_code_state', 'clearance_code', 'quarantine_quantity' + ).order_by('-id') + session = requests.Session() + session.mount('https://', SSLAdapter()) + + for kill in kill_house_request: + if kill.quarantine_code_state != 'merge': + if kill.clearance_code is None: + kill.quarantine_code_state = 'noclearance' + else: + data = {'gid': str(kill.clearance_code)} + m = session.post('https://e.ivo.ir/Rahgiri/Gidprnt.aspx', data=data, verify=False, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36'}) + context = BeautifulSoup(m.text, 'html.parser') + text = context.body.get_text(strip=True) + if text == 'فرآورده هاي خام داميGo Backفهرستخروجتاییده راهداری دریافت نشد به بخش اعلام خاتمه صدور گواهی بهداشتی حمل درهمین سایت مراجعه کنید.': + kill.quarantine_code_state = 'notconfirmed' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + else: + table = context.find_all('table') + if table[5:6]: + row = context.find('div', align="right") + if row: + content = row.get_text(separator=" ", strip=True) + date_match = re.search(r'تاريخ:(\d{4}/\d{2}/\d{2})', content) + + if date_match: + jalali_date = date_match.group(1) + year, month, day = map(int, jalali_date.split('/')) + date = convert_to_miladi(year=year, month=month, day=day) + kill.inquiry_date = date.date() + send_date = kill.kill_request.recive_date.date() + + one_day = timedelta(days=1) + if abs(send_date - date.date()) <= one_day: + for i in table[5:6]: + row = i.find_all('tr') + for r in row[1:2]: + quantity = r.find('td') + match = re.search(r'\d+', quantity.text) + if match: + number = match.group() + kill.quarantine_quantity = int(number) + if kill.quarantine_code_state is not None: + kill.quarantine_code_state = None + for i in table[4:5]: + rows = i.find_all('tr') + + pelak_txt = rows[1].find('span', class_='dynamictxt', dir='ltr', + style='font-family:Tahoma').text.strip() + kill.inquiry_pelak = pelak_txt + td = rows[1].find_all('td')[1] + driver_txt = td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_driver = driver_txt + + for r in rows: + tds = r.find_all('td', colspan="2") + if len(tds) >= 2: + origin_td = tds[0] + origin_text = origin_td.find('span', class_='dynamictxt').text.strip() + kill.inquiry_origin = origin_text + + destination_td = tds[1] + destination_text = destination_td.find('span', + class_='dynamictxt').text.strip() + kill.inquiry_destination = destination_text + else: + kill.quarantine_code_state = 'contradiction' + kill.quarantine_quantity = None + + else: + for table in table: + p_tags = table.find_all('p') + for p in p_tags: + p_text = p.get_text(strip=True) + if p_text == 'شماره رهگيري وارد شده معتبر نيست.': + kill.quarantine_code_state = 'contradiction' + if kill.quarantine_quantity is not None: + kill.quarantine_quantity = None + kill.save() + return HttpResponse('ok') + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_all_pos_transaction(request): + filters = {} + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + price_type = request.GET.get('price_type') + paid = request.GET.get('paid') + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا مجدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + + pos = POSMachine.objects.get(pos_id=validation_device) + filters['trash'] = False + filters['pos'] = pos + + if date1 and date2: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filters['date__date__gte'] = date1 + filters['date__date__lte'] = date2 + + if price_type: + filters['price_type__in'] = price_type.split(',') + + if paid: + filters['paid'] = True if paid == 'true' else False + + transactions = PosMachineTransactions.objects.filter(**filters).only('price', 'price_type').order_by('-date') + product_transactions = ProductsTransactions.objects.filter(trash=False, transaction__in=transactions).only \ + ('price', 'cur_weight', 'targetunit', 'image') + + transactions_aggregate = transactions.aggregate( + total_price=Sum('price'), + total_price_cash=Sum('price', filter=Q(price_type='cash')), + total_price_credit=Sum('price', filter=Q(price_type='credit')), + total_price_card=Sum('price', filter=Q(price_type='card')), + ) + + product_groups = defaultdict(lambda: {'price': 0, 'weight': 0, 'targetunit': None, 'image': None}) + + for pt in product_transactions: + product_groups[pt.name]['price'] += pt.price + product_groups[pt.name]['weight'] += pt.cur_weight + if not product_groups[pt.name]['targetunit']: + product_groups[pt.name]['targetunit'] = pt.targetunit + if not product_groups[pt.name]['image']: + product_groups[pt.name]['image'] = pt.image + + unique_products = [{ + 'name': name, + 'price': data['price'], + 'weight': data['weight'], + 'targetunit': data['targetunit'], + 'image': data['image'] + } for name, data in product_groups.items()] + + result_dict = { + 'count': transactions.count(), + 'total_price': transactions_aggregate['total_price'] or 0, + 'total_price_cash': transactions_aggregate['total_price_cash'] or 0, + 'total_price_credit': transactions_aggregate['total_price_credit'] or 0, + 'total_price_card': transactions_aggregate['total_price_card'] or 0, + 'products': unique_products + } + + return Response(result_dict) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def send_clearance_code_to_rsi(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else None + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + temporary_trash=False, + temporary_deleted=False, + clearance_code__isnull=False + ).values_list('clearance_code', flat=True).distinct() + + kill_house_free_sale = PoultryRequest.objects.filter(trash=False, quarantine_code__isnull=False, out=True) \ + .values_list('quarantine_code', flat=True).distinct() + + result = list(kill_house_request) + list(kill_house_free_sale) + + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar/?province={base_url_for_sms_report}' + f'&date1={date1}&date2={date2}', + json=result, + headers={'Content-Type': 'application/json'} + ) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + sheet_list = [ + 'بار های داخل استان', + 'بار های خارج استان' + ] + + for sheet_name in sheet_list: + + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'بار های داخل استان': + + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد مرغداران', + 'تعداد کشتارگاه ها', + 'حجم کشتار', + + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + value_header_list = [ + + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'تاریخ کشتار', + 'مرغدار', + 'شناسه یکتا مرغدار', + 'شماره مجوز جوجه ریزی', + 'شماره موبایل مرغدار', + 'شهر مرغدار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد قرنطینه', + 'کشتارگاه', + 'شناسه یکتا کشتارگاه', + 'استان', + 'شهر', + 'حجم کشتار', + 'سن کشتار', + + ] + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + unique_poultry_out_false = set() + unique_slaughterhouses_out_false = set() + total_slaughter_out_false = 0 + excel_description(worksheet, 'A1', f'بارهای داخل استان', color='red', + row2='B1') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='C3') + for data in response.json(): + if data['Out'] == False: + vet_farm_mobile = '' + vet_farm_name = '' + vet_farm = VetFarm.objects.filter(trash=False, + poultry__breeding_unique_id=data['hatching']['poultry'][ + 'PartIdCode']).first() + if vet_farm: + vet_farm_mobile = vet_farm.vet.user.mobile + vet_farm_name = vet_farm.vet.user.fullname + unique_poultry_out_false.add(data['hatching']['poultry']['UnitName']) + unique_slaughterhouses_out_false.add(data['DesUnitName']) + total_slaughter_out_false += data['GoodAmount'] + date_str = str(data['Date']).split('T')[0] # جدا کردن بخش تاریخ + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + list1 = [ + m, + str(shamsi_date(date, in_value=True)), + data['hatching']['poultry']['UnitName'], + data['hatching']['poultry']['PartIdCode'], + data['hatching']['RequestCode'], + data['hatching']['poultry']['Mobile'], + data['hatching']['poultry']['City'], + vet_farm_name, + vet_farm_mobile, + data['TrackingCode'], + data['DesUnitName'], + data['DesPartIdCode'], + data['Province'], + data['City'], + data['GoodAmount'], + data['Age'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + value_header_list = [ + len(unique_poultry_out_false), + len(unique_slaughterhouses_out_false), + total_slaughter_out_false + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + quantity = sum( + data['GoodAmount'] for data in response.json() if data['Out'] == False) or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + + ] + + create_value(worksheet, list2, l + 1, 1, color='green') + else: + unique_poultry_out_false = set() + unique_slaughterhouses_out_false = set() + total_slaughter_out_false = 0 + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد مرغداران', + 'تعداد کشتارگاه ها', + 'حجم کشتار', + + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + excel_options = [ + 'ردیف', + 'تاریخ کشتار', + 'مرغدار', + 'شناسه یکتا مرغدار', + 'شماره مجوز جوجه ریزی', + 'شماره موبایل مرغدار', + 'شهر مرغدار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد قرنطینه', + 'کشتارگاه', + 'شناسه یکتا کشتارگاه', + 'استان', + 'شهر', + 'حجم کشتار', + 'سن کشتار', + + ] + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + unique_poultry = set() + unique_slaughterhouses = set() + total_slaughter = 0 + excel_description(worksheet, 'A1', f'بارهای خارج استان', color='red', + row2='B1') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='C3') + for data in response.json(): + if data['Out'] == True: + vet_farm_mobile = '' + vet_farm_name = '' + vet_farm = VetFarm.objects.filter(trash=False, + poultry__breeding_unique_id=data['hatching']['poultry'][ + 'PartIdCode']).first() + if vet_farm: + vet_farm_mobile = vet_farm.vet.user.mobile + vet_farm_name = vet_farm.vet.user.fullname + + unique_poultry_out_false.add(data['hatching']['poultry']['UnitName']) + unique_slaughterhouses_out_false.add(data['DesUnitName']) + total_slaughter_out_false += data['GoodAmount'] + date_str = str(data['Date']).split('T')[0] # جدا کردن بخش تاریخ + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + list1 = [ + m, + str(shamsi_date(date, in_value=True)), + data['hatching']['poultry']['UnitName'], + data['hatching']['poultry']['PartIdCode'], + data['hatching']['RequestCode'], + data['hatching']['poultry']['Mobile'], + data['hatching']['poultry']['City'], + vet_farm_mobile, + vet_farm_name, + data['TrackingCode'], + data['DesUnitName'], + data['DesPartIdCode'], + data['Province'], + data['City'], + data['GoodAmount'], + data['Age'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + value_header_list = [ + len(unique_poultry_out_false), + len(unique_slaughterhouses_out_false), + total_slaughter_out_false + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + quantity = sum( + data['GoodAmount'] for data in response.json() if data['Out'] == False) or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + + ] + + create_value(worksheet, list2, l + 1, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="اختلاف قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def api_send_clearance_code_to_rsi(request): + page = '' + search_filter = '' + province = f'province={base_url_for_sms_report}' + search = request.GET.get('search') + value = request.GET.get('value') + if search: + if search != 'undefined' and value.strip(): + search_filter = f'&search={search}&value={value}' + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else None + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + temporary_trash=False, + temporary_deleted=False, + clearance_code__isnull=False + ).values_list('clearance_code', flat=True).distinct() + + kill_house_free_sale = PoultryRequest.objects.filter(trash=False, quarantine_code__isnull=False, out=True) \ + .values_list('quarantine_code', flat=True).distinct() + + result = list(kill_house_request) + list(kill_house_free_sale) + if 'page' in request.GET: + page = f'&page={request.GET["page"]}&page_size={request.GET["page_size"]}' + + response = requests.get( + f'https://rsibackend.rasadyar.com/app/api_send_different_bar/?{province}{page}' + f'{search_filter}' + f'&date1={date1}&date2={date2}', + json=result, + headers={'Content-Type': 'application/json'} + ) + + return Response(response.json(), status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def create_steward_allocation_from_excel(request): + file = request.FILES['file'].read() + read = openpyxl.load_workbook(BytesIO(file), data_only=True) + sheet = read.active + result_list = [] + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 1: + continue + + mobile = row[3] + kill_house_name = row[4] + allocation_type = row[5] + date = row[6] + sell_type = row[7] + seller_type = 'KillHouse' + type = 'manual' + weight_of_carcasses = row[8] + amount = row[9] + + buyer_type = 'Steward' if allocation_type == 'مباشر' else 'Guild' + try: + miladi_date = date.split('/') + new_date = convert_to_miladi( + year=int(miladi_date[0]), + month=int(miladi_date[1]), + day=int(miladi_date[2]) + ) + kill_house = KillHouse.objects.filter(name=kill_house_name, trash=False).first() + user = SystemUserProfile.objects.filter(trash=False, mobile=mobile).first() + if user: + to_steward = None + to_guild = None + if buyer_type == 'Steward': + to_steward = Guilds.objects.get(user=user, trash=False) + else: + to_guild = Guilds.objects.get(user=user, trash=False) + product = RolesProducts.objects.get(kill_house=kill_house) + steward_allocation = StewardAllocation( + date=new_date, + real_weight_of_carcasses=weight_of_carcasses, + weight_of_carcasses=weight_of_carcasses, + product=product, + kill_house=kill_house, + seller_type=seller_type, + allocation_type='killhouse_guild' if allocation_type == 'صنف' else 'killhouse_steward', + sell_type='exclusive' if sell_type == 'اختصاصی' else 'free', + type=type, + amount=amount, + total_amount=int(amount * weight_of_carcasses), + ) + if buyer_type == 'Steward': + steward_allocation.to_steward = to_steward + else: + steward_allocation.to_guilds = to_guild + steward_allocation.save() + kill_house_allocations_product_warehousing(product) + except: + result_list.append(mobile) + return Response(result_list) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def send_bar_info_from_ticket(request): + user = SystemUserProfile.objects.get(trash=False, key=request.GET['key']) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + kill_house_request = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False) + if kill_house_request: + message = 'با سلام و احترام' \ + '***' \ + 'بدینوسیله گزارش اسناد بارهای کشتارگاه ها از مورخه {0} تا {1} به شرح زیر بحضور ایفاد میگردد:' \ + '***' \ + '***'.format(shamsi_date(date1), shamsi_date(date2)) + else: + message = 'با سلام و احترام' \ + '***' \ + ' از مورخه {0} تا {1} باری وجود ندارد.' \ + '***' \ + '***'.format(shamsi_date(date1), shamsi_date(date2)) + m = 1 + for kill_house in kill_houses: + kill_house_request1 = kill_house_request.filter(trash=False, killhouse_user=kill_house, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, temporary_deleted=False) + bar_count = kill_house_request1.count() + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True').count() + bar_document_status = kill_house_request1.filter(bar_document_status__isnull=False).count() + bar_document_status_titles = kill_house_request1.values_list('bar_document_status__title', flat=True) + bars_info = [] + if (None not in bar_document_status_titles and bar_document_status_titles) or (bar_assigment_pending_count != 0) \ + or (bar_assigment_true_count > 0): + message += '{0}) {1} :' \ + 'تعداد {2} بار ایجاد شده است.***'.format(m, kill_house.name, to_locale_str(bar_count)) + if bar_assigment_pending_count > 0 or bar_assigment_true_count > 0: + message += '📑 {1} بار دارای سند(بارنامه) و تعداد {0} بار فاقد سند(بارنامه) میباشد.*** '. \ + format(to_locale_str(bar_assigment_pending_count), to_locale_str(bar_assigment_true_count)) + if bar_document_status > 0: + message += '🌐 از بارهای دارای سند تعداد {0} بار توسط ربات هوش مصنوعی سامانه مورد بررسی قرار گرفت که به شرح زیر میباشد: '. \ + format(to_locale_str(bar_document_status)) + status_counts = Counter(bar_document_status_titles) + for title, count in status_counts.items(): + if title: + bars_info.append( + '***' \ + '🚛 {0} بار شامل سند ({1})'.format(to_locale_str(count), title)) + + if bars_info: + message += '.'.join(bars_info) + + message += '***' \ + '-------------------------------------------------------' \ + '***' \ + '***' + m += 1 + + new_ticket = TicketSupport( + user=user, + title="استعلام اسناد بارها از مورخه {0} تا {1}".format(shamsi_date(date1), shamsi_date(date2)), + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(user) + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return Response({'result': 'با موفقیت انجام شد.'}, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def all_clearance_code_to_rsi(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else None + # kill_house_request = KillHouseRequest.objects.filter( + # trash=False, + # temporary_trash=False, + # temporary_deleted=False, + # clearance_code__isnull=False + # ).values_list('clearance_code', flat=True).distinct() + # + # kill_house_free_sale = PoultryRequest.objects.filter(trash=False, quarantine_code__isnull=False, out=True) \ + # .values_list('quarantine_code', flat=True).distinct() + + result = [] + + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar/?province={base_url_for_sms_report}' + f'&date1={date1}&date2={date2}', + json=result, + headers={'Content-Type': 'application/json'} + ) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + sheet_list = [ + 'بار های داخل استان', + 'بار های خارج استان' + ] + + for sheet_name in sheet_list: + + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'بار های داخل استان': + + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد مرغداران', + 'تعداد کشتارگاه ها', + 'حجم کشتار', + + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + value_header_list = [ + + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + + excel_options = [ + 'ردیف', + 'تاریخ کشتار', + 'مرغدار', + 'شناسه یکتا مرغدار', + 'شماره مجوز جوجه ریزی', + 'شماره موبایل مرغدار', + 'شهر مرغدار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد قرنطینه', + 'وضعیت بار', + 'کشتارگاه', + 'شناسه یکتا کشتارگاه', + 'استان', + 'شهر', + 'حجم کشتار', + 'سن کشتار', + + ] + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + unique_poultry_out_false = set() + unique_slaughterhouses_out_false = set() + total_slaughter_out_false = 0 + excel_description(worksheet, 'A1', f'بارهای داخل استان', color='red', + row2='B1') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='C3') + for data in response.json(): + if data['Out'] == False: + vet_farm_mobile = '' + vet_farm_name = '' + vet_farm = VetFarm.objects.filter(trash=False, + poultry__breeding_unique_id=data['hatching']['poultry'][ + 'PartIdCode']).first() + if vet_farm: + vet_farm_mobile = vet_farm.vet.user.mobile + vet_farm_name = vet_farm.vet.user.fullname + unique_poultry_out_false.add(data['hatching']['poultry']['UnitName']) + unique_slaughterhouses_out_false.add(data['DesUnitName']) + total_slaughter_out_false += data['GoodAmount'] + date_str = str(data['Date']).split('T')[0] # جدا کردن بخش تاریخ + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + list1 = [ + m, + str(shamsi_date(date, in_value=True)), + data['hatching']['poultry']['UnitName'], + data['hatching']['poultry']['PartIdCode'], + data['hatching']['RequestCode'], + data['hatching']['poultry']['Mobile'], + data['hatching']['poultry']['City'], + vet_farm_name, + vet_farm_mobile, + data['TrackingCode'], + data['TrackingStatusDescription'], + data['DesUnitName'], + data['DesPartIdCode'], + data['Province'], + data['City'], + data['GoodAmount'], + data['Age'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + value_header_list = [ + len(unique_poultry_out_false), + len(unique_slaughterhouses_out_false), + total_slaughter_out_false + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + quantity = sum( + data['GoodAmount'] for data in response.json() if data['Out'] == False) or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + + ] + + create_value(worksheet, list2, l + 1, 1, color='green') + else: + unique_poultry_out_false = set() + unique_slaughterhouses_out_false = set() + total_slaughter_out_false = 0 + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد مرغداران', + 'تعداد کشتارگاه ها', + 'حجم کشتار', + + ] + create_header(worksheet, header_list, 4, 2, height=25, width=25, border_style='thin', color='C00000') + + excel_options = [ + 'ردیف', + 'تاریخ کشتار', + 'مرغدار', + 'شناسه یکتا مرغدار', + 'شماره مجوز جوجه ریزی', + 'شماره موبایل مرغدار', + 'شهر مرغدار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد قرنطینه', + 'وضعیت بار', + 'کشتارگاه', + 'شناسه یکتا کشتارگاه', + 'استان', + 'شهر', + 'حجم کشتار', + 'سن کشتار', + + ] + + m = 1 + + create_header_freez(worksheet, excel_options, 1, 6, 7, 20) + + l = 7 + unique_poultry = set() + unique_slaughterhouses = set() + total_slaughter = 0 + excel_description(worksheet, 'A1', f'بارهای خارج استان', color='red', + row2='B1') + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() + from_date1 = shamsi_date(date1) + from_date2 = shamsi_date(date2) + excel_description(worksheet, 'A3', f'از تاریخ {from_date1} تا {from_date2}', color='red', row2='C3') + for data in response.json(): + if data['Out'] == True: + vet_farm_mobile = '' + vet_farm_name = '' + vet_farm = VetFarm.objects.filter(trash=False, + poultry__breeding_unique_id=data['hatching']['poultry'][ + 'PartIdCode']).first() + if vet_farm: + vet_farm_mobile = vet_farm.vet.user.mobile + vet_farm_name = vet_farm.vet.user.fullname + + unique_poultry_out_false.add(data['hatching']['poultry']['UnitName']) + unique_slaughterhouses_out_false.add(data['DesUnitName']) + total_slaughter_out_false += data['GoodAmount'] + date_str = str(data['Date']).split('T')[0] # جدا کردن بخش تاریخ + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + list1 = [ + m, + str(shamsi_date(date, in_value=True)), + data['hatching']['poultry']['UnitName'], + data['hatching']['poultry']['PartIdCode'], + data['hatching']['RequestCode'], + data['hatching']['poultry']['Mobile'], + data['hatching']['poultry']['City'], + vet_farm_mobile, + vet_farm_name, + data['TrackingCode'], + data['TrackingStatusDescription'], + data['DesUnitName'], + data['DesPartIdCode'], + data['Province'], + data['City'], + data['GoodAmount'], + data['Age'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin', height=35) + + l += 1 + m += 1 + value_header_list = [ + len(unique_poultry_out_false), + len(unique_slaughterhouses_out_false), + total_slaughter_out_false + ] + create_value(worksheet, value_header_list, 3, 4, border_style='thin') + quantity = sum( + data['GoodAmount'] for data in response.json() if data['Out'] == False) or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + + ] + + create_value(worksheet, list2, l + 1, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کلی بار ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def ticket_different_clearance_code_from_rsi(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else None + poultry_hatchings_licence_numbers = PoultryHatching.objects.filter(trash=False, + licence_number=request.GET.get('licence_number')) + + for poultry_hatching in poultry_hatchings_licence_numbers: + poultry_hatching_licence_number = poultry_hatching.licence_number + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar_with_licence_number/?' + f'licence_number={poultry_hatching_licence_number}' + f'&date1={date1}&date2={date2}', + headers={'Content-Type': 'application/json'} + ) + kill_house_request = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__licence_number + =poultry_hatching_licence_number, + temporary_trash=False, + temporary_deleted=False).order_by( + '-kill_request__recive_date') + if date1: + kill_house_request.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2) + vet_farm = VetFarm.objects.filter(trash=False, poultry=poultry_hatching.poultry).first() + code_rasadyar = [] + + all_quantity_in_rsi = 0 + for i in response.json(): + all_quantity_in_rsi += i['GoodAmount'] + bars_info = [] + for kill_req in kill_house_request: + if kill_req.clearance_code: + quarantine_code = kill_req.clearance_code + code_rasadyar.append(quarantine_code) + + else: + quarantine_code = 'ندارد' + bars_info.append( + 'کد قرنطینه: {0} - حجم: {1} قطعه - مقصد بار: {2} - تاریخ بار: ({3})'.format( + quarantine_code, + to_locale_str(int(kill_req.accepted_real_quantity)), + kill_req.killhouse_user.name, + shamsi_date(kill_req.kill_request.recive_date) + )) + poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + hatching=poultry_hatching).order_by( + '-send_date' + ) + # code_rsi=[data['TrackingCode'] for data in response.json()] + bars_info_rsi = [] + rsi_quantity = 0 + for poultry_request in poultry_requests: + if poultry_request.quarantine_code: + quarantine_code = poultry_request.quarantine_code + code_rasadyar.append(quarantine_code) + + else: + quarantine_code = 'ندارد' + bars_info.append( + 'کد قرنطینه: {0} - حجم: {1} قطعه - مقصد بار: {2} - تاریخ بار: ({3})'.format( + quarantine_code, + to_locale_str(int(poultry_request.quantity)), + poultry_request.buyer_fullname, + shamsi_date(poultry_request.send_date), + )) + chain_allocations = ChainAllocation.objects.filter(trash=False, poultry_hatching=poultry_hatching).order_by( + '-date') + for poultry_request in chain_allocations: + if poultry_request.quarantine_code: + quarantine_code = poultry_request.quarantine_code + code_rasadyar.append(quarantine_code) + else: + quarantine_code = 'ندارد' + bars_info.append( + 'کد قرنطینه: {0} - حجم: {1} قطعه - مقصد بار: {2} - تاریخ بار: ({3})'.format( + quarantine_code, + to_locale_str(int(poultry_request.quantity)), + poultry_request.buyer_name, + shamsi_date(poultry_request.date), + )) + for bar in response.json(): + rsi_quantity += bar['GoodAmount'] + date_str = str(bar['Date']).split('T')[0] + date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date() + state = '✅' if bar['TrackingCode'] in code_rasadyar else '❌' + bars_info_rsi.append( + 'کد قرنطینه: {0} - حجم: {1} قطعه - مقصد بار: {2} - تاریخ بار: ({3}){4}'.format( + bar['TrackingCode'], + to_locale_str(int(bar['GoodAmount'])), + bar['DesUnitName'], + shamsi_date(date), + state + )) + + bars_details = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info)]) + bars_details_rsi = "***".join([f"{i + 1}. {info}" for i, info in enumerate(bars_info_rsi)]) + accepted_real_quantity = 0 + accepted_real_quantity += kill_house_request.aggregate( + total_quantity=Sum('accepted_real_quantity')).get('total_quantity') or 0 + accepted_real_quantity += chain_allocations.aggregate( + total_quantity=Sum('quantity')).get('total_quantity') or 0 + accepted_real_quantity += poultry_requests.aggregate( + total_quantity=Sum('quantity')).get('total_quantity') or 0 + if rsi_quantity - accepted_real_quantity > 0: + new_message = 'در مجموع شما {0} قطعه بدون مجوز کشتار در سامانه قرنطینه ثبت کرده اید.' \ + '***' \ + 'در صورت تکرار و عدم رعایت موضوع و ضوابط اجرایی در استان،مراتب و گزارش تخلف به مراجع مسئول ارجاع میگردد.' \ + '***' \ + '***' \ + .format(to_locale_str(int(rsi_quantity - accepted_real_quantity))) + new_message1 = 'خارج از سامانه مجوز حمل' + else: + new_message = '' + new_message1 = 'اطلاعات زیر' + message = " دامپزشک محترم فارم {0}({9})" \ + "***" \ + "با سلام" \ + "***" \ + "با توجه بررسی های انجام شده" \ + " و استعلامات از پایش کشوری سامانه" \ + " رصد یار برای فارم {1} با شناسه یکتا {10} و شماره مجوز جوجه ریزی {11} {12} صادر گردیده است." \ + "***" \ + "***" \ + "اطلاعات مجوز صادر شده در قرنطینه:" \ + "***" \ + "{2}" \ + "***" \ + "جمعا {3} بار با مجموع {4} قطعه" \ + "***" \ + "***" \ + "اطلاعات مجوز صادر شده در رصدیار : " \ + "***" \ + "{5}" \ + "***" \ + "جمعا {6} بار با مجموع {7} قطعه" \ + "***" \ + "***" \ + "{8}" \ + "ربات هوشمند سامانه رصدیار" \ + "".format(vet_farm.vet.user.fullname, poultry_hatching.poultry.unit_name, bars_details_rsi, + len(response.json()), + to_locale_str(int(rsi_quantity)), + bars_details, + len(kill_house_request), to_locale_str(int(accepted_real_quantity)), + new_message, vet_farm.vet.user.mobile, + poultry_hatching.poultry.breeding_unique_id, poultry_hatching.licence_number, new_message1) + + user = SystemUserProfile.objects.filter(trash=False, mobile=request.GET['mobile']).last() + new_ticket = TicketSupport( + user=user, + title="گزارش کشتار جوجه ریزی", + status='open', + read_only=True, + type_ticket='single', + parent=None, + last_message='Admin', + ) + new_ticket.save() + new_ticket.to_user.add(user) + msg = MessageSupport( + ticket=new_ticket, + message=message, + created_by=user, + sender='Admin' + ) + msg.save() + return Response('ok', status=status.HTTP_200_OK) + + +def delete_kill_req_cron(): + current_time = datetime.datetime.now() + kill_requests = KillRequest.objects.filter(Q(market_final_accept=True, market_code_status=True, + input_market_code__isnull=True) | Q(market_final_accept=False), + trash=False, + market=True, + market_state='pending', + market_expire_date_time__lt=current_time + ).select_related('poultry_request') + for kill_request in kill_requests: + kill_request.trash = True + kill_request.market_state_message = { + "fullname": "سیستمی", + "mobile": "سیستمی", + "date": str(datetime.datetime.now()) + } + kill_request.market_state = 'deleted' + kill_request.save() + market_poultry_request_remain_quantity(kill_request.poultry_request) + + +def delete_steward_allocation_cron(): + current_time = datetime.datetime.now().date() + # allow=AllowRegisterCodeForStewardAllocation.objects.filter(trash=False,active=True).first() + # if allow: + steward_allocation = StewardAllocation.objects.filter(trash=False, + date__date=current_time, + receiver_state='pending', + active_expire_date_time=True, + logged_registration_code__isnull=True, + kill_house__isnull=False, + return_trash=False).order_by('id') + for allocation in steward_allocation: + product = allocation.product + seller_type = allocation.seller_type + to_cold_house = allocation.to_cold_house + other_cold_house = allocation.other_cold_house if allocation.other_cold_house else None + allocation.trash = True + allocation.save() + if seller_type == 'KillHouse': + kill_house_allocations_product_warehousing(product) + if to_cold_house and to_cold_house.kill_house == product.kill_house: + kill_house_cold_house_allocations(to_cold_house) + + elif seller_type == 'ColdHouse': + cold_house_warehousing(to_cold_house) + if other_cold_house: + cold_house_warehousing(other_cold_house) + + else: + guild_steward_allocations_product_warehousing(product) + + +def archive_kill_house_remain_limitation_weight_cron(): + production_date = (datetime.datetime.now() - datetime.timedelta(days=3)).date() + archive_date = (datetime.datetime.now() - datetime.timedelta(days=3)) + kill_houses = KillHouse.objects.filter(trash=False, out_province=False) + for kill_house in kill_houses: + kill_house_requests = KillHouseRequest.objects.filter(input_warehouse=kill_house, + province_request__poultry_request__free_sale_in_province=False, + kill_request__recive_date__date=production_date, + ware_house_confirmation=True, trash=False, + calculate_status=True, warehouse=True) + + kill_house_allocations = StewardAllocation.objects.filter( + kill_house=kill_house, trash=False, calculate_status=True, warehouse=True, system_registration_code=True, + receiver_state__in=('pending', 'accepted'), production_date__date=production_date, quota='governmental') + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter(kill_house=kill_house, + quota='governmental', + production_date__date=production_date, + trash=False, + calculate_status=True, + warehouse=True) + segmentations = PosSegmentation.objects.filter(kill_house=kill_house, production_date__date=production_date, + trash=False, warehouse=True, + quota='governmental') + + kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + kill_house_allocations_weight = \ + kill_house_allocations.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + kill_house_free_sale_bars_weight = kill_house_free_sale_bars.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] or 0 + + segmentation_weight = \ + segmentations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + archives = WarehouseArchive.objects.filter(kill_house=kill_house, date__date=production_date, + quota='governmental', + trash=False) + + archives_governmental_weight = \ + archives.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + total_input = kill_house_requests_weight + total_output = kill_house_allocations_weight + kill_house_free_sale_bars_weight + segmentation_weight + archives_governmental_weight + total_remain = total_input - total_output + + if total_remain > 0: + if kill_house.ware_house_remaining_weight_archive_percent > 0: + percent_limitation_weight = total_input * (kill_house.ware_house_remaining_weight_archive_percent / 100) + if percent_limitation_weight >= total_remain: + archive = WarehouseArchive( + kill_house=kill_house, + date=archive_date, + quota='governmental', + weight=total_remain, + registerer='سیستم', + registerer_mobile='سیستم', + registerer_role='سیستم', + description='مانده کمتر از استاندارد تعیین شده', + ) + archive.save() + kill_house_archive_warehousing(archive.kill_house) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def hatching_unknown(request): + age_range = ChickenAgeRange.objects.filter(active=True, trash=False).first() + if age_range: + hatchings = PoultryHatching.objects.filter( + state='pending', + archive=False, + allow_hatching='pending', + trash=False, + unknown=False, + chicken_age__gt=age_range.maximum + ) + poultries = Poultry.objects.filter(id__in=hatchings.values_list('poultry__id', flat=True)).update( + order_limit=True) + hatchings.update(unknown=True) + + return Response("done!") + + +def hatching_unknown_cron(): + age_range = ChickenAgeRange.objects.filter(active=True, trash=False).first() + if age_range: + hatchings = PoultryHatching.objects.filter( + state='pending', + archive=False, + allow_hatching='pending', + trash=False, + unknown=False, + chicken_age__gt=age_range.maximum + ) + poultries = Poultry.objects.filter(id__in=hatchings.values_list('poultry__id', flat=True)).update( + order_limit=True) + hatchings.update(unknown=True) + + +@api_view(["GET"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def management_kill_house_dashboard(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_hatching = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q(date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False).select_related('poultry', 'poultry__user__city') + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False + ).select_related('killhouse_user') + aggregate_kill_house_request = kill_house_request.aggregate( + total_id=Count('id'), + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity_has_quarantine=Sum('accepted_real_quantity', filter=Q(quarantine_quantity__gt=0)), + total_count_has_quarantine=Count('id', filter=Q(quarantine_quantity__gt=0)), + total_quarantine_quantity=Sum('quarantine_quantity', filter=Q(quarantine_quantity__gt=0)), + + total_id_hasnt_code=Count('id', filter=Q(clearance_code__isnull=True)), + total_quantity_hasnt_code=Sum('accepted_real_quantity', filter=Q(clearance_code__isnull=True)), + total_weight_hasnt_code=Sum('accepted_real_weight', filter=Q(clearance_code__isnull=True)), + total_id_hasnt_warehouse=Count('id', filter=Q(ware_house_confirmation=False)), + total_quantity_hasnt_warehouse=Sum('accepted_real_quantity', filter=Q(ware_house_confirmation=False)), + total_weight_hasnt_warehouse=Sum('accepted_real_weight', filter=Q(ware_house_confirmation=False)), + total_id_hasnt_assignment_state_archive=Count('id', filter=Q(assignment_state_archive='pending')), + total_quantity_hasnt_assignment_state_archive=Sum('accepted_real_quantity', + filter=Q(assignment_state_archive='pending')), + total_weight_hasnt_assignment_state_archive=Sum('accepted_real_weight', + filter=Q(assignment_state_archive='pending')), + total_id_hasnt_killing_age=Count('id', filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_quantity_hasnt_killing_age=Sum('accepted_real_quantity', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_weight_hasnt_killing_age=Sum('accepted_real_weight', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + + ) + kill_house_req_stats = kill_house_request.values('killhouse_user__name').annotate( + total_quantity=Sum('accepted_real_quantity'), + transaction_count=Count('id') + ).order_by('-total_quantity') + top_kill_house_req = kill_house_req_stats.first() if kill_house_req_stats else None + kill_house_name_req = "-" + total_quantity_top_inner = 0 + if top_kill_house_req: + kill_house_name_req = top_kill_house_req['killhouse_user__name'] + total_quantity_top_inner = top_kill_house_req['total_quantity'] + + poultry_req_stats = kill_house_request.values( + 'province_request__poultry_request__hatching__poultry__unit_name', + 'province_request__poultry_request__hatching__poultry__user__city__name') \ + .annotate(total_quantity=Sum('accepted_real_quantity'), + ).order_by('-total_quantity') + top_poultry_req_stats = poultry_req_stats.first() if poultry_req_stats else None + top_poultry_req_stats_total_quantity = 0 + poultry_req_name_req = "-" + poultry_city_req_name_req = "-" + if top_poultry_req_stats: + poultry_req_name_req = top_poultry_req_stats['province_request__poultry_request__hatching__poultry__unit_name'] + poultry_city_req_name_req = top_poultry_req_stats[ + 'province_request__poultry_request__hatching__poultry__user__city__name'] + top_poultry_req_stats_total_quantity = to_locale_str(top_poultry_req_stats['total_quantity'] or 0) + + aggregate_hatching = poultry_hatching.aggregate( + total_quantity=Sum('quantity'), + total_losses_vet=Sum('losses'), + total_losses_union=Sum('direct_losses'), + total_losses=Sum('total_losses'), + killed_quantity=Sum('killed_quantity'), + total_killed_weight=Sum('total_killed_weight'), + left_over=Sum('left_over'), + total_killing_ave_age=Avg('poultry__killing_ave_age') + ) + top_total_killed_weight = poultry_hatching.values('id').annotate( + total_killed_weight=Sum('total_killed_weight'), + ).order_by('-total_killed_weight') + top_total_killed_weight_first = top_total_killed_weight.first() if top_total_killed_weight else None + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + trash=False, buy_type='live').select_related('kill_house') + kill_house_stats = free_bars.values('kill_house__name').annotate( + total_quantity=Sum('quantity'), + total_live_weight=Sum('live_weight'), + transaction_count=Count('id') + ).order_by('-total_quantity') + + top_kill_house = kill_house_stats.first() if kill_house_stats else None + kill_house_name = "-" + total_quantity_top_out = 0 + transaction_count = "-" + if top_kill_house: + kill_house_name = top_kill_house['kill_house__name'] + transaction_count = to_locale_str(top_kill_house['transaction_count'] or 0) + total_quantity_top_out = to_locale_str(top_kill_house['total_quantity'] or 0) + # + out_poultry_req_stats = free_bars.values('poultry_name', 'province', 'city').annotate( + total_quantity=Sum('quantity'), + ).order_by('-total_quantity') + top_out_poultry_req_stats = out_poultry_req_stats.first() if out_poultry_req_stats else None + out_top_poultry_req_stats_total_quantity = 0 + out_poultry_req_name_req = "-" + out_poultry_city_req_name_req = "-" + out_poultry_province_req_name_req = "-" + if top_out_poultry_req_stats: + out_poultry_req_name_req = top_out_poultry_req_stats['poultry_name'] + out_poultry_city_req_name_req = top_out_poultry_req_stats['city'] + out_poultry_province_req_name_req = top_out_poultry_req_stats['province'] + out_top_poultry_req_stats_total_quantity = to_locale_str(top_out_poultry_req_stats['total_quantity'] or 0) + + # + aggregate_free_bars = free_bars.aggregate( + id=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + max_kill_day = free_bars.values('date__date').annotate( + daily_quantity=Sum('quantity') + ).order_by('-daily_quantity').first() + persian_date = '-' + daily_quantity = '-' + if max_kill_day: + persian_date = shamsi_date(max_kill_day['date__date']) + daily_quantity = to_locale_str(max_kill_day['daily_quantity']) + + max_kill_day_req = kill_house_request.values('kill_request__recive_date__date').annotate( + daily_quantity=Sum('accepted_real_quantity') + ).order_by('-daily_quantity').first() + persian_date_req = '-' + daily_quantity_req = '-' + if max_kill_day_req: + persian_date_req = shamsi_date(max_kill_day_req['kill_request__recive_date__date']) + daily_quantity_req = to_locale_str(max_kill_day_req['daily_quantity']) + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('name') + kill_house_data = [] + duc_kill_house_data = [] + + for kh in kill_houses: + new_steward_allocations = StewardAllocation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house=kh + ) + in_province_data = kill_house_request.filter( + killhouse_user=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('accepted_real_quantity'), + weight=Sum('accepted_real_weight') + ) + + out_province_data = free_bars.filter( + kill_house=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + in_qty = in_province_data.get('quantity', 0) or 0 + in_weight = in_province_data.get('weight', 0) or 0 + out_qty = out_province_data.get('quantity', 0) or 0 + out_weight = out_province_data.get('live_weight', 0) or 0 + total_quantity = in_qty + out_qty + total_weight = in_weight + out_weight + wight_of_steward = new_steward_allocations.filter(to_steward__isnull=False).aggregate( + total_quantity=Sum('real_weight_of_carcasses') + ) + len_of_steward = new_steward_allocations.filter(to_steward__isnull=False).count() + len_of_guild = new_steward_allocations.filter(to_guilds__isnull=False).count() + wight_of_guild = new_steward_allocations.filter(to_guilds__isnull=False).aggregate( + total_quantity=Sum('real_weight_of_carcasses') + ) + + in_loads = in_province_data.get('load_count', 0) or 0 + out_loads = out_province_data.get('load_count', 0) or 0 + total_loads = in_loads + out_loads + + # if in_qty > 0 or out_qty > 0 or in_loads > 0 or out_loads > 0: + kill_house_data.append({ + 'name': kh.name, + 'load_count': to_locale_str(total_loads or 0), + 'in_province_quantity': to_locale_str(in_qty or 0), + 'in_province_wight': to_locale_str(in_weight or 0), + 'out_province_quantity': to_locale_str(out_qty or 0), + 'out_province_weight': to_locale_str(out_weight or 0), + 'total_quantity': to_locale_str(total_quantity or 0), + 'total_weight': to_locale_str(total_weight or 0), + + 'wight_of_steward': to_locale_str(wight_of_steward['total_quantity'] or 0), + 'wight_of_guild': to_locale_str(wight_of_guild['total_quantity'] or 0), + 'len_of_steward': to_locale_str(len_of_steward), + 'len_of_guild': to_locale_str(len_of_guild), + }) + free_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ).values('kill_house_id', 'kill_house__name').annotate( + total_quantity=Sum('weight_of_carcasses') + ).order_by('-total_quantity') + + bar_assigment_pending_count1 = kill_house_request.filter(assignment_state_archive='True') \ + .exclude(bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + steward_allocations = StewardAllocation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('real_weight_of_carcasses') + ) + in_province_data = kill_house_request.filter( + killhouse_user__in=kill_houses + ).values('killhouse_user_id').annotate( + total_quantity=Sum('accepted_real_weight') + ) + + in_warehouse_data = kill_house_request.filter( + killhouse_user__in=kill_houses, + ware_house_confirmation=True + ).values('killhouse_user_id').annotate( + total_quantity=Sum('ware_house_accepted_real_weight') + ) + + products = RolesProducts.objects.filter( + trash=False, + kill_house__in=kill_houses + ).values('kill_house_id', 'total_remain_weight') + + steward_dict = {item['kill_house_id']: item['total_quantity'] for item in steward_allocations} + free_bar_dict = {item['kill_house_id']: item['total_quantity'] for item in free_bars} + in_province_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_province_data} + in_warehouse_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_warehouse_data} + product_dict = {item['kill_house_id']: item['total_remain_weight'] for item in products} + + management_kill_house_data = [] + for kh in kill_houses: + kh_id = kh.id + + steward_qty = steward_dict.get(kh_id, 0) or 0 + free_bar_qty = free_bar_dict.get(kh_id, 0) or 0 + in_province_qty = in_province_dict.get(kh_id, 0) or 0 + in_warehouse_qty = in_warehouse_dict.get(kh_id, 0) or 0 + product_weight = product_dict.get(kh_id, 0) or 0 + + # if any([in_province_qty, in_warehouse_qty, steward_qty, free_bar_qty]): + total = free_bar_qty + steward_qty + percent = round(total * 100 / in_province_qty, 1) if in_province_qty else 0 + + management_kill_house_data.append({ + 'name': kh.name, + 'in_province_quantity': to_locale_str(in_province_qty), + 'in_ware_house_quantity': to_locale_str(in_warehouse_qty), + 'steward_allocation_quantity': to_locale_str(steward_qty), + 'kill_house_free_bar_quantity': to_locale_str(free_bar_qty), + 'all_quantity': to_locale_str(total), + 'product': to_locale_str(product_weight), + 'percent': percent + }) + n_steward_allocations_n = StewardAllocation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ) + n_steward_allocations = n_steward_allocations_n.aggregate( + total_quantity=Sum('real_weight_of_carcasses') + ) + n_steward_allocations_to_steward = n_steward_allocations_n.filter(to_steward__isnull=False) + aggregate_n_steward_allocations_to_steward = n_steward_allocations_to_steward.aggregate( + total_quantity=Sum('real_weight_of_carcasses') + ) + + n_steward_allocations_to_guild = n_steward_allocations_n.filter(to_guilds__isnull=False) + aggregate_n_steward_allocations_to_guild = n_steward_allocations_to_guild.aggregate( + total_quantity=Sum('real_weight_of_carcasses') + ) + steward_and_guild = { + 'len_of_steward': n_steward_allocations_to_steward.count(), + 'wight_of_steward': aggregate_n_steward_allocations_to_steward['total_quantity'] or 0, + 'len_of_guild': n_steward_allocations_to_guild.count(), + 'wight_of_guild': aggregate_n_steward_allocations_to_guild['total_quantity'] or 0, + 'total_weight': n_steward_allocations['total_quantity'] or 0, + } + n_free_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ).aggregate( + total_quantity=Sum('weight_of_carcasses') + ) + + n_in_province_data = kill_house_request.filter( + killhouse_user__in=kill_houses + ).aggregate( + total_quantity=Sum('accepted_real_weight') + ) + + n_in_warehouse_data = kill_house_request.filter( + killhouse_user__in=kill_houses, + ware_house_confirmation=True + ).aggregate( + total_quantity=Sum('ware_house_accepted_real_weight') + ) + + n_products = RolesProducts.objects.filter( + trash=False, + kill_house__in=kill_houses + ).aggregate( + total_quantity=Sum('total_remain_weight') + ) + all_management_kill_house_data = { + 'in_province': n_in_province_data['total_quantity'] or 0, + 'in_warehouse': n_in_warehouse_data['total_quantity'] or 0, + 'steward_allocations': n_steward_allocations['total_quantity'] or 0, + 'free_bars': n_free_bars['total_quantity'] or 0, + 'total': (n_free_bars['total_quantity'] or 0) + (n_steward_allocations['total_quantity'] or 0), + 'products': n_products['total_quantity'] or 0, + } + + for kh in kill_houses: + kill_house_request1 = kill_house_request.filter( + killhouse_user=kh + ) + + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True') + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + bar_document_status_accepted = bar_assigment_true_count.filter( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + bar_document_status_rejected = bar_assigment_true_count.exclude( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + + # if bar_assigment_true_count.count() > 0 or bar_assigment_pending_count > 0: + duc_kill_house_data.append({ + 'name': kh.name, + 'kill_house_request1_count': kill_house_request1.count(), + "bar_assigment_true_count": bar_assigment_true_count.count(), + "bar_assigment_pending_count": bar_assigment_pending_count, + "bar_document_status_accepted": bar_document_status_accepted, + "percent_bar_document_status_accepted": int((bar_document_status_accepted / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + "bar_document_status_rejected": bar_document_status_rejected, + "percent_bar_document_status_rejected": int((bar_document_status_rejected / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + + }) + + different_bar = (aggregate_kill_house_request['total_quantity_has_quarantine'] or 0) \ + - (aggregate_kill_house_request['total_quarantine_quantity'] or 0) + different_bar_percent = int(different_bar / (aggregate_kill_house_request['total_quarantine_quantity'] or 0) * 100) \ + if (aggregate_kill_house_request['total_quarantine_quantity'] or 0) > 0 else 0 + + result = { + 'all_management_kill_house_data': all_management_kill_house_data, + 'management_kill_house_data': management_kill_house_data, + + "poultry_hatching_total_killed_weight": aggregate_hatching['total_killed_weight'] or 0, + "total_weight_hasnt_warehouse": aggregate_kill_house_request['total_weight_hasnt_warehouse'] or 0, + 'kill_houses_data': kill_house_data, + + # + "kill_house_request_count": to_locale_str(aggregate_kill_house_request['total_id'] or 0), + "kill_house_request_quantity": to_locale_str(aggregate_kill_house_request['total_accepted_real_quantity'] or 0), + "kill_house_request_weight": to_locale_str(aggregate_kill_house_request['total_accepted_real_weight'] or 0), + "kill_house_request_average_weight": round( + aggregate_kill_house_request['total_accepted_real_weight'] / aggregate_kill_house_request[ + 'total_accepted_real_quantity'], 1) + if (aggregate_kill_house_request['total_accepted_real_quantity'] or 0) > 0 else 0, + "free_bars_count": to_locale_str(aggregate_free_bars['id'] or 0), + "free_bars_quantity": to_locale_str(aggregate_free_bars['quantity'] or 0), + "free_bars_live_weight": to_locale_str(aggregate_free_bars['live_weight'] or 0), + "kill_house_name": kill_house_name, + "transaction_count": transaction_count, + "persian_date": persian_date, + "daily_quantity": daily_quantity, + "persian_date_req": persian_date_req, + "daily_quantity_req": daily_quantity_req, + 'kill_house_name_req': kill_house_name_req, + 'poultry_req_name_req': poultry_req_name_req, + 'top_poultry_req_stats_total_quantity': top_poultry_req_stats_total_quantity, + 'poultry_city_req_name_req': poultry_city_req_name_req, + 'out_poultry_req_name_req': out_poultry_req_name_req, + 'out_poultry_city_req_name_req': out_poultry_city_req_name_req, + 'out_poultry_province_req_name_req': out_poultry_province_req_name_req, + 'out_top_poultry_req_stats_total_quantity': out_top_poultry_req_stats_total_quantity, + 'duc_kill_house_data': duc_kill_house_data, + 'avg_losses': to_locale_str(int((aggregate_hatching['total_losses'] or 0) / poultry_hatching.count())), + 'avg_total_killed_weight': round( + (aggregate_hatching['total_killed_weight'] or 0) / (aggregate_hatching['killed_quantity'] or 0), 1), + 'total_killing_ave_age': int(aggregate_hatching['total_killing_ave_age'] or 0), + 'top_total_killed_weight': to_locale_str(top_total_killed_weight_first['total_killed_weight'] or 0), + 'total_quantity_top_inner': to_locale_str(total_quantity_top_inner), + 'total_quantity_top_out': total_quantity_top_out, + 'bar_assigment_pending_count1': to_locale_str(bar_assigment_pending_count1 or 0), + 'base_url': base_url_for_sms_report, + "total_quarantine_quantity": to_locale_str(aggregate_kill_house_request['total_quarantine_quantity'] or 0), + "total_count_has_quarantine": to_locale_str(aggregate_kill_house_request['total_count_has_quarantine'] or 0), + "total_quantity_has_quarantine": to_locale_str( + aggregate_kill_house_request['total_quantity_has_quarantine'] or 0), + "different": to_locale_str(different_bar or 0), + "total_weight_hasnt_code": to_locale_str(aggregate_kill_house_request['total_weight_hasnt_code'] or 0), + "total_quantity_hasnt_code": to_locale_str(aggregate_kill_house_request['total_quantity_hasnt_code'] or 0), + "total_id_hasnt_code": to_locale_str(aggregate_kill_house_request['total_id_hasnt_code'] or 0), + + "total_quantity_hasnt_warehouse": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_warehouse'] or 0), + "total_id_hasnt_warehouse": to_locale_str(aggregate_kill_house_request['total_id_hasnt_warehouse'] or 0), + "total_weight_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_weight_hasnt_assignment_state_archive'] or 0), + "total_quantity_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_assignment_state_archive'] or 0), + "total_id_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_id_hasnt_assignment_state_archive'] or 0), + "total_weight_hasnt_killing_age": to_locale_str( + aggregate_kill_house_request['total_weight_hasnt_killing_age'] or 0), + "total_quantity_hasnt_killing_age": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_killing_age'] or 0), + "total_id_hasnt_killing_age": to_locale_str(aggregate_kill_house_request['total_id_hasnt_killing_age'] or 0), + 'different_bar_percent': different_bar_percent, + "steward_and_guild": steward_and_guild + + } + return Response(result) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def periodic_performance_report_dashboard(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_hatching = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q(date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False).select_related('poultry', 'poultry__user__city') + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False + ).select_related('killhouse_user') + aggregate_kill_house_request = kill_house_request.aggregate( + total_id=Count('id'), + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity_has_quarantine=Sum('accepted_real_quantity', filter=Q(quarantine_quantity__gt=0)), + total_count_has_quarantine=Count('id', filter=Q(quarantine_quantity__gt=0)), + total_quarantine_quantity=Sum('quarantine_quantity', filter=Q(quarantine_quantity__gt=0)), + + total_id_hasnt_code=Count('id', filter=Q(clearance_code__isnull=True)), + total_quantity_hasnt_code=Sum('accepted_real_quantity', filter=Q(clearance_code__isnull=True)), + total_weight_hasnt_code=Sum('accepted_real_weight', filter=Q(clearance_code__isnull=True)), + total_id_hasnt_warehouse=Count('id', filter=Q(ware_house_confirmation=False)), + total_quantity_hasnt_warehouse=Sum('accepted_real_quantity', filter=Q(ware_house_confirmation=False)), + total_weight_hasnt_warehouse=Sum('accepted_real_weight', filter=Q(ware_house_confirmation=False)), + total_id_hasnt_assignment_state_archive=Count('id', filter=Q(assignment_state_archive='pending')), + total_quantity_hasnt_assignment_state_archive=Sum('accepted_real_quantity', + filter=Q(assignment_state_archive='pending')), + total_weight_hasnt_assignment_state_archive=Sum('accepted_real_weight', + filter=Q(assignment_state_archive='pending')), + total_id_hasnt_killing_age=Count('id', filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_quantity_hasnt_killing_age=Sum('accepted_real_quantity', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_weight_hasnt_killing_age=Sum('accepted_real_weight', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + + ) + kill_house_req_stats = kill_house_request.values('killhouse_user__name').annotate( + total_quantity=Sum('accepted_real_quantity'), + transaction_count=Count('id') + ).order_by('-total_quantity') + top_kill_house_req = kill_house_req_stats.first() if kill_house_req_stats else None + kill_house_name_req = "-" + total_quantity_top_inner = 0 + if top_kill_house_req: + kill_house_name_req = top_kill_house_req['killhouse_user__name'] + total_quantity_top_inner = top_kill_house_req['total_quantity'] + + poultry_req_stats = kill_house_request.values( + 'province_request__poultry_request__hatching__poultry__unit_name', + 'province_request__poultry_request__hatching__poultry__user__city__name') \ + .annotate(total_quantity=Sum('accepted_real_quantity'), + ).order_by('-total_quantity') + top_poultry_req_stats = poultry_req_stats.first() if poultry_req_stats else None + top_poultry_req_stats_total_quantity = 0 + poultry_req_name_req = "-" + poultry_city_req_name_req = "-" + if top_poultry_req_stats: + poultry_req_name_req = top_poultry_req_stats['province_request__poultry_request__hatching__poultry__unit_name'] + poultry_city_req_name_req = top_poultry_req_stats[ + 'province_request__poultry_request__hatching__poultry__user__city__name'] + top_poultry_req_stats_total_quantity = to_locale_str(top_poultry_req_stats['total_quantity'] or 0) + + poultry_hatching_gt_60 = poultry_hatching.filter(chicken_age__gt=60) + poultry_hatching_has_killed = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, hatching__in=poultry_hatching) + if poultry_hatching_has_killed: + max_age_poultry = poultry_hatching_has_killed.order_by('-killing_age').first() + min_age_poultry = poultry_hatching_has_killed.order_by('killing_age').first() + max_and_min_dict = {"max_age_poultry": max_age_poultry.killing_age or 0, + "max_age_poultry_name": max_age_poultry.hatching.poultry.unit_name or '-', + "max_age_poultry_city": max_age_poultry.hatching.poultry.user.city.name if max_age_poultry.hatching.poultry.user.city else '-', + "max_age_poultry_quantity": max_age_poultry.hatching.quantity or 0, + "max_age_poultry_killed_quantity": max_age_poultry.hatching.killed_quantity or 0, + "max_age_poultry_left_over": max_age_poultry.hatching.left_over or 0, + "min_age_poultry": min_age_poultry.killing_age or 0, + "min_age_poultry_name": min_age_poultry.hatching.poultry.unit_name or '-', + "min_age_poultry_city": min_age_poultry.hatching.poultry.user.city.name if min_age_poultry.hatching.poultry.user.city else '-', + "min_age_poultry_quantity": min_age_poultry.hatching.quantity or 0, + "min_age_poultry_killed_quantity": min_age_poultry.hatching.killed_quantity or 0, + "min_age_poultry_left_over": min_age_poultry.hatching.left_over or 0} + else: + max_and_min_dict = {"max_age_poultry": 0, + "max_age_poultry_name": '-', + "max_age_poultry_city": '-', + "max_age_poultry_quantity": 0, + "max_age_poultry_killed_quantity": 0, + "max_age_poultry_left_over": 0, + "min_age_poultry": 0, + "min_age_poultry_name": '-', + "min_age_poultry_city": '-', + "min_age_poultry_quantity": 0, + "min_age_poultry_killed_quantity": 0, + "min_age_poultry_left_over": 0} + + aggregate_poultry_hatching_gt_60 = poultry_hatching_gt_60.aggregate( + total_quantity=Sum('quantity'), + left_over=Sum('left_over'), + ) + aggregate_hatching = poultry_hatching.aggregate( + total_quantity=Sum('quantity'), + total_losses_vet=Sum('losses'), + total_losses_union=Sum('direct_losses'), + total_losses=Sum('total_losses'), + killed_quantity=Sum('killed_quantity'), + total_killed_weight=Sum('total_killed_weight'), + left_over=Sum('left_over'), + total_killing_ave_age=Avg('poultry__killing_ave_age') + ) + top_total_killed_weight = poultry_hatching.values('id').annotate( + total_killed_weight=Sum('total_killed_weight'), + ).order_by('-total_killed_weight') + top_total_killed_weight_first = top_total_killed_weight.first() if top_total_killed_weight else None + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + trash=False, buy_type='live').select_related('kill_house') + kill_house_stats = free_bars.values('kill_house__name').annotate( + total_quantity=Sum('quantity'), + total_live_weight=Sum('live_weight'), + transaction_count=Count('id') + ).order_by('-total_quantity') + + top_kill_house = kill_house_stats.first() if kill_house_stats else None + kill_house_name = "-" + total_quantity_top_out = 0 + transaction_count = "-" + if top_kill_house: + kill_house_name = top_kill_house['kill_house__name'] + transaction_count = to_locale_str(top_kill_house['transaction_count'] or 0) + total_quantity_top_out = to_locale_str(top_kill_house['total_quantity'] or 0) + # + out_poultry_req_stats = free_bars.values('poultry_name', 'province', 'city').annotate( + total_quantity=Sum('quantity'), + ).order_by('-total_quantity') + top_out_poultry_req_stats = out_poultry_req_stats.first() if out_poultry_req_stats else None + out_top_poultry_req_stats_total_quantity = 0 + out_poultry_req_name_req = "-" + out_poultry_city_req_name_req = "-" + out_poultry_province_req_name_req = "-" + if top_out_poultry_req_stats: + out_poultry_req_name_req = top_out_poultry_req_stats['poultry_name'] + out_poultry_city_req_name_req = top_out_poultry_req_stats['city'] + out_poultry_province_req_name_req = top_out_poultry_req_stats['province'] + out_top_poultry_req_stats_total_quantity = to_locale_str(top_out_poultry_req_stats['total_quantity'] or 0) + + # + aggregate_free_bars = free_bars.aggregate( + id=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + max_kill_day = free_bars.values('date__date').annotate( + daily_quantity=Sum('quantity') + ).order_by('-daily_quantity').first() + persian_date = '-' + daily_quantity = '-' + if max_kill_day: + persian_date = shamsi_date(max_kill_day['date__date']) + daily_quantity = to_locale_str(max_kill_day['daily_quantity']) + + max_kill_day_req = kill_house_request.values('kill_request__recive_date__date').annotate( + daily_quantity=Sum('accepted_real_quantity') + ).order_by('-daily_quantity').first() + persian_date_req = '-' + daily_quantity_req = '-' + if max_kill_day_req: + persian_date_req = shamsi_date(max_kill_day_req['kill_request__recive_date__date']) + daily_quantity_req = to_locale_str(max_kill_day_req['daily_quantity']) + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('-name') + kill_house_data = [] + duc_kill_house_data = [] + + for kh in kill_houses: + in_province_data = kill_house_request.filter( + killhouse_user=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('accepted_real_quantity'), + weight=Sum('accepted_real_weight') + ) + + out_province_data = free_bars.filter( + kill_house=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + in_qty = in_province_data.get('quantity', 0) or 0 + in_weight = in_province_data.get('weight', 0) or 0 + out_qty = out_province_data.get('quantity', 0) or 0 + out_weight = out_province_data.get('live_weight', 0) or 0 + total_quantity = in_qty + out_qty + total_weight = in_weight + out_weight + + in_loads = in_province_data.get('load_count', 0) or 0 + out_loads = out_province_data.get('load_count', 0) or 0 + total_loads = in_loads + out_loads + + if in_qty > 0 or out_qty > 0 or in_loads > 0 or out_loads > 0: + kill_house_data.append({ + 'name': kh.name, + 'load_count': to_locale_str(total_loads or 0), + 'load_count_in_province': to_locale_str(in_loads or 0), + 'load_count_out_province': to_locale_str(out_loads or 0), + 'in_province_quantity': to_locale_str(in_qty or 0), + 'in_province_wight': to_locale_str(in_weight or 0), + 'out_province_quantity': to_locale_str(out_qty or 0), + 'out_province_weight': to_locale_str(out_weight or 0), + 'total_quantity': to_locale_str(total_quantity or 0), + 'total_weight': to_locale_str(total_weight or 0), + }) + bar_assigment_pending_count1 = kill_house_request.filter(assignment_state_archive='True') \ + .exclude(bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + tomorrow_of_date1 = date1 + datetime.timedelta(days=1) + tomorrow_of_date2 = date2 + datetime.timedelta(days=1) + steward_allocations = StewardAllocation.objects.filter( + trash=False, + date__date__gte=tomorrow_of_date1, + date__date__lte=tomorrow_of_date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('real_weight_of_carcasses') + ) + + free_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, + date__date__gte=tomorrow_of_date1, + date__date__lte=tomorrow_of_date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('weight_of_carcasses') + ) + + in_province_data = kill_house_request.filter( + killhouse_user__in=kill_houses + ).values('killhouse_user_id').annotate( + total_quantity=Sum('accepted_real_weight') + ) + + in_warehouse_data = kill_house_request.filter( + killhouse_user__in=kill_houses, + ware_house_confirmation=True + ).values('killhouse_user_id').annotate( + total_quantity=Sum('ware_house_accepted_real_weight') + ) + + products = RolesProducts.objects.filter( + trash=False, + kill_house__in=kill_houses + ).values('kill_house_id', 'total_remain_weight') + + steward_dict = {item['kill_house_id']: item['total_quantity'] for item in steward_allocations} + free_bar_dict = {item['kill_house_id']: item['total_quantity'] for item in free_bars} + in_province_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_province_data} + in_warehouse_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_warehouse_data} + product_dict = {item['kill_house_id']: item['total_remain_weight'] for item in products} + + management_kill_house_data = [] + management_kill_house_dict = { + 'max_percent': '-', + 'max_in_province': '-', + 'min_in_province': '-', + 'max_out_province': '-', + 'min_out_province': '-', + 'max_product': '-', + } + + # نگه داشتن مقادیر بیشترین/کمترین + max_percent_val = -1 + + max_in_province_val = -1 + min_in_province_val = float("inf") + + max_out_province_val = -1 + min_out_province_val = float("inf") + + max_product_val = -1 + + for kh in kill_houses: + kh_id = kh.id + + steward_qty = steward_dict.get(kh_id, 0) or 0 + free_bar_qty = free_bar_dict.get(kh_id, 0) or 0 + in_province_qty = in_province_dict.get(kh_id, 0) or 0 + in_warehouse_qty = in_warehouse_dict.get(kh_id, 0) or 0 + product_weight = product_dict.get(kh_id, 0) or 0 + + if any([in_province_qty, in_warehouse_qty, steward_qty, free_bar_qty]): + total = free_bar_qty + steward_qty + percent = round(total * 100 / in_province_qty, 1) if in_province_qty else 0 + + # ==== بیشترین‌ها ==== + if percent > max_percent_val: + max_percent_val = percent + management_kill_house_dict['max_percent'] = kh.name + + if steward_qty > max_in_province_val: + max_in_province_val = steward_qty + management_kill_house_dict['max_in_province'] = kh.name + + if free_bar_qty > max_out_province_val: + max_out_province_val = free_bar_qty + management_kill_house_dict['max_out_province'] = kh.name + + if product_weight > max_product_val: + max_product_val = product_weight + management_kill_house_dict['max_product'] = kh.name + + # ==== کمترین‌ها ==== + if steward_qty < min_in_province_val: + min_in_province_val = steward_qty + management_kill_house_dict['min_in_province'] = kh.name + + if free_bar_qty < min_out_province_val: + min_out_province_val = free_bar_qty + management_kill_house_dict['min_out_province'] = kh.name + + management_kill_house_data.append({ + 'name': kh.name, + 'in_province_quantity': to_locale_str(in_province_qty), + 'in_ware_house_quantity': to_locale_str(in_warehouse_qty), + 'steward_allocation_quantity': to_locale_str(steward_qty), + 'kill_house_free_bar_quantity': to_locale_str(free_bar_qty), + 'all_quantity': to_locale_str(total), + 'product': to_locale_str(product_weight), + 'percent': percent + }) + max_and_min_assigment = { + "max_duc_name": '-', + "max_duc_accepted_name": '-', + "max_duc_rejected_name": '-', + "min_duc_name": '-', + "min_duc_accepted_name": '-', + "min_duc_rejected_name": '-', + } + + # نگه داشتن مقادیر بیشترین/کمترین + max_request_count = -1 + min_request_count = float("inf") + + max_true_count = -1 + min_true_count = float("inf") + + max_rejected_count = -1 + min_rejected_count = float("inf") + + for kh in kill_houses: + kill_house_request1 = kill_house_request.filter( + killhouse_user=kh + ) + + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True') + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + bar_document_status_accepted = bar_assigment_true_count.filter( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد') + ).count() + bar_document_status_rejected = bar_assigment_true_count.exclude( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد') + ).count() + + if bar_assigment_true_count.count() > 0 or bar_assigment_pending_count > 0: + req_count = kill_house_request1.count() + true_count = bar_assigment_true_count.count() + rejected_count = bar_document_status_rejected + + # === بیشترین‌ها === + if req_count > max_request_count: + max_request_count = req_count + max_and_min_assigment["max_duc_name"] = kh.name + + if true_count > max_true_count: + max_true_count = true_count + max_and_min_assigment["max_duc_accepted_name"] = kh.name + + if rejected_count > max_rejected_count: + max_rejected_count = rejected_count + max_and_min_assigment["max_duc_rejected_name"] = kh.name + + # === کمترین‌ها === + if req_count < min_request_count: + min_request_count = req_count + max_and_min_assigment["min_duc_name"] = kh.name + + if true_count < min_true_count: + min_true_count = true_count + max_and_min_assigment["min_duc_accepted_name"] = kh.name + + if rejected_count < min_rejected_count: + min_rejected_count = rejected_count + max_and_min_assigment["min_duc_rejected_name"] = kh.name + + duc_kill_house_data.append({ + 'name': kh.name, + 'kill_house_request1_count': req_count, + "bar_assigment_true_count": true_count, + "bar_assigment_pending_count": bar_assigment_pending_count, + "bar_document_status_accepted": bar_document_status_accepted, + "percent_bar_document_status_accepted": int( + (bar_document_status_accepted / true_count) * 100) if true_count > 0 else 0, + "bar_document_status_rejected": rejected_count, + "percent_bar_document_status_rejected": int( + (rejected_count / true_count) * 100) if true_count > 0 else 0, + }) + + different_bar = (aggregate_kill_house_request['total_quantity_has_quarantine'] or 0) \ + - (aggregate_kill_house_request['total_quarantine_quantity'] or 0) + different_bar_percent = int(different_bar / (aggregate_kill_house_request['total_quarantine_quantity'] or 0) * 100) \ + if (aggregate_kill_house_request['total_quarantine_quantity'] or 0) > 0 else 0 + + result = { # noqa + + "poultry_count": len(poultry_hatching.values_list('poultry', flat=True).distinct()), + "chain_count": len( + poultry_hatching.filter(Q(UnionTypeName='زنجیره') | + Q(chain_company__isnull=False)).values_list('poultry', flat=True).distinct()), + "poultry_hatching_quantity": aggregate_hatching['total_quantity'] or 0, + "poultry_hatching_losses_vet": aggregate_hatching['total_losses_vet'] or 0, + "poultry_hatching_losses_union": aggregate_hatching['total_losses_union'] or 0, + "poultry_hatching_total_losses": aggregate_hatching['total_losses'] or 0, + "poultry_hatching_killed_quantity": aggregate_hatching['killed_quantity'] or 0, + "poultry_hatching_total_killed_weight": int(aggregate_hatching['total_killed_weight'] or 0), + "poultry_hatching_left_over": aggregate_hatching['left_over'] or 0, + "poultry_hatching_gt_60": len(poultry_hatching_gt_60.values_list('poultry', flat=True).distinct()), + "poultry_hatching_gt_60_quantity": aggregate_poultry_hatching_gt_60['total_quantity'] or 0, + "poultry_hatching_gt_60_left_over": aggregate_poultry_hatching_gt_60['left_over'] or 0, + **max_and_min_dict, + "kill_house_request_count": aggregate_kill_house_request['total_id'] or 0, + "kill_house_request_quantity": aggregate_kill_house_request['total_accepted_real_quantity'] or 0, + "kill_house_request_weight": int(aggregate_kill_house_request['total_accepted_real_weight'] or 0), + "kill_house_request_average_weight": round( + aggregate_kill_house_request['total_accepted_real_weight'] / aggregate_kill_house_request[ + 'total_accepted_real_quantity'], 1) + if (aggregate_kill_house_request['total_accepted_real_quantity'] or 0) > 0 else 0, + "free_bars_count": aggregate_free_bars['id'] or 0, + "free_bars_quantity": aggregate_free_bars['quantity'] or 0, + "free_bars_live_weight": aggregate_free_bars['live_weight'] or 0, + "kill_house_name": kill_house_name, + "transaction_count": transaction_count, + "persian_date": persian_date, + "daily_quantity": daily_quantity, + "persian_date_req": persian_date_req, + "daily_quantity_req": daily_quantity_req, + 'kill_houses_data': kill_house_data, + 'kill_house_name_req': kill_house_name_req, + 'poultry_req_name_req': poultry_req_name_req, + 'top_poultry_req_stats_total_quantity': top_poultry_req_stats_total_quantity, + 'poultry_city_req_name_req': poultry_city_req_name_req, + 'out_poultry_req_name_req': out_poultry_req_name_req, + 'out_poultry_city_req_name_req': out_poultry_city_req_name_req, + 'out_poultry_province_req_name_req': out_poultry_province_req_name_req, + 'out_top_poultry_req_stats_total_quantity': out_top_poultry_req_stats_total_quantity, + 'management_kill_house_data': management_kill_house_data, + 'duc_kill_house_data': duc_kill_house_data, + 'avg_losses': int((aggregate_hatching['total_losses'] or 0) / poultry_hatching.count()), + 'avg_total_killed_weight': round( + (aggregate_hatching['total_killed_weight'] or 0) / (aggregate_hatching['killed_quantity'] or 0), 1), + 'total_killing_ave_age': int(aggregate_hatching['total_killing_ave_age'] or 0), + 'top_total_killed_weight': top_total_killed_weight_first['total_killed_weight'] or 0, + 'total_quantity_top_inner': total_quantity_top_inner, + 'total_quantity_top_out': total_quantity_top_out, + 'bar_assigment_pending_count1': bar_assigment_pending_count1 or 0, + 'base_url': base_url_for_sms_report, + "total_quarantine_quantity": aggregate_kill_house_request['total_quarantine_quantity'] or 0, + "total_count_has_quarantine": aggregate_kill_house_request['total_count_has_quarantine'] or 0, + "total_quantity_has_quarantine": + aggregate_kill_house_request['total_quantity_has_quarantine'] or 0, + "different": different_bar or 0, + "total_weight_hasnt_code": aggregate_kill_house_request['total_weight_hasnt_code'] or 0, + "total_quantity_hasnt_code": aggregate_kill_house_request['total_quantity_hasnt_code'] or 0, + "total_id_hasnt_code": aggregate_kill_house_request['total_id_hasnt_code'] or 0, + "total_weight_hasnt_warehouse": + aggregate_kill_house_request['total_weight_hasnt_warehouse'] or 0, + "total_quantity_hasnt_warehouse": + aggregate_kill_house_request['total_quantity_hasnt_warehouse'] or 0, + "total_id_hasnt_warehouse": aggregate_kill_house_request['total_id_hasnt_warehouse'] or 0, + "total_weight_hasnt_assignment_state_archive": + aggregate_kill_house_request['total_weight_hasnt_assignment_state_archive'] or 0, + "total_quantity_hasnt_assignment_state_archive": + aggregate_kill_house_request['total_quantity_hasnt_assignment_state_archive'] or 0, + "total_id_hasnt_assignment_state_archive": + aggregate_kill_house_request['total_id_hasnt_assignment_state_archive'] or 0, + "total_weight_hasnt_killing_age": + aggregate_kill_house_request['total_weight_hasnt_killing_age'] or 0, + "total_quantity_hasnt_killing_age": + aggregate_kill_house_request['total_quantity_hasnt_killing_age'] or 0, + "total_id_hasnt_killing_age": aggregate_kill_house_request['total_id_hasnt_killing_age'] or 0, + 'different_bar_percent': different_bar_percent, + 'max_and_min_assigment': max_and_min_assigment, + 'management_kill_house_dict': management_kill_house_dict, + + } + return Response(result) + + +def create_update_chicken_commission_prices_cron(): + now = datetime.datetime.now().date() + for day in range(7): + past_date = now - timedelta(days=day) + past_datetime = datetime.datetime.combine(past_date, datetime.time.min) + + chicken_commission = ChickenCommissionPrices.objects.get_or_create(date__date=past_date, + defaults={'date': past_datetime, + 'kill_house_price': kill_house_price})[ + 0] + # # poultry_request + poultry_request = PoultryRequest.objects.filter(trash=False, send_date__date=past_date, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=False, + amount__gt=0).only( + 'amount') + print(len(poultry_request)) + poultry_request_amount = poultry_request.aggregate(total=Sum('amount'))[ + 'total'] or 0 + # ProvinceKillRequest + province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request__recive_date__date=past_date, + state__in=('pending', 'accepted'), + kill_house_price__gt=0).only( + 'kill_house_price') + + province_kill_req_kill_house_price = province_kill_req.aggregate(total=Sum('kill_house_price'))[ + 'total'] or 0 + + # KillRequest + kill_req = KillRequest.objects.filter(trash=False, recive_date__date=past_date, + province_state__in=('accepted', 'pending') + , poultry__isnull=False, + direct_buying_state__in=('accepted', 'pending'), amount__gt=0).only( + 'amount') + kill_req_amount = kill_req.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + kill_request_amount = round( + kill_req_amount / kill_req.count()) if kill_req.count() > 0 else 0 + + province_kill_request_amount = round(province_kill_req_kill_house_price / province_kill_req.count()) \ + if province_kill_req.count() > 0 else 0 + + poultry_req_amount = round(poultry_request_amount / poultry_request.count()) if poultry_request.count() > 0 \ + else 0 + + amount = round( + kill_req_amount + province_kill_req_kill_house_price + poultry_request_amount) + + counts = poultry_request.count() + province_kill_req.count() + kill_req.count() + + chicken_commission.chicken_average_price = round(amount / counts) if counts > 0 else 0 + chicken_commission.kill_request_amount = kill_request_amount + chicken_commission.province_kill_request_amount = province_kill_request_amount + chicken_commission.poultry_request_amount = poultry_req_amount + + chicken_commission.save() + + +def fix_amount(request): + my_tuple = ( + 31160, 31310, 31311, 31508, 31509, 31558, 31559, 31642, 31643, 31755, 31756, 31817, 31818, 31850, 31852, 31912, + 31913, 32019, 32020) + + steward_allocations = StewardAllocation.objects.filter(id__in=my_tuple) + for steward_allocation in steward_allocations: + amount = steward_allocation.amount - 20000 + total_amount = amount * steward_allocation.real_weight_of_carcasses + steward_allocation.amount = amount + steward_allocation.total_amount = total_amount + steward_allocation.total_amount_remain = total_amount + steward_allocation.save() + return HttpResponse('ok') + + +def fix_killing_age(request): + poultry_request = PoultryRequest.objects.filter(trash=False, killing_age=1).only('killing_age') + for p in poultry_request: + p.killing_age = (p.send_date.date() - p.hatching.date.date()).days + 1 + p.save() + return HttpResponse('ok') + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_bar_from_rsi_with_hatching(request): + page = '' + search_filter = '' + search = request.GET.get('search') + value = request.GET.get('value') + if search: + if search != 'undefined' and value.strip(): + search_filter = f'&search={search}&value={value}' + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else None + poultry_hatching = PoultryHatching.objects.filter( + key=request.GET['key'] + ).first() + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + temporary_trash=False, + temporary_deleted=False, + clearance_code__isnull=False, province_request__poultry_request__hatching=poultry_hatching + ).values_list('clearance_code', flat=True).distinct() + + kill_house_free_sale = PoultryRequest.objects.filter(trash=False, quarantine_code__isnull=False, out=True, + hatching=poultry_hatching) \ + .values_list('quarantine_code', flat=True).distinct() + + result = list(kill_house_request) + list(kill_house_free_sale) + if 'page' in request.GET: + page = f'&page={request.GET["page"]}&page_size={request.GET["page_size"]}' + + response = requests.get( + f'https://rsibackend.rasadyar.com/app/api_send_different_bar-from-hatching/?{page}' + f'{search_filter}' + f'&date1={date1}&date2={date2}&licence_number={poultry_hatching.licence_number}', + json=result, + headers={'Content-Type': 'application/json'} + ) + + return Response(response.json(), status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def driver_from_rsi_excel(request): + response = requests.get( + f'https://rsibackend.rasadyar.com/app/driver/?all' + ) + kill_house = KillHouse.objects.filter(trash=False, out_province=False).values_list('unique_identifier', flat=True) + + excel_options = [ + 'ردیف', + 'نام راننده', + 'نام مالک', + 'شهر', + 'رهگیری خودرو', + 'نوع ماشین', + 'پلاک', + 'محصول', + 'کد کشتارگاه', + 'نام کشتارگاه', + 'شماره موبایل راننده', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + m = 1 + create_header_freez(worksheet, excel_options, 1, 1, 2, 20, width=30) + + l = 2 + for data in response.json(): + if data['part_id_code'] in kill_house: + list1 = [ + m, + data['driver_name'], + data['owner_name'], + data['city'], + data['tracking_code'], + data['car_type'], + data['pelak'], + data['product'], + data['part_id_code'], + data['kill_house_name'], + + ] + create_value(worksheet, list1, l, 1, m=m, border_style='thin') + m += 1 + l += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="راننده ها .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def send_again_sms_for_register_code_guild(request): + guild = Guilds.objects.get(trash=False, key=request.data['key']) + if guild.is_registered == False and not guild.register_date_register_code: + number = random.randint(10000, 99000) + guild.register_code = number + guild.active_register_code = True + guild.register_date_register_code = datetime.datetime.now() + guild.save() + send_sms_for_guild_for_register(guild) + + elif datetime.datetime.now() > (guild.register_date_register_code + timedelta(minutes=10)): + number = random.randint(10000, 99000) + guild.register_code = number + guild.register_date_register_code = datetime.datetime.now() + guild.save() + send_sms_for_guild(guild) + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +def delete_free_bar_info(request): + kill_house_free_bar = KillHouseFreeBarInformation.objects.filter(trash=False, ware_house=False) + bar_clearance_code = kill_house_free_bar.values_list('bar_clearance_code', flat=True) + + bars = requests.post('https://rsibackend.rasadyar.com/app/delete_free_bar_from_rasadyaar/', data=bar_clearance_code) + if bars.json(): + for bar in bars.json(): + delete_kill_req = kill_house_free_bar.filter(bar_clearance_code=bar['TrackingCode']).first() + delete_kill_req.trash = True + delete_kill_req.save() + product = delete_kill_req.product + kill_house_free_buying_product_warehousing(product) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def send_again_sms_steward_allocation(request): + steward_allocation = StewardAllocation.objects.get(key=request.data['key'], trash=False) + if steward_allocation.to_guilds: + mobile = steward_allocation.to_guilds.user.mobile + buyer = steward_allocation.to_guilds.guilds_name + else: + mobile = steward_allocation.to_steward.user.mobile + buyer = steward_allocation.to_steward.guilds_name + + if steward_allocation.kill_house: + seller = steward_allocation.kill_house.name + else: + seller = steward_allocation.guilds.guilds_name + date = shamsi_date(steward_allocation.date) + weight = steward_allocation.weight_of_carcasses + amount = steward_allocation.amount + number = str(steward_allocation.registration_code) + + if (steward_allocation.expire_time_ten_minute and datetime.datetime.now() > ( + steward_allocation.expire_time_ten_minute + timedelta(minutes=10))) or \ + not steward_allocation.expire_time_ten_minute: + steward_allocation.expire_time_ten_minute = datetime.datetime.now() + steward_allocation.save() + steward_allocation_sms(mobile, date, weight, seller, number, buyer, amount) + + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def pos_send_again_sms_steward_allocation(request): + steward_allocation = StewardAllocation.objects.get(key=request.data['key'], trash=False) + if steward_allocation.to_guilds: + mobile = steward_allocation.to_guilds.user.mobile + buyer = steward_allocation.to_guilds.guilds_name + else: + mobile = steward_allocation.to_steward.user.mobile + buyer = steward_allocation.to_steward.guilds_name + + if steward_allocation.kill_house: + seller = steward_allocation.kill_house.name + else: + seller = steward_allocation.guilds.guilds_name + date = shamsi_date(steward_allocation.date) + weight = steward_allocation.weight_of_carcasses + amount = steward_allocation.amount + number = str(steward_allocation.registration_code) + + if (steward_allocation.expire_time_ten_minute and datetime.datetime.now() > ( + steward_allocation.expire_time_ten_minute + timedelta(minutes=10))) or \ + not steward_allocation.expire_time_ten_minute: + steward_allocation.expire_time_ten_minute = datetime.datetime.now() + steward_allocation.save() + steward_allocation_sms(mobile, date, weight, seller, number, buyer, amount) + + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fix_number_from_rsi(request): + poultry = Poultry.objects.filter(trash=False).select_related('user').only('user__mobile', 'breeding_unique_id') + + result = { + str(p.breeding_unique_id): p.user.mobile + for p in poultry + if p.user and p.user.mobile + } + + response = requests.post( + f'https://rsibackend.rasadyar.com/app/fix_number/', + json=result, + headers={'Content-Type': 'application/json'} + ) + for r in response.json(): + for k, v in r.items(): + poultry = Poultry.objects.filter(breeding_unique_id=k).first() + if poultry: + if v is not None: + data = { + "first_mobile_number": poultry.user.mobile, + "second_mobile_number": v, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = v + user = User.objects.get(username=poultry.user.mobile) + user.username = second_mobile_number + user.save() + user_profile = SystemUserProfile.objects.filter(user=user).first() + user_profile.mobile = second_mobile_number + user_profile.save() + + return Response(response.json()) + + +def send_credit_sahandsms_sms(): + filters = {} + if base_url_for_sms_report == 'ha': + filters['username'] = 'hamedan' + elif base_url_for_sms_report == 'ku': + filters['username'] = 'kurdistan' + elif base_url_for_sms_report == 'ma': + filters['username__in'] = ['markazi', 'senfmarkazi'] + managements = ManagementSendSms.objects.filter(**filters) \ + .values('username') \ + .annotate(min_id=Min('id')) \ + .values_list('min_id', flat=True) + + managements = ManagementSendSms.objects.filter(id__in=managements) + + for management in managements: + r = requests.get( + f"http://webservice.sahandsms.com/newsmswebservice.asmx/GetUserCredit?username={management.username}" + f"&password={management.password}") + + url = f'https://eitaayar.ir/api/{token}/sendMessage' + date = datetime.datetime.now().date() + if base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date_shamsi = shamsi_date(date).replace('-', '_') + base_message = '🗓📢❗ سامانه رصدیار، زنجیره تامین،تولید و توزیع مرغ گوشتی📢❗\n' + base_message += f' #گزارش_مانده_حساب_پنل_پیامکی #{date_shamsi}\n' + base_message += f' #استان_{province}\n\n' + base_message += f'➖➖➖➖➖➖➖➖➖➖\n' + + messages = [] + current_message = base_message + + root = ET.fromstring(r.content) + credit_amount = int(root.text) + amount = "{:,}".format(credit_amount) + + new_message_part = "🔸 نام کاربری پنل : {0} \n".format(management.username) + new_message_part += "🔸 مانده حساب پنل : {0} ریال \n".format(amount) + # new_message_part = "🔸 نام کاربری پنل {0}: {1} ریال \n".format(management.username, amount) + if credit_amount < 1000000: + new_message_part += "‼توجه: لطفا برای شارژ پنل پیامکی خود اقدام فرمایید‼" + + new_message_part += '\n➖➖➖➖➖➖➖➖➖➖\n' + + if len(current_message) + len(new_message_part) > 4000: + messages.append(current_message) + current_message = base_message + + current_message += new_message_part + + if current_message and current_message != base_message: + messages.append(current_message) + + for message in messages: + data = { + 'chat_id': chat_id_mali, + 'text': message, + } + response = requests.post(url, data=data, verify=False) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def send_again_sms_steward_free_sale_bar(request): + steward_allocation = StewardFreeSaleBarInformation.objects.get(key=request.data['key'], trash=False) + + if (steward_allocation.expire_time_ten_minute and datetime.datetime.now() > + (steward_allocation.expire_time_ten_minute + timedelta(minutes=10))) or \ + not steward_allocation.expire_time_ten_minute: + steward_allocation.expire_time_ten_minute = datetime.datetime.now() + steward_allocation.save() + send_sms_for_sale_bar_for_steward(steward_allocation) + + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def send_again_sms_kill_house_free_sale_bar(request): + steward_allocation = KillHouseFreeSaleBarInformation.objects.get(key=request.data['key'], trash=False) + + if (steward_allocation.expire_time_ten_minute and datetime.datetime.now() > + (steward_allocation.expire_time_ten_minute + timedelta(minutes=10))) or \ + not steward_allocation.expire_time_ten_minute: + steward_allocation.expire_time_ten_minute = datetime.datetime.now() + steward_allocation.save() + send_sms_for_sale_bar(steward_allocation) + + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def send_again_sms_direct_buying_code(request): + kill_request = KillRequest.objects.get(key=request.data['key'], trash=False) + + if (kill_request.expire_time_ten_minute and datetime.datetime.now() > + (kill_request.expire_time_ten_minute + timedelta(minutes=10))) or \ + not kill_request.expire_time_ten_minute: + kill_request.expire_time_ten_minute = datetime.datetime.now() + kill_request.save() + + # Get required data for SMS + from authentication.sms_management import confirm_price_poultry_request_direct_buying_sms + from panel.helper_excel import shamsi_date + + mobile = kill_request.poultry.user.mobile + poultry_fullname = kill_request.poultry.user.fullname + quantity = "{:,}".format(int(kill_request.kill_capacity)) + chicken_breed = kill_request.chicken_breed + send_date = shamsi_date(kill_request.recive_date.date()) + free_sale_in_province = kill_request.poultry_request.free_sale_in_province if kill_request.poultry_request else False + amount = kill_request.amount + request_kill_house = kill_request.kill_house.name + confirm_code = kill_request.direct_buying_code + + confirm_price_poultry_request_direct_buying_sms( + mobile, + poultry_fullname, + quantity, + chicken_breed, + send_date, + free_sale_in_province, + amount, + request_kill_house, + confirm_code + ) + + else: + return Response({'result': 'شما تا 10 دقیقه دیگر مجاز به ارسال کد نمیباشد!'}, status=status.HTTP_403_FORBIDDEN) + return Response({'result': 'باموفقیت ارسال شد.'}) + + +def delete_sale_bar(): + steward_sale_bar = StewardFreeSaleBarInformation.objects.filter(trash=False, logged_registration_code__isnull=True, + system_registration_code=True, + active_expire_date_time=True, + registration_code__isnull=False) + + for free_sale_bar in steward_sale_bar: + free_sale_bar.trash = True + free_sale_bar.save() + guild_steward_free_sale_product_warehousing(free_sale_bar.product) + + kill_house_sale_bar = KillHouseFreeSaleBarInformation.objects.filter(trash=False, + logged_registration_code__isnull=True, + system_registration_code=True, + active_expire_date_time=True, + registration_code__isnull=False) + + for free_sale_bar_kill_house in kill_house_sale_bar: + product = free_sale_bar_kill_house.product + free_sale_bar_kill_house.trash = True + free_sale_bar_kill_house.save() + kill_house_free_sale_product_warehousing(product) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def delete_guilds_without_allocation(request): + # 1. اول همه صنف‌ها رو می‌گیریم + guilds = Guilds.objects.filter(trash=False, active=True).order_by('id') + + # 2. صنف‌هایی که توزیع دارند رو پیدا می‌کنیم + guilds_with_allocation = StewardAllocation.objects.filter( + trash=False + ).values_list('to_steward_id', 'to_guilds_id') + + allocated_guild_ids = set() + for to_steward_id, to_guilds_id in guilds_with_allocation: + if to_steward_id: + allocated_guild_ids.add(to_steward_id) + if to_guilds_id: + allocated_guild_ids.add(to_guilds_id) + + # 3. از صنف‌ها، فقط اونایی که توزیع ندارند رو می‌گیریم + guilds_without_allocation = guilds.exclude(id__in=allocated_guild_ids) + + # 4. از صنف‌های بدون توزیع، اونایی که اصلاً دستگاه پز ندارند رو پیدا می‌کنیم + guilds_without_pos = guilds_without_allocation.annotate( + has_pos_machine=Count('guild_pos', filter=Q(guild_pos__trash=False)) + ).filter(has_pos_machine=0) + + deleted_count = 0 + + # 5. صنف‌هایی که هم توزیع ندارند و هم دستگاه پز ندارند رو حذف می‌کنیم + for guild in guilds_without_pos: + guild.trash = True + guild.save() + deleted_count += 1 + + return Response({ + 'result': 'باموفقیت انجام شد.', + 'deleted_count': deleted_count, + }, status=status.HTTP_200_OK) + + +def get_evacuation_detail_by_request_code(rcode): + if not rcode: + raise ValueError("پارامتر code الزامی است.") + + payload = {"RequestCode": rcode} + try: + external_response = requests.post( + "https://rsibackend.rasadyar.com/app/get-evacuation-detail-by-request-code/", + json=payload, + timeout=15, + ) + external_response.raise_for_status() + except requests.RequestException as exc: + raise RuntimeError("عدم امکان اتصال به سرویس تخلیه.") from exc + + try: + return external_response.json() + except ValueError as exc: + raise ValueError( + f"پاسخ نامعتبر از سرویس تخلیه: {external_response.text}" + ) from exc + + +def save_mobile_numbers(request): + mobile_numbers = [ + '09188176737', + '09011110919', + '09181112717', + '09185914818', + '09187040838', + '09393946626', + '09127687317', + '09033073493', + ] + + for number in mobile_numbers: + SmsRecipient.objects.get_or_create( + phone_number=number, + defaults={'is_active': True} + ) + return HttpResponse('ok') + + +def _process_auto_warehouse_steward_allocations(): + now = datetime.datetime.now() + threshold = now - timedelta(hours=8) + + total_updated = 0 + + guilds = Guilds.objects.filter(trash=False, active=True).order_by('id') + for guild in guilds: + allocations = StewardAllocation.objects.filter( + trash=False, + receiver_state__in=['accepted', 'pending'], + create_date__lte=threshold + ).filter( + Q(to_steward=guild) | Q(to_guilds=guild), + Q(warehouse=False) | Q(steward_warehouse=False) + ) + + for allocation in allocations: + if allocation.warehouse is False: + allocation.warehouse = True + allocation.steward_warehouse = True + allocation.save() + + seller_product = allocation.product + + buyer_product = None + try: + if allocation.to_steward: + buyer_product = RolesProducts.objects.get( + guild=allocation.to_steward, + parent_product=seller_product.parent_product + ) + elif allocation.to_guilds: + buyer_product = RolesProducts.objects.get( + guild=allocation.to_guilds, + parent_product=seller_product.parent_product + ) + except RolesProducts.DoesNotExist: + buyer_product = None + + if allocation.seller_type == 'KillHouse': + if seller_product: + kill_house_allocations_product_warehousing(seller_product) + if buyer_product: + guild_steward_allocations_product_warehousing(buyer_product) + else: + if seller_product: + guild_steward_allocations_product_warehousing(seller_product) + if buyer_product: + guild_steward_allocations_product_warehousing(buyer_product) + + total_updated += 1 + + return total_updated + + +@api_view(['POST', 'GET']) +@permission_classes([AllowAny]) +def auto_warehouse_steward_allocations(request): + updated = _process_auto_warehouse_steward_allocations() + return Response({ + 'result': 'done', + 'updated_allocations': updated + }, status=status.HTTP_200_OK) + + +def auto_warehouse_steward_allocations_cron(): + try: + _process_auto_warehouse_steward_allocations() + return HttpResponse('ok') + except Exception as e: + return HttpResponse(f'error: {e}', status=500) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def import_poultry_science_from_excel(request): + file_obj = request.FILES.get('file') + if not file_obj: + return Response({"result": "فایل ارسال نشده است."}, status=status.HTTP_400_BAD_REQUEST) + + try: + workbook = openpyxl.load_workbook(BytesIO(file_obj.read()), data_only=True) + except Exception: + return Response({"result": "امکان خواندن فایل وجود ندارد."}, status=status.HTTP_400_BAD_REQUEST) + + sheet = workbook.active + rows = list(sheet.iter_rows(values_only=True)) + if not rows: + return Response({"result": "فایل خالی است."}, status=status.HTTP_400_BAD_REQUEST) + + expected_headers = ["ردیف", "نام", "نام خانوادگی", "شهرستان کاربر", "کد ملی", "کد نظام مهندسی", "شماره همراه"] + header_row = [ + str(value).strip() if value is not None else "" + for value in rows[0][:len(expected_headers)] + ] + if header_row != expected_headers: + return Response( + { + "result": "هدر فایل با قالب مورد انتظار همخوانی ندارد.", + "expected_headers": expected_headers, + "received_headers": header_row + }, + status=status.HTTP_400_BAD_REQUEST + ) + + group = Group.objects.filter(name__exact="PoultryScience").first() + if not group: + return Response({"result": "نقش PoultryScience تعریف نشده است."}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + latest_base_order = SystemUserProfile.objects.filter(trash=False).order_by('-base_order') \ + .values_list('base_order', flat=True).first() + next_base_order = (latest_base_order + 1) if latest_base_order else 1000 + + stats = { + "processed_rows": 0, + "created_profiles": 0, + "updated_profiles": 0, + "created_poultry_science": 0, + "skipped_rows": 0 + } + errors = [] + + def clean_text(value): + if value is None: + return None + text = str(value).strip() + return text or None + + def clean_digits(value): + if value is None: + return None + digits = re.sub(r'\D', '', str(value)) + return digits or None + + def normalize_mobile(value): + digits = clean_digits(value) + if not digits: + return None + if digits.startswith('98') and len(digits) == 12: + digits = digits[2:] + if len(digits) == 10: + digits = f'0{digits}' + if len(digits) == 11 and not digits.startswith('0'): + digits = f'0{digits[1:]}' + return digits if check_mobile_number(digits) else None + + def find_city(name): + if not name: + return None + return City.objects.filter( + trash=False + ).filter( + Q(name__iexact=name) | Q(city_name__iexact=name) + ).select_related('province').first() + + for row_index, row in enumerate(rows[1:], start=2): + if not row or not any(row): + continue + + stats["processed_rows"] += 1 + first_name = clean_text(row[1]) + last_name = clean_text(row[2]) + city_name = clean_text(row[3]) + national_code = clean_digits(row[4]) + engineering_code = clean_digits(row[5]) + mobile = normalize_mobile(row[6]) + + if not mobile: + stats["skipped_rows"] += 1 + errors.append({"row": row_index, "reason": "شماره همراه نامعتبر است."}) + continue + + city = find_city(city_name) + if not city: + stats["skipped_rows"] += 1 + errors.append({"row": row_index, "reason": "شهرستان یافت نشد.", "city": city_name}) + continue + + system_profile = SystemUserProfile.objects.filter(trash=False, mobile=mobile).last() + + if not system_profile: + password = '2025' + register_payload = { + "username": mobile, + "first_name": first_name or "", + "last_name": last_name or "", + "password": password, + "national_code": national_code or '0', + "role": "PoultryScience", + "api_key": PROJECT_API_KEY + } + try: + arta_response = requests.post( + url=ARTA_REGISTER, + data=register_payload, + verify=False, + timeout=20 + ) + except requests.RequestException as exc: + stats["skipped_rows"] += 1 + errors.append({"row": row_index, "reason": f"خطا در ثبت در آرتا: {exc}"}) + continue + + if arta_response.status_code not in (200, 201): + stats["skipped_rows"] += 1 + errors.append( + {"row": row_index, "reason": f"ثبت کاربر در آرتا انجام نشد ({arta_response.status_code})."}) + continue + + hashed_password = hashlib.sha256(password.encode()).hexdigest() + user, _ = User.objects.get_or_create( + username=mobile, + defaults={ + "first_name": first_name or "", + "last_name": last_name or "", + "password": hashed_password + } + ) + if first_name and user.first_name != first_name: + user.first_name = first_name + if last_name and user.last_name != last_name: + user.last_name = last_name + user.save() + + fullname = f"{first_name or ''} {last_name or ''}".strip() or None + system_profile = SystemUserProfile.objects.create( + mobile=mobile, + first_name=first_name, + last_name=last_name, + fullname=fullname, + user=user, + base_order=next_base_order, + password=password, + national_code=national_code, + city=city, + province=city.province, + city_name=city.name, + province_name=city.province.name if city.province else None, + city_number=city.city_number, + province_number=city.province.province_number if city.province else None + ) + next_base_order += 1 + stats["created_profiles"] += 1 + else: + updated = False + if first_name and system_profile.first_name != first_name: + system_profile.first_name = first_name + updated = True + if last_name and system_profile.last_name != last_name: + system_profile.last_name = last_name + updated = True + if national_code and system_profile.national_code != national_code: + system_profile.national_code = national_code + updated = True + if engineering_code and system_profile.system_code != engineering_code: + system_profile.system_code = engineering_code + updated = True + if system_profile.city_id != city.id: + system_profile.city = city + system_profile.city_name = city.name + system_profile.city_number = city.city_number + updated = True + if system_profile.province_id != (city.province.id if city.province else None): + system_profile.province = city.province + system_profile.province_name = city.province.name if city.province else None + system_profile.province_number = city.province.province_number if city.province else None + updated = True + + fullname = f"{system_profile.first_name or ''} {system_profile.last_name or ''}".strip() + if fullname and system_profile.fullname != fullname: + system_profile.fullname = fullname + updated = True + + if not system_profile.user: + hashed_password = hashlib.sha256('123456'.encode()).hexdigest() + user, _ = User.objects.get_or_create( + username=mobile, + defaults={ + "first_name": first_name or system_profile.first_name or "", + "last_name": last_name or system_profile.last_name or "", + "password": hashed_password + } + ) + system_profile.user = user + updated = True + else: + user = system_profile.user + if first_name and user.first_name != first_name: + user.first_name = first_name + user.save(update_fields=["first_name"]) + if last_name and user.last_name != last_name: + user.last_name = last_name + user.save(update_fields=["last_name"]) + + if updated: + system_profile.save() + stats["updated_profiles"] += 1 + + if not system_profile.role.filter(id=group.id).exists(): + system_profile.role.add(group) + + poultry_science = PoultryScience.objects.filter(trash=False, user=system_profile).first() + if not poultry_science: + PoultryScience.objects.create(user=system_profile, engineering_code=engineering_code) + stats["created_poultry_science"] += 1 + else: + updated_fields = [] + if engineering_code and poultry_science.engineering_code != engineering_code: + poultry_science.engineering_code = engineering_code + updated_fields.append("engineering_code") + if updated_fields: + poultry_science.save(update_fields=updated_fields) + + return Response( + { + "result": "done", + "summary": stats, + "errors": errors + }, + status=status.HTTP_200_OK + ) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +def sync_guilds_user_profile_from_inquiry(request): + """ + برگرداندن لیست صنف‌هایی که: + - برای کاربرشان کد ملی ثبت شده است (user__national_id خالی/NULL نیست) + - هنوز استعلام نشده‌اند (has_inquiry = False) + + علاوه بر لیست، برای هر صنف استعلام «شخص» و «صنف» انجام می‌شود + و فقط اطلاعات کاربر (SystemUserProfile) به‌روزرسانی می‌شود. + در صورت موفقیت، روی خود صنف فقط has_inquiry=True ست می‌شود. + """ + queryset = Guilds.objects.filter( + trash=False, + user__national_id__isnull=False, + steward=True + ).exclude(user__national_id__exact="") + + failed_records = [] + updated_ids = [] + + # کش شهرها برای بهبود کارایی جستجوی شهر + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + + def _normalize_fa_ar(text): + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + + def parse_yes_no(val): + if not val: + return False + return str(val).strip() == 'بله' + + for guild in queryset: + national_id = getattr(getattr(guild, "user", None), "national_id", None) + if not national_id: + failed_records.append( + {"guild_id": guild.id, "reason": "کد ملی برای کاربر این صنف ثبت نشده است"} + ) + continue + + try: + # دریافت اطلاعات شخص + try: + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=person" + ) + person_data = person_response.json() + if not person_data.get('status'): + failed_records.append( + {"guild_id": guild.id, "national_id": national_id, "reason": "اطلاعات شخص یافت نشد"} + ) + continue + person_info = person_data.get('data', {}) + except Exception as e: + failed_records.append( + { + "guild_id": guild.id, + "national_id": national_id, + "reason": f"خطا در دریافت اطلاعات شخصی: {str(e)}", + } + ) + continue + + # دریافت اطلاعات صنفی + try: + guild_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=guild" + ) + guild_data = guild_response.json() + if not guild_data.get('status') or not guild_data.get('data'): + failed_records.append( + {"guild_id": guild.id, "national_id": national_id, "reason": "اطلاعات صنفی یافت نشد"} + ) + continue + + guild_list = guild_data.get('data', []) + guild_info = None + + for g in guild_list: + license_status_value = g.get('licenseStatus', '') + if license_status_value and 'فعال' in license_status_value: + guild_info = g + break + + if not guild_info: + failed_records.append( + { + "guild_id": guild.id, + "national_id": national_id, + "reason": "هیچ پروانه کسب فعالی برای این کد ملی یافت نشد (تمام پروانه‌ها ابطال شده‌اند)", + } + ) + continue + + guild_layer_two = guild_info.get('layerTwo', {}) + except Exception as e: + failed_records.append( + { + "guild_id": guild.id, + "national_id": national_id, + "reason": f"خطا در دریافت اطلاعات صنفی: {str(e)}", + } + ) + continue + + # مقادیر مورد نیاز برای به‌روزرسانی + first_name = person_info.get('firstName') + last_name = person_info.get('lastName') + father_name = person_info.get('fatherName') + gender = person_info.get('gender') + identity_no = person_info.get('identityNo') + is_alive = person_info.get('isLive', True) + birth_date = person_info.get('birthDate') + + try: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + except Exception: + birthday_str = None + + city_name = guild_info.get('city') + mobile_from_guild = guild_layer_two.get('mobilenumber') + + has_partner = parse_yes_no(guild_layer_two.get('hasPartner')) + is_foreign_national = parse_yes_no(guild_layer_two.get('isForeigner')) + + # پیدا کردن شهر (همان منطق قبلی) + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + + # به‌روزرسانی اطلاعات کاربر و فلگ استعلام صنف (بدون دست‌زدن به سایر فیلدهای صنف) + try: + user_profile = guild.user + if user_profile: + # اگر شماره موبایل در استعلام صنفی وجود دارد و با موبایل فعلی فرق می‌کند + if mobile_from_guild and mobile_from_guild != user_profile.mobile: + first_mobile_number = user_profile.mobile + second_mobile_number = mobile_from_guild + + # شماره جدید قبلا برای شخص دیگری ثبت نشده باشد + if SystemUserProfile.objects.filter(mobile=second_mobile_number) \ + .exclude(id=user_profile.id).exists(): + failed_records.append( + { + "guild_id": guild.id, + "national_id": national_id, + "reason": "این شماره در سامانه به نام شخص دیگری است", + } + ) + continue + + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + user = User.objects.get(id=user_profile.user.id) + user.username = second_mobile_number + user.save() + user_profile.mobile = second_mobile_number + else: + failed_records.append( + { + "guild_id": guild.id, + "national_id": national_id, + "reason": "در تغییر شماره موبایل در آرتا مشکلی به‌وجود آمده است", + } + ) + continue + + user_profile.national_id = national_id + user_profile.national_code = identity_no + user_profile.first_name = first_name + user_profile.last_name = last_name + user_profile.fullname = f"{first_name} {last_name}".strip() + user_profile.father_name = father_name + user_profile.gender = gender + if birthday_str: + user_profile.birthday = birthday_str + user_profile.is_alive = is_alive + if city: + user_profile.city = city + user_profile.province = city.province + user_profile.save() + + guild.has_inquiry = True + guild.save(update_fields=["has_inquiry"]) + updated_ids.append(guild.id) + except Exception as e: + failed_records.append( + {"guild_id": guild.id, "national_id": national_id, "reason": f"خطا در آپدیت صنف/کاربر: {str(e)}"} + ) + continue + + except Exception as e: + failed_records.append( + {"guild_id": guild.id, "national_id": national_id, "reason": f"خطای کلی: {str(e)}"} + ) + continue + + updated_guilds = Guilds.objects.filter(id__in=updated_ids) + serializer = GuildsSerializer(updated_guilds, many=True) + + return Response( + { + "result": "پردازش کامل شد", + "updated_count": len(updated_ids), + "failed_count": len(failed_records), + "failed_records": failed_records, + "guilds": serializer.data, + }, + status=status.HTTP_200_OK, + ) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +def report_guilds_without_national_or_pos_transactions(request): + """ + برگرداندن لیست صنف‌هایی که: + - کاربرشان کد ملی ندارد (national_id خالی/NULL است) + - یا هیچ تراکنش فعالی در جدول PosMachineTransactions برای آن‌ها ثبت نشده است + """ + # ۱) ابتدا برای همه صنف‌ها has_inquiry را False می‌کنیم + Guilds.objects.filter(trash=False).update(has_inquiry=False) + + # ۲) فقط صنف‌های فعال و غیرحذف‌شده را برای بررسی انتخاب می‌کنیم + queryset = Guilds.objects.filter(trash=False, active=True) + + result_guilds = [] + missing_national_id_count = 0 + missing_pos_txn_count = 0 + deactivated_count = 0 + + for guild in queryset: + national_id = getattr(getattr(guild, "user", None), "national_id", None) + has_national_id = bool(national_id) + + transactions = PosMachineTransactions.objects.filter( + trash=False, + pos__guild=guild, + paid=True + ).order_by('-date') + has_pos_transactions = transactions.exists() + + # صنف‌هایی که یا کد ملی ندارند یا هیچ تراکنش فعالی ندارند + if (not has_national_id) or (not has_pos_transactions): + result_guilds.append(guild) + if not has_national_id: + missing_national_id_count += 1 + if not has_pos_transactions: + missing_pos_txn_count += 1 + + # صنف‌هایی که نه کد ملی دارند و نه تراکنش => غیرفعال می‌شوند + if (not has_national_id) and (not has_pos_transactions) and guild.active: + guild.active = False + guild.save(update_fields=["active"]) + deactivated_count += 1 + + total = len(result_guilds) + serializer = GuildsSerializer(result_guilds, many=True) + + return Response( + { + "result": "ok", + "total": total, + "missing_national_id_count": missing_national_id_count, + "missing_pos_transactions_count": missing_pos_txn_count, + "deactivated_count": deactivated_count, + "guilds": serializer.data, + }, + status=status.HTTP_200_OK, + ) + + +@api_view(["GET"]) +@permission_classes([TokenHasReadWriteScope]) +def get_guilds_for_update_or_create(request): + national_code = request.GET['national_code'] + role = request.GET.get('role') + update_flag = request.GET.get('update', '').lower() == 'true' + users = SystemUserProfile.objects.filter(trash=False, national_id=national_code, active=True).order_by('id') + _guilds = Guilds.objects.filter( + trash=False, + user__national_id=national_code, + active=True + ).order_by('id') + api_data = {"dbRegister": False} + # اگر کاربر یا صنف نباشند، یا اگر update_flag برابر true باشد، برو داخل if + if (not users.exists() or not _guilds.exists()) or update_flag: + try: + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=person" + ) + person_data = person_response.json() + if not person_data.get('status'): + return Response({"result": "اطلاعات شخص یافت نشد"}, status=status.HTTP_403_FORBIDDEN) + person_info = person_data.get('data', {}) + api_data['user'] = person_info + except Exception as e: + return Response({"result": f"خطا در دریافت اطلاعات شخصی: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + try: + guild_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=guild" + ) + guild_data = guild_response.json() + if (not guild_data.get('status') or not guild_data.get('data')) and role == 'AdminX': + return Response(api_data, status=status.HTTP_200_OK) + # بررسی اینکه status true باشد و data وجود داشته باشد + if (not guild_data.get('status') or not guild_data.get('data')) and role != 'AdminX': + return Response({"result": "اطلاعات صنفی یافت نشد با واحد پشتیبانی تماس بگیرید."}, + status=status.HTTP_403_FORBIDDEN) + + guild_list = guild_data.get('data', []) + + # بررسی اینکه لیست guildها خالی نباشد + if not guild_list or len(guild_list) == 0: + return Response({"result": "اطلاعات صنفی یافت نشد با واحد پشتیبانی تماس بگیرید."}, + status=status.HTTP_403_FORBIDDEN) + + # بررسی اینکه حداقل یک guild با licenseIssueDate وجود داشته باشد + has_valid_guild = False + for guild in guild_list: + layer_two = guild.get('layerTwo', {}) + if layer_two and layer_two.get('licenseIssueDate'): + has_valid_guild = True + break + + if not has_valid_guild: + return Response({"result": "اطلاعات صنفی یافت نشد با واحد پشتیبانی تماس بگیرید."}, + status=status.HTTP_403_FORBIDDEN) + + guild_info = None + active_guilds = [] + inactive_guilds = [] + + # جدا کردن guildهای فعال و غیرفعال + for guild in guild_list: + layer_two = guild.get('layerTwo', {}) + license_status_value = layer_two.get('licenseStatus', '') if layer_two else '' + if license_status_value and 'فعال' in license_status_value: + active_guilds.append(guild) + else: + inactive_guilds.append(guild) + + # اول guild فعال را انتخاب کن + if active_guilds: + guild_info = active_guilds[0] + # اگر فعال نداشت، جدیدترین را بر اساس licenseIssueDate انتخاب کن + elif inactive_guilds: + def parse_persian_date(date_str): + """تبدیل تاریخ فارسی به jdatetime برای مقایسه""" + if not date_str: + return None + try: + # فرمت تاریخ فارسی معمولاً YYYY/MM/DD است + date_str = date_str.strip() + parts = date_str.split('/') + if len(parts) == 3: + year = int(parts[0]) + month = int(parts[1]) + day = int(parts[2]) + return jdatetime.date(year, month, day) + except: + pass + return None + + # پیدا کردن guild با جدیدترین تاریخ + latest_guild = None + latest_date = None + + for guild in inactive_guilds: + layer_two = guild.get('layerTwo', {}) + license_issue_date = layer_two.get('licenseIssueDate', '') if layer_two else '' + parsed_date = parse_persian_date(license_issue_date) + if parsed_date: + if latest_date is None or parsed_date > latest_date: + latest_date = parsed_date + latest_guild = guild + + if latest_guild: + guild_info = latest_guild + + # اگر guild_info پیدا نشد، اولین guild از لیست را انتخاب کن + if not guild_info and guild_list: + guild_info = guild_list[0] + + # ذخیره guild_info (که یا فعال است یا جدیدترین تاریخ را دارد) در api_data + if guild_info: + api_data['guild'] = guild_info + except Exception as e: + # اگر خطایی رخ داد، لاگ کن ولی guild_info را اگر پیدا شده بود اضافه کن + import logging + logger = logging.getLogger(__name__) + logger.error(f"خطا در پردازش اطلاعات صنفی: {str(e)}") + # اگر guild_info پیدا شده بود، آن را اضافه کن + if 'guild_info' in locals() and guild_info: + api_data['guild'] = guild_info + # اگر guild_info پیدا نشد ولی guild_list وجود دارد، اولین را انتخاب کن + elif 'guild_list' in locals() and guild_list: + api_data['guild'] = guild_list[0] + + # اگر چند کاربر با این کد ملی وجود داشت، بررسی کن کدام یک صنف دارد و شرایط را دارد + if users.count() > 1: + users_with_valid_guilds = [] + + # برای هر کاربر بررسی کن که آیا صنف دارد و شرایط را دارد + for user in users: + guilds = Guilds.objects.filter(trash=False, user=user, active=True) + + if guilds.exists(): + # بررسی کن که آیا صنف‌های این کاربر شرایط را دارند + has_steward_guild = guilds.filter(steward=True).exists() + + # بررسی کن که آیا صنف‌های این کاربر allocation جدید دارند + has_allocation = False + if not has_steward_guild: + for guild in guilds: + latest_allocation = StewardAllocation.objects.filter( + Q(to_steward=guild) | Q(to_guilds=guild), + trash=False + ).order_by('-date').first() + if latest_allocation: + has_allocation = True + break + + # اگر کاربر صنف دارد و شرایط را دارد، آن را اضافه کن + if has_steward_guild or has_allocation: + users_with_valid_guilds.append(user) + + # اگر کاربرانی با صنف معتبر وجود دارند، فقط آن‌ها را نگه دار + if users_with_valid_guilds: + # اگر چند کاربر با شرایط مناسب وجود داشت، جدیدترین را نگه دار + if len(users_with_valid_guilds) > 1: + # پیدا کردن جدیدترین کاربر بر اساس created_at و updated_at + valid_user_ids = [u.id for u in users_with_valid_guilds] + latest_user = SystemUserProfile.objects.filter(id__in=valid_user_ids).order_by('-id').first() + if latest_user: + users_with_valid_guilds = [latest_user] + else: + # اگر latest_user پیدا نشد، اولین را نگه دار + users_with_valid_guilds = users_with_valid_guilds[:1] + + # بقیه کاربران را غیرفعال کن و کد ملی را 0 بگذار + valid_user_ids = [u.id for u in users_with_valid_guilds] + guilds = Guilds.objects.filter(trash=False, user__in=users, active=True).exclude( + user__id__in=valid_user_ids).update(active=False) + users.exclude(id__in=valid_user_ids).update(active=False, national_id=0) + users = SystemUserProfile.objects.filter(id__in=valid_user_ids, trash=False, active=True) + + else: + # اگر هیچ کاربری صنف معتبر ندارد، جدیدترین را نگه دار + latest_user = users.order_by('-id').first() + users.exclude(id=latest_user.id).update(active=False, national_id=0) + users = SystemUserProfile.objects.filter(id=latest_user.id, trash=False, active=True) + + for user in users: + guilds = Guilds.objects.filter(trash=False, user=user, active=True) + + # اگر چند صنف وجود داشت، فقط آن‌هایی که شرایط را دارند فعال بمانند + if guilds.count() > 1: + # صنف‌هایی که باید فعال بمانند + guilds_to_keep_active = set() + + # 1. صنف‌هایی که steward=True هستند - همه را نگه دار + steward_guilds = guilds.filter(steward=True) + guilds_to_keep_active.update(steward_guilds.values_list('id', flat=True)) + + # 2. صنف‌هایی که در StewardAllocation هستند - فقط آن‌هایی که جدیدترین allocation را دارند + # پیدا کردن همه allocation‌های مربوط به این guilds + guilds_with_allocation_info = [] + for guild in guilds: + # بررسی وجود در StewardAllocation به عنوان to_steward یا to_guilds + latest_allocation = StewardAllocation.objects.filter( + Q(to_steward=guild) | Q(to_guilds=guild), + trash=False + ).order_by('-date').first() + + if latest_allocation: + # تاریخ allocation را بگیر (date یا created_at) + allocation_date = latest_allocation.date if latest_allocation.date else latest_allocation.created_at + guilds_with_allocation_info.append({ + 'guild_id': guild.id, + 'allocation_date': allocation_date, + 'allocation': latest_allocation + }) + + # اگر guildهایی با allocation وجود دارند، فقط آن‌هایی که جدیدترین تاریخ را دارند نگه دار + if guilds_with_allocation_info: + # فیلتر کردن مواردی که تاریخ دارند + valid_allocation_info = [item for item in guilds_with_allocation_info if item['allocation_date']] + if valid_allocation_info: + # پیدا کردن جدیدترین تاریخ + max_date = max(item['allocation_date'] for item in valid_allocation_info) + # اضافه کردن guildهایی که جدیدترین تاریخ را دارند + for item in valid_allocation_info: + if item['allocation_date'] == max_date: + guilds_to_keep_active.add(item['guild_id']) + + # اگر هیچ صنفی شرایط را نداشت، جدیدترین را نگه دار + if not guilds_to_keep_active: + latest_guild = guilds.order_by('-created_at', '-updated_at').first() + if latest_guild: + guilds_to_keep_active.add(latest_guild.id) + + # بقیه صنف‌ها را غیرفعال کن + guilds.exclude(id__in=guilds_to_keep_active).update(active=False) + + # بررسی اینکه آیا در api_data چیزی غیر از dbRegister وجود دارد + if api_data and any(key != 'dbRegister' for key in api_data.keys()): + return Response(api_data, status=status.HTTP_200_OK) + final_guilds = Guilds.objects.filter( + trash=False, + user__national_id=national_code, + active=True + ) + + serializer = GuildsSerializer(final_guilds.first()) + return Response(serializer.data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +def get_legal_person_unit_info(request): + national_code = request.GET.get('national_code') + + if not national_code: + return Response({"result": "کد ملی الزامی است"}, status=status.HTTP_400_BAD_REQUEST) + + existing_user = SystemUserProfile.objects.filter( + trash=False, + national_id=national_code, + active=True + ).first() + + if existing_user: + return Response({ + "result": "کاربر در سیستم وجود دارد!" + }, status=status.HTTP_403_FORBIDDEN) + + try: + unit_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=unit" + ) + unit_data = unit_response.json() + + if not unit_data.get('status') or not unit_data.get('data'): + return Response({"result": "اطلاعات واحد صنفی یافت نشد"}, status=status.HTTP_403_FORBIDDEN) + + unit_info = unit_data.get('data', {}) + unit_name = unit_info.get('name', '') + unit_national_code = unit_info.get('nationalCode', '') + unit_address = unit_info.get('address', '') + city_name = None + province_name = None + + if unit_address: + address_parts = unit_address.split() + if 'استان' in address_parts: + province_idx = address_parts.index('استان') + if province_idx + 1 < len(address_parts): + province_parts = [] + for i in range(province_idx + 1, len(address_parts)): + if address_parts[i] in ['شهرستان', 'شهر', 'بخش']: + break + province_parts.append(address_parts[i]) + if province_parts: + province_name = ' '.join(province_parts) + + if 'شهرستان' in address_parts: + city_idx = address_parts.index('شهرستان') + if city_idx + 1 < len(address_parts): + city_parts = [] + for i in range(city_idx + 1, len(address_parts)): + if address_parts[i] in ['بخش', 'شهر']: + break + city_parts.append(address_parts[i]) + if city_parts: + city_name = ' '.join(city_parts) + + if not city_name and 'شهر' in address_parts: + city_idx = address_parts.index('شهر') + if city_idx + 1 < len(address_parts): + city_parts = [] + for i in range(city_idx + 1, len(address_parts)): + if address_parts[i] in ['بخش', 'کوچه', 'خیابان', 'پلاک']: + break + city_parts.append(address_parts[i]) + if city_parts: + city_name = ' '.join(city_parts) + + first_name = unit_name.split(' ')[0] + last_name = unit_name.split(' ')[1] + result_data = { + "is_real_person": False, + "first_name": first_name or "", + "last_name": last_name or "", + "national_id": unit_national_code, + "province": province_name or "", + "address": unit_address, + "unit_name": unit_name, + + } + + return Response(result_data, status=status.HTTP_200_OK) + + except requests.RequestException as e: + return Response({"result": f"خطا در ارتباط با API: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + except Exception as e: + import logging + logger = logging.getLogger(__name__) + logger.error(f"خطا در پردازش اطلاعات واحد صنفی: {str(e)}") + return Response({"result": f"خطا در پردازش اطلاعات: {str(e)}"}, + status=status.HTTP_500_INTERNAL_SERVER_ERROR) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +def update_all_active_guilds_from_api(request): + """ + دریافت تمام guild های فعال و آپدیت آن‌ها از API + """ + import logging + logger = logging.getLogger(__name__) + + # دریافت تمام guild های فعال + active_guilds = Guilds.objects.filter(trash=False, active=True) + + success_count = 0 + failed_count = 0 + skipped_count = 0 + failed_records = [] + + def _normalize_fa_ar(text): + """نرمالایز کردن متن فارسی/عربی""" + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + + def parse_yes_no(val): + """تبدیل مقدار به boolean""" + if isinstance(val, bool): + return val + if isinstance(val, str): + return False if val == 'خیر' else True + return bool(val) + + def persian_date_to_datetime(persian_date_str): + """تبدیل تاریخ فارسی به datetime""" + if not persian_date_str: + return None + try: + persian_numbers = '۰۱۲۳۴۵۶۷۸۹' + english_numbers = '0123456789' + translation_table = str.maketrans(persian_numbers, english_numbers) + english_date = persian_date_str.translate(translation_table) + parts = english_date.split('/') + if len(parts) != 3: + return None + year = int(parts[0]) + month = int(parts[1]) + day = int(parts[2]) + return convert_to_miladi(year=year, month=month, day=day) + except: + return None + + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + + for guild in active_guilds: + try: + # دریافت کد ملی کاربر + user = guild.user + if not user or not user.national_id: + skipped_count += 1 + continue + + national_code = user.national_id + + # دریافت اطلاعات شخصی از API + try: + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=person" + ) + person_data = person_response.json() + if not person_data.get('status') or not person_data.get('data'): + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': 'اطلاعات شخصی یافت نشد' + }) + continue + person_info = person_data.get('data', {}) + except Exception as e: + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': f'خطا در دریافت اطلاعات شخصی: {str(e)}' + }) + continue + + # دریافت اطلاعات صنفی از API + try: + guild_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_code}&type=guild" + ) + guild_data = guild_response.json() + if not guild_data.get('status') or not guild_data.get('data'): + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': 'اطلاعات صنفی یافت نشد' + }) + continue + + guild_list = guild_data.get('data', []) + if not guild_list or len(guild_list) == 0: + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': 'لیست صنف‌ها خالی است' + }) + continue + + # انتخاب guild مناسب (فعال یا جدیدترین) + guild_info = None + active_guilds_list = [] + inactive_guilds_list = [] + + for g in guild_list: + layer_two = g.get('layerTwo', {}) + license_status_value = layer_two.get('licenseStatus', '') if layer_two else '' + if license_status_value and 'فعال' in license_status_value: + active_guilds_list.append(g) + else: + inactive_guilds_list.append(g) + + if active_guilds_list: + guild_info = active_guilds_list[0] + elif inactive_guilds_list: + def parse_persian_date(date_str): + if not date_str: + return None + try: + date_str = date_str.strip() + parts = date_str.split('/') + if len(parts) == 3: + year = int(parts[0]) + month = int(parts[1]) + day = int(parts[2]) + return jdatetime.date(year, month, day) + except: + pass + return None + + latest_guild = None + latest_date = None + for g in inactive_guilds_list: + layer_two = g.get('layerTwo', {}) + license_issue_date = layer_two.get('licenseIssueDate', '') if layer_two else '' + parsed_date = parse_persian_date(license_issue_date) + if parsed_date: + if latest_date is None or parsed_date > latest_date: + latest_date = parsed_date + latest_guild = g + + if latest_guild: + guild_info = latest_guild + + if not guild_info: + guild_info = guild_list[0] + + except Exception as e: + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': f'خطا در دریافت اطلاعات صنفی: {str(e)}' + }) + continue + + # استخراج اطلاعات از API + layer_one = guild_info.get('layerOne', {}) + layer_two = guild_info.get('layerTwo', {}) + + # اطلاعات شخصی + first_name = person_info.get('firstName', '') + last_name = person_info.get('lastName', '') + father_name = person_info.get('fatherName', '') + gender = person_info.get('gender', '') + identity_no = person_info.get('identityNo', '') + birth_date = person_info.get('birthDate', '') + city_name = layer_two.get('city', '') + address_text = layer_two.get('address', '') + postal_code = layer_two.get('postalcode', '') + mobile = person_info.get('mobile', '') or person_info.get('mobilenumber', '') + + # اطلاعات صنفی + title = layer_one.get('title', '') or layer_two.get('title', '') or guild_info.get('title', '') + license_number = guild_info.get('licenseNumber', '') + license_type = guild_info.get('licenseType', '') + license_status = guild_info.get('licenseStatus', '') + license_issue_date = layer_two.get('licenseIssueDate', '') + license_expire_date = guild_info.get('licenseExpireDate', '') + type_activity_name = layer_one.get('isicname', '') or layer_two.get('isicname', '') + company_name = layer_one.get('corporationName', '') or layer_two.get('corporationName', '') + company_identifier = layer_one.get('nationalId', '') or layer_two.get('nationalId', '') + union_name = layer_one.get('unionName', '') or layer_two.get('unionName', '') + phone = layer_one.get('phonenumber', '') or layer_two.get('phonenumber', '') + has_partner_val = layer_one.get('hasPartner', '') or layer_two.get('hasPartner', '') + is_foreigner_val = layer_one.get('isForeigner', '') or layer_two.get('isForeigner', '') + steward = guild.steward # حفظ مقدار فعلی + + # تبدیل تاریخ تولد + birthday_str = None + if birth_date: + try: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + except: + pass + + # تبدیل boolean ها + has_partner = parse_yes_no(has_partner_val) + is_foreign_national = parse_yes_no(is_foreigner_val) + + # پیدا کردن شهر + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + + if not city: + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': national_code, + 'error': f"شهر '{city_name}' یافت نشد" + }) + continue + + province = city.province + + # آپدیت اطلاعات کاربر + if user: + user.national_id = national_code + user.national_code = identity_no + user.father_name = father_name + user.gender = gender + user.birthday = birthday_str + if city: + user.city = city + user.province = province + if first_name: + user.first_name = first_name + if last_name: + user.last_name = last_name + user.fullname = f"{first_name} {last_name}".strip() + if mobile and not user.mobile: + user.mobile = mobile + user.save() + + # ایجاد یا آپدیت آدرس + if address_text: + address = SystemAddress(city=city, province=province, address=address_text, postal_code=postal_code) + address.save() + else: + address = guild.address if guild.address else None + + # پیدا کردن TypeActivity و AreaActivity + from panel.models import TypeActivity, AreaActivity + type_activity = TypeActivity.objects.filter(title__icontains=type_activity_name, trash=False).first() + if not type_activity: + type_activity = TypeActivity.objects.filter(trash=False).first() + + area_activity = AreaActivity.objects.filter(trash=False).first() + + # آپدیت guild + guild.guilds_name = title + guild.license_number = license_number + guild.license_type = license_type + guild.license_status = license_status + guild.is_foreign_national = is_foreign_national + guild.has_partner = has_partner + guild.has_inquiry = True + guild.company_name = company_name + guild.company_identifier = company_identifier + if address: + guild.address = address + guild.type_activity = type_activity.title if type_activity else type_activity_name + guild.area_activity = area_activity.title if area_activity else '' + guild.guild_type_activity = type_activity + guild.guild_area_activity = area_activity + guild.union_name = union_name + guild.phone_number = phone + guild.active = True + + if license_issue_date: + converted_date = persian_date_to_datetime(license_issue_date) + if converted_date: + guild.license_issue_date = converted_date + + if license_expire_date: + converted_date = persian_date_to_datetime(license_expire_date) + if converted_date: + guild.license_expire_date = converted_date + + guild.save() + success_count += 1 + + except Exception as e: + failed_count += 1 + failed_records.append({ + 'guild_id': guild.id, + 'national_id': getattr(guild.user, 'national_id', '') if guild.user else '', + 'error': f'خطای کلی: {str(e)}' + }) + logger.error(f"خطا در آپدیت guild {guild.id}: {str(e)}") + continue + + return Response({ + 'result': 'پردازش کامل شد', + 'total_guilds': active_guilds.count(), + 'success_count': success_count, + 'failed_count': failed_count, + 'skipped_count': skipped_count, + 'failed_records': failed_records[:100] # فقط 100 مورد اول خطاها + }, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def find_users_with_duplicate_national_id(request): + users = SystemUserProfile.objects.filter( + trash=False, + national_id__isnull=False, + role__name__in=['Guilds', 'Steward'] + ).exclude(national_id__exact='').exclude(national_id__exact='0').distinct() + + national_id_dict = {} + for user in users: + nid = str(user.national_id).strip() + if nid.isdigit() and len(nid) == 10: + if nid not in national_id_dict: + national_id_dict[nid] = [] + national_id_dict[nid].append(user) + + result = [] + for nid, user_list in national_id_dict.items(): + if len(user_list) > 1: + users_data = [] + for user in user_list: + users_data.append({ + 'id': user.id, + 'mobile': user.mobile, + 'first_name': user.first_name, + 'last_name': user.last_name, + 'fullname': user.fullname, + 'national_id': user.national_id + }) + result.append({ + 'national_id': nid, + 'count': len(user_list), + 'users': users_data + }) + + result.sort(key=lambda x: x['count'], reverse=True) + + total_duplicate = len(result) + total_users = 0 + for item in result: + total_users += item['count'] + + return Response({ + 'result': 'ok', + 'total_duplicate_national_ids': total_duplicate, + 'total_users_with_duplicate': total_users, + 'duplicate_national_ids': result + }, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fix_duplicate_national_id_users(request): + users = SystemUserProfile.objects.filter( + trash=False, + national_id__isnull=False, + role__name__in=['Guilds', 'Steward'] + ).exclude(national_id__exact='').exclude(national_id__exact='0') + + national_id_dict = {} + for user in users: + nid = str(user.national_id).strip() + if nid.isdigit() and len(nid) == 10: + if nid not in national_id_dict: + national_id_dict[nid] = [] + national_id_dict[nid].append(user) + + duplicate_national_ids = {} + for nid, user_list in national_id_dict.items(): + if len(user_list) > 1: + duplicate_national_ids[nid] = user_list + + all_cities_cache = list(City.objects.filter(trash=False).values('id', 'name')) + + def _normalize_fa_ar(text): + if not text: + return text + mapping = { + 'ك': 'ک', + 'ي': 'ی', + 'ى': 'ی', + '\u0649': 'ی', + '\u06CC': 'ی', + '\u064A': 'ی', + 'ۀ': 'ه', + 'ة': 'ه', + 'ؤ': 'و', + 'أ': 'ا', + 'إ': 'ا', + 'ٱ': 'ا', + '\u200c': ' ', + } + out = str(text) + for src, dst in mapping.items(): + out = out.replace(src, dst) + return out.strip() + + def parse_yes_no(val): + if isinstance(val, bool): + return val + if isinstance(val, str): + x = False if val.strip() == 'خیر' else True + return x + return bool(val) + + def find_city(city_name): + if not city_name: + return None + city = City.objects.filter(name__icontains=city_name, trash=False).first() + if not city: + normalized_city = _normalize_fa_ar(city_name) + city = City.objects.filter(name__icontains=normalized_city, trash=False).first() + if not city: + alt_city = str(city_name or '') + alt_city = alt_city.replace('ک', 'ك').replace('ی', 'ي') + city = City.objects.filter(name__icontains=alt_city, trash=False).first() + if not city: + try: + target = _normalize_fa_ar(city_name or '') + best_id = None + best_ratio = 0.0 + for c in all_cities_cache: + cand = _normalize_fa_ar(c.get('name', '') or '') + ratio = difflib.SequenceMatcher(None, target, cand).ratio() + if ratio > best_ratio: + best_ratio = ratio + best_id = c['id'] + if best_id is not None and best_ratio >= 0.72: + city = City.objects.filter(id=best_id, trash=False).first() + except Exception: + city = None + return city + + def generate_random_mobile(): + while True: + random_num = ''.join([str(random.randint(0, 9)) for _ in range(9)]) + mobile = '08' + random_num + if not SystemUserProfile.objects.filter(mobile=mobile).exists(): + try: + check_response = requests.get( + f"{ARTA_URL_CHECK_USER_EXISTS}?username={mobile}", + verify=False + ) + if check_response.status_code == 200: + return mobile + except Exception: + continue + + processed = [] + failed = [] + + for national_id, user_list in duplicate_national_ids.items(): + try: + guild_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=guild" + ) + guild_data = guild_response.json() + + if not guild_data.get('status') or not guild_data.get('data'): + failed.append({ + 'national_id': national_id, + 'reason': 'اطلاعات صنفی یافت نشد' + }) + continue + + guild_list = guild_data.get('data', []) + guild_info = None + + for g in guild_list: + license_status_value = g.get('licenseStatus', '') + if license_status_value and 'فعال' in license_status_value: + guild_info = g + break + + if not guild_info and guild_list: + guild_info = guild_list[0] + + if not guild_info: + failed.append({ + 'national_id': national_id, + 'reason': 'اطلاعات صنفی یافت نشد' + }) + continue + + guild_layer_two = guild_info.get('layerTwo', {}) + mobile_from_api = guild_layer_two.get('mobilenumber') + steward_from_api = guild_layer_two.get('steward', False) + + if isinstance(steward_from_api, str): + steward_value = steward_from_api.strip().lower() in ('true', 'بله', '1', 'yes') + else: + steward_value = bool(steward_from_api) + + if not mobile_from_api: + failed.append({ + 'national_id': national_id, + 'reason': 'شماره موبایل در API یافت نشد' + }) + continue + + existing_user = SystemUserProfile.objects.filter( + trash=False, + mobile=mobile_from_api + ).first() + + if existing_user: + has_killhouse = existing_user.role.filter(name='KillHouse').exists() + if not has_killhouse: + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=person" + ) + person_data = person_response.json() + + if not person_data.get('status'): + failed.append({ + 'national_id': national_id, + 'reason': 'اطلاعات شخص یافت نشد' + }) + continue + + person_info = person_data.get('data', {}) + + first_name = person_info.get('firstName') + last_name = person_info.get('lastName') + father_name = person_info.get('fatherName') + gender = person_info.get('gender') + identity_no = person_info.get('identityNo') + is_alive = person_info.get('isLive', True) + birth_date = person_info.get('birthDate') + + try: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + except Exception: + birthday_str = None + + city_name = guild_info.get('city') + city = find_city(city_name) + + existing_user.national_id = national_id + existing_user.national_code = identity_no + existing_user.first_name = first_name + existing_user.last_name = last_name + existing_user.fullname = f"{first_name} {last_name}".strip() + existing_user.father_name = father_name + existing_user.gender = gender + if birthday_str: + existing_user.birthday = birthday_str + existing_user.is_alive = is_alive + if city: + existing_user.city = city + existing_user.province = city.province + existing_user.save() + + for user in user_list: + has_killhouse = user.role.filter(name='KillHouse').exists() + if user.id != existing_user.id: + user_guilds = Guilds.objects.filter(trash=False, user=user) + if user_guilds.exists(): + user_guilds.update(active=False) + + has_killhouse = user.role.filter(name='KillHouse').exists() + if not has_killhouse: + random_mobile = generate_random_mobile() + data = { + "first_mobile_number": user.mobile, + "second_mobile_number": random_mobile, + } + user.national_id = '0' + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + user.user.username = random_mobile + user.user.save() + user.mobile = random_mobile + user.save() + + else: + user_guilds = Guilds.objects.filter(trash=False, user=user) + if user_guilds.exists(): + user_guilds.update(active=False) + user.national_id = '0' + user.save() + else: + if has_killhouse: + user_guilds = Guilds.objects.filter(trash=False, user=user) + if user_guilds.exists(): + user_guilds.update(active=False) + user.national_id = '0' + user.save() + + processed.append({ + 'national_id': national_id, + 'action': 'updated_existing_user', + 'user_id': existing_user.id + }) + else: + for user in user_list: + has_killhouse = existing_user.role.filter(name='KillHouse').exists() + if not has_killhouse: + user.active = False + user.save() + + user_guilds = Guilds.objects.filter(trash=False, user=user) + user_guilds.update(active=False) + + person_response = requests.get( + f"https://pay.rasadyar.net/national-documents?info={national_id}&type=person" + ) + person_data = person_response.json() + + if not person_data.get('status'): + failed.append({ + 'national_id': national_id, + 'reason': 'اطلاعات شخص یافت نشد' + }) + continue + + person_info = person_data.get('data', {}) + + first_name = person_info.get('firstName') + last_name = person_info.get('lastName') + father_name = person_info.get('fatherName') + gender = person_info.get('gender') + identity_no = person_info.get('identityNo') + is_alive = person_info.get('isLive', True) + birth_date = person_info.get('birthDate') + + try: + jalali_date = jdatetime.datetime.strptime(birth_date, "%Y/%m/%d").togregorian().date() + birthday_str = jalali_date.strftime("%Y-%m-%d") + except Exception: + birthday_str = None + + city_name = guild_info.get('city') + city = find_city(city_name) + + role_name = "Steward" if steward_value else "Guilds" + + password = '123456' + register_payload = { + "username": mobile_from_api, + "first_name": first_name or "", + "last_name": last_name or "", + "password": password, + "national_code": identity_no or '0', + "role": role_name, + "api_key": PROJECT_API_KEY + } + + req = requests.post( + url=ARTA_REGISTER, + data=register_payload, + verify=False + ) + + if req.status_code == 200: + hashed_password = hashlib.sha256(password.encode()).hexdigest() + user = User.objects.filter(username=mobile_from_api).first() + if not user: + user = User( + username=mobile_from_api, + first_name=first_name or "", + last_name=last_name or "", + password=hashed_password + ) + user.save() + + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + + new_user = SystemUserProfile( + mobile=mobile_from_api, + first_name=first_name, + last_name=last_name, + fullname=f"{first_name} {last_name}".strip(), + user=user, + base_order=base_id, + password=password, + national_id=national_id, + national_code=identity_no, + father_name=father_name, + gender=gender, + birthday=birthday_str if birthday_str else str(datetime.datetime.now().date()), + is_alive=is_alive, + city=city, + province=city.province if city else None + ) + new_user.save() + + if steward_value: + group = Group.objects.get(name__exact="Steward") + else: + group = Group.objects.get(name__exact="Guilds") + new_user.role.add(group) + + wallet = Wallet() + wallet.save() + + address = SystemAddress( + province=city.province if city else None, + city=city, + address=city_name or '' + ) + address.save() + + title = guild_info.get('title', f"{first_name} {last_name}".strip()) + license_number = guild_info.get('licenseNumber', '') + license_type = guild_info.get('licenseType', '') + license_status = guild_info.get('licenseStatus', '') + type_activity_name = guild_info.get('isicname', '') + company_name = guild_info.get('corporationName', '') + company_identifier = guild_info.get('nationalId', '') + union_name = guild_info.get('unionName', '') + phone = guild_layer_two.get('phonenumber', '') + has_partner_val = guild_layer_two.get('hasPartner', False) + is_foreigner_val = guild_layer_two.get('isForeigner', False) + + has_partner = parse_yes_no(has_partner_val) + is_foreign_national = parse_yes_no(is_foreigner_val) + + from panel.models import TypeActivity, AreaActivity + type_activity = TypeActivity.objects.filter(title__icontains=type_activity_name, + trash=False).first() + if not type_activity: + type_activity = TypeActivity.objects.filter(trash=False).first() + + area_activity = AreaActivity.objects.filter(trash=False).first() + + new_guild = Guilds( + user=new_user, + guilds_name=title, + license_number=license_number, + license_type=license_type, + license_status=license_status, + is_foreign_national=is_foreign_national, + has_partner=has_partner, + has_inquiry=True, + steward=steward_value, + company_name=company_name, + company_identifier=company_identifier, + address=address, + wallet=wallet, + type_activity=type_activity.title if type_activity else type_activity_name, + area_activity=area_activity.title if area_activity else '', + guild_type_activity=type_activity, + guild_area_activity=area_activity, + union_name=union_name, + phone_number=phone, + active=True, + province_accept_state='pending' + ) + new_guild.save() + + from panel.models import NewProduct, BroadcastPrice + parent_product = NewProduct.objects.all().first() + price = BroadcastPrice.objects.filter(trash=False).first() + + if parent_product and price: + approved_price = price.steward_price if steward_value else price.guild_price + approved_type = price.active if approved_price > 0 else False + + product = RolesProducts( + parent_product=parent_product, + guild=new_guild, + name='مرغ گرم', + approved_price_status=approved_type, + approved_price=approved_price, + ) + product.save() + + processed.append({ + 'national_id': national_id, + 'action': 'created_new_user', + 'user_id': new_user.id + }) + else: + failed.append({ + 'national_id': national_id, + 'reason': 'خطا در ثبت کاربر در آرتا' + }) + except Exception as e: + failed.append({ + 'national_id': national_id, + 'reason': f'خطا: {str(e)}' + }) + continue + + return Response({ + 'result': 'ok', + 'processed_count': len(processed), + 'failed_count': len(failed), + 'processed': processed, + 'failed': failed + }, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def fix_duplicate_guilds_steward_allocation(request): + users_with_multiple_guilds = SystemUserProfile.objects.filter( + trash=False, + role__name__in=['Guilds', 'Steward'] + ).annotate( + guilds_count=Count('guilds_user', filter=Q(guilds_user__trash=False)) + ).filter(guilds_count__gt=1) + + processed = [] + failed = [] + + for user in users_with_multiple_guilds: + try: + user_guilds = Guilds.objects.filter( + user=user, + trash=False, + ).order_by('-active', '-create_date') + + if user_guilds.count() <= 1: + continue + + active_guild = user_guilds.filter(active=True).first() + + if not active_guild: + continue + + inactive_guilds = user_guilds.exclude(id=active_guild.id).filter(active=False) + + if not inactive_guilds.exists(): + continue + + allocations_to_move = StewardAllocation.objects.filter( + trash=False + ).filter( + Q(guilds__in=inactive_guilds) | + Q(to_guilds__in=inactive_guilds) | + Q(to_steward__in=inactive_guilds) + ) + + allocations_moved_count = 0 + steward_updated = False + for allocation in allocations_to_move: + if allocation.guilds and allocation.guilds in inactive_guilds: + allocation.guilds = active_guild + if allocation.to_guilds and allocation.to_guilds in inactive_guilds: + allocation.to_guilds = active_guild + if allocation.to_steward and allocation.to_steward in inactive_guilds: + allocation.to_steward = active_guild + if not active_guild.steward: + active_guild.steward = True + active_guild.save() + steward_updated = True + allocation.save() + allocations_moved_count += 1 + + if steward_updated: + try: + steward_group = Group.objects.get(name__exact="Steward") + if not user.role.filter(id=steward_group.id).exists(): + user.role.add(steward_group) + except Group.DoesNotExist: + pass + + pos_machines_to_move = POSMachine.objects.filter( + trash=False, + guild__in=inactive_guilds + ) + + pos_machines_moved_count = 0 + for pos_machine in pos_machines_to_move: + pos_machine.guild = active_guild + pos_machine.save() + pos_machines_moved_count += 1 + + pos_segmentations_to_move = PosSegmentation.objects.filter( + trash=False + ).filter( + Q(guild__in=inactive_guilds) | + Q(to_guild__in=inactive_guilds) + ) + + pos_segmentations_moved_count = 0 + for pos_segmentation in pos_segmentations_to_move: + + if pos_segmentation.guild and pos_segmentation.guild in inactive_guilds: + pos_segmentation.guild = active_guild + if pos_segmentation.to_guild and pos_segmentation.to_guild in inactive_guilds: + pos_segmentation.to_guild = active_guild + pos_segmentation.save() + pos_segmentations_moved_count += 1 + + roles_products_to_trash = RolesProducts.objects.filter( + trash=False, + guild__in=inactive_guilds + ) + + roles_products_trashed_count = 0 + for roles_product in roles_products_to_trash: + roles_product.trash = True + roles_product.save() + roles_products_trashed_count += 1 + + for inactive_guild in inactive_guilds: + inactive_guild.trash = True + inactive_guild.save() + + active_guild_products = RolesProducts.objects.get( + trash=False, + guild=active_guild + ) + + try: + guild_steward_allocations_product_warehousing(active_guild_products) + except Exception: + pass + + processed.append({ + 'user_id': user.id, + 'user_mobile': user.mobile, + 'user_national_id': user.national_id, + 'active_guild_id': active_guild.id, + 'active_guild_name': active_guild.guilds_name, + 'inactive_guilds_count': inactive_guilds.count(), + 'inactive_guild_ids': list(inactive_guilds.values_list('id', flat=True)), + 'allocations_moved': allocations_moved_count, + 'pos_machines_moved': pos_machines_moved_count, + 'pos_segmentations_moved': pos_segmentations_moved_count, + 'roles_products_trashed': roles_products_trashed_count + }) + + except Exception as e: + failed.append({ + 'user_id': user.id, + 'user_mobile': user.mobile, + 'reason': f'خطا: {str(e)}' + }) + continue + + return Response({ + 'result': 'ok', + 'processed_count': len(processed), + 'failed_count': len(failed), + 'processed': processed, + 'failed': failed + }, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def upload_image_to_server_for_poultry_science(request): + files = request.FILES.getlist('file') + if not files: + single_file = request.FILES.get('file') + if single_file: + files = [single_file] + + uploaded_urls = [] + + for idx, f in enumerate(files): + now = datetime.datetime.now() + name = now.strftime('%Y%m%d%H%M%S') + name = f"{name}{idx}.jpg" + + url = send_image_to_server_for_poultry_science(f, name) + uploaded_urls.append(url) + + return Response({ + 'urls': uploaded_urls + }, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def poultry_science_for_bazresi(request): + query = PoultryScienceReport.objects.filter(trash=False).order_by('-id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if search != 'undefined' and search.strip(): + query = query.filter( + build_query(PoultryScienceReportFilterSet.Meta.fields, value) + ) + + serializer = PoultryScienceReportSerializer(query, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) \ No newline at end of file diff --git a/panel/VetFarm/__init__.py b/panel/VetFarm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/VetFarm/excel_processing.py b/panel/VetFarm/excel_processing.py new file mode 100644 index 0000000..29c8c72 --- /dev/null +++ b/panel/VetFarm/excel_processing.py @@ -0,0 +1,679 @@ +import datetime +from io import BytesIO +from django.db.models import Sum, Q, F +from openpyxl import Workbook +from openpyxl.styles import Alignment +from django.http import HttpResponse +from panel.helper_excel import shamsi_date, create_header, excel_description, create_header_freez, create_value +from panel.models import Poultry, PoultryHatching, VetFarm, PoultryRequest, KillHouseRequest + + +def technical_responsible_performance_excel(request): + vat_farm = VetFarm.objects.filter(trash=False, poultry__isnull=False, vet__key=request.GET.get('key')) + poultry_id = vat_farm.values_list('poultry__id', flat=True).distinct() + poultries = Poultry.objects.filter(id__in=poultry_id, trash=False) + excel_options = [ + 'ردیف', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'نام واحد', + 'نام و خانوادگی مالک', + 'تلفن مالک', + 'جوجه ریزی فعال', + 'تعداد دوره جوجه ریزی', + 'مجموع جوجه ریزی', + 'تعداد درخواست کشتار', + 'حجم درخواست کشتار', + 'وزن درخواست کشتار', + 'میانگین وزنی درخواست کشتار', + 'تعداد بار', + 'حجم بار', + 'وزن بارها', + 'تعداد بارهای دارای مجوز قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'وزن بارهای دارای کد قرنطینه', + 'تعداد بارهای فاقد مجوز قرنطینه', + 'حجم بارهای فاقد کد قرنطینه', + 'وزن بارهای فاقد کد قرنطینه', + 'تعداد بارهای مغایرت دار', + 'حجم بارهای مغایرت دار', + 'وزن بارهای مغایرت دار', + 'تعداد بار خارج استان', + 'حجم بار خارج استان', + 'وزن بار خارج استان', + 'میانگین وزن خارج از استان', + + ] + date1 = datetime.datetime.now().date() + from_date_1 = shamsi_date(date1) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد واحد تحت نظر', + 'مجموع جوجه ریزی تحت نظر', + 'مجموع درخواست کشتار', + 'مجموع حجم درخواست کشتار', + 'مجموع وزن درخواست کشتار', + 'مجموع تعداد بارها', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'مجموع تعداد بارهای قرنطینه شده', + 'مجموع حجم بارهای قرنطینه شده', + 'مجموع وزن بارهای قرنطینه شده', + 'مجموع تعداد بارهای فاقد قرنطینه', + 'مجموع حجم بارهای فاقد قرنطینه', + 'مجموع وزن بارهای فاقد قرنطینه نشده', + 'مجموع تعداد بارهای دارای مغایرت', + 'مجموع حجم بارهای دارای مغایرت', + 'مجموع وزن بارهای دارای مغایرت', + 'مجموع تعداد بارهای خارج استان', + 'مجموع حجم بارهای خارج استان', + 'مجموع وزن بارهای خارج استان', + 'مجموع وزن تقریبی بارهای خارج استان', + + ] + header_list2 = [ + 'درصد قرنطینه سازی بارها', + 'درصد عدم قرنطینه سازی بارها', + + ] + excel_description(worksheet, 'A2', 'عملکرد مسئول فنی', color='red', row2='B2') + vat_farm = vat_farm.first() + description = f'{vat_farm.vet.user.fullname}/{vat_farm.vet.user.mobile}' + excel_description(worksheet, 'A3', description, color='red', row2='B3') + + create_header(worksheet, header_list, 3, 2, height=20, color='green') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=22) + + l = 6 + m = 1 + poultry_hatchings = PoultryHatching.objects.filter(poultry__in=poultries, trash=False).only('quantity', 'left_over' + ) + poultry_requests = PoultryRequest.objects.filter(trash=False, poultry__in=poultries, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only('quantity', + 'Index_weight') + kill_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_requests).only( + 'accepted_real_quantity', 'accepted_real_weight') + + out_poultry_requests = poultry_requests.filter(out=True, out_province_request_cancel=False).only( + 'quantity', 'Index_weight' + ) + + for poultry in poultries: + poultry_hatching = poultry_hatchings.filter(poultry=poultry) + poultry_hatching_pending = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False).last() + + hatching = 'ندارد' if not poultry_hatching_pending else f'دارد' + period='-' + if poultry_hatching_pending: + period = poultry_hatching_pending.period + else: + if poultry_hatching: + period = poultry_hatching.last().period + + total_quantity = \ + poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_request = poultry_requests.filter(poultry=poultry) + total_quantity_poultry_request = \ + poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request = \ + poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request = \ + poultry_request.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight = round(total_index_weight_poultry_request / len(poultry_request), 2) if len( + poultry_request) > 0 else 0 + kill_request = kill_requests.filter(province_request__poultry_request__in=poultry_request) + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight = kill_request.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + has_code = kill_request.filter(clearance_code__isnull=False) + kill_request_quantity_has_code = has_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_has_code = has_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + hasnt_code = kill_request.filter(clearance_code__isnull=True) + kill_request_quantity_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + deffrent_bar = kill_request.filter( + ~Q(quantity=F('quarantine_quantity') + , quarantine_quantity__isnull=False)) + kill_request_quantity_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + out_poultry_request = out_poultry_requests.filter(poultry=poultry) + total_quantity_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight_out = round(total_index_weight_poultry_request_out / len(out_poultry_request), 2) if len( + out_poultry_request) > 0 else 0 + + list1 = [ + m, + vat_farm.vet.user.fullname, + vat_farm.vet.user.mobile, + poultry.unit_name, + poultry.user.fullname, + poultry.user.mobile, + hatching, + period, + total_quantity, + len(poultry_request), + total_quantity_poultry_request, + total_weight_poultry_request, + index_weight, + len(kill_request), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_request), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + ] + create_value(worksheet, list1, l, 1) + m += 1 + l += 1 + total_quantity = \ + poultry_hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_quantity_poultry_request = \ + poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + kill_request_quantity = kill_requests.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight = kill_requests.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + has_code = kill_requests.filter(clearance_code__isnull=False) + kill_request_quantity_has_code = has_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_has_code = has_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + deffrent_bar = kill_requests.filter( + ~Q(quantity=F('quarantine_quantity') + , quarantine_quantity__isnull=False)) + kill_request_quantity_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + hasnt_code = kill_requests.filter(clearance_code__isnull=True) + kill_request_quantity_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_quantity_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight_out = round(total_index_weight_poultry_request_out / len(out_poultry_requests), 2) if len( + out_poultry_requests) > 0 else 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + len(poultry_requests), + total_quantity_poultry_request, + total_weight_poultry_request, + '', + len(kill_requests), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_requests), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + + ] + + create_value(worksheet, list2, l + 2, 1, color='green') + + value_header_list = [ + len(poultries), + total_quantity, + len(poultry_requests), + total_quantity_poultry_request, + total_weight_poultry_request, + len(kill_requests), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_requests), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + ] + create_value(worksheet, value_header_list, 3, 3) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="عملکرد مسئول فنی({vat_farm.vet.user.fullname}).xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + +def totoal_technical_responsible_performance_excel(request): + vat_farm = VetFarm.objects.filter(trash=False, poultry__isnull=False) + poultry_id = vat_farm.values_list('poultry__id', flat=True).distinct() + poultries = Poultry.objects.filter(id__in=poultry_id, trash=False) + excel_options = [ + 'ردیف', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'تعداد واحد تحت نظر', + 'مجموع جوجه ریزی تحت نظر', + 'مجموع درخواست کشتار', + 'مجموع حجم درخواست کشتار', + 'مجموع وزن درخواست کشتار', + 'مجموع تعداد بارها', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'مجموع تعداد بارهای قرنطینه شده', + 'مجموع حجم بارهای قرنطینه شده', + 'مجموع وزن بارهای قرنطینه شده', + 'مجموع تعداد بارهای فاقد قرنطینه', + 'مجموع حجم بارهای فاقد قرنطینه', + 'مجموع وزن بارهای فاقد قرنطینه نشده', + 'مجموع تعداد بارهای دارای مغایرت', + 'مجموع حجم بارهای دارای مغایرت', + 'مجموع وزن بارهای دارای مغایرت', + 'مجموع تعداد بارهای خارج استان', + 'مجموع حجم بارهای خارج استان', + 'مجموع وزن بارهای خارج استان', + 'مجموع وزن تقریبی بارهای خارج استان', + + ] + date1 = datetime.datetime.now().date() + from_date_1 = shamsi_date(date1) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد واحد تحت نظر', + 'مجموع جوجه ریزی تحت نظر', + 'مجموع درخواست کشتار', + 'مجموع حجم درخواست کشتار', + 'مجموع وزن درخواست کشتار', + 'مجموع تعداد بارها', + 'مجموع حجم بارها', + 'مجموع وزن بارها', + 'مجموع تعداد بارهای قرنطینه شده', + 'مجموع حجم بارهای قرنطینه شده', + 'مجموع وزن بارهای قرنطینه شده', + 'مجموع تعداد بارهای فاقد قرنطینه', + 'مجموع حجم بارهای فاقد قرنطینه', + 'مجموع وزن بارهای فاقد قرنطینه نشده', + 'مجموع تعداد بارهای دارای مغایرت', + 'مجموع حجم بارهای دارای مغایرت', + 'مجموع وزن بارهای دارای مغایرت', + 'مجموع تعداد بارهای خارج استان', + 'مجموع حجم بارهای خارج استان', + 'مجموع وزن بارهای خارج استان', + 'مجموع وزن تقریبی بارهای خارج استان', + + ] + + excel_description(worksheet, 'A2', 'عملکرد مسئول فنی', color='red', row2='B2') + + + create_header(worksheet, header_list, 3, 2, height=20, color='green') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=22) + + l = 6 + m = 1 + poultry_hatchings = PoultryHatching.objects.filter(poultry__in=poultries, trash=False).only('quantity', 'left_over') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(send_date__date__gte=date1,send_date__date__lte=date2,trash=False, poultry__in=poultries, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only('quantity', + 'Index_weight') + kill_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1,kill_request__recive_date__date__lte=date2,trash=False, + province_request__poultry_request__in=poultry_requests).only( + 'accepted_real_quantity', 'accepted_real_weight') + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, poultry__in=poultries, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only('quantity', + 'Index_weight') + + kill_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_requests).only( + 'accepted_real_quantity', 'accepted_real_weight') + + + out_poultry_requests = poultry_requests.filter(out=True, out_province_request_cancel=False).only( + 'quantity', 'Index_weight' + ) + for vet in vat_farm: + poultry = Poultry.objects.filter(id=vet.poultry.id, trash=False) + poultry_hatchings = PoultryHatching.objects.filter(poultry__in=poultry, trash=False).only('quantity', + 'left_over') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(send_date__date__gte=date1, send_date__date__lte=date2, + trash=False, poultry__in=poultry, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only( + 'quantity', + 'Index_weight') + kill_requests = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, trash=False, + province_request__poultry_request__in=poultry).only( + 'accepted_real_quantity', 'accepted_real_weight') + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, poultry__in=poultry, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only( + 'quantity', + 'Index_weight') + + kill_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_requests).only( + 'accepted_real_quantity', 'accepted_real_weight') + + out_poultry_requests = poultry_requests.filter(out=True, out_province_request_cancel=False).only( + 'quantity', 'Index_weight' + ) + poultry_hatching = poultry_hatchings.filter(poultry=poultries) + total_quantity = \ + poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_request = poultry_requests.filter(poultry=poultry) + total_quantity_poultry_request = \ + poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request = \ + poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request = \ + poultry_request.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight = round(total_index_weight_poultry_request / len(poultry_request), 2) if len( + poultry_request) > 0 else 0 + kill_request = kill_requests.filter(province_request__poultry_request__in=poultry_request) + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight = kill_request.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + has_code = kill_request.filter(clearance_code__isnull=False) + kill_request_quantity_has_code = has_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_has_code = has_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + hasnt_code = kill_request.filter(clearance_code__isnull=True) + kill_request_quantity_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + deffrent_bar = kill_request.filter( + ~Q(quantity=F('quarantine_quantity') + , quarantine_quantity__isnull=False)) + kill_request_quantity_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + out_poultry_request = out_poultry_requests.filter(poultry=poultry) + total_quantity_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request_out = \ + out_poultry_request.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight_out = round(total_index_weight_poultry_request_out / len(out_poultry_request), 2) if len( + out_poultry_request) > 0 else 0 + + list1 = [ + m, + vet.vet.user.fullname, + vet.vet.user.mobile, + len(poultries), + total_quantity, + len(poultry_requests), + total_quantity_poultry_request, + total_weight_poultry_request, + len(kill_requests), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_requests), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + ] + create_value(worksheet, list1, l, 1) + m += 1 + l += 1 + total_quantity = \ + poultry_hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_quantity_poultry_request = \ + poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + kill_request_quantity = kill_requests.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight = kill_requests.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + has_code = kill_requests.filter(clearance_code__isnull=False) + kill_request_quantity_has_code = has_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_has_code = has_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + + deffrent_bar = kill_requests.filter( + ~Q(quantity=F('quarantine_quantity') + , quarantine_quantity__isnull=False)) + kill_request_quantity_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_deffrent_bar = deffrent_bar.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + hasnt_code = kill_requests.filter(clearance_code__isnull=True) + kill_request_quantity_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_request_weight_hasnt_code = hasnt_code.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + total_quantity_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + total_index_weight_poultry_request_out = \ + out_poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + index_weight_out = round(total_index_weight_poultry_request_out / len(out_poultry_requests), 2) if len( + out_poultry_requests) > 0 else 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + total_quantity, + len(poultry_requests), + total_quantity_poultry_request, + total_weight_poultry_request, + '', + len(kill_requests), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_requests), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + + ] + + create_value(worksheet, list2, l + 2, 1, color='green') + + value_header_list = [ + len(poultries), + total_quantity, + len(poultry_requests), + total_quantity_poultry_request, + total_weight_poultry_request, + len(kill_requests), + kill_request_quantity, + kill_request_weight, + len(has_code), + kill_request_quantity_has_code, + kill_request_weight_has_code, + len(hasnt_code), + kill_request_quantity_hasnt_code, + kill_request_weight_hasnt_code, + len(deffrent_bar), + kill_request_quantity_deffrent_bar, + kill_request_weight_deffrent_bar, + len(out_poultry_requests), + total_quantity_poultry_request_out, + total_weight_poultry_request_out, + index_weight_out, + ] + create_value(worksheet, value_header_list, 3, 3) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="عملکرد مسئول فنی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response \ No newline at end of file diff --git a/panel/VetFarm/helpers.py b/panel/VetFarm/helpers.py new file mode 100644 index 0000000..864aee9 --- /dev/null +++ b/panel/VetFarm/helpers.py @@ -0,0 +1,260 @@ +from django.db.models import Sum, F, Q + +from panel.KillHouse.helpers import get_difference_carcasses_percent +from panel.models import PoultryRequest, ProvinceKillRequest, KillHouse, KillHouseRequest, PercentageOfWageType, \ + WageType, SubSectorTransactions, BarDifferenceRequest + + +def get_vet_sub_sector_finance_info(vet,date1,date2): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + other_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='other').first().percent / 100 + other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent + other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent + + other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + if date1: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm=vet, + send_date__date__gte=date1, + send_date__date__lte=date2) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm=vet, + clearance_code__isnull=False, + # clearance_code__isnull=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet=vet, date__date__gte=date1, + date__date__lte=date2) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted', acceptor_date__date__gte=date1, + acceptor_date__date__lte=date2) + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm=vet, + ) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm=vet, + clearance_code__isnull=False, + # clearance_code__isnull=False, + trash=False, calculate_status=True + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet=vet) + + # quarantine_code__isnull=False) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + # archive_wage=False, return_to_province=False, + # state__in=('pending', 'accepted'), + # province_request__poultry_request__vet_farm=vet, + # province_request__poultry_request__quarantine_code__isnull=False, + # + # first_car_allocated_quantity=0).order_by('id') + + # province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + # 'total'] or 0 + # province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + # 'total'] or 0 + province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + total_quantity += province_live_quantity + out_province_poultry_request_quantity + total_weight += province_live_weight + out_province_poultry_request_weight + + province_carcasses_weight = province_live_weight * 0.75 + if date1: + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent(date1,date2) + else: + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent() + + external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight + + total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount + total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount + + vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_remain_wage = total_wage - vet_deposit_amount + + result = { + "total_quantity": total_quantity, + "total_weight": total_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "province_live_quantity": province_live_quantity, + "province_live_weight": province_live_weight, + "province_carcasses_weight": province_carcasses_weight, + "internal_pure_province_carcasses_weight": internal_pure_province_carcasses_weight, + "external_pure_province_carcasses_weight": external_pure_province_carcasses_weight, + "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, + "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, + "out_province_poultry_request_amount": out_province_poultry_request_amount, + "total_wage": total_wage, + "number_of_deposit": len(vet_deposit), + "vet_deposit_amount": vet_deposit_amount, + "total_remain_wage": total_remain_wage, + } + return result + + +def get_vet_sub_sector_finance_info_with_date(vet,date1,date2): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + other_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='other').first().percent / 100 + other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent + other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent + + other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + if date1: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm=vet, send_date__date__gte=date1, + send_date__date__lte=date2) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm=vet, + clearance_code__isnull=False, + # clearance_code__isnull=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet=vet, date__date__gte=date1, + date__date__lte=date2) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted',acceptor_date__date__gte=date1,acceptor_date__date__lte=date2) + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm=vet, + ) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm=vet, + clearance_code__isnull=False, + # clearance_code__isnull=False, + trash=False, calculate_status=True + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet=vet) + + # quarantine_code__isnull=False) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + # province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user__in=kill_houses, trash=False, + # archive_wage=False, return_to_province=False, + # state__in=('pending', 'accepted'), + # province_request__poultry_request__vet_farm=vet, + # province_request__poultry_request__quarantine_code__isnull=False, + # + # first_car_allocated_quantity=0).order_by('id') + + + # province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + # 'total'] or 0 + # province_live_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + # 'total'] or 0 + province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + total_quantity += province_live_quantity + out_province_poultry_request_quantity + total_weight += province_live_weight + out_province_poultry_request_weight + + province_carcasses_weight = province_live_weight * 0.75 + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent(date1,date2) + external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight + + total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount + total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount + + vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_remain_wage = total_wage - vet_deposit_amount + + result = { + "total_quantity": total_quantity, + "total_weight": total_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "province_live_quantity": province_live_quantity, + "province_live_weight": province_live_weight, + "province_carcasses_weight": province_carcasses_weight, + "internal_pure_province_carcasses_weight": internal_pure_province_carcasses_weight, + "external_pure_province_carcasses_weight": external_pure_province_carcasses_weight, + "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, + "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, + "out_province_poultry_request_amount": out_province_poultry_request_amount, + "total_wage": total_wage, + "number_of_deposit": len(vet_deposit), + "vet_deposit_amount": vet_deposit_amount, + "total_remain_wage": total_remain_wage, + } + return result diff --git a/panel/VetFarm/serializers.py b/panel/VetFarm/serializers.py new file mode 100644 index 0000000..1bdabb4 --- /dev/null +++ b/panel/VetFarm/serializers.py @@ -0,0 +1,190 @@ +import datetime + +from rest_framework import serializers + +from authentication.serializer.serializer import SystemUserProfileForGuildSerializer +# سریالایزر مربوط به درخواست بورسی مرغدار +from authentication.serializers import SystemAddressSerializer +from panel.KillHouse.serializers import VetSerializer, VetForBarManagementSerializer +from panel.VetFarm.helpers import get_vet_sub_sector_finance_info, get_vet_sub_sector_finance_info_with_date +from panel.models import VetFarm, VetFarmInspection, PoultryHatching, Poultry, Vet +from panel.poultry.serializers import PoultrySerializer, PoultryHatchingSerializer + + +class VetFarmSerializer(serializers.ModelSerializer): + vet = VetSerializer(read_only=True) + poultry = PoultrySerializer(read_only=True) + inspection_info = serializers.SerializerMethodField('get_inspections') + hatching_quantity = serializers.SerializerMethodField('get_hatching_quantity') + + class Meta: + model = VetFarm + fields = '__all__' + + def get_inspections(self, instance): + inspections = len(VetFarmInspection.objects.filter(vet_farm=instance)) + hatching = PoultryHatching.objects.filter(poultry=instance.poultry, hall=int(instance.hall)).only( + 'quantity').last() + number_of_hatching = 0 + if hatching: + number_of_hatching = hatching.quantity + dict1 = {} + if inspections > 0: + dict1 = { + "number_of_inspections": inspections, + "number_of_hatching": number_of_hatching + } + return dict1 + + def get_hatching_quantity(self, instance): + quantity = 0 + poultry = Poultry.objects.get(key=instance.poultry.key) + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry).only('left_over').last() + if poultry_hatching: + quantity = poultry_hatching.left_over + + return quantity + + +class VetForSubSectorSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = Vet + fields = ['key', 'user', 'wage_info'] + + def get_wage_info(self, obj): + if self.context.get('request').GET.get('date1'): + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + else: + date1=None + date2=None + return get_vet_sub_sector_finance_info(obj,date1,date2) + + +class VetForSubSectorTransactionSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['key', 'user'] + + +class VetFarmInspectionSerializer(serializers.ModelSerializer): + vet_farm = VetFarmSerializer(read_only=True) + poultry_hatching = PoultryHatchingSerializer(read_only=True) + + class Meta: + model = VetFarmInspection + fields = '__all__' + + +class ManagementVetFarmSerializer(serializers.ModelSerializer): + # vet = VetSerializer(read_only=True) + poultry = PoultrySerializer(read_only=True) + inspection_info = serializers.SerializerMethodField('get_inspections') + hatching_quantity = serializers.SerializerMethodField('get_hatching_quantity') + + class Meta: + model = VetFarm + fields = '__all__' + + def get_inspections(self, instance): + inspections = len(VetFarmInspection.objects.filter(vet_farm=instance)) + hatching = PoultryHatching.objects.filter(poultry=instance.poultry, hall=int(instance.hall)).only( + 'quantity').last() + number_of_hatching = 0 + if hatching: + number_of_hatching = hatching.quantity + dict1 = {} + if inspections > 0: + dict1 = { + "number_of_inspections": inspections, + "number_of_hatching": number_of_hatching + } + return dict1 + + def get_hatching_quantity(self, instance): + quantity = 0 + poultry = Poultry.objects.get(key=instance.poultry.key) + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry).only('left_over').last() + if poultry_hatching: + quantity = poultry_hatching.left_over + + return quantity + + +class PoultryForCityVetSerializer(serializers.ModelSerializer): + address = SystemAddressSerializer(read_only=True) + inspection_info = serializers.SerializerMethodField('get_inspections') + hatching_quantity = serializers.SerializerMethodField('get_hatching_quantity') + + class Meta: + model = Poultry + fields = ['key', 'unit_name', 'address', 'number_of_halls', 'breeding_unique_id', 'inspection_info', + 'hatching_quantity'] + + def get_inspections(self, instance): + inspections = len(VetFarmInspection.objects.filter(vet_farm__poultry=instance)) + hatching = PoultryHatching.objects.filter(poultry=instance, trash=False).only('quantity').last() + number_of_hatching = 0 + if hatching: + number_of_hatching = hatching.quantity + dict1 = {} + if inspections > 0: + dict1 = { + "number_of_inspections": inspections, + "number_of_hatching": number_of_hatching + } + return dict1 + + def get_hatching_quantity(self, instance): + total_quantity = 0 + left_over = 0 + vet_farm_losses = 0 + union_losses = 0 + period = None + hatching_key = None + poultry_hatching = PoultryHatching.objects.filter(poultry=instance, allow_hatching='pending', state='pending', + archive=False, violation=False, trash=False).last() + if poultry_hatching: + total_quantity = poultry_hatching.quantity + left_over = poultry_hatching.left_over + vet_farm_losses = poultry_hatching.losses + union_losses = poultry_hatching.direct_losses + period = poultry_hatching.period + hatching_key = poultry_hatching.key + + return { + "total_quantity": total_quantity, + "left_over": left_over, + "vet_farm_losses": vet_farm_losses, + "union_losses": union_losses, + "period": period, + "total_losses": union_losses + vet_farm_losses, + "hatching_key": hatching_key, + } + + +class VetForSubSectorSerializerForExcel(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + wage_info = serializers.SerializerMethodField('get_wage_info') + + class Meta: + model = Vet + fields = ['key', 'user', 'wage_info'] + + def get_wage_info(self, obj): + if self.context.get('request').GET['date1']: + date1 = datetime.datetime.strptime(str(self.context.get('request').GET['date1']), + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(self.context.get('request').GET['date2']), + '%Y-%m-%d').date() + else: + date1=None + date2=None + return get_vet_sub_sector_finance_info_with_date(obj,date1,date2) \ No newline at end of file diff --git a/panel/VetFarm/views.py b/panel/VetFarm/views.py new file mode 100644 index 0000000..1b8f69a --- /dev/null +++ b/panel/VetFarm/views.py @@ -0,0 +1,452 @@ +import datetime + +from django.db.models import Prefetch, Q, Sum, F +from django.http import QueryDict +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from rest_framework.pagination import PageNumberPagination +from rest_framework.permissions import AllowAny + +from ticket.helper import send_image_to_server +from authentication.helper.refresh import refresh +from authentication.models import SystemUserProfile +from panel.KillHouse.helpers import get_difference_carcasses_percent +from panel.ReportingPanel.filterset import ProfileFilterSet, ManagementVetFarmFilterSet, PoultryFilterSet +from panel.VetFarm.serializers import VetFarmSerializer, VetFarmInspectionSerializer, ManagementVetFarmSerializer, \ + PoultryForCityVetSerializer, VetForSubSectorSerializer, VetForSubSectorTransactionSerializer +from rest_framework.response import Response +from rest_framework import status +import string +import random +import os + +ARVAN_Vet_Farm_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' +# ARVAN_Vet_Farm_URL = 'https://vet-farm.s3.ir-thr-at1.arvanstorage.ir/' + +from panel.models import VetFarm, Poultry, PoultryHatching, Vet, VetFarmInspection, PoultryRequest, KillHouseRequest, \ + PercentageOfWageType, WageType, KillHouse, SubSectorTransactions, BarDifferenceRequest + + +# ویوست مربوط به ثبت و نمایش و ... دامپزشک فارم +class VetFarmViewSet(viewsets.ModelViewSet): + queryset = VetFarm.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetFarmSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + + user = SystemUserProfile.objects.get(user=request.user) + if 'vet_key' in request.data.keys(): + vet = Vet.objects.get(key=request.data['vet_key']) + request.data.pop('vet_key') + else: + vet = Vet.objects.get(user=user) + poultry = Poultry.objects.get(key=request.data['poultry_key']) + request.data.pop('poultry_key') + halls = request.data['halls'] + request.data.pop('halls') + # vet_farm = VetFarm.objects.filter(poultry=poultry, hall=int(request.data['hall'])) + # if vet_farm.count() > 0: + # vet_farm = vet_farm.last() + # if vet_farm.vet.id == vet.id: + # return Response({"result": "object exist"}, status=status.HTTP_403_FORBIDDEN) + # else: + # pass + for hall in halls: + vet_farm = VetFarm( + vet=vet, + poultry=poultry, + hall=int(hall), + ) + vet_farm.save() + return Response({"result": "created"}, status=status.HTTP_201_CREATED) + + # serializer = self.serializer_class(data=request.data) + # if serializer.is_valid(): + # vetfarm = serializer.create(validated_data=request.data) + # vetfarm.vet = vet + # vetfarm.poultry = poultry + # vetfarm.save() + # return Response(serializer.data, status=status.HTTP_201_CREATED) + # return Response(serializer.errors) + + # تابع مربوط به نمایش دوره جوجه ریزی مرغدار + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + # list of self poultry houses + user = SystemUserProfile.objects.get(user=request.user) + vet = Vet.objects.get(user=user) + vet_farm = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry', 'vet') + serializer = VetFarmSerializer(vet_farm, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + try: + vet_farm = VetFarm.objects.get(key=request.GET["vet_farm_key"]) + # if VetFarmInspection.objects.filter(vet_farm=vet_farm).exists(): + # return Response({"result": "object can not delete"}, status=status.HTTP_403_FORBIDDEN) + vet_farm.trash = True + vet_farm.save() + return Response({"result": "object deleted"}, status=status.HTTP_200_OK) + except: + return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_403_FORBIDDEN) + + +class TotalVetSubSectorWageDashboardViewSet(viewsets.ModelViewSet): + queryset = Vet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetForSubSectorSerializer + + def list(self, request, *args, **kwargs): + + total_quantity = 0 + total_weight = 0 + total_wage = 0 + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_amount = total_wage_type.filter(en_name='province-kill-request', trash=False).first().amount + free_sell_carcasses_wage_amount = total_wage_type.filter(en_name='carcasse-sell', trash=False).first().amount + out_poultry_request_wage_amount = total_wage_type.filter(en_name='poultry-sell-out-province', + trash=False).first().amount + + percentages_wage_type = PercentageOfWageType.objects.filter(trash=False) + other_province_kill_request_percent = percentages_wage_type.filter( + wage_type__en_name='province-kill-request', share_type__en_name='other').first().percent / 100 + other_free_sell_carcasses_percent = percentages_wage_type.filter(wage_type__en_name='carcasse-sell', + share_type__en_name='other').first().percent / 100 + + other_out_poultry_request_percent = percentages_wage_type.filter(wage_type__en_name='poultry-sell-out-province', + share_type__en_name='other').first().percent / 100 + other_province_kill_request_amount = province_live_wage_amount * other_province_kill_request_percent + other_free_sell_carcasses_amount = free_sell_carcasses_wage_amount * other_free_sell_carcasses_percent + + other_out_poultry_request_amount = out_poultry_request_wage_amount * other_out_poultry_request_percent + + kill_houses = KillHouse.objects.filter(out_province=False, trash=False).order_by('id') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm__isnull=False, + send_date__date__gte=date1, + send_date__date__lte=date2 + ) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm__isnull=False, + # clearance_code__isnull=False, + clearance_code__isnull=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False, date__date__gte=date1, + date__date__lte=date2) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted',acceptor_date__date__gte=date1, + acceptor_date__date__lte=date2) + else: + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, temporary_trash=False, + wage_pay=True, has_wage=True, + temporary_deleted=False, vet_farm__isnull=False, + ) + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user__in=kill_houses) & Q(killer__in=kill_houses)) | Q( + Q(killhouse_user__in=kill_houses) & Q(killer__isnull=True)) | Q( + Q(killhouse_user__in=kill_houses) | Q(killer__in=kill_houses)), archive_wage=False, + province_request__poultry_request__vet_farm__isnull=False, + # clearance_code__isnull=False, + clearance_code__isnull=False, + trash=False, calculate_status=True + ) + difference_requests = BarDifferenceRequest.objects.filter(kill_house__in=kill_houses, trash=False, + state='accepted') + vet_deposit = SubSectorTransactions.objects.filter(trash=False, vet__isnull=False) + # quarantine_code__isnull=False) + out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + out_province_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + + + province_live_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + province_live_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + + province_live_weight += \ + difference_requests.aggregate(total=Sum('weight'))['total'] or 0 + total_quantity += province_live_quantity + out_province_poultry_request_quantity + total_weight += province_live_weight + out_province_poultry_request_weight + + province_carcasses_weight = province_live_weight * 0.75 + if 'date1' in request.GET: + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent(date1,date2) + else: + internal_pure_province_carcasses_weight = province_carcasses_weight * get_difference_carcasses_percent() + + external_pure_province_carcasses_weight = province_carcasses_weight - internal_pure_province_carcasses_weight + + total_pure_internal_province_carcasses_amount = internal_pure_province_carcasses_weight * other_province_kill_request_amount + total_pure_external_province_carcasses_amount = external_pure_province_carcasses_weight * other_free_sell_carcasses_amount + out_province_poultry_request_amount = out_province_poultry_request_weight * other_out_poultry_request_amount + + + vet_deposit_amount = vet_deposit.aggregate(total=Sum('amount'))['total'] or 0 + total_wage += total_pure_internal_province_carcasses_amount + total_pure_external_province_carcasses_amount + out_province_poultry_request_amount + total_remain_wage = total_wage - vet_deposit_amount + + result = { + "total_quantity": total_quantity, + "total_weight": total_weight, + "out_province_poultry_request_quantity": out_province_poultry_request_quantity, + "out_province_poultry_request_weight": out_province_poultry_request_weight, + "province_live_quantity": province_live_quantity, + "province_live_weight": province_live_weight, + "province_carcasses_weight": province_carcasses_weight, + "internal_pure_province_carcasses_weight": internal_pure_province_carcasses_weight, + "external_pure_province_carcasses_weight": external_pure_province_carcasses_weight, + "total_pure_internal_province_carcasses_amount": total_pure_internal_province_carcasses_amount, + "total_pure_external_province_carcasses_amount": total_pure_external_province_carcasses_amount, + "out_province_poultry_request_amount": out_province_poultry_request_amount, + "total_wage": total_wage, + "number_of_deposit": len(vet_deposit), + "vet_deposit_amount": vet_deposit_amount, + "total_remain_wage": total_remain_wage, + } + + return Response(result, status=status.HTTP_200_OK) + + +class VetForSubSectorViewSet(viewsets.ModelViewSet): + queryset = Vet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetForSubSectorSerializer + + # تابع مربوط به نمایش دوره جوجه ریزی مرغدار + def list(self, request, *args, **kwargs): + vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by('id') + serializer = self.serializer_class(vet, many=True,context={'request':request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + try: + vet_farm = VetFarm.objects.get(key=request.GET["vet_farm_key"]) + # if VetFarmInspection.objects.filter(vet_farm=vet_farm).exists(): + # return Response({"result": "object can not delete"}, status=status.HTTP_403_FORBIDDEN) + vet_farm.trash = True + vet_farm.save() + return Response({"result": "object deleted"}, status=status.HTTP_200_OK) + except: + return Response({"result": "مشکلی پیش آمده است !"}, status=status.HTTP_403_FORBIDDEN) + + +class VetForSubSectorTransactionViewSet(viewsets.ModelViewSet): + queryset = Vet.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetForSubSectorTransactionSerializer + + def list(self, request, *args, **kwargs): + vet = Vet.objects.filter(pk__in=VetFarm.objects.all().values_list('vet', flat=True), trash=False).order_by('id') + serializer = self.serializer_class(vet, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به ثبت و نمایش و ... دامپزشک فارم +class VetFarmInspectionViewSet(viewsets.ModelViewSet): + queryset = VetFarmInspection.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = VetFarmInspectionSerializer + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + vet = Vet.objects.get(user=user) + image_list = [] + vet_farm = VetFarm.objects.get(key=request.data['key']) + request.data.pop('key') + try: + poultry_hatching = PoultryHatching.objects.get(key=request.data['poultry_hatching_key']) + request.data.pop('poultry_hatching_key') + except: + poultry_hatching = None + try: + images = request.data['image'] + request.data.pop('image') + except: + images = None + if poultry_hatching != None: + if PoultryRequest.objects.filter(hatching=poultry_hatching, hatching__left_over=0, + hatching__allow_hatching='pending', hatching__state='pending').exists(): + return Response({"result": "باقی مانده موجود در سالن صفر میباشد."}, + status=status.HTTP_406_NOT_ACCEPTABLE) + today = datetime.datetime.now().date() + inspections = VetFarmInspection.objects.filter(vet_farm__vet=vet, state='pending', create_date__year=today.year, + create_date__month=today.month, create_date__day=today.day) + if inspections.count() > 0: + inspection = inspections.last() + if poultry_hatching != None: + if inspection.poultry_hatching.poultry.id != poultry_hatching.poultry.id: + return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN) + elif inspection.poultry_hatching.poultry.id == poultry_hatching.poultry.id and inspection.poultry_hatching.hall == int( + request.data['hall']): + return Response({"result": "can not register"}, status=status.HTTP_400_BAD_REQUEST) + elif poultry_hatching == None: + if inspection.vet_farm.poultry != vet_farm.poultry: + return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN) + elif inspection.vet_farm.hall == int(request.data['hall']): + return Response({"result": "can not register"}, status=status.HTTP_400_BAD_REQUEST) + + # + # else: + # for inspect in inspections: + # if inspect.hall == int(request.data['hall']): + # return Response({"result": "can not register"}, status=status.HTTP_403_FORBIDDEN) + # else: + # pass + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + vet_farm_inspection = serializer.create(validated_data=request.data) + vet_farm_inspection.vet_farm = vet_farm + if images != None: + for image in images: + image_list.append(send_image_to_server(image)) + + vet_farm_inspection.image = image_list + if poultry_hatching != None: + if int(vet_farm_inspection.Losses) > 0: + vet_farm.vetfarm_losses += int(vet_farm_inspection.Losses) + vet_farm.save() + if poultry_hatching.losses != 0: + poultry_hatching.losses = poultry_hatching.losses + int(vet_farm_inspection.Losses) + poultry_hatching.left_over = poultry_hatching.left_over - int(vet_farm_inspection.Losses) + else: + poultry_hatching.losses = vet_farm_inspection.Losses + poultry_hatching.left_over = poultry_hatching.quantity - int(vet_farm_inspection.Losses) + poultry_hatching.save() + vet_farm_inspection.poultry_hatching = poultry_hatching + vet_farm_inspection.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + if 'key' in request.GET: + vet_farm_inspection = VetFarmInspection.objects.filter(vet_farm__key=request.GET['key']) + serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True) + elif 'poultry_key' in request.GET: + if 'hall' in request.GET: + vet_farm_inspection = VetFarmInspection.objects.filter( + vet_farm__poultry__key=request.GET['poultry_key'], hall=int(request.GET['hall'])) + if vet_farm_inspection.count() == 0: + vet_farm_inspection = [] + serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True) + + else: + user = SystemUserProfile.objects.get(user=request.user) + vet = Vet.objects.get(userprofile=user) + vet_farm_inspection = VetFarmInspection.objects.filter(vet_farm__vet=vet) + serializer = VetFarmInspectionSerializer(vet_farm_inspection, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +class ManagementVetFarmViewSet(viewsets.ModelViewSet): + queryset = VetFarm.objects.all() + permission_classes = [AllowAny] + serializer_class = ManagementVetFarmSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ManagementVetFarmFilterSet + poultry_filterset_class = PoultryFilterSet + filterset_fields = [ + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + + ] + poultry_filterset_fields = [ + 'user__mobile', + 'unit_name', + 'address__city__name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + if request.GET['role'] == 'VetFarm': + vet = Vet.objects.get(user=user) + vet_farm = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry', 'vet') + vet_farm_list = [] + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=vet_farm + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=vet_farm) + vet_farm_list = ps.filter() + vet_farm = [] if len(vet_farm_list) == 0 else vet_farm_list + page_size = request.query_params.get('page_size', None) + + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(vet_farm) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = ManagementVetFarmSerializer(vet_farm, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + else: + poultries = Poultry.objects.filter( + pk__in=PoultryHatching.objects.filter(trash=False, allow_hatching='pending', state='pending', + archive=False).values_list('poultry__id', flat=True), + address__city=user.city) + poultries_list = [] + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.poultry_filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.poultry_filterset_class( + data=query, + queryset=poultries + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultries) + poultries_list = ps.filter() + poultries = [] if len(poultries_list) == 0 else poultries_list + page_size = request.query_params.get('page_size', None) + + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultries) + if page is not None: + serializer = PoultryForCityVetSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryForCityVetSerializer(poultries, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) diff --git a/panel/__init__.py b/panel/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/admin.py b/panel/admin.py new file mode 100644 index 0000000..273059b --- /dev/null +++ b/panel/admin.py @@ -0,0 +1,4 @@ +from django.contrib import admin + +# Register your models here. +PROJECT_API_KEY = '22d14a14-bd14-1414-a03f-2cc1cbf5e1d1' diff --git a/panel/apps.py b/panel/apps.py new file mode 100644 index 0000000..2f860e5 --- /dev/null +++ b/panel/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PanelConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'panel' diff --git a/panel/convert_date.py b/panel/convert_date.py new file mode 100644 index 0000000..31d74fd --- /dev/null +++ b/panel/convert_date.py @@ -0,0 +1,80 @@ +import datetime +import jdatetime + + +def convert_to_shamsi(year=None, month=None, day=None,datetime=None,date=None,in_value=None): + if datetime is not None: + date = jdatetime.datetime.fromgregorian(year=year, month=month, day=day,datetime=datetime).strftime("%Y-%m-%d (%H:%M)") + if in_value and date is not None: + if "(" in date: # اگر زمان وجود دارد + date_part, time_part = date.split(" (") + parts = date_part.split("-") + reversed_date = "-".join(reversed(parts)) + date = f"{reversed_date} ({time_part}" + else: + parts = date.split("-") + reversed_date = "-".join(reversed(parts)) + date = reversed_date + elif date: + date = jdatetime.datetime.fromgregorian(date=date).strftime( + "%Y-%m-%d") + else: + date = jdatetime.datetime.fromgregorian(year=int(year), month=int(month), day=int(day), datetime=datetime).strftime( + "%Y-%m-%d") + return date + + +def convert_to_miladi(year=None, month=None, day=None): + date = jdatetime.datetime(year, month, day).togregorian() + return date + + +def get_month_start_end_dates(period_type): + today = jdatetime.date.today() + + day_of_month = today.day + + # Function to convert Jalali date to Gregorian date + def to_gregorian(jalali_date): + return jalali_date.togregorian() + + # Function to get start and end dates for a given Jalali month + def get_start_end_of_month(jalali_date): + start_of_month = jdatetime.date(jalali_date.year, jalali_date.month, 1) + # Calculate the end of the month + if jalali_date.month == 12: + end_of_month = jdatetime.date(jalali_date.year + 1, 1, 1) - jdatetime.timedelta(days=1) + else: + end_of_month = jdatetime.date(jalali_date.year, jalali_date.month + 1, 1) - jdatetime.timedelta(days=1) + return to_gregorian(start_of_month), to_gregorian(end_of_month) + + # Helper function to get the previous month in Jalali calendar + def get_previous_month(jalali_date): + if jalali_date.month == 1: + return jdatetime.date(jalali_date.year - 1, 12, jalali_date.day) + else: + return jdatetime.date(jalali_date.year, jalali_date.month - 1, jalali_date.day) + + # Determine the months to consider based on the period type and current day + months_to_consider = 1 if period_type == 'oneMonth' else 3 if period_type == 'threeMonths' else 6 if period_type == 'sixMonths' else 12 + + # List to hold the start and end dates + start_end_dates = [] + + if day_of_month >= 30: + # Include the current month if today is the 30th or 31st + for _ in range(months_to_consider): + start, end = get_start_end_of_month(today) + start_end_dates.append({"start_date": start, "end_date": end}) + today = get_previous_month(today) + else: + # Exclude the current month if today is less than the 30th + today = get_previous_month(today) + for _ in range(months_to_consider): + start, end = get_start_end_of_month(today) + start_end_dates.append({"start_date": start, "end_date": end}) + today = get_previous_month(today) + + return start_end_dates[::-1] # Reverse to get chronological order + + diff --git a/panel/excel_processing.py b/panel/excel_processing.py new file mode 100644 index 0000000..d8158eb --- /dev/null +++ b/panel/excel_processing.py @@ -0,0 +1,38244 @@ +import hashlib +import uuid +import random +import cryptocode +import requests +import jdatetime +import datetime +import openpyxl + +from django.http import HttpResponse +from django.utils import timezone +from oauth2_provider.contrib.rest_framework import TokenHasReadWriteScope +from django.db.models import Q, Sum +from datetime import timedelta + +from oauth2_provider.models import AccessToken + +from general_urls import base_url_for_sms_report +from panel.filterset import \ + PoultryRequestFilterSet, KillRequestFilterSet, GuildsFilterSet, ProvinceKillRequestNewFilterSet, \ + KillHouseRequestFilterSet, ChainAllocationFilterSet +from django.db import models + +from django.db.models import F, Count + +from panel.admin import PROJECT_API_KEY +from rest_framework.decorators import permission_classes, api_view +from .convert_date import convert_to_miladi, convert_to_shamsi +from django.views.decorators.csrf import csrf_exempt +from django.http import JsonResponse, QueryDict +from rest_framework.permissions import AllowAny + +from .helper import build_query +from .helper_excel import shamsi_date, create_header, excel_description, create_header_freez, create_value, \ + percent_of_losses, start_excel, close_excel, convert_str_to_date +from .models import Poultry, PoultryHatching, PoultryRequest, ProvinceKillRequest, KillHouseRequest, VetFarm, \ + KillRequest, KillHouseVet, KillHouseAssignmentInformation, VetCheckRequest, \ + ProvinceFactorToKillHouse, ProvinceCheckOperatorRequest, KillHouseFactorToProvince, KillHouseWareHouse, \ + KillHouseFreeBarInformation, Guilds, Wallet, Steward, StewardAllocation, KillHouseOperator, KillHousePercentage, \ + CityOperator, KillHouseDriver, \ + ProvinceOperator, POSMachine, StewardWareHouse, Vet, WagePayment, ChainCompany, ReportsUsers, \ + PoultryRequestQuarantineCode, ChainAllocation +from authentication.models import ( + UserProfile, + User, + BankCard, + SystemUserProfile, + SystemAddress, + City, + Province, ExternalTransaction +) + +from .models import ( + KillHouse, + KillHouseADDCAR +) +from django.contrib.auth.models import Group +from rest_framework.response import Response +from authentication.models import Address +from django.shortcuts import get_object_or_404 + +ARTA_REGISTER = "https://userbackend.rasadyar.com/api/register_all/" + + +# تابع برای ثبت اطلاعات مرغداران از سامانه سماسط +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def user_excel(request): + file = request.FILES['file'].read() + read = openpyxl.load_workbook(BytesIO(file), data_only=True) + sheet = read.active + group = Group.objects.get(id=1) + password = '00100' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 1: + continue + if row[3] is not None: + last_name = row[3] + else: + last_name = '' + + first_name = row[2] + mobile = "0" + str(row[4]) + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).exists() + if not system_profile: + data = { + "username": mobile, + "first_name": first_name, + "last_name": last_name, + "password": hashed_password, + "national_code": '0', + "role": "Poultry", + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User.objects.filter(username=mobile).first() + if not user: + user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=mobile, + first_name=str(first_name), + last_name=str(last_name), + fullname=str(first_name) + ' ' + str(last_name), + user=user, + base_order=base_id, + password=password, + birthday=str(datetime.datetime.now().date()), + ) + system_profile.save() + system_profile.role.add(group) + wallet = Wallet() + wallet.save() + poultry = Poultry( + unit_name=row[7], + system_code=row[10], + epidemiological_code=row[9], + breeding_unique_id=row[11], + unit_status=row[13], + samasat_user_code=row[0], + ) + address = SystemAddress() + address.save() + poultry.address = address + poultry.user = system_profile + poultry.wallet = wallet + poultry.save() + # send_sms(userprofile.mobile, rand) + return JsonResponse({"Msg": "Done"}) + + +# تابع برای آپدیت اطلاعات ثبت شذه مرغداران از سامانه سماسط +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def user_excel_update(request): + file = request.FILES['file'].read() + read = openpyxl.load_workbook(filename=BytesIO(file), data_only=True) + sheet = read.active + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i == 0: + continue + if row[6] is not None: + if Poultry.objects.filter(breeding_unique_id=row[6]).exists(): + poultry = Poultry.objects.get(breeding_unique_id=row[6]) + poultry.total_capacity = row[9] + poultry.save() + poultry.fullname = row[8] + poultry.unit_name = row[7] + poultry.operating_licence_capacity = 0 + poultry.system_code = row[3] + poultry.epidemiological_code = row[5] + poultry.breeding_unique_id = row[6] + poultry.licence_number = row[10] + poultry.health_certificate_number = row[11] + poultry.number_of_requests = row[12] + poultry.number_of_incubators = row[15] + poultry.herd_age_by_day = row[16] + poultry.herd_age_by_week = row[17] + poultry.number_of_party = row[18] + poultry.communication_type = row[19] + poultry.cooperative = "" + poultry.save() + if row[13] != 'تاریخ جوجه ریزی': + date_of_incubators = row[13] + date_incube = date_of_incubators.split('/') + date = convert_to_miladi( + year=int(date_incube[0]), + month=int(date_incube[1]), + day=int(date_incube[2]) + ) + poultry.incubation_date = date + if row[14] != 'تاریخ آخرین پارتی': + last_party_date = row[14].split('/') + party_date = convert_to_miladi( + year=int(last_party_date[0]), + month=int(last_party_date[1]), + day=int(last_party_date[2]) + ) + poultry.last_party_date = party_date + if row[1] != 'استان' and row[2] != 'شهر': + if not Province.objects.filter(name=row[1]).exists(): + province = Province(name=row[1]) + province.save() + else: + province = Province.objects.get(name=row[1]) + + if not City.objects.filter(name=row[2]).exists(): + city = City(name=row[2]) + city.save() + else: + city = City.objects.get(name=row[2]) + + # if poultry.address.city != row[2] and poultry.address.province != row[1]: + poultry.address.city = city + poultry.address.province = province + poultry.address.save() + poultry.user.province = province + poultry.user.city = city + poultry.user.save() + poultry.save() + return JsonResponse({"msg": "Done"}) + + +# تابع برای ثبت نام کاربر درون سیستم +# @api_view(["POST"]) +# @csrf_exempt +# @permission_classes([AllowAny]) +# def test_register(request): +# # last_user = UserProfile.objects.all().last().base_orde + 1 +# last_user = UserProfile.objects.all() +# if len(last_user) > 0: +# last_user = last_user.last().base_order + 1 +# else: +# last_user = 1000 +# rand = random.randint(100000, 999000) +# str_rand = str(rand) +# password = cryptocode.encrypt(str_rand, str_rand) +# first = "آقای" +# mobile = "09121196753" +# last = "امیدی" +# userprofile = UserProfile( +# key=uuid.uuid4(), +# company="", +# fullname=first + " " + last, +# first_name=first, +# last_name=last, +# natinal_id="", +# mobile=mobile, +# birthday="", +# image="", +# state="", +# unit_name="", +# gis_code="", +# operating_licence_capacity=0, +# number_of_halls=0, +# tenant="", +# person_type="", +# economic_code="", +# system_code="", +# epidemiological_code="", +# breeding_unique_id="", +# total_capacity=0, +# licence_number="", +# health_certificate_number="", +# number_of_requests=0, +# number_of_incubators=0, +# herd_age_by_day=0, +# herd_age_by_week=0, +# number_of_party=0, +# communication_type="", +# cooperative="", +# unit_status="", +# samasat_user_code="", +# base_order=last_user, +# password=str_rand +# ) +# userprofile.save() +# user = User( +# first_name=first, +# username=userprofile.key, +# password=password, +# ) +# user.save() +# userprofile.user = user +# userprofile.save() +# # send_sms(mobile, rand) +# return Response("ok") + + +# تابع برای ثبت کستارگاه ار لیست اکسل +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def upload_kill_house(request): + last_user = UserProfile.objects.all() + if len(last_user) > 0: + last_user = last_user.last().base_order + 1 + else: + last_user = 1000 + rand = random.randint(100000, 999000) + str_rand = str(rand) + password = cryptocode.encrypt(str_rand, str_rand) + role = Group.objects.get(id=4) + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i == 0: + continue + [name, family, mobile, national_id, kill_hose, province, city, address, capocity, phone, name_of_bank_user, + bank_name, shaba, + account, card + ] = row + userprofile = UserProfile( + key=uuid.uuid4(), + fullname=name + " " + family, + first_name=name, + last_name=family, + mobile=str(mobile), + natinal_id=national_id + ) + userprofile.save() + user = User( + first_name=rand, + last_name=family, + username=mobile, + password=password, + ) + user.save() + address = Address(province=province, city=city, address=address) + address.save() + userprofile.user = user + userprofile.role = role + userprofile.address = address + userprofile.base_order = last_user + userprofile.save() + kill__house = KillHouse(user=userprofile, address=address, capacity=capocity, name=kill_hose, phone=phone) + kill__house.save() + bank = BankCard(name_of_bank_user=name_of_bank_user, bank_name=bank_name, card=str(card), shaba=str(shaba), + account=str(account)) + bank.save() + userprofile.user_bank_info = bank + userprofile.save() + + return Response(200) + + +# تابع برای ثبت ماشین های کستارگاه برای کشتارگاه های ثبت شده ار لیست اکسل +# @api_view(["POST"]) +# @permission_classes([TokenHasReadWriteScope]) +# @csrf_exempt +# def upload_kill_house_cars(request): +# file = request.FILES['file'].read() +# wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) +# sheet = wb_obj.active +# for i, row in enumerate(sheet.iter_rows(values_only=True)): +# if i == 0: +# continue +# [kill_house_name, national_id, driver_name, driver_mobile, type_car, type_weight, pelak, capacity, +# weight_without_load, +# health_code +# ] = row +# user = UserProfile.objects.filter(natinal_id=str(national_id)) +# id = user[0].id +# userprofile = UserProfile.objects.get(id=id) +# kill_house = KillHouse.objects.get(user=userprofile, name=kill_house_name) +# car_dict2 = {} +# if kill_house.car == None: +# kill_house.car = [] +# kill_house.save() +# car_list1 = list(kill_house.car) +# add_car = KillHouseADDCAR( +# kill_house=kill_house, +# driver_name=driver_name, +# driver_mobile=driver_mobile, +# type_car=type_car, +# type_weight=type_weight, +# pelak=pelak, +# capocity=capacity, +# weight_without_load=weight_without_load, +# health_code=health_code +# +# ) +# add_car.save() +# car_dict2.update( +# {"driver_name": add_car.driver_name, +# "driver_mobile": add_car.driver_mobile, "pelak": add_car.pelak, +# "quantity": add_car.capocity, +# "type_car": add_car.type_car, "health_code": add_car.health_code}) +# car_list1.append(car_dict2) +# kill_house.car = car_list1 +# kill_house.save() +# +# return Response(200) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def find_password(request): + user = UserProfile.objects.get(mobile=request.data['mobile']) + decrypted_password = cryptocode.decrypt(user.user.password, user.user.password) + return HttpResponse(decrypted_password) + + +# تابع برای ارسال اطلاعات برای مرغدار +# @api_view(["POST"]) +# @csrf_exempt +# @permission_classes([AllowAny]) +# def send_info_poultry(request): +# users = UserProfile.objects.filter(role_id=1).order_by('id') +# for user in users: +# mobile = user.mobile +# password = user.password +# send_sms(mobile, password) +# return Response({"result": "done!"}, status=status.HTTP_200_OK) + + +# تابع برای ارسال اطلاعات برای کشتارگاه +# @api_view(["POST"]) +# @csrf_exempt +# @permission_classes([AllowAny]) +# def send_info_kill_house(request): +# users = UserProfile.objects.filter(role_id=4).order_by('id') +# for user in users: +# mobile = user.mobile +# password = user.password +# send_sms_kill_house(mobile, password) +# return Response({"result": "done!"}, status=status.HTTP_200_OK) + + +# تابع برای ارسال اطلاعات برای شهرستان +# @api_view(["POST"]) +# @csrf_exempt +# @permission_classes([AllowAny]) +# def send_info_city(request): +# users = UserProfile.objects.filter(role_id=2).order_by('id') +# for user in users: +# mobile = user.mobile +# password = user.password +# send_sms_city(mobile, password) +# return Response({"result": "done!"}, status=status.HTTP_200_OK) + + +# +# def poultry(request): +# list2 = [] +# users = SystemUserProfile.objects.filter(role__name='Poultry', trash=False).order_by('create_date') +# for user in users: +# list2.append(user) +# +# excel_options = ['نام و نام خانوادگی', 'شماره همراه' +# ] +# output = BytesIO() +# workbook = xlsxwriter.Workbook(output) +# worksheet = workbook.add_worksheet() +# for count in range(len(excel_options)): +# worksheet.write(0, count, excel_options[count]) +# l = 0 +# for user in users: +# l += 1 +# +# list1 = [user.fullname, user.mobile] +# for item in range(len(list1)): +# worksheet.write(l, item, list1[item]) +# +# list1 = [] +# +# workbook.close() +# output.seek(0) +# +# response = HttpResponse(content_type='application/vnd.ms-excel') +# +# response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"' +# response.write(output.getvalue()) +# +# return response + + +# def hatching_report_excel(request): +# hatching_list = [] +# today = datetime.now().date() +# if 'age' in request.GET: +# hatchings = PoultryHatching.objects.filter(trash=False) +# input_age = int(request.GET['age']) +# if hatchings.count() > 0: +# for hatching in hatchings: +# age = (today - hatching.date.date()).days + 1 +# if int(age) == input_age: +# hatching_list.append(hatching) +# +# excel_options = [ +# 'نام و نام خانوادگی', +# 'تاریخ جوجه ریزی', +# 'سن مرغ', +# 'تعداد جوجه ریزی', +# 'تعداد باقی مانده', +# 'شماره همراه', +# 'استان', +# 'شهرستان', +# ] +# output = BytesIO() +# workbook = xlsxwriter.Workbook(output, {'strings_to_numbers': True}) +# worksheet = workbook.add_worksheet() +# +# # Set the cell format for right alignment +# right_align_format = workbook.add_format({'align': 'right'}) +# +# # Adjust the column width in reverse order +# for count, option in enumerate(reversed(excel_options)): +# worksheet.write(0, count, option) +# worksheet.set_column(count, count, None, right_align_format) +# +# l = 0 +# for hatch in hatching_list: +# l += 1 +# age = (today - hatch.date.date()).days + 1 +# gregorian_date = jdatetime.date.fromgregorian( +# day=hatch.date.day, +# month=hatch.date.month, +# year=hatch.date.year +# ) +# incubation_date = gregorian_date +# +# list1 = [ +# hatch.poultry.user.fullname, +# str(incubation_date), +# str(age), +# hatch.quantity, +# hatch.left_over, +# hatch.poultry.user.mobile, +# hatch.poultry.address.province.name, +# hatch.poultry.address.city.name, +# ] +# for item in range(len(list1)): +# worksheet.write(l, item, list1[item]) +# list1 = [] +# workbook.close() +# output.seek(0) +# +# response = HttpResponse(content_type='application/vnd.ms-excel') +# response['Content-Disposition'] = 'attachment;filename="Reporting.xlsx"' +# response.write(output.getvalue()) +# +# return response + + +# def hatching_report_excel(request): +# hatching_list = [] +# today = datetime.now().date() +# if 'age' in request.GET: +# hatchings = PoultryHatching.objects.filter(trash=False) +# input_age = int(request.GET['age']) +# if hatchings.count() > 0: +# for hatching in hatchings: +# age = (today - hatching.date.date()).days + 1 +# if int(age) == input_age: +# hatching_list.append(hatching) +# +# excel_options = [ +# 'نام و نام خانوادگی', +# 'تاریخ جوجه ریزی', +# 'سن مرغ', +# 'تعداد جوجه ریزی', +# 'تعداد باقی مانده', +# 'شماره همراه', +# 'استان', +# 'شهرستان', +# ] +# output = BytesIO() +# workbook = Workbook() +# worksheet = workbook.active +# +# # Set the right-to-left direction +# worksheet.sheet_view.rightToLeft = True +# +# # Set the fill color for the first row +# yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid") +# for col_num, option in enumerate(excel_options, 1): +# col_letter = get_column_letter(col_num) +# cell = worksheet.cell(row=1, column=col_num, value=option) +# cell.alignment = Alignment(horizontal='center') +# cell.fill = yellow_fill +# +# # Set the font size for the first row +# cell.font = Font(size=12, bold=True) +# +# # Set the width of the column +# worksheet.column_dimensions[col_letter].width = 20.01 +# +# l = 0 +# for hatch in hatching_list: +# l += 1 +# age = (today - hatch.date.date()).days + 1 +# gregorian_date = jdatetime.date.fromgregorian( +# day=hatch.date.day, +# month=hatch.date.month, +# year=hatch.date.year +# ) +# incubation_date = gregorian_date +# +# list1 = [ +# hatch.poultry.user.fullname, +# str(incubation_date), +# str(age), +# hatch.quantity, +# hatch.left_over, +# hatch.poultry.user.mobile, +# hatch.poultry.address.province.name, +# hatch.poultry.address.city.name, +# ] +# for item in range(len(list1)): +# cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) +# cell.alignment = Alignment(horizontal='center') +# +# list1 = [] +# +# workbook.save(output) +# output.seek(0) +# +# response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') +# response['Content-Disposition'] = 'attachment; filename="Reporting.xlsx"' +# response.write(output.getvalue()) +# +# return response + + +def vet_check_excel(request): + kill_house_req = KillHouseRequest.objects.filter(trash=False, clearance_code=None, + ).order_by('-create_date') + + excel_options = [ + 'نام و نام خانوادگی مرغدار', + 'تاریخ', + 'نام دکتر ', + 'تعداد بار', + 'کشتارگاه', + 'کد بهداشتی', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + # worksheet.merge_cells(start_row=1, end_row=2, start_column=1, end_column=1) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 0 + + for kill in kill_house_req: + l += 1 + vet_farm = VetFarm.objects.filter(trash=False, poultry=kill.province_request.poultry_request.poultry) + for vets in vet_farm: + date = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + list1 = [ + kill.province_request.poultry_request.poultry.unit_name, + str(date), + vets.vet.user.fullname, + kill.quantity, + kill.kill_request.kill_house.name, + kill.traffic_code + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename="Reporting.xlsx"' + response.write(output.getvalue()) + return response + + +def kill_house_request_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filterset_class = KillRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + ] + filtered_kill_reqs = ( + KillRequest.objects.filter(trash=False, recive_date__date__gte=date1, recive_date__date__lte=date2, + poultry__isnull=True) + .select_related('kill_house').order_by('-recive_date')) + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + excel_options = [ + 'ردیف', + 'نام خریدار', + 'ماهیت خریدار', + 'محل کشتار', + 'تاریخ ایجاد درخواست', + 'تعداد درخواست(قطعه)', + 'مانده(قطعه)', + 'تعداد تخصیص داده شده(قطعه)', + 'زمان دریافت', + 'تاریخ درخواستی کشتار', + 'وضعیت تایید استان', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=30, width=20.1) + l = 4 + m = 1 + + worksheet['A2'] = f'اعلام نیاز خریداران و کشتارگاه ها' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range2 = 'A2:B2' + + worksheet.merge_cells(merge_range2) + worksheet['A2'].font = Font(size=11) + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + + merge_range1 = 'A3:B3' + + worksheet.merge_cells(merge_range1) + + worksheet['A3'].font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد خریداران', + 'مجموع تعداد درخواست (قطعه)', + 'مانده(قطعه)', + 'مجموع تعداد تخصیص داده شده(قطعه)', + + ] + + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + all_kill_capacity = filtered_kill_reqs.aggregate( + total_quantity=Sum('kill_capacity')).get( + 'total_quantity', 0) + all_remain_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('remain_quantity')).get( + 'total_quantity', 0) + if filtered_kill_reqs: + for kill_request in filtered_kill_reqs: + l += 1 + + create_date = jdatetime.date.fromgregorian( + day=kill_request.create_date.day, + month=kill_request.create_date.month, + year=kill_request.create_date.year, + ) + recive_date = jdatetime.date.fromgregorian( + day=kill_request.recive_date.day, + month=kill_request.recive_date.month, + year=kill_request.recive_date.year + ) + + if kill_request.kill_house.killer == False: + killer = 'کشتارگاه' + else: + killer = 'کشتار کن' + if kill_request.slaughter_house != None: + kill_place = kill_request.slaughter_house.name + else: + kill_place = kill_request.kill_house.name + if kill_request.province_state == 'accepted': + province_state = 'تایید شده' + elif kill_request.province_state == 'pending': + province_state = 'در انتظار تایید' + else: + province_state = 'رد شده' + + allocation = kill_request.kill_capacity - kill_request.remain_quantity + list1 = [ + m, + kill_request.kill_house.name, + killer, + kill_place, + str(create_date), + kill_request.kill_capacity, + kill_request.remain_quantity, + allocation, + kill_request.recive_time, + str(recive_date), + province_state, + ] + m += 1 + + create_value(worksheet, list1, l + 1, 1) + value_list = [ + len(filtered_kill_reqs), + all_kill_capacity, + all_remain_quantity, + all_kill_capacity - all_remain_quantity if all_kill_capacity and all_remain_quantity != None else 0, + + ] + + create_value(worksheet, value_list, 3, 3) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + all_kill_capacity, + all_remain_quantity, + all_kill_capacity - all_remain_quantity if all_kill_capacity and all_remain_quantity != None else 0, + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="درخواست کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def request_report_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + today = datetime.datetime.now().date() + poultry_reqs = PoultryRequest.objects.filter(trash=False).order_by('-send_date') + filtered_poultry_reqs = [ + poultry_req for poultry_req in poultry_reqs + if date1 <= poultry_req.send_date.date() <= date2 + ] + + excel_options = [ + 'کد سفارش', + 'نام واحد', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'تاریخ جوجه ریزی', + 'تعداد کل جوجه ریزی', + 'سن مرغ', + 'کشتار شده', + 'تعداد باقی مانده', + 'نژاد', + 'تاریخ درخواست کشتار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'زمان تخصیص', + 'ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس خریدار', + 'محل کشتار', + 'دامپزشک کشتارگاه', + 'تلفن دامپزشک کشتارگاه', + 'راننده', + 'تلفن راننده', + 'ماشین حمل', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تحویلی', + 'وزن بار', + 'تاریخ تخلیه کشتارگاه', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + + for filtered_poultry_req in filtered_poultry_reqs: + l += 1 + vet_farm = VetFarm.objects.filter(poultry=filtered_poultry_req.poultry, trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + + age = (today - filtered_poultry_req.hatching.date.date()).days + 1 + gregorian_date = jdatetime.date.fromgregorian( + day=filtered_poultry_req.hatching.date.day, + month=filtered_poultry_req.hatching.date.month, + year=filtered_poultry_req.hatching.date.year + ) + incubation_date = gregorian_date + + province_kill_reqs = ProvinceKillRequest.objects.filter(province_request__poultry_request=filtered_poultry_req, + trash=False) + for province_kill_req in province_kill_reqs: + kill_house_vet = KillHouseVet.objects.filter(kill_house=province_kill_req.kill_request.kill_house, + trash=False).last() + kill_house_vet_name = kill_house_vet.vet.user.fullname if kill_house_vet else '-' + kill_house_vet_mobile = kill_house_vet.vet.user.mobile if kill_house_vet else '-' + date_of_inner_bar = '-' + kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_req, trash=False) + for kill_house_request in kill_house_requests: + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request) + killers = 'کشتارکن' + if kill_house_request.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).last() + assignment_quantity = assignment.real_quantity if assignment else '-' + assignment_weight = assignment.net_weight if assignment else '-' + + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request).last() + factor_amount = factor.total_price if factor else '-' + date_factor = '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request).last() + if factor_payment: + date_factor = jdatetime.date.fromgregorian( + day=factor_payment.create_date.day, + month=factor_payment.create_date.month, + year=factor_payment.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_req.create_date.day, + month=filtered_poultry_req.create_date.month, + year=filtered_poultry_req.create_date.year + ) + + time = jdatetime.date.fromgregorian( + day=kill_house_request.create_date.day, + month=kill_house_request.create_date.month, + year=kill_house_request.create_date.year + ) + for vet_checks in vet_check: + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) + + code = kill_house_request.clearance_code if kill_house_request.clearance_code else '-' + list1 = [ + filtered_poultry_req.order_code, + filtered_poultry_req.poultry.unit_name, + filtered_poultry_req.poultry.user.fullname, + filtered_poultry_req.poultry.user.mobile, + filtered_poultry_req.poultry.user.city.name, + str(incubation_date), + filtered_poultry_req.hatching.quantity, + str(age), + filtered_poultry_req.quantity, + filtered_poultry_req.hatching.left_over, + filtered_poultry_req.hatching.chicken_breed, + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + str(time), + killers, + province_kill_req.kill_request.kill_house.name, + province_kill_req.kill_request.kill_house.phone, + province_kill_req.kill_request.kill_house.system_address.city.name, + province_kill_req.kill_request.kill_house.system_address.city.name, + kill_house_vet_name, + kill_house_vet_mobile, + kill_house_request.add_car.driver.driver_name, + kill_house_request.add_car.driver.driver_mobile, + kill_house_request.add_car.driver.type_car, + kill_house_request.traffic_code, + code, + assignment_quantity, + assignment_weight, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename="Reporting.xlsx"' + response.write(output.getvalue()) + + return response + + +def allocated_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() if 'start' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() if 'end' in request.GET else now + filterset_class = ProvinceKillRequestNewFilterSet + if request.GET.get('type') == 'deleted': + filtered_province_kill = ProvinceKillRequest.objects.filter( + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, trash=True, delete_message__isnull=False) \ + .select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', + 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request__poultry__address').order_by('-create_date') + else: + filtered_province_kill = ProvinceKillRequest.objects.filter( + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', + 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request__poultry__address').order_by('-create_date') + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_province_kill_reqs = filtered_province_kill.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_province_kill_reqs = filtered_province_kill.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user) + filtered_province_kill_reqs = filtered_province_kill.filter( + Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house)) + else: + filtered_province_kill_reqs = filtered_province_kill + else: + filtered_province_kill_reqs = filtered_province_kill + value = request.GET.get('value') + search = request.GET.get('filter') + if value and search == 'search': + if value != 'undefined' and value.strip(): + filtered_province_kill_reqs = filtered_province_kill.filter( + build_query(filterset_class, value) + ) + if request.GET.get('type') == 'deleted': + excel_options = [ + 'ردیف', + 'وضعیت', + 'کد سفارش', + 'نوع درخواست', + 'نوع فروش', + 'کشتار', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'شهر', + 'تاریخ کشتار', + 'تعداد کشتار', + 'وزن کشتار', + 'زمان تخصیص', + 'نوع تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + 'مانده قابل تخصیص', + ' تلفن خریدار', + ' آدرس خریدار', + 'قیمت مرغدار', + 'قیمت کشتارگاه', + 'وضعیت تایید خریدار', + 'تخصیص ماشین', + 'پیام حذف', + + ] + else: + excel_options = [ + 'ردیف', + 'وضعیت', + 'کد سفارش', + 'درخواست', + 'نوع فروش', + 'کشتار', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'شهر', + 'تاریخ کشتار', + 'تعداد کشتار', + 'وزن کشتار', + 'زمان تخصیص', + 'نوع تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + 'مانده قابل تخصیص', + ' تلفن خریدار', + ' آدرس خریدار', + 'قیمت مرغدار', + 'قیمت کشتارگاه', + 'وضعیت تایید خریدار', + 'تخصیص ماشین', + + ] + header_list = [ + 'تعداد تخصیصات', + 'مجموع کل کشتار(قطعه)', + 'وزن کل کشتار', + 'مجموع تخصیص داده شده(قطعه)', + 'تعداد تایید شده', + 'تعداد تخصیصی ماشین', + + ] + + to_date_1 = shamsi_date(date1) + + to_date_2 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + create_header(worksheet, header_list, 3, 2, height=21, width=16.01) + if request.GET.get('type') == 'deleted': + excel_description(worksheet, 'A1', f' مدیریت تخصیصات حذف شده', color='red', row2='B1') + else: + excel_description(worksheet, 'A1', f' مدیریت تخصیصات', color='red', row2='B1') + excel_description(worksheet, 'A3', f'از تاریخ {to_date_1} تا {to_date_2}', color='red', row2='B3') + + if filtered_province_kill_reqs.exists(): + province = filtered_province_kill_reqs.first().province_request.poultry_request.poultry.address.province.name + excel_description(worksheet, 'A2', f'استان {province}', color='red', row2='B2') + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=19, width=21.01) + + l = 4 + m = 1 + all_state = 0 + all_car = 0 + all_return_quantity = 0 + for filtered_province_kill_req in filtered_province_kill_reqs: + + if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, + trash=False).exists(): + car = 'دارد' + all_car += 1 + else: + car = '-' + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + if filtered_province_kill_req.state == "accepted": + state_1 = 'تایید شده' + all_state += 1 + elif filtered_province_kill_req.state == "pending": + state_1 = 'در انتظار تایید' + else: + state_1 = 'رد شده' + + automatic = 'خودکار' if filtered_province_kill_req.automatic else 'دستی' + if filtered_province_kill_req.province_request.poultry_request.union == True: + type = 'اتحادیه' + elif filtered_province_kill_req.province_request.poultry_request.direct_buying == True: + type = 'خرید مستقیم' + elif filtered_province_kill_req.market == True: + type = 'پنل معاملات' + + else: + type = 'اتحادیه' + if filtered_province_kill_req.province_request.poultry_request.free_sale_in_province == True: + free_type = 'آزاد' + else: + free_type = 'دولتی' + + freez_state = 'منجمد' if filtered_province_kill_req.province_request.poultry_request.freezing == True else 'عادی' + + if filtered_province_kill_req.return_to_province == True: + state = 'تخصیص برگشت داده شده' + elif filtered_province_kill_req.quantity == 0: + state = 'تخصیص بسته شده' + elif filtered_province_kill_req.trash == True: + state = 'حذف شده' + else: + state = 'فعال' + message = filtered_province_kill_req.message if filtered_province_kill_req.message is not None else '-' + return_quantity = filtered_province_kill_req.quantity if filtered_province_kill_req.return_to_province == False else 0 + all_return_quantity += return_quantity + if request.GET.get('type') == 'deleted': + list1 = [ + m, + state, + str(filtered_province_kill_req.province_request.poultry_request.order_code), + type, + free_type, + freez_state, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.address.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(filtered_province_kill_req.province_request.poultry_request.Index_weight), + str(date_of_allocation), + automatic, + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + return_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + filtered_province_kill_req.kill_request.kill_house.system_address.city.name, + filtered_province_kill_req.province_request.city_request_Poultry.poultry_request.amount, + filtered_province_kill_req.kill_house_price, + state_1, + car, + message + + ] + else: + list1 = [ + m, + state, + str(filtered_province_kill_req.province_request.poultry_request.order_code), + type, + free_type, + freez_state, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.address.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(filtered_province_kill_req.province_request.poultry_request.Index_weight), + str(date_of_allocation), + automatic, + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + return_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + filtered_province_kill_req.kill_request.kill_house.system_address.city.name, + filtered_province_kill_req.province_request.city_request_Poultry.poultry_request.amount, + filtered_province_kill_req.kill_house_price, + state_1, + car + + ] + create_value(worksheet, list1, l + 1, 1) + + m += 1 + total_requests_quantity = \ + filtered_province_kill_reqs.aggregate(total=Sum('province_request__poultry_request__quantity'))['total'] or 0 + total_main_quantity = \ + filtered_province_kill_reqs.aggregate(total=Sum('main_quantity'))['total'] or 0 + total_requests_weight = filtered_province_kill_reqs.aggregate( + total=Sum( + F('province_request__poultry_request__quantity') * F('province_request__poultry_request__Index_weight')))[ + 'total'] or 0 + + value_list = [ + m - 1, + total_requests_quantity, + int(total_requests_weight), + total_main_quantity, + all_state, + all_car + ] + create_value(worksheet, value_list, 3, 3) + + total_requests_quantity = \ + filtered_province_kill_reqs.aggregate(total=Sum('province_request__poultry_request__quantity'))['total'] or 0 + if request.GET.get('type') == 'deleted': + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_requests_quantity, + '', + '', + '', + '', + total_main_quantity, + all_return_quantity, + '', + '', + '', + '', + '', + + ] + else: + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + total_requests_quantity, + '', + '', + '', + '', + total_main_quantity, + all_return_quantity, + '', + '', + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت تخصیصات.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def allocated_trash_true_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + prvince_kill_requests = ProvinceKillRequest.objects.filter(trash=True, delete_message__isnull=False).order_by( + '-create_date') + filtered_province_kill_reqs = [ + province_kill for province_kill in prvince_kill_requests + if date1 <= province_kill.province_request.poultry_request.send_date.date() <= date2 + ] + excel_options = [ + 'کد سفارش', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'تاریخ کشتار', + 'تعداد کشتار', + 'زمان تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + ' تلفن خریدار', + ' آدرس خریدار', + 'تایید تخصیص', + 'تخصیص ماشین', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + for filtered_province_kill_req in filtered_province_kill_reqs: + if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, trash=False).exists(): + car = 'دارد' + else: + car = '-' + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + if filtered_province_kill_req.state == "accepted": + state = 'تایید شده' + elif filtered_province_kill_req.state == "pending": + state = 'در انتظار تایید' + else: + state = 'رد شده' + list1 = [ + filtered_province_kill_req.province_request.poultry_request.order_code, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.user.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(date_of_allocation), + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + filtered_province_kill_req.killhouse_user.system_address.city.name, + state, + car + + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت تخصیصات حذف شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_kill_request_excel(request): + access = AccessToken.objects.get(token=request.GET['token']) + user = get_object_or_404(SystemUserProfile, user=access.user) + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filtered_province_kill_reqs = PoultryRequest.objects.filter(poultry__city_operator=city_operator.unit_name, + trash=False, send_date__date__gte=date1, + send_date__date__lte=date2).select_related( + 'poultry', 'poultry__user').order_by( + '-send_date') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_province_kill_reqs = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, send_date__date__gte=date1, + send_date__date__lte=date2, + poultry__address__city=user.city, ).select_related( + 'poultry', 'poultry__user').order_by( + '-send_date') + else: + filtered_province_kill_reqs = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, send_date__date__gte=date1, + send_date__date__lte=date2).select_related( + 'poultry', 'poultry__user').order_by( + '-send_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_province_kill_reqs + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_province_kill_reqs) + filtered_province_kill_reqs = ps.filter() + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'فروش', + 'کشتار', + 'درخواست', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'میانگین وزنی هر قطعه(کیلوگرم)', + 'وزن تقریبی(کیلوگرم)', + 'حجم درخواست کشتار', + 'قیمت مرغدار(ریال)', + 'مانده در سالن', + 'تایید شده', + 'تخصیص داده شده', + 'مانده قابل تخصیص', + 'وضعیت', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد درخواست', + 'مجموع تعداد قطعه', + 'وزن تقریبی کل درخواست', + 'مجموع مانده در سالن', + 'میانگین سنی', + ] + create_header(worksheet, header_list, 4, 2, height=17) + + excel_description(worksheet, 'A2', 'درخواست کشتار مرغداران', size=11, row2='B2') + + from_date_1 = shamsi_date(date1) + to_date_1 = shamsi_date(date2) + + excel_description(worksheet, 'A3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', color='red', row2='C3') + m = 1 + + create_header_freez(worksheet, excel_options, 1, 5, 6, height=23, width=21.01) + l = 4 + all_quantity = 0 + all_wight = 0 + all_left_over = 0 + all_age = [] + if filtered_province_kill_reqs: + for filtered_poultry_kill_request in filtered_province_kill_reqs: + all_quantity += filtered_poultry_kill_request.quantity + all_wight += int(filtered_poultry_kill_request.quantity * filtered_poultry_kill_request.Index_weight) + l += 1 + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '-' + if filtered_poultry_kill_request.kill_house_list is not None: + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '/' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + + if age not in all_age: + all_age.append(age) + + if filtered_poultry_kill_request.union == True: + type = 'اتحادیه' + elif filtered_poultry_kill_request.direct_buying == True: + type = 'خرید مستقیم' + elif filtered_poultry_kill_request.market == True: + type = 'پنل معاملات' + + else: + type = 'اتحادیه' + + freez_state = 'منجمد' if filtered_poultry_kill_request.freezing == True else 'عادی' + + sale_type = 'دولتی' if filtered_poultry_kill_request.free_sale_in_province == False else 'آزاد' + all_left_over += filtered_poultry_kill_request.hatching.left_over + + list1 = [ + m, + str(filtered_poultry_kill_request.order_code), + sale_type, + freez_state, + type, + str(date_of_create), + str(date_of_kill), + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + str(age), + str(filtered_poultry_kill_request.Index_weight), + int(filtered_poultry_kill_request.quantity * filtered_poultry_kill_request.Index_weight), + filtered_poultry_kill_request.first_quantity, + filtered_poultry_kill_request.amount, + filtered_poultry_kill_request.hatching.left_over, + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.quantity - filtered_poultry_kill_request.remain_quantity, + filtered_poultry_kill_request.remain_quantity, + + state + ] + m += 1 + create_value(worksheet, list1, l + 1, 1) + all_age1 = sorted(all_age) + value_header_list = [ + len(filtered_province_kill_reqs), + all_quantity, + all_wight, + all_left_over, + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + + ] + create_value(worksheet, value_header_list, 3, 4) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="درخواست مرغدار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def request_registration_kill_house(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + kill_requests = KillRequest.objects.filter( + kill_house__kill_house_operator__user_id=SystemUserProfile.objects.get(user_id=request.user), + trash=False).order_by('-recive_date') + filtered_kill_reqs = [ + kill_request for kill_request in kill_requests + if date1 <= kill_request.recive_date.date() <= date2 + ] + + excel_options = [ + 'نام خریدار', + 'تاریخ ایجاد درخواست', + 'تعداد درخواست(قطعه)', + 'مانده(قطعه)', + 'تعداد تخصیص داده شده(قطعه)', + 'زمان دریافت', + 'تاریخ درخواستی کشتار', + 'وضعیت تایید استان', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + if filtered_kill_reqs: + for kill_request in filtered_kill_reqs: + l += 1 + create_date = jdatetime.date.fromgregorian( + day=kill_request.create_date.day, + month=kill_request.create_date.month, + year=kill_request.create_date.year + ) + recive_date = jdatetime.date.fromgregorian( + day=kill_request.recive_date.day, + month=kill_request.recive_date.month, + year=kill_request.recive_date.year + ) + + if kill_request.province_state == 'accepted': + province_state = 'تایید شده' + elif kill_request.province_state == 'pending': + province_state = 'در انتظار تایید' + else: + province_state = 'رد شده' + + allocation = kill_request.kill_capacity - kill_request.remain_quantity + list1 = [ + kill_request.kill_house.name, + str(create_date), + kill_request.kill_capacity, + kill_request.remain_quantity, + allocation, + kill_request.recive_time, + str(recive_date), + province_state, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="kill_request {date1} to {date2}.xlsx"' + response.write(output.getvalue()) + return response + + +def request_pending_allocation(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + prvince_kill_requests = ProvinceKillRequest.objects.filter( + killhouse_user__kill_house_operator__user_id=SystemUserProfile.objects.get(user_id=request.user), + trash=False).order_by('-create_date') + filtered_province_kill_reqs = [ + province_kill for province_kill in prvince_kill_requests + if date1 <= province_kill.province_request.poultry_request.send_date.date() <= date2 + ] + excel_options = [ + 'کد سفارش', + 'تاریخ درخواست', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'سن مرغ', + 'تعداد کشتار', + 'نژاد', + 'میانگین وزن', + 'زمان تخصیص', + 'تعداد تخصیص داده شده', + 'تایید تخصیص', + 'تخصیص ماشین', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + for filtered_province_kill_req in filtered_province_kill_reqs: + if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, trash=False).exists(): + car = 'دارد' + else: + car = '-' + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + age = ( + filtered_province_kill_req.create_date - filtered_province_kill_req.province_request.poultry_request.hatching.date).days + 1 + if filtered_province_kill_req.state == "accepted": + state = 'تایید شده' + elif filtered_province_kill_req.state == "pending": + state = 'در انتظار تایید' + else: + state = 'رد شده' + list1 = [ + filtered_province_kill_req.province_request.poultry_request.order_code, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.user.city.name, + age, + filtered_province_kill_req.province_request.poultry_request.quantity, + filtered_province_kill_req.province_request.poultry_request.chicken_breed, + filtered_province_kill_req.province_request.poultry_request.Index_weight, + str(date_of_allocation), + filtered_province_kill_req.main_quantity, + state, + car, + + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="Awaiting confirmation {date1} to {date2} .xlsx"' + response.write(output.getvalue()) + + return response + + +def new_load_of_kill_house_vet(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + kill_house_requests = KillHouseRequest.objects.filter( + killhouse_user__kill_house_operator__user=SystemUserProfile.objects.get(user=request.user), + trash=False).order_by('-create_date') + + filtered_kill_house_requests = [ + kill_house for kill_house in kill_house_requests + if date1 <= kill_house.kill_request.recive_date.date() <= date2 + ] + excel_options = [ + 'کد بار', + 'کد رهگیری سامانه قرنطینه', + 'خریدار', + 'تاریخ درخواست', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'سن مرغ', + 'تعداد', + 'راننده', + 'ماشین', + 'پلاک', + 'نژاد', + 'میانگین وزن', + 'کد حمل و نقل' + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + for filtered_kill_house_request in filtered_kill_house_requests: + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_kill_house_request.kill_request.recive_date + .day, + month=filtered_kill_house_request.kill_request.recive_date + .month, + year=filtered_kill_house_request.kill_request.recive_date + .year + ) + traffic_code = filtered_kill_house_request.traffic_code if filtered_kill_house_request.traffic_code else '-' + clearance_code = filtered_kill_house_request.clearance_code if filtered_kill_house_request.clearance_code else '-' + age = ( + filtered_kill_house_request.kill_request.recive_date - filtered_kill_house_request.province_request.poultry_request.hatching.date).days + 1 + list1 = [ + str(filtered_kill_house_request.bar_code), + clearance_code, + filtered_kill_house_request.killhouse_user.name, + str(date_of_kill), + filtered_kill_house_request.province_request.poultry_request.poultry.unit_name, + filtered_kill_house_request.province_request.poultry_request.poultry.user.mobile, + filtered_kill_house_request.province_request.poultry_request.poultry.address.city.name, + age, + filtered_kill_house_request.province_kill_request.main_quantity, + filtered_kill_house_request.add_car.driver.driver_name, + filtered_kill_house_request.add_car.driver.type_car, + filtered_kill_house_request.add_car.driver.pelak, + filtered_kill_house_request.province_request.poultry_request.chicken_breed, + filtered_kill_house_request.province_request.poultry_request.Index_weight, + traffic_code, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="kill_house_vet {date1} to {date2} .xlsx"' + response.write(output.getvalue()) + return response + + +def car_allocation_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + kill_house_requests = KillHouseRequest.objects.filter( + killhouse_user__kill_house_operator__user=SystemUserProfile.objects.get(user=request.user), + trash=False).order_by('-create_date') + + filtered_kill_house_requests = [ + kill_house for kill_house in kill_house_requests + if date1 <= kill_house.kill_request.recive_date.date() <= date2 + ] + excel_options = [ + 'کد سفارش', + 'کد بار', + 'تاریخ کشتار', + 'تاریخ ثبت خودرو', + 'مرغدار', + 'راننده', + 'ماشین', + 'پلاک', + 'تعداد', + 'کد حمل و نقل' + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + for filtered_kill_house_request in filtered_kill_house_requests: + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_kill_house_request.kill_request.recive_date + .day, + month=filtered_kill_house_request.kill_request.recive_date + .month, + year=filtered_kill_house_request.kill_request.recive_date + .year + ) + date_of_allocation_car = jdatetime.date.fromgregorian( + day=filtered_kill_house_request.create_date + .day, + month=filtered_kill_house_request.create_date + .month, + year=filtered_kill_house_request.create_date + .year + ) + list1 = [ + filtered_kill_house_request.province_request.poultry_request.order_code, + str(filtered_kill_house_request.bar_code), + str(date_of_kill), + str(date_of_allocation_car), + filtered_kill_house_request.province_request.poultry_request.poultry.unit_name, + filtered_kill_house_request.add_car.driver.driver_name, + filtered_kill_house_request.add_car.driver.type_car, + filtered_kill_house_request.add_car.driver.pelak, + filtered_kill_house_request.quantity, + filtered_kill_house_request.traffic_code, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="car allocation {date1} to {date2} .xlsx"' + response.write(output.getvalue()) + return response + + +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def Test(request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() if 'start' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + timedelta( + days=1) if 'end' in request.GET else now + killhouse_names = KillHouse.objects.filter(trash=False, system_address__province=user.province).values_list('name', + flat=True).distinct() + + names_list = [] + for killhouse_name in killhouse_names: + names_list.append(killhouse_name) + + excel_options = [ + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name in names_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + for kill in KillHouseRequest.objects.filter(trash=False, killhouse_user__name=name, + kill_request__recive_date__range=(date1, date2)): + if kill: + l += 1 + vet_farm = VetFarm.objects.filter(poultry=kill.province_request.poultry_request.poultry, + trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.killhouse_user).last() + vet_checks = VetCheckRequest.objects.filter(kill_house_request=kill).last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill).last() + factor_amount = factor.total_price if factor else '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill).last() + date_factor = jdatetime.date.fromgregorian( + day=factor_payment.create_date.day, + month=factor_payment.create_date.month, + year=factor_payment.create_date.year + ) if factor_payment else '-' + code = kill.clearance_code if kill.clearance_code else '-' + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill, trash=False).last() + net_weighte = assignment.net_weight if assignment else '-' + real_quantity = assignment.real_quantity if assignment else '-' + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) if vet_checks else '-' + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + + list1 = [ + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + vet_farm_name, + vet_farm_mobile, + kill.kill_request.kill_house.name, + kill.killhouse_user.phone, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.add_car.driver.driver_name, + kill.add_car.driver.driver_mobile, + kill.add_car.driver.type_car, + kill.add_car.driver.health_code, + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename="Reporting.xlsx"' + response.write(output.getvalue()) + return response + + +@permission_classes([AllowAny]) +def Test1(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + today = datetime.datetime.now().date() + poultry_reqs = PoultryRequest.objects.filter(trash=False).order_by('-send_date') + total = 0 + filtered_poultry_reqs = [ + poultry_req for poultry_req in poultry_reqs + if date1 <= poultry_req.send_date.date() <= date2 + ] + + excel_options = [ + 'کد سفارش', + 'نام واحد', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'تاریخ جوجه ریزی', + 'تعداد کل جوجه ریزی', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'تعداد باقی مانده', + 'نژاد', + 'تاریخ درخواست کشتار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'زمان تخصیص', + 'ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس خریدار', + 'محل کشتار', + 'دامپزشک کشتارگاه', + 'تلفن دامپزشک کشتارگاه', + 'راننده', + 'تلفن راننده', + 'ماشین حمل', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تحویلی', + 'وزن بار', + 'تاریخ تخلیه کشتارگاه', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + + for filtered_poultry_req in filtered_poultry_reqs: + vet_farm = VetFarm.objects.filter(poultry=filtered_poultry_req.poultry, trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + + age = (today - filtered_poultry_req.hatching.date.date()).days + 1 + gregorian_date = jdatetime.date.fromgregorian( + day=filtered_poultry_req.hatching.date.day, + month=filtered_poultry_req.hatching.date.month, + year=filtered_poultry_req.hatching.date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_req.create_date.day, + month=filtered_poultry_req.create_date.month, + year=filtered_poultry_req.create_date.year + ) + incubation_date = gregorian_date + + province_kill_reqs = ProvinceKillRequest.objects.filter(province_request__poultry_request=filtered_poultry_req, + trash=False) + for province_kill_req in province_kill_reqs: + kill_house_vet = KillHouseVet.objects.filter(kill_house=province_kill_req.kill_request.kill_house, + trash=False).last() + kill_house_vet_name = kill_house_vet.vet.user.fullname if kill_house_vet else '-' + kill_house_vet_mobile = kill_house_vet.vet.user.mobile if kill_house_vet else '-' + date_of_inner_bar = '-' + kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_req, trash=False) + for kill_house_request in kill_house_requests: + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request) + killers = 'کشتارکن' + if kill_house_request.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).last() + assignment_quantity = assignment.real_quantity if assignment else '-' + assignment_weight = assignment.net_weight if assignment else '-' + + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request).last() + factor_amount = factor.total_price if factor else '-' + date_factor = '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request).last() + if factor_payment: + date_factor = jdatetime.date.fromgregorian( + day=factor_payment.create_date.day, + month=factor_payment.create_date.month, + year=factor_payment.create_date.year + ) + + time = jdatetime.date.fromgregorian( + day=kill_house_request.create_date.day, + month=kill_house_request.create_date.month, + year=kill_house_request.create_date.year + ) + for vet_checks in vet_check: + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) + total += filtered_poultry_req.hatching.quantity + code = kill_house_request.clearance_code if kill_house_request.clearance_code else '-' + list1 = [ + filtered_poultry_req.order_code, + filtered_poultry_req.poultry.unit_name, + filtered_poultry_req.poultry.user.fullname, + filtered_poultry_req.poultry.user.mobile, + filtered_poultry_req.poultry.user.city.name, + str(incubation_date), + filtered_poultry_req.hatching.quantity, + str(age), + filtered_poultry_req.quantity, + filtered_poultry_req.hatching.left_over, + filtered_poultry_req.hatching.chicken_breed, + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + str(time), + killers, + province_kill_req.kill_request.kill_house.name, + province_kill_req.kill_request.kill_house.phone, + province_kill_req.kill_request.kill_house.system_address.city.name, + province_kill_req.kill_request.kill_house.system_address.city.name, + kill_house_vet_name, + kill_house_vet_mobile, + kill_house_request.add_car.driver.driver_name, + kill_house_request.add_car.driver.driver_mobile, + kill_house_request.add_car.driver.type_car, + kill_house_request.traffic_code, + code, + assignment_quantity, + assignment_weight, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + list1 = [ + filtered_poultry_req.order_code, + filtered_poultry_req.poultry.unit_name, + filtered_poultry_req.poultry.user.fullname, + filtered_poultry_req.poultry.user.mobile, + filtered_poultry_req.poultry.user.city.name, + str(incubation_date), + filtered_poultry_req.hatching.quantity, + str(age), + filtered_poultry_req.quantity, + filtered_poultry_req.hatching.left_over, + filtered_poultry_req.hatching.chicken_breed, + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-' + ] + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + # اضافه کردن ستون جدید + max_col = worksheet.max_column + worksheet.insert_cols(max_col + 1) + + # افزودن هدر جدید + header_cell = worksheet.cell(row=1, column=max_col + 1, value="تعداد کل کشتار") + header_cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + header_cell.fill = PatternFill(start_color="9fff40", end_color="9fff40", fill_type="solid") + header_cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + # افزودن مقدار جدید + header_cell_below = worksheet.cell(row=2, column=max_col + 1, value=total) + header_cell_below.alignment = Alignment(horizontal='center', vertical='center') + worksheet.column_dimensions[get_column_letter(max_col + 1)].width = 20.01 + + workbook.save(output) + output.seek(0) + + response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="file {date1} to {date2}.xlsx"' + response.write(output.getvalue()) + + return response + + +from io import BytesIO +from openpyxl import Workbook +from openpyxl.styles import PatternFill, Alignment, Font +from openpyxl.utils import get_column_letter + + +@permission_classes([AllowAny]) +@csrf_exempt +def excel_for_all_user(request): + users = SystemUserProfile.objects.filter(trash=False) + poultry_list = Poultry.objects.filter(trash=False) + kill_house_list = KillHouse.objects.filter(trash=False) + vet_list = VetFarm.objects.filter(trash=False) + + excel_options = { + 'مرغدار': ['نام کامل', + 'شماره تلفن', + 'تاریخ تولد', + 'کد کاربری', + 'شهر', + 'کلمه عبور', + 'نام فارم', + 'آدرس', + 'شهر', + 'کد پستی', + 'موبایل', + 'شناسه یکتا', + 'کد اقتصادی', + 'کد اپیدمیولوژیک', + 'تعداد سالن', ], + 'دامپزشک کشتارگاه': ['کد بار', 'نام دامپزشک', 'شماره تلفن'], + 'دامپزشک فارم': ['کد بار', 'نام دامپزشک', 'شماره تلفن'], + 'کشتارگاه': ['کد بار', 'نام کشتارگاه', 'شماره تلفن'], + } + output = BytesIO() + workbook = Workbook() + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 0 + if sheet_name == 'مرغدار': + for p in poultry_list: + list1 = [ + p.user.fullname, + p.user.mobile, + p.user.birthday, + p.user.base_order, + p.user.city.name, + p.user.password, + p.unit_name, + p.address.address, + p.address.city.name, + p.address.postal_code, + p.address.phone, + p.breeding_unique_id, + p.economic_code, + p.epidemiological_code, + p.number_of_halls, + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + elif sheet_name == 'کشتارگاه': + for kill in kill_house_list: + list1 = [ + kill.name + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + elif sheet_name == 'دامپزشک فارم': + for vet in vet_list: + list1 = [ + vet.state + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = 'attachment; filename="Reporting.xlsx"' + response.write(output.getvalue()) + return response + + +def inventory(request): + now = datetime.datetime.now().date() + date = datetime.datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else now + + kill_house = KillHouse.objects.filter(key=request.GET['kill_house_key'], trash=False).select_related( + 'system_address__province').first() + + if kill_house.killer == True: + percentage = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + kill_house_vet = KillHouseVet.objects.filter(kill_house=percentage.kill_house_for_killer, + trash=False).select_related( + 'vet__user').last() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_house, trash=False).select_related( + 'vet__user').last() + + kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, + date__year=date.year, + date__month=date.month, + date__day=date.day, + trash=False).last() + kill_house_free_bar_info_list = KillHouseFreeBarInformation.objects.filter(kill_house=kill_house, + date__year=date.year, + date__month=date.month, + date__day=date.day, + trash=False) + date = date - timedelta(days=1) + + queryset = PoultryRequest.objects.filter( + poultry__address__province=kill_house.system_address.province, + final_state__in=('pending', 'archive'), + trash=False, out=False, + send_date__date=date, + + ).select_related('poultry', 'poultry__user', 'poultry__address__city').order_by('-send_date') + + excel_options = { + + 'اطلاعات بارهای سیستمی': ['کد بار', + 'مرغدار', + 'کد سفارش', + 'شهر مرغدار', + 'تاریخ کشتار', + 'نژاد', + 'دامپزشک فارم', + ' موبایل دامپزشک فارم', + ' دامپزشک کشتارگاه', + 'موبایل دامپزشک کشتارگاه', + 'راننده', + 'نوع خودرو', + 'کدبهداشتی حمل و نقل', + 'کدرهگیری قرنطینه', + 'تعداد تخصیصی', + 'وضعیت', + 'تعداد تخلیه شده', + 'وزن بار(کیلوگرم)'], + 'اطلاعات بارهای آزاد': ['مرغدار', + 'استان/شهر', + 'تاریخ خرید', + 'نام دامپزشک', + 'موبایل دامپزشک', + 'ماشین', + 'راننده', + ' موبایل راننده', + 'کدقرنطینه', + 'تعداد قطعه', + 'وزن زنده (کیلوگرم)', + 'تعداد لاشه', + 'وزن لاشه(کیلوگرم)', + ], + } + red_font = Font(color="C00000", bold=True) + + output = BytesIO() + workbook = Workbook() + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="0070C0", fill_type="solid") + blue_fill1 = PatternFill(start_color="00B0F0", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 32 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 4 + if sheet_name == 'اطلاعات بارهای سیستمی': + worksheet['B1'] = f'موجودی انبار' + worksheet['A4'] = f'اطلاعات بارهای سیستمی' + + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:C1' + merge_range2 = 'A4:C4' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + # worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['A4'].font = red_font + header_list = ['تعداد بار سیستمی', + 'تعداد قطعه تخصیصی', + 'وزن بار زنده', + 'تعداد لاشه', + 'وزن لاشه ها (افت 25٪) کیلوگرم', + 'میانگین وزن لاشه ها (کیلوگرم)' + , 'تعداد بار (خرید آزاد)', 'تعداد لاشه (خرید آزاد)' + , 'وزن لاشه (خرید آزاد) (کیلوگرم)' + , 'مجموع بارها' + , 'مجموع لاشه ها ' + , 'مجموع وزن لاشه ها (کیلوگرم)', + 'تعداد لاشه(ویرایش شده)', + 'وزن لاشه ها (افت 25٪) کیلوگرم(ویرایش شده)', + ] + for item in range(len(header_list)): + cell = worksheet.cell(row=2, column=item + 2, value=header_list[item]) + value = header_list[item] + cell.fill = blue_fill1 + cell.font = Font(size=9, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 25 + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + if len(queryset) > 0: + for poultry_req in queryset: + vet_farm = VetFarm.objects.filter(poultry=poultry_req.poultry).select_related('vet__user').last() + if vet_farm: + vet_name = vet_farm.vet.user.fullname + vet_mobile = vet_farm.vet.user.mobile + else: + vet_name = None + vet_mobile = None + + kill_house_requests = KillHouseRequest.objects.filter( + province_kill_request__province_request__poultry_request=poultry_req, + killhouse_user=kill_house, trash=False).select_related( + 'kill_request__kill_house__kill_house_operator__user', 'add_car__driver', + 'kill_request__kill_house') + if kill_house_requests: + for kill_house_request in kill_house_requests: + + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request).last() + if assignment: + assignment_state = 'تایید نهایی' + assignment_real_quantity = kill_house_request.accepted_real_quantity + assignment_net_weight = kill_house_request.accepted_real_weight + + else: + if kill_house_request.vet_state == 'pending': + assignment_state = 'در انتظار تایید تخلیه' + else: + assignment_state = 'در انتظار وروداطلاعات بار' + assignment_real_quantity = kill_house_request.accepted_real_quantity + assignment_net_weight = kill_house_request.accepted_real_weight + clearance_code = kill_house_request.clearance_code if kill_house_request.clearance_code else '-' + + list1 = [ + str(kill_house_request.bar_code), + poultry_req.poultry.unit_name, + str(poultry_req.order_code), + poultry_req.poultry.address.city.name, + str(date), + poultry_req.chicken_breed, + vet_name, + vet_mobile, + kill_house_vet.vet.user.fullname, + kill_house_vet.vet.user.mobile, + kill_house_request.add_car.driver.driver_name, + kill_house_request.add_car.driver.type_car, + kill_house_request.traffic_code, + clearance_code, + kill_house_request.quantity, + assignment_state, + assignment_real_quantity, + assignment_net_weight + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + if kill_house_ware_house: + list1 = [ + kill_house_ware_house.bar_quantity, + kill_house_ware_house.allocated_quantity, + kill_house_ware_house.bar_live_weight, + kill_house_ware_house.number_of_carcasses, + kill_house_ware_house.weight_of_carcasses, + kill_house_ware_house.ave_weight_of_carcasses, + kill_house_ware_house.free_bar_quantity, + kill_house_ware_house.number_of_free_carcasses, + kill_house_ware_house.free_weight_of_carcasses, + kill_house_ware_house.total_bar_quantity, + kill_house_ware_house.total_number_of_carcasses, + kill_house_ware_house.total_weight_of_carcasses, + kill_house_ware_house.updated_number_of_carcasses, + kill_house_ware_house.updated_weight_of_carcasses, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=3, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + else: + list1 = [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=3, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + elif sheet_name == 'اطلاعات بارهای آزاد': + header_list = [ + 'تعداد بار (خرید آزاد)', + 'تعداد لاشه (خرید آزاد)', + 'وزن لاشه (خرید آزاد) (کیلوگرم)', + 'مجموع بارها', + 'مجموع لاشه ها ', + 'مجموع وزن لاشه ها (کیلوگرم)', + 'تعداد لاشه(ویرایش شده)', + 'وزن لاشه ها (افت 25٪) کیلوگرم(ویرایش شده)', + ] + for item in range(len(header_list)): + cell = worksheet.cell(row=2, column=item + 2, value=header_list[item]) + value = header_list[item] + cell.fill = blue_fill1 + cell.font = Font(size=9, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 25 + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + for kill_house_free_bar in kill_house_free_bar_info_list: + date = jdatetime.date.fromgregorian(year=kill_house_free_bar.date.year, + month=kill_house_free_bar.date.month, + day=kill_house_free_bar.date.day) + list1 = [ + kill_house_free_bar.poultry_name, + kill_house_free_bar.province + ' ' + kill_house_free_bar.city, + str(date), + kill_house_free_bar.vet_farm_name, + kill_house_free_bar.vet_farm_mobile, + kill_house_free_bar.car, + kill_house_free_bar.driver_name, + kill_house_free_bar.driver_mobile, + kill_house_free_bar.clearance_code, + kill_house_free_bar.quantity, + kill_house_free_bar.live_weight, + kill_house_free_bar.number_of_carcasses, + kill_house_free_bar.weight_of_carcasses, + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + if kill_house_ware_house: + list1 = [ + kill_house_ware_house.free_bar_quantity, + kill_house_ware_house.number_of_free_carcasses, + kill_house_ware_house.free_weight_of_carcasses, + kill_house_ware_house.total_bar_quantity, + kill_house_ware_house.total_number_of_carcasses, + kill_house_ware_house.total_weight_of_carcasses, + kill_house_ware_house.updated_number_of_carcasses, + kill_house_ware_house.updated_weight_of_carcasses, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=3, column=item + 2, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' + else: + cell.value = value + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="{kill_house.name} در تاریخ {str(date)}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def steward_excel(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + group = Group.objects.get(name__exact="Guilds") + l = 0 + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i <= 0: + continue + mobile = str(row[5]) + if len(mobile) == 10: + mobile = '0' + str.zfill(mobile, 10) + postal_code = row[4] + national_code = row[9] + guild_id = row[8] + first_name = row[2] + last_name = row[3] + license_num = 0 + password = '00100' + hashed_password = hashlib.sha256(str(password).encode()).hexdigest() + province = Province.objects.filter(name='مرکزی') + province = province.first() + city = City.objects.filter(name='اراک') + city = city.first() + system_profile = SystemUserProfile.objects.filter(mobile=mobile, trash=False).first() + if system_profile: + pass + # if not system_profile: + # pass + # # data = { + # # "username": mobile, + # # "first_name": first_name, + # # "last_name": last_name, + # # "password": hashed_password, + # # "national_code": '0', + # # "role": "Guilds", + # # "api_key": PROJECT_API_KEY + # # } + # # req = requests.post( + # # url=ARTA_REGISTER, + # # data=data, + # # verify=False + # # ) + # # + # # if req.status_code == 200: + # # user = User(username=mobile, first_name=first_name, last_name=last_name, password=hashed_password) + # # user.save() + # # base_id = SystemUserProfile.objects.all() + # # if base_id.count() > 0: + # # base_id = int(base_id.last().base_order) + 1 + # # else: + # # base_id = 1000 + # # system_profile = SystemUserProfile( + # # mobile=mobile, + # # first_name=first_name, + # # last_name=last_name, + # # fullname=first_name + ' ' + last_name, + # # user=user, + # # base_order=base_id, + # # password=password, + # # birthday=str(datetime.datetime.now().date()), + # # city=city, + # # province=province + # # ) + # # system_profile.save() + # # system_profile.role.add(group) + # # l+=1 + # else: + # guilds = Guilds.objects.filter(user=system_profile).exists() + # if not guilds: + # address = SystemAddress(city=city, province=province, address=row[6]) + # address.save() + # wallet = Wallet() + # wallet.save() + # guilds = Guilds( + # user=system_profile, + # address=address, + # wallet=wallet, + # guilds_name=first_name + ' ' + last_name, + # type_activity='خرده فروش', + # area_activity='گوشت و مرغ', + # guilds_id=guild_id, + # license_number=license_num, + # + # ) + # guilds.save() + # l += 1 + + # Guilds.objects.bulk_create(guilds_list) + return Response( + l + ) + + +def Broadcast_management(request): + abc_list = ['A', 'B', 'C', 'D', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S'] + + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + kill_house = KillHouse.objects.get(key=request.GET['kill_house_key'], trash=False) + + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, date__date__lte=date2, + kill_house=kill_house, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + # to_date = jdatetime.date.fromgregorian( + # year=date2.year, + # month=date2.month, + # day=date2.day + # ).strftime('%Y-%m-%d') + # reversed_date = reversed(to_date.split("-")) + # separate = "-" + # to_date_1 = separate.join(reversed_date) + + names_list = [kill_house.name] + output = BytesIO() + workbook = Workbook() + for name in names_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['F2'] = f'اطلاعات کلی توزیع و پخش مرغ گرم در تاریخ {from_date_1}' + + worksheet['F2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'F2:N2' + worksheet.merge_cells(merge_range122) + + worksheet['F2'].font = Font(size=10) + + for abc in abc_list[2:11]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + withe_font = Font(size=12, bold=True, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'بارهای روزانه' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center') + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + + worksheet['C3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + list2 = [ + + 0, + 0, + total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + total_pre_cold_weight if total_pre_cold_weight != None else 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=6, column=item + 3, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه تخصیص', + 'وزن لاشه تخصیصی', + 'تعداد لاشه تحویلی', + 'وزن لاشه تحویلی', + 'وضعیت', + 'کد احراز', + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[9].height = 26 + worksheet.freeze_panes = worksheet['A10'] + max_col = worksheet.max_column + range_str = f'A9:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + m = 1 + l = 10 + + stewards = ( + StewardAllocation.objects.filter(trash=False, ware_house__kill_house=kill_house, date__date=date1, + ) + .select_related('guilds', + 'guilds__user', + 'guilds__address__city', + 'kill_house', + 'kill_house__kill_house_operator').order_by( + 'id')) + + if stewards.exists(): + for steward_allocation in stewards: + create_date = jdatetime.date.fromgregorian( + day=steward_allocation.create_date.day, + month=steward_allocation.create_date.month, + year=steward_allocation.create_date.year + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + if steward_allocation.receiver_state == 'pending': + reciver_type = 'در انتظار تحویل' + register = '-' + elif steward_allocation.receiver_state == 'accepted': + reciver_type = 'تحویل گرفته شد' + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else 'وارد نشده' + + else: + reciver_type = 'رد شده' + register = '-' + + list2 = [ + m, + guilds_id, + str(create_date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + steward_allocation.receiver_real_number_of_carcasses, + steward_allocation.receiver_real_weight_of_carcasses, + reciver_type, + register, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + m += 1 + l += 1 + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="{kill_house.name} در تاریخ {str(now)}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def guilds_excel(request): + filterset_class = GuildsFilterSet + filterset_fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__city__name', + 'user__province__name', + 'address__city__name', + 'guilds_name', + 'type_activity', + 'area_activity', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + + active_state = request.GET.get('active_state') + active_filter = {} + if active_state == 'active': + active_filter['active'] = True + elif active_state == 'deactive': + active_filter['active'] = False + if request.GET['role'] in ['CityCommerce', 'CityJahad', 'CityPoultry']: + guilds = Guilds.objects.filter(trash=False, province_accept_state='accepted', + address__city=user.city, **active_filter).order_by('id') + elif request.GET['role'] == 'Guilds': + + guilds = [] + + if request.GET['steward'] == 'true': + steward = Steward.objects.get(guilds__user=user, trash=False) + guilds_list = [] + first_guilds = Guilds.objects.filter(trash=False, centers_allocation__isnull=False, + province_accept_state__in=('pending', 'accepted'), + **active_filter).order_by('id') + for guild in first_guilds: + + if len(guild.centers_allocation) == 0 or guild.centers_allocation == None: + continue + if guild.centers_allocation[0]['value'] == str( + steward.key): + guilds_list.append(guild.key) + if len(guilds_list) > 0: + guilds = Guilds.objects.filter(key__in=guilds_list, **active_filter).order_by('id') + + elif request.GET['role'] == 'KillHouse': + guilds_list = [] + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'steward' in request.GET and request.GET['steward'] == 'true': + guilds = Guilds.objects.filter(trash=False, steward=True, + kill_house_centers_allocation__isnull=False, + province_accept_state__in=('pending', 'accepted'), + **active_filter).order_by('id') + else: + guilds = Guilds.objects.filter(trash=False, kill_house_centers_allocation__isnull=False, + province_accept_state__in=('pending', 'accepted'), + **active_filter).order_by('id') + for guild in guilds: + + if len(guild.kill_house_centers_allocation) == 0 or guild.kill_house_centers_allocation == None: + continue + if guild.kill_house_centers_allocation[0]['value'] == str( + kill_house.key): + guilds_list.append(guild.key) + if len(guilds_list) > 0: + guilds = Guilds.objects.filter(key__in=guilds_list, **active_filter).order_by('id') + else: + guilds = [] + + else: + if 'check' in request.GET: + if request.GET['state'] == 'pending': + guilds = Guilds.objects.filter( + Q(kill_house_register=True) | Q(steward_register=True) | Q(pos_company_register=True), + province_accept_state='pending', + trash=False, **active_filter).order_by('id') + else: + guilds = Guilds.objects.filter(kill_house_register=True, + trash=False, **active_filter).order_by('id') + else: + if 'steward' in request.GET and request.GET['steward'] == 'true': + guilds = Guilds.objects.filter(province_accept_state='accepted', steward=True, + trash=False, **active_filter).order_by('id') + else: + guilds = Guilds.objects.filter(province_accept_state='accepted', trash=False, + **active_filter).order_by('id') + if 'value' in request.GET and request.GET['value'] == 'undefined': + pass + else: + if 'search' in request.GET and request.GET['search'] == 'filter': + if request.GET.get('value', '') != "": + guilds_list = [] + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + filtered_queryset = filterset_class(data=query, queryset=guilds).filter() + if filtered_queryset.exists(): + if len(guilds_list) == 0: + guilds_list = list(filtered_queryset.values_list('id', flat=True)) + else: + guilds_list = list(set(guilds_list) & set(filtered_queryset.values_list('id', flat=True))) + if len(guilds_list) > 0: + guilds = guilds.filter(id__in=guilds_list) + excel_options = [ + 'ردیف', + 'کد ملی', + 'نام', + 'نام خانوادگی', + 'شماره شناسنامه', + 'در قید حیات', + 'تاریخ تولد', + 'نام پدر', + 'جنسیت', + 'شهر', + 'شماره همراه', + 'نام واحد', + 'رسته واحد صنفی', + 'استان', + 'شهرستان', + 'تاریخ انقضا مجوز', + 'شماره مجوز', + 'نام اتحادیه', + 'وضعیت', + 'کد پستی', + 'شماره تلفن', + 'آیا اتباع است؟', + 'نام شرکت', + 'شناسه ملی شرکت', + 'وضعیت مجوز', + 'آدرس', + 'مباشر', + 'احراز شماره موبایل', + ] + header_list = [ + 'تعداد اصناف', + 'تعداد مباشرین', + 'تعداد دارای کارتخوان', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'] = f'گزارش اصناف' + red_font = Font(color="C00000", bold=True) + + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + worksheet['A1'].font = red_font + + worksheet.merge_cells(merge_range1) + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + col_letter = get_column_letter(col_num) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 21 + worksheet.column_dimensions[col_letter].width = 16.01 + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 18 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 4 + m = 1 + has_pos = 0 + is_steward = 0 + for guild in guilds: + user = guild.user if getattr(guild, 'user', None) else None + address = guild.address if getattr(guild, 'address', None) else None + + national_id = getattr(user, 'national_id', None) if user else None + national_id = national_id if national_id else '-' + first_name = getattr(user, 'first_name', '-') if user else '-' + last_name = getattr(user, 'last_name', '-') if user else '-' + id_number = getattr(user, 'national_code', None) if user else None + id_number = id_number if id_number else '-' + is_alive_value = getattr(user, 'is_alive', None) if user else None + is_alive = 'بلی' if is_alive_value == True else ('خیر' if is_alive_value == False else '-') + birthday = '-' + if user: + birthday_value = getattr(user, 'birthday', None) + if birthday_value: + try: + if type(birthday_value) == str: + birthday_value = convert_str_to_date(birthday_value) + birthday = str(shamsi_date(birthday_value, in_value=True)) + else: + birthday = str(shamsi_date(birthday_value, in_value=True)) + + except: + birthday = '-' + father_name = getattr(user, 'father_name', None) if user else None + father_name = father_name if father_name else '-' + gender_value = getattr(user, 'gender', None) if user else None + if gender_value == True or str(gender_value).lower() in ['true', '1', 'male', 'مرد', 'm']: + gender = 'مرد' + elif gender_value == False or str(gender_value).lower() in ['false', '0', 'female', 'زن', 'f']: + gender = 'زن' + else: + gender = '-' + user_city = getattr(user.city, 'name', '-') if user and getattr(user, 'city', None) else '-' + mobile = getattr(user, 'mobile', '-') if user else '-' + user_province = getattr(user.province, 'name', '-') if user and getattr(user, 'province', None) else '-' + + guild_name = getattr(guild, 'guilds_name', None) + guild_name = guild_name if guild_name else '-' + area_activity = getattr(guild, 'area_activity', None) + area_activity = area_activity if area_activity else '-' + + address_city = getattr(address.city, 'name', '-') if address and getattr(address, 'city', None) else '-' + postal_code = getattr(address, 'postal_code', '-') if address else '-' + phone = getattr(address, 'phone', None) if address else None + phone = phone if phone else '-' + address_value = getattr(address, 'address', '-') if address else '-' + + license_expire_date = '-' + if getattr(guild, 'license_expire_date', None): + try: + license_expire_date = str(shamsi_date(guild.license_expire_date.date(), in_value=True)) + except: + license_expire_date = '-' + license_number = getattr(guild, 'license_number', None) + license_number = license_number if license_number else '-' + union_name = getattr(guild, 'union_name', None) + union_name = union_name if union_name else '-' + license_status = getattr(guild, 'license_status', None) + license_status = license_status if license_status else '-' + + active_status = 'فعال' if getattr(guild, 'active', False) else 'غیر فعال' + + is_foreign = getattr(guild, 'is_foreign_national', None) + if is_foreign == True: + is_foreign_national = 'بلی' + elif is_foreign == False: + is_foreign_national = 'خیر' + else: + is_foreign_national = '-' + + company_name = getattr(guild, 'company_name', None) + company_name = company_name if company_name else '-' + company_identifier = getattr(guild, 'company_identifier', None) + company_identifier = company_identifier if company_identifier else '-' + + if guild.steward == True: + steward = 'می باشد' + is_steward += 1 + else: + steward = 'نمی باشد' + + register_code = getattr(guild, 'register_code', None) + mobile_verified = 'احراز دارد' if register_code and str(register_code).strip() else '-' + + if guild.has_pos == True: + has_pos += 1 + + list1 = [ + m, + national_id, + first_name, + last_name, + id_number, + is_alive, + birthday, + father_name, + gender, + user_city, + mobile, + guild_name, + area_activity, + user_province, + address_city, + license_expire_date, + license_number, + union_name, + active_status, + postal_code, + phone, + is_foreign_national, + company_name, + company_identifier, + license_status, + address_value, + steward, + mobile_verified, + ] + l += 1 + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value_list = [ + m - 1, + is_steward, + has_pos + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_list[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت اصناف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def commerce_report_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + today = datetime.datetime.now().date() + poultry_reqs = PoultryRequest.objects.filter(trash=False).select_related('poultry').order_by('-send_date') + filtered_poultry_reqs = [ + poultry_req for poultry_req in poultry_reqs + if date1 <= poultry_req.send_date.date() <= date2 + ] + + excel_options = [ + 'کد سفارش', + 'نام واحد', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'تاریخ جوجه ریزی', + 'تعداد کل جوجه ریزی', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'تعداد باقی مانده', + 'نژاد', + 'تاریخ درخواست کشتار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'زمان تخصیص', + 'ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس خریدار', + 'محل کشتار', + 'دامپزشک کشتارگاه', + 'تلفن دامپزشک کشتارگاه', + 'راننده', + 'تلفن راننده', + 'ماشین حمل', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تحویلی', + 'وزن بار', + 'تاریخ تخلیه کشتارگاه', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + + for filtered_poultry_req in filtered_poultry_reqs: + vet_farm = VetFarm.objects.filter(poultry=filtered_poultry_req.poultry, trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + + age = (today - filtered_poultry_req.hatching.date.date()).days + 1 + gregorian_date = jdatetime.date.fromgregorian( + day=filtered_poultry_req.hatching.date.day, + month=filtered_poultry_req.hatching.date.month, + year=filtered_poultry_req.hatching.date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_req.create_date.day, + month=filtered_poultry_req.create_date.month, + year=filtered_poultry_req.create_date.year + ) + incubation_date = gregorian_date + + province_kill_reqs = ProvinceKillRequest.objects.filter(province_request__poultry_request=filtered_poultry_req, + trash=False) + for province_kill_req in province_kill_reqs: + kill_house_vet = KillHouseVet.objects.filter(kill_house=province_kill_req.kill_request.kill_house, + trash=False).only('vet__user__fullname', + 'vet__user__mobile').last() + kill_house_vet_name = kill_house_vet.vet.user.fullname if kill_house_vet else '-' + kill_house_vet_mobile = kill_house_vet.vet.user.mobile if kill_house_vet else '-' + date_of_inner_bar = '-' + kill_house_requests = KillHouseRequest.objects.filter(province_kill_request=province_kill_req, trash=False) + for kill_house_request in kill_house_requests: + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request).only('create_date') + killers = 'کشتارکن' + if kill_house_request.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter(kill_house_request=kill_house_request).only( + 'real_quantity', 'net_weight').last() + assignment_quantity = assignment.real_quantity if assignment else '-' + assignment_weight = assignment.net_weight if assignment else '-' + + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request).only( + 'total_price').last() + factor_amount = factor.total_price if factor else '-' + date_factor = '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request).only( + 'create_date').last() + if factor_payment: + date_factor = jdatetime.date.fromgregorian( + day=factor_payment.create_date.day, + month=factor_payment.create_date.month, + year=factor_payment.create_date.year + ) + + time = jdatetime.date.fromgregorian( + day=kill_house_request.create_date.day, + month=kill_house_request.create_date.month, + year=kill_house_request.create_date.year + ) + for vet_checks in vet_check: + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) + + code = kill_house_request.clearance_code if kill_house_request.clearance_code else '-' + list1 = [ + filtered_poultry_req.order_code, + filtered_poultry_req.poultry.unit_name, + filtered_poultry_req.poultry.user.fullname, + filtered_poultry_req.poultry.user.mobile, + filtered_poultry_req.poultry.user.city.name, + str(incubation_date), + filtered_poultry_req.hatching.quantity, + str(age), + filtered_poultry_req.quantity, + filtered_poultry_req.hatching.left_over, + filtered_poultry_req.hatching.chicken_breed, + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + str(time), + killers, + province_kill_req.kill_request.kill_house.name, + province_kill_req.kill_request.kill_house.phone, + province_kill_req.kill_request.kill_house.system_address.city.name, + province_kill_req.kill_request.kill_house.system_address.city.name, + kill_house_vet_name, + kill_house_vet_mobile, + kill_house_request.add_car.driver.driver_name, + kill_house_request.add_car.driver.driver_mobile, + kill_house_request.add_car.driver.type_car, + kill_house_request.traffic_code, + code, + assignment_quantity, + assignment_weight, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + list1 = [ + filtered_poultry_req.order_code, + filtered_poultry_req.poultry.unit_name, + filtered_poultry_req.poultry.user.fullname, + filtered_poultry_req.poultry.user.mobile, + filtered_poultry_req.poultry.user.city.name, + str(incubation_date), + filtered_poultry_req.hatching.quantity, + str(age), + filtered_poultry_req.quantity, + filtered_poultry_req.hatching.left_over, + filtered_poultry_req.hatching.chicken_breed, + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-' + ] + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="وضعیت پرونده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def commerce_bar_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + kill_requests = KillHouseRequest.objects.filter(trash=False).order_by('-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry') + filtered_kill_reqs = [ + kill_request for kill_request in kill_requests + if date1 <= kill_request.kill_request.recive_date.date() <= date2 + ] + excel_options = [ + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + l += 1 + vet_farm = VetFarm.objects.filter(poultry=kill.province_request.poultry_request.poultry, trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.killhouse_user).last() + vet_checks = VetCheckRequest.objects.filter(kill_house_request=kill).only('create_date').last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill).only('total_price').last() + factor_amount = factor.total_price if factor else '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill).only( + 'create_date').last() + date_factor = jdatetime.date.fromgregorian( + day=factor_payment.create_date.day, + month=factor_payment.create_date.month, + year=factor_payment.create_date.year + ) if factor_payment else '-' + code = kill.clearance_code if kill.clearance_code else '-' + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill, trash=False).last() + net_weighte = assignment.net_weight if assignment else '-' + real_quantity = assignment.real_quantity if assignment else '-' + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) if vet_checks else '-' + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + + list1 = [ + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + vet_farm_name, + vet_farm_mobile, + kill.kill_request.kill_house.name, + kill.killhouse_user.phone, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.add_car.driver.driver_name, + kill.add_car.driver.driver_mobile, + kill.add_car.driver.type_car, + kill.add_car.driver.health_code, + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def number_of_kills_weight_excel(request): + now = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'تعداد تخصیصی', + 'وزن بار', + + ] + to_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + worksheet['A1'] = f'گزارش تعداد کشتار' + worksheet['A3'] = f'در تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + now = timezone.now().date() + ten_days_ago = now - timedelta(days=int(request.GET['day'])) + for day in range(int(request.GET['day']) + 1): + date = ten_days_ago + timedelta(days=day) + + kill_reqs = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date, + trash=False).select_related( + 'killhouse_user', 'province_request__poultry_request__poultry', 'province_request__poultry_request', + 'kill_request').order_by( + '-kill_request__recive_date') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + kill_requests = kill_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + kill_requests = kill_reqs.filter(province_request__poultry_request__poultry__user__city=user.city) + else: + kill_requests = kill_reqs + else: + kill_requests = kill_reqs + if kill_requests: + for kill in kill_requests: + l += 1 + total_weight = 0 + kill_house_request_information = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill).first() + if kill_house_request_information: + total_weight += kill_house_request_information.net_weight + else: + total_weight += kill.province_request.poultry_request.Index_weight * kill.quantity + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + + list1 = [ + m, + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + kill.kill_request.kill_house.name, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + quantity, + total_weight, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش تعداد کشتار {request.GET["day"]} روز گذشته (براساس بار).xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def number_of_kills_excel(request): + now = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'تعداد تخصیصی', + 'وزن بار', + + ] + to_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + worksheet['A1'] = f'گزارش تعداد کشتار' + worksheet['A3'] = f'در تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + now = timezone.now().date() + ten_days_ago = now - timedelta(days=int(request.GET['day'])) + for day in range(int(request.GET['day']) + 1): + date = ten_days_ago + timedelta(days=day) + + kill_reqs = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date, + trash=False).select_related( + 'killhouse_user', 'province_request__poultry_request__poultry', 'province_request__poultry_request', + 'kill_request').order_by( + '-kill_request__recive_date') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + kill_requests = kill_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + kill_requests = kill_reqs.filter(province_request__poultry_request__poultry__user__city=user.city) + else: + kill_requests = kill_reqs + else: + kill_requests = kill_reqs + + if kill_requests: + for kill in kill_requests: + l += 1 + total_weight = 0 + kill_house_request_information = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill).first() + if kill_house_request_information: + total_weight += kill_house_request_information.net_weight + else: + total_weight += kill.province_request.poultry_request.Index_weight * kill.quantity + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + + list1 = [ + m, + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + kill.kill_request.kill_house.name, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + quantity, + total_weight, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش تعداد کشتار {request.GET["day"]} روز گذشته (براساس بار).xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def single_hatching_age_range_excel(request): + filtered_poultry_hatchs = PoultryHatching.objects.filter(state__in=('pending', 'complete'), archive=False, + allow_hatching='pending', + trash=False).order_by('-create_date').select_related( + 'poultry') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_poultry_hatch = filtered_poultry_hatchs.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_hatch = filtered_poultry_hatchs.filter(poultry__user__city=user.city) + else: + filtered_poultry_hatch = filtered_poultry_hatchs + else: + filtered_poultry_hatch = filtered_poultry_hatchs + + excel_options = [ + 'ردیف', + 'نام فارم', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'کشتار شده', + 'مانده در سالن', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + header_list = [ + 'تعداد کل فارم ها', + 'مجموع جوجه ریزی', + 'مجموع کشتار شده', + 'مجموع مانده در سالن', + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 30 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 4 + m = 1 + for poultry_hatching in filtered_poultry_hatch: + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + poultry_requests = PoultryRequest.objects.filter(hatching=poultry_hatching, trash=False).only('quantity') + age = (datetime.datetime.now().date() - poultry_hatching.date.date()).days + 1 + quantity_sum = 0 + for poultry_request in poultry_requests: + if poultry_request and hasattr(poultry_request, 'quantity'): + quantity_sum += poultry_request.quantity + list1 = [ + m, + poultry_hatching.poultry.unit_name, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.left_over, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + total_poultry_hatchings_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + total_poultry_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity') or 0 + total_poultry_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity') or 0 + value_list = [ + m - 1, + total_poultry_hatchings_quantity, + total_poultry_killed_quantity, + total_poultry_left_over, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_list[item]) + cell.alignment = Alignment(horizontal='center') + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="موجودی جوجه ریزی (مانده در سالن) بر اساس سن.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def total_poultry_request_dashboard_excel(request): + now = datetime.datetime.now().date() + + filtered_province_kill = PoultryRequest.objects.filter(send_date__date=now, trash=False).order_by('-send_date') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_province_kill_reqs = filtered_province_kill.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_province_kill_reqs = filtered_province_kill.filter(poultry__user__city=user.city) + else: + filtered_province_kill_reqs = filtered_province_kill + else: + filtered_province_kill_reqs = filtered_province_kill + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'نام و نام خانوادگی مرغدار', + 'نام فارم', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'مانده در سالن', + 'تایید شده', + ] + to_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if filtered_province_kill_reqs.exists(): + province = filtered_province_kill_reqs.first().poultry.address.province.name + worksheet['A2'] = f'استان {province}' + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + + worksheet['A1'] = f'درخواست های کشتار' + worksheet['A3'] = f'در تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + if filtered_province_kill_reqs: + for filtered_poultry_kill_request in filtered_province_kill_reqs: + l += 1 + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '' + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '-' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + list1 = [ + m, + filtered_poultry_kill_request.order_code, + str(date_of_create), + str(date_of_kill), + filtered_poultry_kill_request.poultry.user.fullname, + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + age, + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.hatching.left_over, + state + ] + m += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="درخواست کشتار .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def total_poultry_hatching_dashboard_excel(request): + excel_options = [ + 'تعداد فارم', + 'جوجه ریزی', + 'تلفات (10٪)', + 'کشتار شده', + 'مانده در سالن', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 1 + poultry_counts = Poultry.objects.filter(trash=False) + poultry_hatchings = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', archive=False, + trash=False) + total_poultry_hatchings_quantity = poultry_hatchings.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + total_poultry_hatchings_left = poultry_hatchings.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + losses = poultry_hatchings.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + total_kill_house_request_quantity = KillHouseRequest.objects.filter( + trash=False + ).aggregate(total_quantity=Sum('quantity'))['total_quantity'] or 0 + + list1 = [ + poultry_counts.count(), + total_poultry_hatchings_quantity, + losses, + total_kill_house_request_quantity, + total_poultry_hatchings_left + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="فارم های فعال.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def doughnut_left_hatching_excel(request): + now = datetime.datetime.now().date() + # user = SystemUserProfile.objects.get(token=request.GET['token']) + # total = 0 + # city_list = [] + # hatchings_list = [] + hatchings = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', archive=False + ).order_by('-date') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(token=request.GET['token']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchingss_list = hatchings.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + hatchingss_list = hatchings.filter(poultry__user__city=user.city) + else: + hatchingss_list = hatchings + else: + hatchingss_list = hatchings + + excel_options = [ + 'ردیف', + 'نام فارم', + 'شهر', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'کشتار شده', + 'مانده در سالن', + ] + + to_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if hatchingss_list.exists(): + province = hatchingss_list.first().poultry.address.province.name + worksheet['A2'] = f'استان {province}' + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'] = f'گزارش کل جوجه ریزی بر اساس شهرستان' + worksheet['A3'] = f'در تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + for hatchingss in hatchingss_list: + + if (jdatetime.datetime.fromgregorian(year=hatchingss.date.year, month=hatchingss.date.month, + day=hatchingss.date.day)).month == int(request.GET['month']): + # hatchings_list.append(hatchingss) + # total += hatchingss.quantity + # if hatchingss.poultry.address.city not in city_list: + # city_list.append(hatchingss.poultry.address.city) + + create_date = jdatetime.date.fromgregorian( + day=hatchingss.create_date.day, + month=hatchingss.create_date.month, + year=hatchingss.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=hatchingss.date.day, + month=hatchingss.date.month, + year=hatchingss.date.year + ) + age = (datetime.datetime.now().date() - hatchingss.date.date()).days + 1 + # for city in city_list: + # for hatch in hatchings_list: + list1 = [ + m, + hatchingss.poultry.unit_name, + hatchingss.poultry.address.city.name, + hatchingss.hall, + hatchingss.period, + str(create_date), + str(date), + hatchingss.chicken_breed, + age, + hatchingss.quantity, + hatchingss.losses, + hatchingss.killed_quantity, + hatchingss.left_over, + ] + l += 1 + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کل جوجه ریزی بر اساس شهرستان .xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def doughnut_hatching_excel(request): + now = datetime.datetime.now().date() + # total = 0 + # city_list = [] + # hatchings_list = [] + hatchings = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', archive=False + ).order_by('-date') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(token=request.GET['token']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchingss_list = hatchings.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + hatchingss_list = hatchings.filter(poultry__user__city=user.city) + else: + hatchingss_list = hatchings + else: + hatchingss_list = hatchings + + province = hatchingss_list.first().poultry.address.province.name + excel_options = [ + 'ردیف', + 'نام فارم', + 'شهر', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'کشتار شده', + 'مانده در سالن', + ] + + to_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + worksheet['A1'] = f'گزارش کل جوجه ریزی بر اساس شهرستان' + worksheet['A2'] = f'استان {province}' + worksheet['A3'] = f'در تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + for hatchingss in hatchingss_list: + + if (jdatetime.datetime.fromgregorian(year=hatchingss.date.year, month=hatchingss.date.month, + day=hatchingss.date.day)).month == int(request.GET['month']): + # hatchings_list.append(hatchingss) + # total += hatchingss.quantity + # if hatchingss.poultry.address.city not in city_list: + # city_list.append(hatchingss.poultry.address.city) + + create_date = jdatetime.date.fromgregorian( + day=hatchingss.create_date.day, + month=hatchingss.create_date.month, + year=hatchingss.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=hatchingss.date.day, + month=hatchingss.date.month, + year=hatchingss.date.year + ) + age = (datetime.datetime.now().date() - hatchingss.date.date()).days + 1 + # for city in city_list: + # for hatch in hatchings_list: + list1 = [ + m, + hatchingss.poultry.unit_name, + hatchingss.poultry.address.city.name, + hatchingss.hall, + hatchingss.period, + str(create_date), + str(date), + hatchingss.chicken_breed, + age, + hatchingss.quantity, + hatchingss.losses, + hatchingss.killed_quantity, + hatchingss.left_over, + ] + l += 1 + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کل جوجه ریزی بر اساس شهرستان های استان {province}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def forecast_hatching_left_over_excel(request): + user = SystemUserProfile.objects.get(user=request.user) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + age = int(request.GET['age']) + days_interval = (date2 - date1).days + hatchings = PoultryHatching.objects.filter(state='pending', poultry__address__province=user.province, + allow_hatching='pending', archive=False, + trash=False) + excel_options = [ + 'نام فارم', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'کشتار شده', + 'مانده در سالن', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + if hatchings: + l = 0 + for i in range(days_interval + 1): + hatching_left_over = 0 + first_date = date1 + timedelta(days=i) + for hatch in hatchings: + if (first_date - hatch.date.date()).days + 1 == age: + l += 1 + hatching_left_over += hatch.left_over + create_date = jdatetime.date.fromgregorian( + day=hatch.create_date.day, + month=hatch.create_date.month, + year=hatch.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=hatch.date.day, + month=hatch.date.month, + year=hatch.date.year + ) + poultry_requests = PoultryRequest.objects.filter(hatching=hatch, trash=False).only('quantity') + quantity_sum = 0 + for poultry_request in poultry_requests: + if poultry_request and hasattr(poultry_request, 'quantity'): + quantity_sum += poultry_request.quantity + list1 = [ + hatch.poultry.unit_name, + hatch.hall, + hatch.period, + str(create_date), + str(date), + hatch.chicken_breed, + hatch.quantity, + hatch.losses, + quantity_sum, + hatching_left_over, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + # hatching_list.append({"date": first_date, "hatching_left_over": hatching_left_over}) + if days_interval == 0: + break + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جوجه ریزی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def manager_of_farm_excel(request): + now = datetime.datetime.now().date() + filtered_kill_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__date=now, trash=False).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry') + + excel_options = [ + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + vet_farm = VetFarm.objects.filter(poultry=kill.province_request.poultry_request.poultry, trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.killhouse_user).last() + vet_checks = VetCheckRequest.objects.filter(kill_house_request=kill).only('create_date').last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + + code = kill.clearance_code if kill.clearance_code else '-' + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill, trash=False).last() + net_weighte = assignment.net_weight if assignment else '-' + real_quantity = assignment.real_quantity if assignment else '-' + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) if vet_checks else '-' + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + if kill.clearance_code: + l += 1 + list1 = [ + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + vet_farm_name, + vet_farm_mobile, + kill.kill_request.kill_house.name, + kill.killhouse_user.phone, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response['Content-Disposition'] = f'attachment; filename="Reporting.xlsx"' + response.write(output.getvalue()) + return response + + +def kill_house__request_vet_killing_process_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date2' in request.GET else now + + filtered_kill_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by('-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry') + # filtered_kill_reqs = [ + # kill_request for kill_request in kill_requests + # if date1 <= kill_request.kill_request.recive_date.date() <= date2 + # ] + excel_options = [ + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + l += 1 + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.killhouse_user).last() + vet_checks = VetCheckRequest.objects.filter(kill_house_request=kill).only('create_date').last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill, trash=False).last() + net_weighte = assignment.net_weight if assignment else '-' + real_quantity = assignment.real_quantity if assignment else '-' + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) if vet_checks else '-' + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + + list1 = [ + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + kill.kill_request.kill_house.name, + kill.killhouse_user.phone, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="دامپزشک کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_percent_excel(request): + user_profile = SystemUserProfile.objects.get(user=request.user, trash=False) + # kill_house = KillHouse.objects.filter(system_address__province=user_profile.province, trash=False) + kill_house = KillHousePercentage.objects.filter( + kill_house__system_address__province=user_profile.province).prefetch_related('kill_house', + 'kill_house_for_killer') + excel_options = [ + 'نام واحد', + 'نام و نام خانوادگی', + 'تلفن', + 'آدرس', + 'ماهیت', + 'محل کشتار', + 'نام دامپزشک', + 'تلفن دامپزشک', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 0 + if kill_house: + for kill in kill_house: + l += 1 + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.kill_house).prefetch_related('vet__user').last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + kill_place = kill.kill_house_for_killer.name if kill.kill_house_for_killer else kill.kill_house.name + killer = 'کشتارکن' if kill.kill_house.killer == True else 'کشتارگاه' + list1 = [ + kill.kill_house.name, + kill.kill_house.kill_house_operator.user.fullname, + kill.kill_house.kill_house_operator.user.mobile, + kill.kill_house.kill_house_operator.address.address, + killer, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="محل کشتار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_request_out_excel(request): + now = datetime.datetime.now().date() + date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') if 'date' in request.GET else now + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=user.province, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day, + trash=False, out=True, out_province_request_cancel=False).order_by( + '-send_date').select_related( + 'poultry__user') + list1 = [] + for poultry_request in poultry_requests: + for buyer in poultry_request.buyer: + list1.append(buyer) + return HttpResponse(list1) + + # excel_options = [ + # 'نام فارم', + # 'سالن', + # ' دوره جوجه ریزی', + # 'تاریخ ثبت جوجه ریزی', + # 'تاریخ جوجه ریزی', + # 'نژاد', + # 'سن', + # 'تعداد جوجه ریزی', + # 'تلفات دوره', + # 'کشتار شده', + # 'مانده در سالن', + # ] + # output = BytesIO() + # workbook = Workbook() + # worksheet = workbook.active + # worksheet.sheet_view.rightToLeft = True + # worksheet.insert_rows(1) + # blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + # for col_num, option in enumerate(excel_options, 1): + # col_letter = get_column_letter(col_num) + # cell = worksheet.cell(row=1, column=col_num, value=option) + # cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + # cell.fill = blue_fill + # cell.font = Font(size=10, bold=True, color='D9FFFFFF') + # worksheet.column_dimensions[col_letter].width = 20.01 + # worksheet.row_dimensions[1].height = 18 + # worksheet.freeze_panes = worksheet['A2'] + # max_col = worksheet.max_column + # range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + # worksheet.auto_filter.ref = range_str + # + # l = 0 + # if poultry_requests: + # for poultry_request in poultry_requests: + # buyer_list = poultry_request.buyer + # for buyer in buyer_list: + # list1 = [ + # poultry_request.poultry.unit_name, + # ] + # for item in range(len(list1)): + # cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + # cell.alignment = Alignment(horizontal='center') + # workbook.save(output) + # output.seek(0) + # + # response = HttpResponse( + # content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + # response[ + # 'Content-Disposition'] = f'attachment; filename="دامپزشک کشتارگاه.xlsx"'.encode( + # 'utf-8') + # response.write(output.getvalue()) + # return response + + +def get_all_user_excel(request): + users = SystemUserProfile.objects.filter(trash=False).prefetch_related('role').only( + 'role__name', 'fullname', 'mobile', 'city__name', 'user_gate_way_id' + ).exclude(role__name='Rancher').order_by('id') + + excel_options = [ + 'ردیف', + 'نام کامل', + 'شماره تلفن', + 'رمز', + 'توکن', + 'شهرستان', + 'مرغدار', + 'کشتارگاه', + 'اپراتور استان', + 'اپراتور شهرستان', + 'دامپزشک فارم', + 'دامپزشک کشتارگاه', + 'راننده', + 'اصناف', + 'مباشر', + 'اپراتور مالی', + 'دامپزشک کل', + 'شرکت psp', + 'استانداری', + 'بازرس استان', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 26.01 + worksheet.row_dimensions[3].height = 25 + worksheet.freeze_panes = worksheet['A4'] + max_col = worksheet.max_column + range_str = f'A3:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['A2'] = f'گزارش کاربران استان {users.first().province.name}' + + worksheet['A2'].font = Font(color="C00000", bold=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:B2' + + worksheet.merge_cells(merge_range1) + l = 2 + m = 1 + + for user in users: + role_list = [role.name for role in user.role.all()] + + poultry = '✔' if 'Poultry' in role_list else '-' + KillHouse = '✔' if 'KillHouse' in role_list else '-' + ProvinceOperator = '✔' if 'ProvinceOperator' in role_list else '-' + CityOperator = '✔' if 'CityOperator' in role_list else '-' + VetFarm = '✔' if 'VetFarm' in role_list else '-' + KillHouseVet = '✔' if 'KillHouseVet' in role_list else '-' + Driver = '✔' if 'Driver' in role_list else '-' + Guilds = '✔' if 'Guilds' in role_list else '-' + Steward = '✔' if 'Steward' in role_list else '-' + ProvinceFinancial = '✔' if 'ProvinceFinancial' in role_list else '-' + VetSupervisor = '✔' if 'VetSupervisor' in role_list else '-' + PosCompany = '✔' if 'PosCompany' in role_list else '-' + ProvincialGovernment = '✔' if 'ProvincialGovernment' in role_list else '-' + ProvinceInspector = '✔' if 'ProvinceInspector' in role_list else '-' + city = user.city.name if user.city else '-' + list1 = [ + m, + user.fullname, + user.mobile, + user.password, + user.user_gate_way_id, + city, + poultry, + KillHouse, + ProvinceOperator, + CityOperator, + VetFarm, + KillHouseVet, + Driver, + Guilds, + Steward, + ProvinceFinancial, + VetSupervisor, + PosCompany, + ProvincialGovernment, + ProvinceInspector, + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + m += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت کاربران.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def stewards_excel(request): + stewards = Steward.objects.filter(guilds__steward=True, trash=False).order_by('-create_date') + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] in ['CityCommerce', 'CityJahad', 'CityPoultry']: + stewards = stewards.filter(guilds__address__city=user.city).order_by('id') + + elif request.GET['role'] in ['ProvinceOperator', 'Commerce', 'ProvinceSupervisor''GuildRoom', 'SuperAdmin', + 'ImprovingLivestock', 'AdminX', 'Supporter']: + stewards = stewards.filter(guilds__address__province=user.province, + ).order_by('id') + else: + stewards = stewards + + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'نام واحد صنفی', + 'نام شخص/شرکت', + 'موبایل شخص/شرکت', + 'کدملی', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'استان', + 'شهرستان', + 'آدرس واحد صنفی', + 'محدودیت تخصیص', + 'حداکثر تخصیص', + 'مراکز تخصیص', + 'کارتخوان دارد / ندارد', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[4].height = 18 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + header_list = [ + 'تعداد کل مباشرین', + 'تعداد مباشرین فاقد کشتارگاه', + 'تعداد مباشرین دارای کارتخوان', + ] + if stewards: + city = 'استان' + ' ' + stewards.first().guilds.address.province.name + else: + city = '' + worksheet['A2'] = f'مدیریت مباشرین {city}' + + worksheet['A2'].font = Font(color="C00000", bold=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:B2' + worksheet.merge_cells(merge_range1) + + l = 3 + m = 1 + all_centers_allocations = 0 + all_has_pos = 0 + for steward in stewards: + l += 1 + max_allocation = steward.allocation_limit if steward.allocation_limit else 0 + limitation_allocation = 'دارد' if steward.limitation_allocation == True else 'ندارد' + + centers_allocations = '-' + if steward.centers_allocation == None: + centers_allocations = '-' + all_centers_allocations += 1 + + else: + for center_allocation in steward.centers_allocation: + centers_allocations = center_allocation['label'] + + if steward.guilds.has_pos == True: + has_pos = 'دارد' + all_has_pos += 1 + else: + has_pos = 'ندارد' + list1 = [ + m, + steward.guilds.guilds_id, + steward.guilds.guilds_name, + steward.guilds.user.fullname, + steward.guilds.user.mobile, + steward.guilds.user.national_id if steward.guilds.user.national_id else '-', + steward.guilds.type_activity, + steward.guilds.area_activity, + steward.guilds.license_number, + steward.guilds.address.province.name, + steward.guilds.address.city.name, + steward.guilds.address.address, + limitation_allocation, + max_allocation, + centers_allocations, + has_pos + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + m += 1 + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + col_letter = get_column_letter(col_num) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 21 + worksheet.column_dimensions[col_letter].width = 16.01 + values_list = [ + m - 1, + all_centers_allocations, + all_has_pos + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت مباشرین.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def all_kill_house_total_wage_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + access = AccessToken.objects.get(token=request.GET['token']) + + user = get_object_or_404(SystemUserProfile, user=access.user) + kill_houses = KillHouse.objects.filter(system_address__province=user.province, trash=False) + if 'date1' in request.GET: + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, killhouse_user=kill_house, + trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + else: + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + excel_options = [ + 'ردیف', + 'خریدار', + 'مالک', + 'تلفن خریدار', + 'شهر', + 'تعداد کل سفارشات', + 'تعداد کل قطعه ها', + 'وزن کل(کیلوگرم)', + 'مبلغ کل(ریال)', + 'تعداد سفارشات پرداخت شده', + 'تعداد قطعات پرداخت شده', + 'وزن قطعات پرداخت شده(کیلوگرم)', + 'مبلغ قطعات پرداخت شده(ریال)', + 'تعداد سفارشات پرداخت نشده', + 'تعداد قطعات پرداخت نشده', + 'وزن قطعات پرداخت نشده(کیلوگرم)', + 'مبلغ قطعات پرداخت نشده(ریال)', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 29 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 4 + m = 1 + if 'date1' in request.GET: + province_kill_requests = ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + trash=False, return_to_province=False, + state__in=('accepted', 'pending') + ).annotate( + total_quantity=Sum('total_killed_quantity'), + total_weight=Sum('total_killed_weight'), + total_amount_wage=Sum( + F('wage') * F('total_killed_weight')), + total_paid=Count('id', filter=models.Q(wage_pay=True, archive_by_province=False)), + total_unpaid=Count('id', filter=models.Q(wage_pay=False, archive_by_province=False)), + total_archive=Count('id', filter=models.Q(wage_pay=False, archive_by_province=True)), + ) + else: + province_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, return_to_province=False, state__in=('accepted', 'pending') + ).annotate( + total_quantity=Sum('total_killed_quantity'), + total_weight=Sum('total_killed_weight'), + total_amount_wage=Sum( + F('wage') * F('total_killed_weight')), + total_paid=Count('id', filter=models.Q(wage_pay=True, archive_by_province=False)), + total_unpaid=Count('id', filter=models.Q(wage_pay=False, archive_by_province=False)), + total_archive=Count('id', filter=models.Q(wage_pay=False, archive_by_province=True)), + ) + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['A2'] = f'گزارش کارمزدها از {from_date_1} تا {from_date_2}' + + worksheet['A2'].font = Font(color="C00000", bold=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:B2' + + worksheet.merge_cells(merge_range1) + total_requests_buyers = province_kill_requests.values('kill_request__kill_house').distinct().count() + total_requests = province_kill_requests.count() + total_requests_quantity = province_kill_requests.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = province_kill_requests.aggregate(total=Sum('total_weight'))['total'] + total_requests_amount = province_kill_requests.aggregate(total=Sum('total_amount_wage'))['total'] + total_paid_requests = province_kill_requests.aggregate(total=Sum('total_paid'))['total'] + total_paid_requests_quantity = \ + province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_quantity'))['total'] + total_paid_requests_weight = province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_weight'))[ + 'total'] + total_paid_requests_amount = \ + province_kill_requests.filter(wage_pay=True).aggregate(total=Sum('total_amount_wage'))['total'] + total_unpaid_requests = province_kill_requests.aggregate(total=Sum('total_unpaid'))['total'] + total_unpaid_requests_quantity = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_quantity'))['total'] + total_unpaid_requests_weight = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_weight'))['total'] + total_unpaid_requests_amount = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=False).aggregate( + total=Sum('total_amount_wage'))['total'] + + total_archive_requests = province_kill_requests.aggregate(total=Sum('total_archive'))['total'] + total_archive_requests_quantity = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_quantity'))['total'] + total_archive_requests_weight = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_weight'))['total'] + total_archive_requests_amount = \ + province_kill_requests.filter(wage_pay=False, archive_by_province=True).aggregate( + total=Sum('total_amount_wage'))['total'] + head_list = [ + 'تعداد خریداران', + 'تعداد کل سفارشات', + 'تعداد کل قطعه', + 'وزن کل سفارشات (کیلوگرم)', + 'مبلغ کل سفارشات (ریال)', + 'تعداد سفارش پرداخت شده', + 'تعداد قطعه پرداخت شده', + 'وزن سفارشات پرداخت شده (کیلوگرم)', + 'مبلغ سفارشات پرداخت شده (ریال)', + 'تعداد سفارش پرداخت نشده', + 'تعداد قطعه پرداخت نشده', + 'وزن سفارشات پرداخت نشده (کیلوگرم)', + 'مبلغ سفارشات پرداخت نشده (ریال)', + 'تعداد سفارش بایگانی شده', + 'تعداد قطعه بایگانی شده', + 'وزن سفارشات بایگانی شده (کیلوگرم)', + 'مبلغ سفارشات بایگانی شده (ریال)', + ] + for col_num, option in enumerate(head_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + value_list = [ + total_requests_buyers, + total_requests, + total_requests_quantity, + total_requests_weight, + total_requests_amount, + total_paid_requests, + total_paid_requests_quantity if total_paid_requests_quantity != None else 0, + total_paid_requests_weight if total_paid_requests_weight != None else 0, + total_paid_requests_amount if total_paid_requests_amount != None else 0, + total_unpaid_requests, + total_unpaid_requests_quantity, + total_unpaid_requests_weight, + total_unpaid_requests_amount, + total_archive_requests, + total_archive_requests_quantity, + total_archive_requests_weight, + total_archive_requests_amount, + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_list[item]) + cell.alignment = Alignment(horizontal='center') + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + for kill_houses in kill_house_list: + l += 1 + province_kill_request = province_kill_requests.filter(killhouse_user=kill_houses) + + paid_count = 0 # + unpaid_count = 0 # + total_weight_unpaid = 0 # + total_weight_paid = 0 # + total_unpaid_wage = 0 # + total_paid_wage = 0 # + total_paid_quantity = 0 # + total_unpaid_quantity = 0 # + fullname = kill_houses.kill_house_operator.user.fullname + city = kill_houses.kill_house_operator.user.city.name + mobile = kill_houses.kill_house_operator.user.mobile + total_count = len(province_kill_request) # + total_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) # + + for province_kill in province_kill_request: + if province_kill.wage_pay == True: + paid_count += 1 # + total_paid_quantity += province_kill.total_killed_quantity # + total_paid_wage += int(province_kill.depositor['total_amount']) # + total_weight_paid += province_kill.total_killed_weight # + elif province_kill.wage_pay == False and province_kill.archive_by_province == False: + unpaid_count += 1 # + total_unpaid_quantity += province_kill.total_killed_quantity # + total_unpaid_wage += province_kill.total_killed_weight * province_kill.wage # + total_weight_unpaid += province_kill.total_killed_weight # + + else: + pass + killer = 'کشتارگاه' if kill_houses.killer == False else 'کشتارکن' + list1 = [ + m, + killer + '(' + kill_houses.name + ')', + fullname, + mobile, + city, + total_count, + total_quantity, + int(total_weight_paid + total_weight_unpaid), + total_paid_wage + total_unpaid_wage, + paid_count, + total_paid_quantity, + int(total_weight_paid), + total_paid_wage, + unpaid_count, + total_unpaid_quantity, + int(total_weight_unpaid), + total_unpaid_wage, + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کارمزد ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_wage_not_payid_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + access = AccessToken.objects.get(token=request.GET['token']) + user = get_object_or_404(SystemUserProfile, user=access.user) + kill_houses = KillHouse.objects.filter(system_address__province=user.province, trash=False) + if 'date1' in request.GET: + + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, killhouse_user=kill_house, + wage_pay=True, + archive_by_province=False, return_to_province=False, + trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + else: + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(killhouse_user=kill_house, wage_pay=True, + archive_by_province=False, return_to_province=False, + trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['C2'] = f'کارمزد های پرداخت شده از {from_date_1} تا {from_date_2}' + + worksheet['C2'].font = Font(color="C00000", bold=True) + worksheet['C2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + header_list1 = [ + 'تعداد کل سفارشات ', + 'مجموع تعداد کل(قطعه)', + 'مجموع وزن کل(کیلوگرم)', + 'میانگین کل کارمزداتحادیه(ریال)', + 'مبلغ کل کارمزدها(ریال)', + + ] + header_list = [ + 'خریدار', + 'مالک', + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[5].height = 45 + worksheet.column_dimensions[col_letter].width = 27 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list1, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l = 6 + all_province_kill_request = 0 + final_quantity = 0 + fianl_wage = 0 + final_wage_all = [] + final_total_amount = 0 + if 'date1' in request.GET: + for kill_house in kill_house_list: + province_kill_request = ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + killhouse_user__key=kill_house.key, + state__in=('pending', 'accepted'), + wage_pay=True, + trash=False).select_related( + 'province_request').only('province_request__key', 'main_quantity', 'wage', 'total_amount').order_by( + '-kill_request__recive_date') + all_quantity = province_kill_request.aggregate(total_quantity=Sum('main_quantity')).get( + 'total_quantity', 0) + all_wiegh = 0 + all_wage = [] + all_total_amount = 0 + all_province_kill_request += len(province_kill_request) + final_quantity += all_quantity + for province in province_kill_request: + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request').filter( + key=province.province_request.key, + trash=False).only('poultry_request__Index_weight').first() + wieght = int(province.main_quantity * province_request.poultry_request.Index_weight) + all_wiegh += wieght + wage = province.wage + if wage > 0: + all_wage.append(wage) + total_amount = province.total_amount if province.total_amount > 0 else int(province.wage) * int( + province.main_quantity * province_request.poultry_request.Index_weight) + all_total_amount += total_amount + final_total_amount += all_total_amount + fianl_wage += all_wiegh + + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + final_wage_all.append(wage_all) + else: + wage_all = 0 + killer = 'کشتارگاه' if kill_house.killer == False else 'کشتارکن' + + values_list = [ + killer + '(' + kill_house.name + ')', + kill_house.kill_house_operator.user.fullname, + len(province_kill_request), + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=l, column=item + 3, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + else: + for kill_house in kill_house_list: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user__key=kill_house.key, + state__in=('pending', 'accepted'), + wage_pay=True, + trash=False).select_related( + 'province_request').only('province_request__key', 'main_quantity', 'wage', 'total_amount').order_by( + '-kill_request__recive_date') + all_quantity = province_kill_request.aggregate(total_quantity=Sum('main_quantity')).get( + 'total_quantity', 0) + all_wiegh = 0 + all_wage = [] + all_total_amount = 0 + all_province_kill_request += len(province_kill_request) + final_quantity += all_quantity + for province in province_kill_request: + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request').filter( + key=province.province_request.key, + trash=False).only('poultry_request__Index_weight').first() + wieght = int(province.main_quantity * province_request.poultry_request.Index_weight) + all_wiegh += wieght + wage = province.wage + if wage > 0: + all_wage.append(wage) + total_amount = province.total_amount if province.total_amount > 0 else int(province.wage) * int( + province.main_quantity * province_request.poultry_request.Index_weight) + all_total_amount += total_amount + final_total_amount += all_total_amount + fianl_wage += all_wiegh + + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + final_wage_all.append(wage_all) + else: + wage_all = 0 + killer = 'کشتارگاه' if kill_house.killer == False else 'کشتارکن' + + values_list = [ + killer + '(' + kill_house.name + ')', + kill_house.kill_house_operator.user.fullname, + len(province_kill_request), + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=l, column=item + 3, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + + if len(final_wage_all) > 0: + wage = sum(final_wage_all) / len(final_wage_all) + else: + wage = 0 + values_list = [ + all_province_kill_request, + final_quantity, + fianl_wage, + wage, + final_total_amount + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for kill_house in kill_house_list: + sheet_name = kill_house.kill_house_operator.user.fullname + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + province_kill_request = ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + killhouse_user__key=kill_house.key, + wage_pay=True, + state__in=('pending', 'accepted'), + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', + 'kill_request').order_by( + '-kill_request__recive_date') + else: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user__key=kill_house.key, + wage_pay=True, + state__in=('pending', 'accepted'), + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', + 'kill_request').order_by( + '-kill_request__recive_date') + all_quantity = province_kill_request.aggregate(total_quantity=Sum('main_quantity')).get( + 'total_quantity', 0) + all_wiegh = 0 + all_wage = [] + + all_total_amount = 0 + + # برای بالای هدر + header_list = [ + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + + l = 4 + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 27 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for province in province_kill_request: + + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').filter( + key=province.province_request.key, + trash=False).only('poultry_request__send_date', 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').first() + kill_place = province.kill_request.slaughter_house.name if province.kill_request.slaughter_house != None else province.kill_request.kill_house.name + total_amount = province.total_amount if province.total_amount > 0 else int(province.wage) * int( + province.main_quantity * province_request.poultry_request.Index_weight) + all_total_amount += total_amount + send_date = jdatetime.date.fromgregorian( + day=province_request.poultry_request.send_date.day, + month=province_request.poultry_request.send_date.month, + year=province_request.poultry_request.send_date.year + ) if province_request.poultry_request.send_date else '-' + wieght = int(province.main_quantity * province_request.poultry_request.Index_weight) + all_wiegh += wieght + wage = province.wage + if wage > 0: + all_wage.append(wage) + list1 = [ + m, + str(province_request.poultry_request.order_code), + province_request.poultry_request.poultry.user.fullname, + province_request.poultry_request.poultry.user.mobile, + province_request.poultry_request.poultry.address.city.name, + str(send_date), + kill_place, + province_request.poultry_request.chicken_breed, + province.main_quantity, + wieght, + province_request.poultry_request.Index_weight, + province.wage, + total_amount + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + else: + wage_all = 0 + values_list = [ + m - 1, + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + '', + all_quantity, + all_wiegh, + '', + wage_all, + all_total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def slaughterhouse_fee_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' and 'date2' in request.GET: + + province_kill_request = (ProvinceKillRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=True, + trash=False, + archive_by_province=False, + return_to_province=False, + ).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', ).order_by( + '-kill_request__recive_date')) + else: + province_kill_request = (ProvinceKillRequest.objects.filter( + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=True, + trash=False, + archive_by_province=False, + return_to_province=False, + ).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight', 'kill_request__recive_date') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', 'kill_request__recive_date').order_by( + '-kill_request__recive_date')) + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + + all_total_amount = 0 + + red_font = Font(color="C00000", bold=True) + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', ) + if kill_house: + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های پرداخت شده خریدار {kill_house.name} از تاریخ {from_date_1} تا {to_date_1}' + else: + first = province_kill_request.first()['kill_request__recive_date'] + last = province_kill_request.last()['kill_request__recive_date'] + from_date = jdatetime.date.fromgregorian( + year=first.year, + month=first.month, + day=first.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=last.year, + month=last.month, + day=last.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های پرداخت شده خریدار {kill_house.name} از تاریخ {to_date_1} تا {from_date_1}' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'A2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['A2'].font = red_font + # برای بالای هدر + header_list = [ + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + + l = 4 + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 27 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for province in province_kill_request: + + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').filter( + key=province['province_request__key'], + trash=False).only('poultry_request__send_date', 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').values('poultry_request__send_date', + 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', + 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').first() + kill_place = province['kill_request__slaughter_house__name'] if province[ + 'kill_request__slaughter_house'] != None else \ + province['kill_request__kill_house__name'] + total_amount = (province['total_killed_weight'] * province['wage']) if province['total_amount'] == 0 else \ + province['total_amount'] + all_total_amount += total_amount + send_date = jdatetime.date.fromgregorian( + day=province_request['poultry_request__send_date'].day, + month=province_request['poultry_request__send_date'].month, + year=province_request['poultry_request__send_date'].year + ) if province_request['poultry_request__send_date'] else '-' + wieght = province['total_killed_weight'] + wage = province['wage'] + if wage > 0: + all_wage.append(wage) + list1 = [ + m, + str(province_request['poultry_request__order_code']), + province_request['poultry_request__poultry__user__fullname'], + province_request['poultry_request__poultry__user__mobile'], + province_request['poultry_request__poultry__address__city__name'], + str(send_date), + kill_place, + province_request['poultry_request__chicken_breed'], + province['total_killed_quantity'], + wieght, + province_request['poultry_request__Index_weight'], + province['wage'], + total_amount + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + else: + wage_all = 0 + values_list = [ + m - 1, + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + '', + all_quantity, + all_wiegh, + '', + wage_all, + all_total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if kill_house: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت شده {kill_house.name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def slaughterhouse_fee_not_paid_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' and 'date2' in request.GET: + + province_kill_request = (ProvinceKillRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=False, + trash=False, + archive_by_province=False, + return_to_province=False, + ).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', ).order_by( + '-kill_request__recive_date')) + else: + province_kill_request = (ProvinceKillRequest.objects.filter( + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=False, + trash=False, + archive_by_province=False, + return_to_province=False, + ).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight', 'kill_request__recive_date') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', 'kill_request__recive_date').order_by( + '-kill_request__recive_date')) + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + + all_total_amount = 0 + + red_font = Font(color="C00000", bold=True) + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', ) + if kill_house: + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های پرداخت نشده خریدار {kill_house.name} از تاریخ {from_date_1} تا {to_date_1}' + else: + first = province_kill_request.first()['kill_request__recive_date'] + last = province_kill_request.last()['kill_request__recive_date'] + from_date = jdatetime.date.fromgregorian( + year=first.year, + month=first.month, + day=first.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=last.year, + month=last.month, + day=last.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های پرداخت شده خریدار {kill_house.name} از تاریخ {to_date_1} تا {from_date_1}' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'A2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['A2'].font = red_font + # برای بالای هدر + header_list = [ + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + + l = 4 + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 27 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for province in province_kill_request: + + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').filter( + key=province['province_request__key'], + trash=False).only('poultry_request__send_date', 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').values('poultry_request__send_date', + 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', + 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').first() + kill_place = province['kill_request__slaughter_house__name'] if province[ + 'kill_request__slaughter_house'] != None else \ + province['kill_request__kill_house__name'] + total_amount = (province['total_killed_weight'] * province['wage']) if province['total_amount'] == 0 else \ + province['total_amount'] + all_total_amount += total_amount + send_date = jdatetime.date.fromgregorian( + day=province_request['poultry_request__send_date'].day, + month=province_request['poultry_request__send_date'].month, + year=province_request['poultry_request__send_date'].year + ) if province_request['poultry_request__send_date'] else '-' + wieght = province['total_killed_weight'] + wage = province['wage'] + if wage > 0: + all_wage.append(wage) + list1 = [ + m, + str(province_request['poultry_request__order_code']), + province_request['poultry_request__poultry__user__fullname'], + province_request['poultry_request__poultry__user__mobile'], + province_request['poultry_request__poultry__address__city__name'], + str(send_date), + kill_place, + province_request['poultry_request__chicken_breed'], + province['total_killed_quantity'], + wieght, + province_request['poultry_request__Index_weight'], + province['wage'], + total_amount + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + else: + wage_all = 0 + values_list = [ + m - 1, + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + '', + all_quantity, + all_wiegh, + '', + wage_all, + all_total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if kill_house: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت نشده {kill_house.name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای پرداخت نشده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def car_province_excel(request): + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + cars = KillHouseDriver.objects.filter(trash=False).select_related('user').order_by( + 'id') + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user).first() + kill_house_cars = KillHouseADDCAR.objects.filter(kill_house=kill_house, trash=False).values_list('driver__id', + flat=True).distinct() + cars = cars.filter(id__in=kill_house_cars) + excel_options = [ + 'ردیف', + 'مدل خودرو', + 'ماهیت', + 'پلاک', + 'ظرفیت', + 'کد بهداشتی', + 'نام راننده', + 'موبایل راننده', + 'کشتارگاه ها/کشتارکن ها', + 'وضعیت' + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A2'] + max_col = worksheet.max_column + range_str = f'A1:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 0 + m = 1 + for car in cars: + l += 1 + + kill_house_list_name = '' + kill_house_list = [] + active = 'فعال' if car.active_state else 'غیرفعال' + + add_car = KillHouseADDCAR.objects.filter(driver=car, trash=False).select_related('kill_house').only( + 'kill_house__name') + kill_house_list = [add_car_obj.kill_house.name if add_car_obj.kill_house else '-' for add_car_obj in add_car] + + if car.type == "rental": + car_type = "اجاره ای" + kill_house_list_name = 'همه کشتارگاه ها/کشتارکن ها' + else: + car_type = "اختصاصی" + if kill_house_list: + if len(kill_house_list) > 1: + kill_house_list_name = '/'.join(kill_house_list) + else: + kill_house_list_name = kill_house_list[0] + else: + kill_house_list_name = '-' + fullname = car.user.fullname if car.user else '-' + + mobile = car.user.mobile if car.user else '-' + list1 = [ + m, + car.type_car, + car_type, + car.pelak, + car.capocity, + car.health_code, + fullname, + mobile, + kill_house_list_name, + active + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + m += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="خودروها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_wage_archive_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if 'date1' in request.GET else '-' + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).first() + if 'date1' and 'date2' in request.GET: + province_kill_request = (ProvinceKillRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=False, + archive_by_province=True, return_to_province=False, + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', ).order_by( + '-kill_request__recive_date')) + else: + province_kill_request = (ProvinceKillRequest.objects.filter( + killhouse_user=kill_house, + state__in=('pending', 'accepted'), wage_pay=False, + archive_by_province=True, return_to_province=False, + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('kill_request__kill_house__name', 'total_killed_quantity', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight', 'kill_request__recive_date') + .values('kill_request__kill_house__name', 'total_killed_quantity', 'total_killed_weight', + 'province_request__key', 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', 'kill_request__recive_date').order_by( + '-kill_request__recive_date')) + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + + all_total_amount = 0 + + red_font = Font(color="C00000", bold=True) + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', ) + if kill_house: + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های بایگانی شده خریدار {kill_house.name} از تاریخ {from_date_1} تا {to_date_1}' + else: + first = province_kill_request.first()['kill_request__recive_date'] + last = province_kill_request.last()['kill_request__recive_date'] + from_date = jdatetime.date.fromgregorian( + year=first.year, + month=first.month, + day=first.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=last.year, + month=last.month, + day=last.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + worksheet['A2'] = f'کارمزد های پرداخت شده خریدار {kill_house.name} از تاریخ {to_date_1} تا {from_date_1}' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'A2:C2' + + worksheet.merge_cells(merge_range1) + worksheet['A2'].font = red_font + # برای بالای هدر + header_list = [ + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + + l = 4 + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 27 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for province in province_kill_request: + + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').filter( + key=province['province_request__key'], + trash=False).only('poultry_request__send_date', 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').values('poultry_request__send_date', + 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', + 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').first() + kill_place = province['kill_request__slaughter_house__name'] if province[ + 'kill_request__slaughter_house'] != None else \ + province['kill_request__kill_house__name'] + total_amount = (province['total_killed_weight'] * province['wage']) if province['total_amount'] == 0 else \ + province['total_amount'] + all_total_amount += total_amount + send_date = jdatetime.date.fromgregorian( + day=province_request['poultry_request__send_date'].day, + month=province_request['poultry_request__send_date'].month, + year=province_request['poultry_request__send_date'].year + ) if province_request['poultry_request__send_date'] else '-' + wieght = province['total_killed_weight'] + wage = province['wage'] + if wage > 0: + all_wage.append(wage) + list1 = [ + m, + str(province_request['poultry_request__order_code']), + province_request['poultry_request__poultry__user__fullname'], + province_request['poultry_request__poultry__user__mobile'], + province_request['poultry_request__poultry__address__city__name'], + str(send_date), + kill_place, + province_request['poultry_request__chicken_breed'], + province['total_killed_quantity'], + wieght, + province_request['poultry_request__Index_weight'], + province['wage'], + total_amount + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + else: + wage_all = 0 + values_list = [ + m - 1, + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + '', + all_quantity, + all_wiegh, + '', + wage_all, + all_total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + if kill_house: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای بایگانی شده {kill_house.name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای بایگانی شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_total_wage_archive_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else None + kill_house_list = [] + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + kill_houses = (KillHouse.objects.filter(system_address__province=user.province, trash=False).select_related( + 'kill_house_operator__user') + .only('name', 'key', 'kill_house_operator__user__fullname', 'killer').values('name', 'key', + 'kill_house_operator__user__fullname', + 'killer')) + if 'date1' in request.GET: + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + killhouse_user__key=kill_house['key'], wage_pay=False, + archive_by_province=True, return_to_province=False, + trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + else: + for kill_house in kill_houses: + if ProvinceKillRequest.objects.filter(killhouse_user__key=kill_house['key'], wage_pay=False, + archive_by_province=True, return_to_province=False, + trash=False).exists(): + if kill_house not in kill_house_list: + kill_house_list.append(kill_house) + excel_options = [ + 'ردیف', + 'کد سفارش', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'تاریخ کشتار', + 'محل کشتار', + 'نژاد', + 'تعداد(قطعه)', + 'وزن(کیلوگرم)', + 'میانگین وزنی(کیلوگرم)', + 'کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = 'اطلاعات کلی' + worksheet = workbook.create_sheet(sheet_name) + if sheet_name == 'اطلاعات کلی': + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + if 'date1' in request.GET: + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date1 = reversed(to_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date1) + worksheet['C2'] = f'کارمزد های معوقه از {from_date_1} تا {from_date_2}' + + worksheet['C2'].font = Font(color="C00000", bold=True) + worksheet['C2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.alignment = Alignment(horizontal='center', vertical='center') + header_list1 = [ + 'تعداد کل سفارشات ', + 'مجموع تعداد کل(قطعه)', + 'مجموع وزن کل(کیلوگرم)', + 'میانگین کل کارمزداتحادیه(ریال)', + 'مبلغ کل کارمزدها(ریال)', + + ] + header_list = [ + 'خریدار', + 'مالک', + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[5].height = 45 + worksheet.column_dimensions[col_letter].width = 27 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list1, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 35 + worksheet.column_dimensions[col_letter].width = 18 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l = 6 + all_province_kill_request = 0 + final_quantity = 0 + fianl_wage = 0 + final_wage_all = [] + final_total_amount = 0 + if 'date1' in request.GET: + for kill_house in kill_house_list: + province_kill_request = ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + killhouse_user__key=kill_house['key'], + state__in=('pending', 'accepted'), + wage_pay=False, archive_by_province=True, + return_to_province=False, + trash=False).select_related( + 'province_request').only('total_killed_quantity', 'province_request__key', 'main_quantity', 'wage', + 'total_amount').order_by( + '-kill_request__recive_date') + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + all_total_amount = 0 + all_province_kill_request += len(province_kill_request) + final_quantity += all_quantity + for province in province_kill_request: + wage = province.wage + if wage > 0: + all_wage.append(wage) + total_amount = (province.total_killed_weight * province.wage) + all_total_amount += total_amount + final_total_amount += all_total_amount + fianl_wage += all_wiegh + + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + final_wage_all.append(wage_all) + else: + wage_all = 0 + killer = 'کشتارگاه' if kill_house['killer'] == False else 'کشتارکن' + values_list = [ + killer + '(' + kill_house['name'] + ')', + kill_house['kill_house_operator__user__fullname'], + len(province_kill_request), + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=l, column=item + 3, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + else: + for kill_house in kill_house_list: + province_kill_request = ProvinceKillRequest.objects.filter(killhouse_user__key=kill_house['key'], + state__in=('pending', 'accepted'), + wage_pay=False, archive_by_province=True, + return_to_province=False, + trash=False).select_related( + 'province_request').only('total_killed_quantity', 'province_request__key', 'main_quantity', + 'wage', + 'total_amount').order_by( + '-kill_request__recive_date') + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + all_total_amount = 0 + all_province_kill_request += len(province_kill_request) + final_quantity += all_quantity + for province in province_kill_request: + wage = province.wage + if wage > 0: + all_wage.append(wage) + total_amount = (province.total_killed_weight * province.wage) + all_total_amount += total_amount + final_total_amount += all_total_amount + fianl_wage += all_wiegh + + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + final_wage_all.append(wage_all) + else: + wage_all = 0 + killer = 'کشتارگاه' if kill_house['killer'] == False else 'کشتارکن' + values_list = [ + killer + '(' + kill_house['name'] + ')', + kill_house['kill_house_operator__user__fullname'], + len(province_kill_request), + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=l, column=item + 3, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + l += 1 + + if len(final_wage_all) > 0: + wage = sum(final_wage_all) / len(final_wage_all) + else: + wage = 0 + values_list = [ + all_province_kill_request, + final_quantity, + fianl_wage, + wage, + final_total_amount + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.fill = PatternFill(start_color="EEEAF2", fill_type="solid") + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for kill_house in kill_house_list: + sheet_name = kill_house['name'] + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + if 'date1' in request.GET: + province_kill_request = ( + ProvinceKillRequest.objects.filter(kill_request__recive_date__gte=date1, + kill_request__recive_date__lte=date2, + killhouse_user__key=kill_house['key'], wage_pay=False, + archive_by_province=True, return_to_province=False, + state__in=('pending', 'accepted'), + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('total_killed_quantity', 'province_request__key', 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight') + .values('total_killed_quantity', 'total_killed_weight', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', ).order_by( + '-kill_request__recive_date')) + else: + province_kill_request = ( + ProvinceKillRequest.objects.filter(killhouse_user__key=kill_house['key'], wage_pay=False, + archive_by_province=True, return_to_province=False, + state__in=('pending', 'accepted'), + trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', 'kill_request') + .only('total_killed_quantity', 'province_request__key', 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount' + , 'total_killed_weight') + .values('total_killed_quantity', 'total_killed_weight', 'province_request__key', + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', + 'main_quantity', 'wage', 'total_amount', ).order_by( + '-kill_request__recive_date')) + all_quantity = province_kill_request.aggregate(total_quantity=Sum('total_killed_quantity')).get( + 'total_quantity', 0) + all_wiegh = province_kill_request.aggregate(total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_wage = [] + + all_total_amount = 0 + + # برای بالای هدر + header_list = [ + 'تعداد سفارشات ', + 'مجموع تعداد(قطعه)', + 'مجموع وزن(کیلوگرم)', + 'میانگین کارمزد اتحادیه(ریال)', + 'مبلغ کل کارمزد(ریال)', + + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 36 + worksheet.column_dimensions[col_letter].width = 16 + + l = 4 + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 27 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for province in province_kill_request: + + province_request = ProvinceCheckOperatorRequest.objects.select_related( + 'poultry_request__poultry__user', 'poultry_request__poultry__address__city', 'poultry_request').filter( + key=province['province_request__key'], + trash=False).only('poultry_request__send_date', 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').values('poultry_request__send_date', + 'poultry_request__order_code', + 'poultry_request__poultry__user__fullname', + 'poultry_request__poultry__user__mobile', + 'poultry_request__poultry__address__city__name', + 'poultry_request__chicken_breed', + 'poultry_request__Index_weight').first() + kill_place = province['kill_request__slaughter_house__name'] if province[ + 'kill_request__slaughter_house'] != None else \ + province['kill_request__slaughter_house__name'] + total_amount = (province['total_killed_weight'] * province['wage']) + all_total_amount += total_amount + send_date = jdatetime.date.fromgregorian( + day=province_request['poultry_request__send_date'].day, + month=province_request['poultry_request__send_date'].month, + year=province_request['poultry_request__send_date'].year + ) if province_request['poultry_request__send_date'] else '-' + wieght = province['total_killed_weight'] + wage = province['wage'] + if wage > 0: + all_wage.append(wage) + list1 = [ + m, + str(province_request['poultry_request__order_code']), + province_request['poultry_request__poultry__user__fullname'], + province_request['poultry_request__poultry__user__mobile'], + province_request['poultry_request__poultry__address__city__name'], + str(send_date), + kill_place, + province_request['poultry_request__chicken_breed'], + province['total_killed_quantity'], + wieght, + province_request['poultry_request__Index_weight'], + province['wage'], + total_amount + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + if len(all_wage) > 0: + wage_all = sum(all_wage) / len(all_wage) + else: + wage_all = 0 + values_list = [ + m - 1, + all_quantity, + all_wiegh, + wage_all, + all_total_amount, + + ] + for item in range(len(values_list)): + cell = worksheet.cell(row=3, column=item + 4, value=values_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10) + value = values_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + '', + all_quantity, + all_wiegh, + '', + wage_all, + all_total_amount, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="کارمزدهای معوقه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def process_for_each_hatching(request): + hatching = PoultryHatching.objects.get(trash=False, key=request.GET['key']) + name = hatching.poultry.unit_name + province_name = hatching.poultry.address.province.name + now = datetime.datetime.now().date() + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + date_now = separate.join(reversed_date) + + hatch_date = jdatetime.date.fromgregorian( + day=hatching.date.day, + month=hatching.date.month, + year=hatching.date.year + ) + quantity = hatching.quantity + ninety_percent = (quantity * 90) / 100 + killed = 0 + + poultry_requests = PoultryRequest.objects.filter(out_province_request_cancel=False, trash=False, hatching=hatching, + archive=False, + state_process__in=('accepted', 'pending')).order_by('id') + all_quantity_of_request = poultry_requests.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + excel_options = [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'سن کشتار', + 'نوع درخواست', + 'فروش', + 'تعداد درخواست کشتار', + 'میانگین وزنی درخواست', + 'وزن کل درخواست ', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار', + 'مانده در سالن', + ' تعداد بار', + 'تعداد بار قطعه', + 'وزن بار', + 'تعداد قطعه وارد شده در قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + red_font = Font(color="C00000", bold=True) + sheet_list = [ + 'مدیریت بارها', + 'بار های زنجیره' + ] + + for name in sheet_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + + if sheet_name == 'مدیریت بارها': + header_list = [ + 'نام واحد', + 'نام مالک', + 'تاریخ جوجه ریزی', + 'تعداد جوجه ریزی', + 'نود درصد جوجه ریزی', + 'تعداد نهایی قطعه کشتار شده', + 'وزن نهایی کشتار شده', + 'مجموع تلفات', + 'مانده در سالن', + 'متوسط سن کشتار', + 'تعداد ثبت سفارش', + 'تعداد درخواست کشتار (قطعه)', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار(کیلوگرم)', + 'درصد کشتار نسبت به جوجه ریزی', + 'مجموع تخصیصی به ماشین(قطعه)', + 'مجموع وزن تخصیصی به ماشین(کیلوگرم)', + 'تعداد تخلیه شده دامپزشک', + 'وزن تخلیه شده دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'حجم زنجیره', + 'وزن زنجیره', + + ] + # برای بالای هدر + for col_num, option in enumerate(header_list, 2): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=9, bold=True, color='FFFFFF') + worksheet.row_dimensions[3].height = 36 + worksheet.column_dimensions[col_letter].width = 14 + + worksheet['A5'] = 'جزئیات سفارشات' + worksheet[ + 'F1'] = f'گزارش پایش اطلاعاتی مرغداری {name} سامانه رصدیار استان {province_name} در تاریخ {date_now}' + worksheet['C2'] = f'اطلاعات کلی' + + worksheet['F1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['C2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A5'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'F1:K1' + + worksheet.merge_cells(merge_range1) + worksheet['F1'].font = red_font + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=36, width=15) + + l = 6 + + final_left_over = [] + all_quantity_of_car = 0 + average_age_list = [] + all_percent = 0 + m = 1 + all_weight = [] + all_quantity_of_car_vet_state_accepted = 0 + request_weight = [] + all_request_weight = [] + all_free_sale_in_province_true = 0 + all_kill_province_request_poultry_request_Index_weight = [] + all_weight_of_car = 0 + all_weight_of_car_vet_state_accepted = 0 + all_main_quantity = 0 + sum_quantity_qarantineh = 0 + sum_all_quantity_vet_kill = 0 + sum_all_wight_vet_kill = 0 + sum_net_weight = 0 + sum_real_quantity_assigment = 0 + sum_accepted_real_quantity = 0 + sum_accepted_real_weight = 0 + all_free_sale_in_province_false = 0 + all_loses = 0 + all_province_quantity = 0 + for poultry_request in poultry_requests: + all_loses += poultry_request.hatching.losses + kill_request = ProvinceKillRequest.objects.filter(province_request__poultry_request=poultry_request, + trash=False, + state__in=('pending', 'accepted'), + return_to_province=False).select_related( + 'killhouse_user', 'province_request__poultry_request').order_by('-create_date') + car_date = shamsi_date(poultry_request.send_date, in_value=True) + + create_date = shamsi_date(poultry_request.create_date, in_value=True) + + average_age = (poultry_request.send_date.date() - hatching.date.date()).days + 1 + average_age_list.append(average_age) + + if poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + free_sale_in_province_false = 0 + Index_weight_sale_in_province_false = 0 + free_sale_in_province_true = 0 + + all_province_quantity += poultry_request.quantity + if poultry_request.out == True: + sale_type = 'خارج از استان' + elif poultry_request.free_sale_in_province == False: + free_sale_in_province_false = poultry_request.quantity + all_free_sale_in_province_false += free_sale_in_province_false + Index_weight_sale_in_province_false = poultry_request.Index_weight + sale_type = 'دولتی' + else: + sale_type = 'آزاد' + free_sale_in_province_true = poultry_request.quantity + + all_free_sale_in_province_true += free_sale_in_province_true + + all_request_weight.append(poultry_request.Index_weight * poultry_request.quantity) + list1 = [ + m, + str(poultry_request.order_code), + str(create_date), + str(car_date), + average_age, + type, + sale_type, + poultry_request.quantity, + poultry_request.Index_weight, + round(poultry_request.quantity * poultry_request.Index_weight, 2), + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 1)].width = 17.01 + worksheet.row_dimensions[l + 1].height = 21 + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + # l += 1 + if kill_request.exists(): + o = l + 1 + if len(kill_request) > 1: + s = len(kill_request) - 1 + + for col in range(ord('A'), ord('J') + 1): + # rng = chr(col) + '7:{}'.format(r) + rng = f'{chr(col)}{o}:{chr(col)}{o + s}' + worksheet.merge_cells(rng) + worksheet[chr(col) + f'{o}'].alignment = Alignment(horizontal='center', vertical='center') + for kill in kill_request: + + all_main_quantity += kill.main_quantity + state_s = '' + if kill.state == 'pending': + state_s = 'درانتظار تایید' + elif kill.state == 'accepted': + state_s = ' تایید شده' + quantity_of_car_vet_state_accepted = 0 + weight_of_car_vet_state_accepted = 0 + quantity_of_car = 0 + weight_of_car = 0 + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request=kill).order_by( + 'id').only('create_date', 'vet_state') + all_net_weight = 0 + all_real_quantity_assigment = 0 + if kill_house_requests: + for kill_house_request in kill_house_requests: + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False).only('net_weight', + 'real_quantity').first() + if assignment: + all_net_weight += assignment.net_weight if assignment.net_weight != None else 0 + all_real_quantity_assigment += assignment.real_quantity if assignment.real_quantity != None else 0 + quantity_of_car += kill_house_request.quantity + all_quantity_of_car += kill_house_request.quantity + weight_of_car += int( + kill_house_request.quantity * kill_house_request.province_request.poultry_request.Index_weight) + + if kill_house_request.vet_state == 'accepted': + quantity_of_car_vet_state_accepted += kill_house_request.quantity + weight_of_car_vet_state_accepted += kill_house_request.accepted_real_weight + all_quantity_of_car_vet_state_accepted += kill_house_request.quantity + killed += kill.main_quantity + all_quantity_qarantineh = kill_house_requests.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + + all_quantity_vet_kill = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_weight_vet_kill = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + all_accepted_real_quantity = kill.total_killed_quantity + all_accepted_real_weight = kill.total_killed_weight + sum_all_wight_vet_kill += all_weight_vet_kill if all_weight_vet_kill != None else 0 + sum_all_quantity_vet_kill += all_quantity_vet_kill if all_quantity_vet_kill != None else 0 + sum_quantity_qarantineh += all_quantity_qarantineh if all_quantity_qarantineh != None else 0 + sum_accepted_real_quantity += all_accepted_real_quantity if all_accepted_real_quantity != None else 0 + sum_accepted_real_weight += all_accepted_real_weight if all_accepted_real_weight != None else 0 + left_over = (quantity - killed) + final_left_over.append(left_over) + percent_after_assigment = (quantity_of_car_vet_state_accepted * 100) / quantity + all_percent += percent_after_assigment + + all_weight.append(kill.main_quantity * kill.province_request.poultry_request.Index_weight) + killer = 'کشتارکن' if kill.killhouse_user.killer == True else 'کشتارگاه' + + request_weight.append(Index_weight_sale_in_province_false) + all_kill_province_request_poultry_request_Index_weight.append( + kill.province_request.poultry_request.Index_weight) + all_weight_of_car_vet_state_accepted += weight_of_car_vet_state_accepted + all_weight_of_car += weight_of_car + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = \ + ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = \ + ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + list1 = [ + killer, + kill.killhouse_user.name, + kill.killhouse_user.kill_house_operator.user.mobile, + kill.main_quantity, + kill.province_request.poultry_request.Index_weight, + left_over, + len(kill_house_requests) if kill_house_requests else 0, + quantity_of_car, + weight_of_car, + all_quantity_qarantineh if all_quantity_qarantineh else '-', + all_quantity_vet_kill if all_quantity_vet_kill else '-', + all_weight_vet_kill if all_weight_vet_kill else '-', + all_real_quantity_assigment if all_real_quantity_assigment > 0 else '-', + all_net_weight if all_net_weight > 0 else '-', + kill.total_killed_quantity, + kill.total_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + l += 1 + + sum_net_weight += all_net_weight + sum_real_quantity_assigment += all_real_quantity_assigment + else: + if poultry_request.out == True: + left_over = (quantity - killed) + list1 = [ + 'خارج از استان', + poultry_request.buyer_fullname, + poultry_request.buyer_mobile, + poultry_request.quantity, + int(poultry_request.Index_weight), + left_over, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + poultry_request.quantity, + int(poultry_request.quantity * poultry_request.Index_weight), + '-', + '-', + '-', + '-', + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + sum_accepted_real_weight += int(poultry_request.quantity * poultry_request.Index_weight) + sum_accepted_real_quantity += poultry_request.quantity + else: + list1 = [ + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + l += 1 + + try: + avrage_age1 = round((sum(average_age_list) / len(average_age_list))) + rw = round(sum(request_weight) / len(request_weight)) + dd = round(sum(all_kill_province_request_poultry_request_Index_weight) / len( + all_kill_province_request_poultry_request_Index_weight)) + except: + avrage_age1 = 0 + rw = 0 + dd = 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_requests) + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + int(all_province_quantity), + '', + int(sum(all_request_weight)), + # int(all_free_sale_in_province_true), + '', + '', + '', + int(all_main_quantity), + int(dd), + f'', + '', + + int(all_quantity_of_car), + int(all_weight_of_car), + int(sum_quantity_qarantineh), + int(sum_all_quantity_vet_kill), + int(sum_all_wight_vet_kill), + int(sum_real_quantity_assigment), + int(sum_net_weight), + int(sum_accepted_real_quantity), + int(sum_accepted_real_weight), + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + try: + all_car = round((all_quantity_of_car * 100) / hatching.killed_quantity) + except: + all_car = 0 + try: + all_car_vet = round((all_quantity_of_car_vet_state_accepted * 100) / all_quantity_of_car) + except: + all_car_vet = 0 + + value_header_list = [ + hatching.poultry.unit_name, + hatching.poultry.user.fullname, + str(hatch_date), + quantity, + ninety_percent, + sum_accepted_real_quantity, + sum_accepted_real_weight, + all_loses, + hatching.left_over, + avrage_age1, + len(poultry_requests), + all_quantity_of_request, + hatching.out_province_killed_quantity, + hatching.out_province_killed_weight, + all_main_quantity, + sum(all_weight), + round((hatching.killed_quantity * 100) / quantity), + all_quantity_of_car, + all_weight_of_car, + sum_all_quantity_vet_kill, + sum_all_wight_vet_kill, + sum_real_quantity_assigment, + sum_net_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + hatching.chain_killed_quantity, + hatching.chain_killed_weight, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=4, column=item + 2, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + else: + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + chain_allocations = ChainAllocation.objects.filter(state='accepted',poultry_hatching=hatching + ).order_by('id') + + state1 = 'تایید شده' + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=chain_allocations + ) + ).filter(): + ps = filterset_class(data=query, queryset=chain_allocations) + chain_allocations = ps.filter() + + excel_options = [ + 'ردیف', + 'وضعیت', + ' تاریخ سفارش', + 'نوع فروش', + 'ثبت کننده سفارش', + 'تلفن ثبت کننده سفارش', + 'خریدار', + 'تلفن خریدار', + 'مرغداری', + 'تلفن مرغداری', + 'شرکت زنجیره', + ' تلفن شرکت زنجیره', + 'کد بهداشتی', + 'کد قرنطینه', + 'راننده ', + 'تلفن راننده ', + 'خودرو', + 'پلاک', + 'حجم', + 'میانگین وزن', + 'وزن', + 'حذف/رد کننده', + 'تلفن حذف/رد کننده', + ] + + + + + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if state1 == 'تایید شده': + for col_num, option in enumerate(excel_options[:21], 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + else: + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {state1} شرکت زنجیره' + if chain_allocations.exists(): + name = chain_allocations.first().poultry_hatching.poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_age = [] + + all_quantity = chain_allocations.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_weighte = chain_allocations.aggregate( + total=Sum('weight'))[ + 'total'] or 0 + has_code = 0 + if chain_allocations: + for chain_allocation in chain_allocations: + age = (chain_allocation.poultry_hatching.chicken_age) + all_age.append(age) + chain_date = jdatetime.date.fromgregorian( + day=chain_allocation.date.day, + month=chain_allocation.date.month, + year=chain_allocation.date.year + ) + + if chain_allocation.quarantine_code: + has_code += 1 + + remover_fullname = '-' + remover_mobile = '-' + if chain_allocation.state == 'accepted': + state = 'تایید شده' + elif chain_allocation.state == 'rejected': + state = 'رد شده' + remover_fullname = chain_allocation.seconder['fullname'] if chain_allocation.seconder else None + remover_mobile = chain_allocation.seconder['mobile'] if chain_allocation.seconder else None + elif chain_allocation.state == 'pending': + state = 'در انتظار تایید' + else: + state = 'حذف شده' + remover_fullname = chain_allocation.remover['fullname'] if chain_allocation.remover else None + remover_mobile = chain_allocation.remover['mobile'] if chain_allocation.remover else None + out_province = 'خارج استان' if chain_allocation.out_province == True else 'داخل استان' + + full_name_registerer = chain_allocation.registerer[ + 'fullname'] if chain_allocation.registerer else '-' + mobile_registerer = chain_allocation.registerer['mobile'] if chain_allocation.registerer else '-' + + if chain_allocation.kill_house is not None: + buyer_fullname = chain_allocation.kill_house.name + buyer_mobile = chain_allocation.kill_house.kill_house_operator.user.mobile + else: + buyer_fullname = chain_allocation.buyer_name + buyer_mobile = chain_allocation.buyer_mobile + + list1 = [ + m, + state, + str(chain_date), + out_province, + full_name_registerer, + mobile_registerer, + buyer_fullname, + buyer_mobile, + chain_allocation.poultry_hatching.poultry.unit_name, + chain_allocation.poultry_hatching.poultry.user.mobile, + chain_allocation.company_name, + chain_allocation.company_user_mobile, + chain_allocation.health_code if chain_allocation.health_code else '-', + chain_allocation.quarantine_code if chain_allocation.quarantine_code else '-', + chain_allocation.driver_name if chain_allocation.driver_name else '-', + chain_allocation.driver_mobile if chain_allocation.driver_mobile else '-', + chain_allocation.type_car if chain_allocation.type_car else '-', + chain_allocation.pelak if chain_allocation.pelak else '-', + chain_allocation.quantity, + chain_allocation.index_weight, + chain_allocation.weight, + remover_fullname, + remover_mobile, + ] + m += 1 + if state1 == 'تایید شده': + for item in range(len(list1) - 2): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + else: + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(chain_allocations), + all_quantity, + all_weighte, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + '', + all_weighte, + '', + '', + + ] + if state1 == 'تایید شده': + for item in range(len(list2) - 2): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش اطلاعاتی مرغدار {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def process_for_all_hatching(request): + hatchings = PoultryHatching.objects.filter(trash=False, allow_hatching='pending', archive=False) + name = hatchings.first().poultry.unit_name + province_name = hatchings.first().poultry.address.province.name + now = datetime.datetime.now().date() + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + date_now = separate.join(reversed_date) + + excel_options = [ + 'نام واحد', + 'نام مالک', + 'تاریخ جوجه ریزی', + 'تعداد جوجه ریزی', + 'نود درصد جوجه ریزی', + 'مانده در سالن', + 'متوسط سن کشتار', + 'تعداد ثبت سفارش', + 'تعداد درخواست کشتار (قطعه)', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار(کیلوگرم)', + 'درصد کشتار نسبت به نود درصد', + 'مجموع تخصیصی به ماشین(قطعه)', + 'درصد تخصیصی به ماشین نسبت به تخصیص استان به خریدار', + 'درصد تخلیه شده نسبت به تخصیص به ماشین', + 'تعداد تخلیه شده در کشتارگاه', + 'کد سفارش', + 'تاریخ کشتار', + 'سن کشتار', + 'نوع درخواست', + 'فروش', + 'تعداد درخواست کشتار دولتی', + 'میانگین وزنی درخواست', + 'وزن کل درخواست ', + 'تعداد درخواست کشتار آزاد', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار', + 'مانده در سالن', + 'ماهیت خریدار', + 'خریدار', + 'تخصیصی خریدار به ماشین', + 'وزن تخصیصی خریدار به ماشین', + 'تلفات غیرعادی گله', + 'تعداد تخلیه شده در کشتار گاه', + 'وزن تخلیه شده در کشتارگاه', + 'درصد تخلیه شده به تخصیص به ماشین', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + red_font = Font(color="C00000", bold=True) + + worksheet['F1'] = f'گزارش پایش اطلاعاتی مرغداری {name} سامانه رصدیار استان {province_name} در تاریخ {date_now}' + worksheet['A2'] = f'اطلاعات کلی' + + worksheet['F1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['C2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'F1:K1' + + worksheet.merge_cells(merge_range1) + worksheet['F1'].font = red_font + + # برای کل + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + worksheet.column_dimensions[col_letter].width = 14 + + worksheet.row_dimensions[3].height = 36 + + worksheet.freeze_panes = worksheet['A4'] + max_col = worksheet.max_column + range_str = f'A3:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + final_left_over = [] + all_quantity_of_car = 0 + all_percent = 0 + all_weight = [] + all_quantity_of_car_vet_state_accepted = 0 + request_weight = [] + average_age_list = [] + all_request_weight = [] + all_free_sale_in_province_true = 0 + all_kill_province_request_poultry_request_Index_weight = [] + all_weight_of_car = 0 + all_weight_of_car_vet_state_accepted = 0 + for hatching in hatchings: + l = 2 + + hatch_date = jdatetime.date.fromgregorian( + day=hatching.date.day, + month=hatching.date.month, + year=hatching.date.year + ) + quantity = hatching.quantity + ninety_percent = (quantity * 90) / 100 + killed = 0 + + poultry_requests = PoultryRequest.objects.filter(trash=False, hatching=hatching, archive=False).order_by('-id') + all_quantity_of_request = poultry_requests.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + for poultry_request in poultry_requests: + + kill_request = ProvinceKillRequest.objects.filter(province_request__poultry_request=poultry_request, + trash=False).select_related( + 'killhouse_user', 'province_request__poultry_request').order_by('-create_date') + + car_date = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + average_age = (poultry_request.send_date.date() - hatching.date.date()).days + 1 + average_age_list.append(average_age) + if poultry_request.union == True: + type = 'خارج از استان' + elif poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + free_sale_in_province_false = 0 + Index_weight_sale_in_province_false = 0 + free_sale_in_province_true = 0 + + if poultry_request.free_sale_in_province == False: + free_sale_in_province_false = poultry_request.quantity + Index_weight_sale_in_province_false = poultry_request.Index_weight + sale_type = 'دولتی' + else: + free_sale_in_province_true = poultry_request.quantity + sale_type = 'آزاد' + + all_free_sale_in_province_true += free_sale_in_province_true + + all_request_weight.append(Index_weight_sale_in_province_false * free_sale_in_province_false) + try: + avrage_age1 = round((sum(average_age_list) / len(average_age_list))) + rw = round(sum(request_weight) / len(request_weight)) + dd = round(sum(all_kill_province_request_poultry_request_Index_weight) / len( + all_kill_province_request_poultry_request_Index_weight)) + except: + avrage_age1 = 0 + rw = 0 + dd = 0 + try: + all_car = round((all_quantity_of_car * 100) / hatching.killed_quantity) + except: + all_car = 0 + try: + all_car_vet = round((all_quantity_of_car_vet_state_accepted * 100) / all_quantity_of_car) + except: + all_car_vet = 0 + + if kill_request: + for kill in kill_request: + quantity_of_car_vet_state_accepted = 0 + weight_of_car_vet_state_accepted = 0 + quantity_of_car = 0 + weight_of_car = 0 + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request=kill).order_by( + 'id').only('create_date', 'vet_state') + if kill_house_requests: + + for kill_house_request in kill_house_requests: + quantity_of_car += kill_house_request.quantity + all_quantity_of_car += kill_house_request.quantity + weight_of_car += kill_house_request.accepted_real_weight + + if kill_house_request.vet_state == 'accepted': + quantity_of_car_vet_state_accepted += kill_house_request.quantity + weight_of_car_vet_state_accepted += kill_house_request.accepted_real_weight + all_quantity_of_car_vet_state_accepted += kill_house_request.quantity + killed += kill.main_quantity + + left_over = (quantity - killed) + final_left_over.append(left_over) + percent_after_assigment = (quantity_of_car_vet_state_accepted * 100) / quantity + all_percent += percent_after_assigment + + all_weight.append(kill.main_quantity * kill.province_request.poultry_request.Index_weight) + killer = 'کشتارکن' if kill.killhouse_user.killer == True else 'کشتارگاه' + + request_weight.append(Index_weight_sale_in_province_false) + all_kill_province_request_poultry_request_Index_weight.append( + kill.province_request.poultry_request.Index_weight) + all_weight_of_car_vet_state_accepted += weight_of_car_vet_state_accepted + all_weight_of_car += weight_of_car + list1 = [ + hatching.poultry.unit_name, + hatching.poultry.user.fullname, + str(hatch_date), + quantity, + ninety_percent, + hatching.left_over, + avrage_age1, + len(poultry_requests), + all_quantity_of_request, + hatching.killed_quantity, + sum(all_weight), + round((hatching.killed_quantity * 100) / ninety_percent), + all_quantity_of_car, + all_car, + all_car_vet, + all_quantity_of_car_vet_state_accepted, + poultry_request.order_code, + str(car_date), + average_age, + type, + sale_type, + free_sale_in_province_false, + Index_weight_sale_in_province_false, + round(free_sale_in_province_false * Index_weight_sale_in_province_false, 2), + free_sale_in_province_true, + kill.main_quantity, + kill.province_request.poultry_request.Index_weight, + left_over, + killer, + kill.killhouse_user.name, + quantity_of_car, + weight_of_car, + '0', + quantity_of_car_vet_state_accepted, + weight_of_car_vet_state_accepted, + round(percent_after_assigment), + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + else: + list1 = [ + hatching.poultry.unit_name, + hatching.poultry.user.fullname, + str(hatch_date), + quantity, + ninety_percent, + hatching.left_over, + avrage_age1, + len(poultry_requests), + all_quantity_of_request, + hatching.killed_quantity, + sum(all_weight), + round((hatching.killed_quantity * 100) / ninety_percent), + all_quantity_of_car, + all_car, + all_car_vet, + all_quantity_of_car_vet_state_accepted, + poultry_request.order_code, + str(car_date), + average_age, + type, + sale_type, + free_sale_in_province_false, + Index_weight_sale_in_province_false, + round(free_sale_in_province_false * Index_weight_sale_in_province_false, 2), + free_sale_in_province_true, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '0', + '-', + '-', + '-', + + ] + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + r = l + 1 + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش اطلاعاتی مرغدار {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_management_kill_house_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key']) + try: + operator = KillHouseOperator.objects.get(user=user, trash=False) + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator=operator) + except: + kill_house = KillHouse.objects.filter(trash=False) + kill_house_assignments_list = KillHouseAssignmentInformation.objects.filter( + kill_house_request__killhouse_user__in=kill_house, + trash=False, + unusual_casualties=False, + kill_house_request__kill_request__recive_date__date__gte=date1, + kill_house_request__kill_request__recive_date__date__lte=date2) + + excel_options = [ + 'ردیف', + 'کد بار', + 'کد سفارش', + 'خریدار', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + 'راننده', + 'موبایل راننده', + 'ماشین', + 'پلاک', + 'تاریخ کشتار', + 'مرغدار', + 'تلفن مرغدار', + 'شهر', + 'استان', + 'تعداد تخصیصی بار(قطعه)', + 'وزن(کیلوگرم)', + 'وزن کل(کیلوگرم)', + 'تعداد واقعی تحویلی(قطعه)', + 'وزن واقعی تحویلی(کیلوگرم)', + 'وزن وارد شده ماشین بدون بار باسکول(کیلوگرم)', + 'وزن وارد شده ماشین با بار باسکول(کیلوگرم)', + 'وزن بدست آمده از بار باسکول(کیلوگرم)', + 'لاشه استحصالی(قطعه)', + 'وضعیت بار', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد تخصیصی', + 'مجموع تعداد واقعی تحویلی', + 'مجموع وزن واقعی تحویلی', + ] + # برای بالای هدر + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 17 + + worksheet['A1'] = f' مدیریت بارهای تکمیل شده ' + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[4].height = 28 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 3 + m = 1 + kill_kill_house_request_quantity_all = 0 + kill_kill_house_request_accepted_real_quantity_all = 0 + kill_kill_house_request_accepted_real_weight_all = 0 + killer_exclusive = 0 + for kill in kill_house_assignments_list: + kill_kill_house_request_quantity_all += kill.kill_house_request.quantity + kill_kill_house_request_accepted_real_quantity_all += kill.kill_house_request.accepted_real_quantity + kill_kill_house_request_accepted_real_weight_all += kill.kill_house_request.accepted_real_weight + + kill_date = jdatetime.date.fromgregorian( + year=kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date.year, + month=kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date.month, + day=kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.send_date.day + ) + final_state = 'در انتظار تایید' if kill.state == 'pending' else 'تایید شده' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.kill_house_request.killer != None: + name_killer_exclusive = kill.kill_house_request.killer.name + mobile_killer_exclusive = str(kill.kill_house_request.killhouse_user.kill_house_operator.user.mobile) + killer_exclusive += 1 + list1 = [ + m, + str(kill.kill_house_request.bar_code), + str(kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.order_code), + kill.kill_house_request.killhouse_user.name, + name_killer_exclusive, + mobile_killer_exclusive, + kill.kill_house_request.add_car.driver.driver_name, + kill.kill_house_request.add_car.driver.driver_mobile, + kill.kill_house_request.add_car.driver.type_car, + kill.kill_house_request.add_car.driver.pelak, + str(kill_date), + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.poultry.user.fullname, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.poultry.user.mobile, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.poultry.user.city.name, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.poultry.user.province.name, + kill.kill_house_request.quantity, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.Index_weight * kill.kill_house_request.quantity, + kill.kill_house_request.accepted_real_quantity, + kill.kill_house_request.accepted_real_weight, + kill.car_weight_without_load, + kill.car_weight_with_load, + kill.net_weight, + kill.kill_house_request.province_kill_request.province_request.city_request_Poultry.poultry_request.hatching.losses, + final_state, + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + m += 1 + + value_header_list = [ + killer_exclusive, + kill_kill_house_request_quantity_all, + kill_kill_house_request_accepted_real_quantity_all, + kill_kill_house_request_accepted_real_weight_all + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + value = value_header_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def all_inventory_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + names_list = ['اطلاعات کلی'] + + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + for kill in kill_house_ware_houses: + if kill.kill_house.name not in names_list: + names_list.append(kill.kill_house.name) + # names_list= kill_house_ware_houses.values('kill_house__name') + # print(names_list) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + abc_list = ['A', 'B', 'C', 'D', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'T'] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + now_date_1 = separate.join(reversed_date) + kill_houses = KillHouse.objects.filter( + pk__in=kill_house_ware_houses.values('kill_house') + ) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name in names_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + if sheet_name == 'اطلاعات کلی': + worksheet.row_dimensions[2].height = 24 + worksheet.row_dimensions[3].height = 30 + worksheet.row_dimensions[5].height = 19.04 + worksheet.row_dimensions[8].height = 32 + + worksheet['A2'] = f'این گزارش در مورخ {now_date_1} صادر شده است.' + worksheet['G2'] = f'اطلاعات کلی توزیع و پخش مرغ گرم از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'A2:D2' + merge_range123 = 'G2:N2' + worksheet.merge_cells(merge_range122) + worksheet.merge_cells(merge_range123) + + worksheet['G2'].font = Font(size=12, color='FF0000') + + for abc in abc_list: + worksheet[f'{abc}8'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for abc in abc_list[1:]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + withe_font = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + green = PatternFill(start_color="00B050", fill_type="solid") + worksheet['B3'] = f'تعداد خریداران' + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'بارهای روزانه' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + worksheet['S3'] = f'تعداد مباشر تخصیص داده شده' + worksheet['T3'] = f'تعداد صنف تخصیص داده شده' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['S3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['T3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + merge_range9 = 'B3:B5' + merge_range10 = 'S3:S5' + merge_range11 = 'T3:T5' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + worksheet.merge_cells(merge_range11) + + worksheet['C3'].font = withe_font + worksheet['B3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + worksheet['S3'].font = withe_font + worksheet['T3'].font = withe_font + + worksheet['B3'].fill = blue + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + worksheet['S3'].fill = blue + worksheet['T3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + worksheet['A8'] = f'ردیف' + worksheet['B8'] = f'خریدار' + worksheet['C8'] = f'شهرستان' + worksheet['D8'] = f'تعداد مباشر/صنف تخصیصی' + worksheet['E8'] = f'ورودی از سردخانه' + worksheet['G8'] = f'پیش سرد' + worksheet['I8'] = f'خرید خارج از استان' + worksheet['K8'] = f'بارهای روزانه' + worksheet['M8'] = f'جمع کل انبار' + worksheet['O8'] = f'توزیع شده' + worksheet['Q8'] = f'توزیع / تحویل شده' + worksheet['S8'] = f'مانده انبار' + + worksheet['A8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['C8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['D8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['K8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['O8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['Q8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['S8'].alignment = Alignment(horizontal='center', vertical='center') + + merge_range11 = 'A8:A10' + merge_range12 = 'B8:B10' + merge_range13 = 'C8:C10' + merge_range14 = 'D8:D10' + merge_range1 = 'E8:F9' + merge_range2 = 'G8:H9' + merge_range3 = 'I8:J9' + merge_range4 = 'K8:L9' + merge_range5 = 'M8:N9' + merge_range6 = 'O8:P9' + merge_range7 = 'Q8:R9' + merge_range8 = 'S8:T9' + + worksheet.merge_cells(merge_range11) + worksheet.merge_cells(merge_range12) + worksheet.merge_cells(merge_range13) + worksheet.merge_cells(merge_range14) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + + worksheet['A8'].font = withe_font + worksheet['B8'].font = withe_font + worksheet['C8'].font = withe_font + worksheet['D8'].font = withe_font + worksheet['E8'].font = withe_font + worksheet['G8'].font = withe_font + worksheet['I8'].font = withe_font + worksheet['K8'].font = withe_font + worksheet['M8'].font = withe_font + worksheet['O8'].font = withe_font + worksheet['Q8'].font = withe_font + worksheet['S8'].font = withe_font + + worksheet['A8'].fill = green + worksheet['B8'].fill = green + worksheet['C8'].fill = green + worksheet['D8'].fill = green + worksheet['E8'].fill = blue + worksheet['G8'].fill = blue + worksheet['I8'].fill = blue + worksheet['K8'].fill = blue + worksheet['M8'].fill = blue + worksheet['O8'].fill = blue + worksheet['Q8'].fill = blue + worksheet['S8'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + for item in range(len(list1)): + cell = worksheet.cell(row=10, column=item + 5, value=list1[item]) + worksheet.row_dimensions[5].height = 28 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + head_list1 = [len(names_list) - 1 + , 0, + 0, + total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + total_pre_cold_weight if total_pre_cold_weight != None else 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_steward, + number_of_guild, + + ] + for item in range(len(head_list1)): + cell = worksheet.cell(row=6, column=item + 2, value=head_list1[item]) + worksheet.row_dimensions[6].height = 12 + value = head_list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + l = 11 + m = 1 + for kill_house in kill_houses: + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, kill_house=kill_house, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + if kill_house.killer == True: + kill_house_name = 'کشتارکن' + '(' + kill_house.name + ')' + else: + kill_house_name = 'کشتارگاه' + '(' + kill_house.name + ')' + + list2 = [ + m, + kill_house_name, + kill_house.kill_house_operator.user.city.name, + number_of_guild + number_of_steward, + 0, + 0, + total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + total_pre_cold_weight if total_pre_cold_weight != None else 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + l += 1 + m += 1 + else: + worksheet['F2'] = f'اطلاعات کلی توزیع و پخش مرغ گرم از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['F2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'F2:N2' + worksheet.merge_cells(merge_range122) + + worksheet['F2'].font = Font(size=10) + + for abc in abc_list[2:]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + withe_font = Font(size=12, bold=True, color='D9FFFFFF') + withe_font1 = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'مجموع بارها' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + worksheet['S3'] = f'تعداد مباشر تخصیص داده شده' + worksheet['T3'] = f'تعداد صنف تخصیص داده شده' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['S3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['T3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + merge_range9 = 'S3:S5' + merge_range10 = 'T3:T5' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + + worksheet['C3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + worksheet['S3'].font = withe_font1 + worksheet['T3'].font = withe_font1 + + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + worksheet['S3'].fill = blue + worksheet['T3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=date1, + date__date__lte=date2, kill_house__name=sheet_name, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + list2 = [ + + 0, + 0, + total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + total_pre_cold_weight if total_pre_cold_weight != None else 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_steward, + number_of_guild, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=6, column=item + 3, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه تخصیص', + 'وزن لاشه تخصیصی', + 'تعداد لاشه تحویلی', + 'وزن لاشه تحویلی', + 'وضعیت', + 'کد احراز', + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[9].height = 26 + worksheet.freeze_panes = worksheet['A10'] + max_col = worksheet.max_column - 1 + range_str = f'A9:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + m = 1 + l = 10 + + stewards = (StewardAllocation.objects.filter(trash=False, ware_house__kill_house__name=sheet_name, + date__date__gte=date1, date__date__lte=date2) + .select_related('guilds', + 'guilds__user', + 'guilds__address__city', + 'kill_house', + 'kill_house__kill_house_operator').order_by( + 'id')) + + if stewards.exists(): + for steward_allocation in stewards: + create_date = jdatetime.date.fromgregorian( + day=steward_allocation.create_date.day, + month=steward_allocation.create_date.month, + year=steward_allocation.create_date.year + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + if steward_allocation.receiver_state == 'pending': + reciver_type = 'در انتظار تحویل' + register = '-' + elif steward_allocation.receiver_state == 'accepted': + reciver_type = 'تحویل گرفته شد' + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else 'وارد نشده' + + else: + reciver_type = 'رد شده' + register = '-' + + list2 = [ + m, + guilds_id, + str(create_date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + steward_allocation.receiver_real_number_of_carcasses, + steward_allocation.receiver_real_weight_of_carcasses, + reciver_type, + register, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + m += 1 + l += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش پخش لاشه مرغ گرم.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def daily_process_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() if 'date' in request.GET else now + date_one_day_ago = date1 - timedelta(days=1) + + # user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + poultry_requests = PoultryRequest.objects.filter( + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date=date_one_day_ago).select_related('poultry', + 'poultry__user', + 'poultry__address__province').order_by( + '-send_date') + if poultry_requests: + province_name = poultry_requests.first().poultry.user.province.name + else: + province_name = '' + excel_options = { + 'درخواست کشتار مرغداران': [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'نام و نام خانوادگی مرغدار', + 'نام فارم', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'مانده در سالن', + 'تایید شده', + ], + 'تخصیص به خریداران توسط اتحادیه': [ + 'ردیف', + 'کد سفارش', + 'نوع درخواست', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'شهر', + 'تاریخ کشتار', + 'تعداد کشتار', + 'زمان تخصیص', + 'نوع تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + ' تلفن خریدار', + ' آدرس خریدار', + 'تایید تخصیص', + 'تخصیص ماشین', + + ], + 'ثبت ماشین(ایجاد بار)': [ + 'ردیف', + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + + ], + 'اطلاعات انبار خریداران': [ + 'ردیف', + 'خریدار', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه', + 'وزن لاشه', + 'کد احراز', + + ] + + } + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + fro_date = jdatetime.date.fromgregorian( + year=date_one_day_ago.year, + month=date_one_day_ago.month, + day=date_one_day_ago.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(fro_date.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date) + output = BytesIO() + workbook = Workbook() + # worksheet = workbook.active + + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.column_dimensions[col_letter].height = len(option) + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 3 + if sheet_name == 'درخواست کشتار مرغداران': + m = 1 + worksheet['A1'] = f'درخواست کشتار مرغداران استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_2})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + if poultry_requests: + for filtered_poultry_kill_request in poultry_requests: + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '-' + if filtered_poultry_kill_request.kill_house_list is not None: + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '/' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + + list1 = [ + m, + filtered_poultry_kill_request.order_code, + str(date_of_create), + str(date_of_kill), + filtered_poultry_kill_request.poultry.user.fullname, + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + str(age), + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.hatching.left_over, + state + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'تخصیص به خریداران توسط اتحادیه': + m = 1 + worksheet['A1'] = f'تخصیص به خریداران توسط اتحادیه استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_2})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + prvince_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + province_request__poultry_request__in=poultry_requests).order_by('-create_date') + for filtered_province_kill_req in prvince_kill_requests: + car = 'دارد' if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, + trash=False).exists() else '-' + + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + if filtered_province_kill_req.state == "accepted": + state = 'تایید شده' + elif filtered_province_kill_req.state == "pending": + state = 'در انتظار تایید' + else: + state = 'رد شده' + + automatic = 'خودکار' if filtered_province_kill_req.automatic else 'دستی' + if filtered_province_kill_req.province_request.poultry_request.union == True: + type = 'فروش آزاد' + elif filtered_province_kill_req.province_request.poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + list1 = [ + m, + filtered_province_kill_req.province_request.poultry_request.order_code, + type, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.address.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(date_of_allocation), + automatic, + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + # filtered_province_kill_req.killhouse_user.kill_house_operator.address.city.name, + filtered_province_kill_req.kill_request.kill_house.system_address.city.name, + state, + car + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'ثبت ماشین(ایجاد بار)': + m = 1 + worksheet['A1'] = f'ثبت ماشین توسط خریدار(ایجاد بار) استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_2})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + filtered_kill_reqs = KillHouseRequest.objects.filter( + kill_request__recive_date__date=date_one_day_ago, + trash=False).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code').values( + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + ) + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + l += 1 + date_of_inner_bar = '-' + date_factor = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__key=kill.get('key')).only( + 'total_price').values( + 'total_price').first() + factor_amount = factor.get('total_price') if factor else '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__key=kill.get( + 'key')).only('create_date').values( + 'create_date').first() + if factor_payment: + factor_date = factor_payment.get('create_date') + date_factor = jdatetime.date.fromgregorian( + day=factor_date.day, + month=factor_date.month, + year=factor_date.year + ) if factor_payment else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity').first() + if assignment: + net_weighte = assignment.get('net_weight') if assignment else '-' + real_quantity = assignment.get('real_quantity') + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_check_date.day, + month=vet_check_date.month, + year=vet_check_date.year + ) if vet_checks else '-' + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + list1 = [ + m, + str(kill.get('bar_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__order_code'), + kill.get('province_request__poultry_request__poultry__user__city__name'), + str(date_of_poultry_request), + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + killers, + kill.get('killhouse_user__system_address__city__name'), + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + kill.get('add_car__driver__health_code'), + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'اطلاعات انبار خریداران': + m = 1 + worksheet['A1'] = f' اطلاعات انبار خریداران استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date=date_one_day_ago).select_related( + 'killhouse_user') + kill_house_list = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + + ).select_related('kill_house_operator', 'kill_house_operator__user', 'kill_house_operator__address__city') + # برای بالای هدر + kill_house_ware_houses = KillHouseWareHouse.objects.filter(kill_house__in=kill_house_list, date__date=date1) + steward_allocations = StewardAllocation.objects.filter( + system_registration_code=True, + ware_house__in=kill_house_ware_houses, trash=False, + date__date=date1).select_related('guilds', 'guilds__user', 'guilds__address__city', 'kill_house', + 'kill_house__kill_house_operator').order_by('id') + + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + allocated_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_number_of_carcasses'))['total'] + allocated_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_weight_of_carcasses'))['total'] + remain_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))['total'] + remain_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))['total'] + + header_list = [ + 'تعداد خریداران', + 'تعداد مباشرین', + 'تعداد لاشه ها', + 'وزن لاشه ها (کیلوگرم)', + 'تعداد لاشه تخصیص داده شده', + 'وزن تخصیص داده شده (کیلوگرم)', + 'تعداد لاشه قابل تخصیص', + 'وزن قابل تخصیص (کیلوگرم)', + + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 17 + worksheet.column_dimensions[col_letter].width = 21.01 + + # worksheet.row_dimensions[2].width = 21 + value_header_list = [ + len(kill_house_ware_houses), + len(steward_allocations), + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + allocated_total_number_of_carcasses if allocated_total_number_of_carcasses != None else 0, + allocated_total_weight_of_carcasses if allocated_total_weight_of_carcasses != None else 0, + remain_total_number_of_carcasses if remain_total_number_of_carcasses != None else 0, + remain_total_weight_of_carcasses if remain_total_weight_of_carcasses != None else 0, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=11) + + for steward_allocation in steward_allocations: + killer = 'کشتارکن' if steward_allocation.kill_house.killer == True else 'کشتارگاه' + kill_house_name = steward_allocation.kill_house.name + + date = jdatetime.date.fromgregorian( + year=steward_allocation.date.year, + month=steward_allocation.date.month, + day=steward_allocation.date.day + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else '-' + list1 = [ + m, + f'{killer} {kill_house_name}({steward_allocation.kill_house.kill_house_operator.user.fullname})', + guilds_id, + str(date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + register, + ] + l += 1 + m += 1 + for col_num, option in enumerate(list1, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=l + 1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center') + + worksheet.row_dimensions[4].height = 19 + worksheet.column_dimensions[col_letter].width = 21.01 + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش پخش روزانه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def daily_process_klling_proccess_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + + user = get_object_or_404(SystemUserProfile, key=request.GET['key']) + poultry_requests = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date=date1).select_related('poultry', + 'poultry__user', + 'poultry__address__province').order_by( + '-send_date') + province_name = user.province.name + + excel_options = { + 'درخواست کشتار مرغداران': [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'نام و نام خانوادگی مرغدار', + 'نام فارم', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'مانده در سالن', + 'تایید شده', + ], + 'تخصیص به خریداران توسط اتحادیه': [ + 'ردیف', + 'کد سفارش', + 'نوع درخواست', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'شهر', + 'تاریخ کشتار', + 'تعداد کشتار', + 'زمان تخصیص', + 'نوع تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + ' تلفن خریدار', + ' آدرس خریدار', + 'تایید تخصیص', + 'تخصیص ماشین', + + ], + 'ثبت ماشین(ایجاد بار)': [ + 'ردیف', + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)', + 'مبلغ فاکتور', + 'تاریخ پرداخت فاکتور', + + ] + } + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + # worksheet = workbook.active + + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.column_dimensions[col_letter].height = len(option) + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 3 + if sheet_name == 'درخواست کشتار مرغداران': + m = 1 + worksheet['A1'] = f'درخواست کشتار مرغداران استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + if poultry_requests: + for filtered_poultry_kill_request in poultry_requests: + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '-' + if filtered_poultry_kill_request.kill_house_list is not None: + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '/' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + + list1 = [ + m, + filtered_poultry_kill_request.order_code, + str(date_of_create), + str(date_of_kill), + filtered_poultry_kill_request.poultry.user.fullname, + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + str(age), + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.hatching.left_over, + state + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'تخصیص به خریداران توسط اتحادیه': + m = 1 + worksheet['A1'] = f'تخصیص به خریداران توسط اتحادیه استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + prvince_kill_requests = ProvinceKillRequest.objects.filter( + trash=False, + province_request__poultry_request__in=poultry_requests).order_by('-create_date') + for filtered_province_kill_req in prvince_kill_requests: + car = 'دارد' if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, + trash=False).exists() else '-' + + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + if filtered_province_kill_req.state == "accepted": + state = 'تایید شده' + elif filtered_province_kill_req.state == "pending": + state = 'در انتظار تایید' + else: + state = 'رد شده' + + automatic = 'خودکار' if filtered_province_kill_req.automatic else 'دستی' + if filtered_province_kill_req.province_request.poultry_request.union == True: + type = 'فروش آزاد' + elif filtered_province_kill_req.province_request.poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + list1 = [ + m, + filtered_province_kill_req.province_request.poultry_request.order_code, + type, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.address.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(date_of_allocation), + automatic, + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + # filtered_province_kill_req.killhouse_user.kill_house_operator.address.city.name, + filtered_province_kill_req.kill_request.kill_house.system_address.city.name, + state, + car + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'ثبت ماشین(ایجاد بار)': + m = 1 + worksheet['A1'] = f'ثبت ماشین توسط خریدار(ایجاد بار) استان {province_name}' + worksheet['A3'] = f'در تاریخ:({from_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + # worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__poultry__address__province=user.province, + kill_request__recive_date__date=date1, + + trash=False).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code').values( + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + ) + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + l += 1 + date_of_inner_bar = '-' + date_factor = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__key=kill.get('key')).only( + 'total_price').values( + 'total_price').first() + factor_amount = factor.get('total_price') if factor else '-' + factor_payment = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__key=kill.get( + 'key')).only('create_date').values( + 'create_date').first() + if factor_payment: + factor_date = factor_payment.get('create_date') + date_factor = jdatetime.date.fromgregorian( + day=factor_date.day, + month=factor_date.month, + year=factor_date.year + ) if factor_payment else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity').first() + if assignment: + net_weighte = assignment.get('net_weight') if assignment else '-' + real_quantity = assignment.get('real_quantity') + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_check_date.day, + month=vet_check_date.month, + year=vet_check_date.year + ) if vet_checks else '-' + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + list1 = [ + m, + str(kill.get('bar_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__order_code'), + kill.get('province_request__poultry_request__poultry__user__city__name'), + str(date_of_poultry_request), + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + killers, + kill.get('killhouse_user__system_address__city__name'), + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + kill.get('add_car__driver__health_code'), + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + factor_amount, + str(date_factor) + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کشتار روزانه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def killing_process_from_date_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + day_before_date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() - timedelta(days=1) + day_before_date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() - timedelta(days=1) + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + excel_options = { + 'درخواست کشتار': [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'نام و نام خانوادگی مرغدار', + 'نام فارم', + 'موبایل', + 'کشتارگاه های پیشنهادی', + 'آدرس', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'مانده در سالن', + 'تایید شده', + ], + 'تخصیصات': [ + 'ردیف', + 'کد سفارش', + 'نوع درخواست', + 'نام فارم', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'شهر', + 'تاریخ کشتار', + 'تعداد کشتار', + 'زمان تخصیص', + 'نوع تخصیص', + 'خریدار', + 'تعداد تخصیص داده شده', + ' تلفن خریدار', + ' آدرس خریدار', + 'تایید تخصیص', + 'تخصیص ماشین', + + ], + 'مسئول فنی مزرعه': [ + 'ردیف', + 'کد بار', + 'مرغدار', + 'تلفن مرغدار', + 'کدسفارش مرغدار', + ' شهر مرغدار', + ' تاریخ کشتار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'خریدار', + ' تلفن خریدار', + ' ماهیت خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'تعداد تخلیه شده', + 'وزن بار', + 'تاریخ تخلیه (کشتارگاه)'], + + 'دامپزشک کشتارگاه': [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد تخصیصی', + 'وزن تخصیصی', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده', + 'وزن بار تخلیه شده(کیلوگرم)', + + ] + , + 'اطلاعات کلی پخش به مباشر': [ + 'ردیف', + ' ماهیت خریدار', + 'خریدار', + 'تاریخ پخش', + 'موبایل خریدار', + 'شهر', + 'تعداد لاشه ها', + 'وزن لاشه ها(کیلوگرم)', + 'تعداد لاشه تخصیص داده شده', + 'وزن تخصیص داده شده(کیلوگرم)', + 'مانده لاشه قابل تخصیص(قطعه)', + ' مانده وزن قابل تخصیص(کیلوگرم)', + + ], + 'جزئیات پخش به مباشر': [ + 'ردیف', + 'خریدار', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه', + 'وزن لاشه', + 'کد احراز', + + ], + } + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + # date_one_day_ago = date - timedelta(days=1) + + province_kill_requests = ProvinceKillRequest.objects.filter(state__in=('pending', 'accepted'), + kill_request__recive_date__date__gte=day_before_date1, + kill_request__recive_date__date__lte=day_before_date2).select_related( + 'killhouse_user') + kill_house_list = KillHouse.objects.filter( + pk__in=province_kill_requests.values('killhouse_user') + + ).select_related('kill_house_operator', 'kill_house_operator__user', 'kill_house_operator__address__city') + + kill_house_ware_houses = KillHouseWareHouse.objects.filter(kill_house__in=kill_house_list, date__date__gte=date1, + date__date__lte=date2).order_by('id') + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, trash=False, + date__date__gte=date1, date__date__lte=date2).select_related('guilds', 'guilds__user', 'guilds__address__city', + 'kill_house', + 'kill_house__kill_house_operator').order_by('id') + + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + allocated_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_number_of_carcasses'))['total'] + allocated_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('allocated_total_weight_of_carcasses'))['total'] + remain_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))['total'] + remain_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))['total'] + + filtered_kill_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + trash=False).order_by('-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry') + output = BytesIO() + workbook = Workbook() + + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + worksheet.column_dimensions[col_letter].height = len(option) + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 3 + m = 1 + if sheet_name == 'درخواست کشتار': + worksheet['A1'] = f'درخواست کشتار' + worksheet['A3'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:C2' + merge_range = 'A3:C3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + filtered_province_kill_reqs = PoultryRequest.objects.filter(send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).select_related('poultry', + 'poultry__user', + 'poultry__address__province').order_by( + '-send_date') + if filtered_province_kill_reqs: + province = filtered_province_kill_reqs.first().poultry.address.province.name + worksheet['A2'] = f'استان {province}' + for filtered_poultry_kill_request in filtered_province_kill_reqs: + l += 1 + date_of_create = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.create_date.day, + month=filtered_poultry_kill_request.create_date.month, + year=filtered_poultry_kill_request.create_date.year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_kill_request.send_date.day, + month=filtered_poultry_kill_request.send_date.month, + year=filtered_poultry_kill_request.send_date.year + ) + state = 'تایید شده' + if filtered_poultry_kill_request.state == 'pending': + state = 'در انتظار تایید' + kill_house = '-' + if filtered_poultry_kill_request.kill_house_list is not None: + for name in filtered_poultry_kill_request.kill_house_list: + kill_house += name + '/' + age = ( + filtered_poultry_kill_request.send_date.date() - filtered_poultry_kill_request.hatching.date.date()).days + 1 + + list1 = [ + m, + filtered_poultry_kill_request.order_code, + str(date_of_create), + str(date_of_kill), + filtered_poultry_kill_request.poultry.user.fullname, + filtered_poultry_kill_request.poultry.unit_name, + filtered_poultry_kill_request.poultry.user.mobile, + kill_house, + filtered_poultry_kill_request.poultry.address.city.name, + str(age), + filtered_poultry_kill_request.quantity, + filtered_poultry_kill_request.hatching.left_over, + state + ] + m += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'تخصیصات': + filtered_province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request__send_date__date__gte=date1, + province_request__poultry_request__send_date__date__lte=date2, trash=False).select_related( + 'province_request__poultry_request', 'province_request__poultry_request__poultry', + 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request__poultry__address').order_by('-create_date') + + worksheet['A1'] = f' مدیریت تخصیصات' + worksheet['A3'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + if filtered_province_kill_reqs.exists(): + province = filtered_province_kill_reqs.first().province_request.poultry_request.poultry.address.province.name + worksheet['A2'] = f'استان {province}' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:C2' + merge_range = 'A3:C3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + for filtered_province_kill_req in filtered_province_kill_reqs: + car = 'دارد' if KillHouseRequest.objects.filter(province_kill_request=filtered_province_kill_req, + trash=False).exists() else '-' + + l += 1 + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.province_request.poultry_request.send_date.day, + month=filtered_province_kill_req.province_request.poultry_request.send_date.month, + year=filtered_province_kill_req.province_request.poultry_request.send_date.year + ) + date_of_allocation = jdatetime.date.fromgregorian( + day=filtered_province_kill_req.create_date.day, + month=filtered_province_kill_req.create_date.month, + year=filtered_province_kill_req.create_date.year + ) + if filtered_province_kill_req.state == "accepted": + state = 'تایید شده' + elif filtered_province_kill_req.state == "pending": + state = 'در انتظار تایید' + else: + state = 'رد شده' + + automatic = 'خودکار' if filtered_province_kill_req.automatic else 'دستی' + if filtered_province_kill_req.province_request.poultry_request.union == True: + type = 'فروش آزاد' + elif filtered_province_kill_req.province_request.poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + list1 = [ + m, + filtered_province_kill_req.province_request.poultry_request.order_code, + type, + filtered_province_kill_req.province_request.poultry_request.poultry.unit_name, + filtered_province_kill_req.province_request.poultry_request.poultry.user.fullname, + filtered_province_kill_req.province_request.poultry_request.poultry.user.mobile, + filtered_province_kill_req.province_request.poultry_request.poultry.address.city.name, + str(date_of_kill), + filtered_province_kill_req.province_request.poultry_request.quantity, + str(date_of_allocation), + automatic, + filtered_province_kill_req.killhouse_user.name, + filtered_province_kill_req.main_quantity, + filtered_province_kill_req.killhouse_user.kill_house_operator.user.mobile, + # filtered_province_kill_req.killhouse_user.kill_house_operator.address.city.name, + filtered_province_kill_req.kill_request.kill_house.system_address.city.name, + state, + car + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'مسئول فنی مزرعه': + worksheet['A1'] = f' مسئول فنی مزرعه' + worksheet['A3'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:C2' + merge_range = 'A3:C3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + # filtered_kill_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__date__gte=date1,kill_request__recive_date__date__lte=date2, + # trash=False).order_by( + # '-create_date').select_related( + # 'killhouse_user', 'province_request__poultry_request__poultry') + if filtered_kill_reqs.exists(): + province = filtered_kill_reqs.first().province_request.poultry_request.poultry.address.province.name + worksheet['A2'] = f'استان {province}' + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + vet_farm = VetFarm.objects.filter(poultry=kill.province_request.poultry_request.poultry, + trash=False).last() + vet_farm_name = vet_farm.vet.user.fullname if vet_farm else '-' + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.killhouse_user).last() + vet_checks = VetCheckRequest.objects.filter(kill_house_request=kill).only('create_date').last() + kill_house_vet_name = kil_house_vet.vet.user.fullname if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.vet.user.mobile if kil_house_vet else '-' + + code = kill.clearance_code if kill.clearance_code else '-' + quantity = kill.quantity if kill.quantity else '-' + date_of_poultry_request = jdatetime.date.fromgregorian( + day=kill.province_request.poultry_request.send_date.day, + month=kill.province_request.poultry_request.send_date.month, + year=kill.province_request.poultry_request.send_date.year + ) + killers = 'کشتارکن' + if kill.killhouse_user.killer == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill, trash=False).last() + net_weighte = assignment.net_weight if assignment else '-' + real_quantity = assignment.real_quantity if assignment else '-' + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_checks.create_date.day, + month=vet_checks.create_date.month, + year=vet_checks.create_date.year + ) if vet_checks else '-' + if kill.kill_request.slaughter_house != None: + kill_place = kill.kill_request.slaughter_house.name + else: + kill_place = kill.killhouse_user.name + if kill.clearance_code: + l += 1 + list1 = [ + m, + str(kill.bar_code), + kill.province_request.poultry_request.poultry.unit_name, + str(kill.province_request.poultry_request.poultry.user.mobile), + kill.province_request.poultry_request.order_code, + kill.province_request.poultry_request.poultry.user.city.name, + str(date_of_poultry_request), + kill.province_request.poultry_request.chicken_breed, + vet_farm_name, + vet_farm_mobile, + kill.kill_request.kill_house.name, + kill.killhouse_user.phone, + killers, + kill.killhouse_user.system_address.city.name, + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + code, + quantity, + real_quantity, + net_weighte, + str(date_of_inner_bar), + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'دامپزشک کشتارگاه': + + worksheet['A1'] = f'دامپزشک کشتارگاه' + worksheet['A3'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:C1' + merge_range2 = 'A2:C2' + merge_range = 'A3:C3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'vet_state').values( + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'vet_state', + ) + header_list = [ + 'تعداد بارایجاد شده', + 'مجموع تعداد قطعه تخصیصی', + 'مجموع وزن بار تخصیصی', + 'تعداد بار تخلیه شده', + 'مجموع تعداد قطعه تخلیه شده', + 'مجموع وزن بار تخلیه شده', + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_assigment = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + all_assigment += len(assignment) + vet_check_date = assignment.get('create_date') + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_check_date.day, + month=vet_check_date.month, + year=vet_check_date.year + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + + date_of_inner_bar = jdatetime.date.fromgregorian( + day=vet_check_date.day, + month=vet_check_date.month, + year=vet_check_date.year + ) + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + if kill.get('vet_state') == 'pending': + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + else: + + weight = kill.get('accepted_real_weight') + all_weighte += weight + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + kill.get('province_request__poultry_request__order_code'), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + kill.get('add_car__driver__health_code'), + code, + quantity, + weight, + str(date_of_inner_bar), + real_quantity, + net_weighte, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + all_assigment, + all_real_quantity, + all_net_weighte + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + elif sheet_name == 'اطلاعات کلی پخش به مباشر': + header_list = [ + 'تعداد خریداران', + 'تعداد مباشرین', + 'تعداد لاشه ها', + 'وزن لاشه ها (کیلوگرم)', + 'تعداد لاشه تخصیص داده شده', + 'وزن تخصیص داده شده (کیلوگرم)', + 'تعداد لاشه قابل تخصیص', + 'وزن قابل تخصیص (کیلوگرم)', + + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 17 + worksheet.column_dimensions[col_letter].width = 21.01 + + value_header_list = [ + len(kill_house_ware_houses), + len(steward_allocations), + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + allocated_total_number_of_carcasses if allocated_total_number_of_carcasses != None else 0, + allocated_total_weight_of_carcasses if allocated_total_weight_of_carcasses != None else 0, + remain_total_number_of_carcasses if remain_total_number_of_carcasses != None else 0, + remain_total_weight_of_carcasses if remain_total_weight_of_carcasses != None else 0, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=11) + m = 1 + + for kill_house in kill_house_list: + kill_house_ware_house = KillHouseWareHouse.objects.filter(kill_house=kill_house, + date__date__gte=date1, + date__date__lte=date2) + for kill_house_ware in kill_house_ware_house: + total_number_of_carcasses_temp = kill_house_ware.update_total_number_of_carcasses if kill_house_ware.update_total_number_of_carcasses > 0 else kill_house_ware.total_number_of_carcasses + total_weight_of_carcasses_temp = kill_house_ware.update_total_weight_of_carcasses if kill_house_ware.update_total_weight_of_carcasses > 0 else kill_house_ware.total_weight_of_carcasses + + date_of_create = jdatetime.date.fromgregorian( + day=kill_house_ware.date.day, + month=kill_house_ware.date.month, + year=kill_house_ware.date.year + ) + list1 = [ + m, + 'کشتار کن' if kill_house.killer == True else 'کشتارگاه', + f'{kill_house.name} ({kill_house.kill_house_operator.user.fullname})', + str(date_of_create), + kill_house.kill_house_operator.user.mobile, + kill_house.kill_house_operator.address.city.name, + total_number_of_carcasses_temp, + total_weight_of_carcasses_temp, + kill_house_ware.allocated_total_number_of_carcasses, + kill_house_ware.allocated_total_weight_of_carcasses, + kill_house_ware.remain_total_number_of_carcasses, + kill_house_ware.remain_total_weight_of_carcasses + + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + + elif sheet_name == 'جزئیات پخش به مباشر': + for steward_allocation in steward_allocations: + killer = 'کشتارکن' if steward_allocation.kill_house.killer == True else 'کشتارگاه' + kill_house_name = steward_allocation.kill_house.name + + date = jdatetime.date.fromgregorian( + year=steward_allocation.date.year, + month=steward_allocation.date.month, + day=steward_allocation.date.day + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else '-' + list1 = [ + m, + f'{killer} {kill_house_name}({steward_allocation.kill_house.kill_house_operator.user.fullname})', + guilds_id, + str(date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + register, + ] + l += 1 + m += 1 + for col_num, option in enumerate(list1, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=l + 1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center') + + worksheet.row_dimensions[4].height = 19 + worksheet.column_dimensions[col_letter].width = 21.01 + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="روند کشتار بر اساس بازه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def discrepancy_report_excel(request): + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + poultry_reqs = PoultryRequest.objects.filter( + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + ).order_by('-send_date').annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')), + total_remain_quantity=Sum('remain_quantity'), + total_remain_weight=Sum(F('remain_quantity') * F('Index_weight')), + + ) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultry_requests = poultry_reqs.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = poultry_reqs.filter(poultry__user__city=user.city) + else: + poultry_requests = poultry_reqs + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request__in=poultry_requests, trash=False, + state__in=('pending', 'accepted')).annotate( + total_quantity=Sum('main_quantity'), + total_weight=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight')), + ) + + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province), + trash=False).select_related( + 'user').first() + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + excel_options = { + 'مغایرت در تخصیص و ایجاد بار': [ + 'ردیف', + 'خریدار', + 'تلفن', + 'تاریخ کشتار', + 'فروشنده', + 'تلفن فروشنده', + 'سهم کشتار(قطعه)', + 'سهم کشتار(وزن)', + 'تعداد ماشین' + , 'تخصیص به ماشین(قطعه)' + , 'تخصیص به ماشین(وزن)' + , 'مانده قطعه قابل تخصیصی' + , 'مانده وزن قابل تخصیصی(کیلوگرم)' + , 'اپراتور' + , 'موبایل اپراتور' + ], + + 'بار های فاقد کد قرنطینه': ['ردیف', + 'کدبار', + 'خریدار', + 'تلفن خریدار', + 'فروشنده', + 'تلفن فروشنده', + 'تاریخ کشتار', + 'ماشین', + 'راننده', + 'نژاد', + 'تعداد(قطعه)', + 'وزن بار(کیلوگرم)', + 'میانگین وزن(کیلوگرم)', + 'محل کشتار', + 'دامپزشک', + 'موبایل دامپزشک'], + 'بارهای تخلیه نشده': [ + 'ردیف', + 'کد بار', + 'خریدار', + ' تلفن خریدار', + 'فروشنده', + ' تلفن فروشنده', + 'تاریخ کشتار', + 'ماشین', + 'راننده', + 'نژاد', + 'تعداد(قطعه)', + 'وزن بار(کیلوگرم)', + 'میانگین وزن(کیلوگرم)', + 'کد قرنطینه', + 'دامپزشک', + 'تلفن دامپزشک', + ], + 'بارهای تکمیل نشده': [ + 'ردیف', + 'کدبار', + 'خریدار', + ' تلفن خریدار', + 'فروشنده', + ' تلفن فروشنده', + 'تاریخ کشتار', + 'ماشین', + 'راننده', + 'نژاد', + 'تعداد(قطعه)', + 'وزن بار(کیلوگرم)', + 'میانگین وزن(کیلوگرم)', + 'کد قرنطینه', + 'تعداد تخلیه شده(دامپزشک)', + 'وزن تخلیه شده(دامپزشک)', + 'کاربر', + 'تلفن کاربر', + ], + 'مغایرت در اطلاعات بار': [ + 'ردیف', + 'کدبار', + 'خریدار', + ' تلفن خریدار', + 'فروشنده', + ' تلفن فروشنده', + 'تاریخ کشتار', + 'ماشین', + 'راننده', + 'کد قرنطینه', + 'تعداد اولیه(قطعه)', + 'وزن بار اولیه (کیلوگرم)', + 'تعداد تخلیه شده(دامپزشک)', + 'وزن تخلیه شده(دامپزشک)', + 'اطلاعات بار کشتارگاه(تعداد)', + 'اطلاعات بار کشتارگاه(وزن)', + + ] + + } + kill_house = KillHouseRequest.objects.filter( + province_kill_request__in=province_kill_requests, + trash=False) + output = BytesIO() + workbook = Workbook() + for name, options in excel_options.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + # worksheet.column_dimensions[col_letter].height = len(option) + worksheet.row_dimensions[5].height = 20 + + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 4 + m = 1 + if sheet_name == 'مغایرت در تخصیص و ایجاد بار': + worksheet['A4'] = f'مغایرت درتعداد تخصیصی به خریدار و ایجاد بار' + worksheet['A2'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['D1'] = f'مغایرت در درخواست کشتار و تخصیص' + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['D1'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:C2' + merge_range2 = 'D1:E1' + merge_range = 'A4:C4' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A4'].fill = PatternFill(start_color="C5D9F1", fill_type="solid") + worksheet['D1'].fill = PatternFill(start_color="C5D9F1", fill_type="solid") + province_kill_requests_with_left_over = (ProvinceKillRequest.objects.filter( + province_request__poultry_request__in=poultry_requests, trash=False, + state__in=('pending', 'accepted'), quantity__gt=0).select_related('killhouse_user', + 'killhouse_user__kill_house_operator__user', + 'province_request__poultry_request').only( + 'key', 'killhouse_user__name', 'killhouse_user__kill_house_operator__user__mobile', 'main_quantity', + 'province_request__poultry_request__Index_weight', 'quantity', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', 'province_request__poultry_request__key') + .values('province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name', + 'key', 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'main_quantity', + 'province_request__poultry_request__Index_weight', + 'quantity', + 'killhouse_user__kill_house_operator__user__fullname' + , 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__key', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile')) + + poultry_request_total_quantity = poultry_requests.aggregate(total=Sum('total_quantity'))['total'] + poultry_request_total_weight = poultry_requests.aggregate(total=Sum('total_weight'))['total'] + province_kill_requests_total_weight = province_kill_requests.aggregate(total=Sum('total_weight'))['total'] + province_kill_requests_total_quantity = province_kill_requests.aggregate(total=Sum('total_quantity'))[ + 'total'] + poultry_request_total_remain_quantity = poultry_requests.aggregate(total=Sum('total_remain_quantity'))[ + 'total'] + poultry_request_remain_weight = poultry_requests.aggregate(total=Sum('total_remain_weight'))['total'] + + for province in province_kill_requests_with_left_over: + poultry_request = PoultryRequest.objects.get( + key=province['province_request__poultry_request__key']) + date_of_kill = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + kill_house_requests = kill_house.filter(province_kill_request__key=province[ + 'key']).annotate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight'), + + ) + kill_house_request_quantity = kill_house_requests.aggregate(total=Sum('total_quantity'))['total'] + kill_house_request_weight = kill_house_requests.aggregate(total=Sum('total_weight'))['total'] + list1 = [ + m, + province['killhouse_user__name'], + province['killhouse_user__kill_house_operator__user__mobile'], + str(date_of_kill), + province['province_request__poultry_request__poultry__unit_name'], + province['province_request__poultry_request__poultry__user__mobile'], + province['main_quantity'], + int(province['main_quantity'] * province['province_request__poultry_request__Index_weight']), + kill_house_requests.count(), + kill_house_request_quantity if kill_house_request_quantity != None else 0, + kill_house_request_weight if kill_house_request_weight != None else 0, + province['quantity'], + int(province['quantity'] * province['province_request__poultry_request__Index_weight']), + province['killhouse_user__kill_house_operator__user__fullname'], + province['killhouse_user__kill_house_operator__user__mobile'], + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + blue = Font(color="0070C0") + red = Font(color="C00000") + green = Font(color="00863D") + + if cell.column in [7, 8]: + cell.font = blue + + elif cell.column in [10, 11]: + cell.font = green + else: + if cell.column in [12, 13]: + cell.font = red + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + header_list = [ + 'تعداد درخواست', + 'مجموع درخواست کشتار (قطعه)', + 'مجموع درخواست کشتار (وزن)', + 'تعداد تخصیص به خریدار(قطعه)', + 'وزن تخصیص به خریدار(کیلوگرم)', + 'مانده قطعه قابل تخصیص', + 'وزن قابل تخصیص(کیلوگرم)', + 'اپراتور', + ' موبایل اپراتور', + ] + for col_num, option in enumerate(header_list, 4): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 17 + worksheet.column_dimensions[col_letter].width = 21.01 + + value_header_list = [ + poultry_requests.count(), + poultry_request_total_quantity if poultry_request_total_quantity != None else 0, + poultry_request_total_weight if poultry_request_total_weight != None else 0, + province_kill_requests_total_quantity if province_kill_requests_total_quantity != None else 0, + province_kill_requests_total_weight if province_kill_requests_total_weight != None else 0, + poultry_request_total_remain_quantity if poultry_request_total_remain_quantity != None else 0, + poultry_request_remain_weight if poultry_request_remain_weight != None else 0, + province_operator.user.fullname, + province_operator.user.mobile, + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=11) + worksheet['G3'].font = Font(color="0070C0", bold=True) + worksheet['H3'].font = Font(color="0070C0", bold=True) + worksheet['I3'].font = red_font + worksheet['J3'].font = red_font + value = value_header_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + + elif sheet_name == 'بار های فاقد کد قرنطینه': + worksheet['A2'] = f'بار های فاقد کد قرنطینه' + worksheet['A4'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:C2' + merge_range = 'A4:C4' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet['A2'].fill = PatternFill(start_color="92CDDC", fill_type="solid") + + kill_house_request_without_clearance_code = (kill_house.filter( + clearance_code__isnull=True, + ).select_related('add_car__driver', + 'province_kill_request__province_request__poultry_request', + 'province_kill_request__province_request__poultry_request__poultry', + 'killhouse_user__kill_house_operator__user', 'kill_request') + .only( + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'killhouse_user__name', + 'kill_request__kill_house__name') + .values( + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name', + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'killhouse_user__name', + 'kill_request__kill_house__name', 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile')) + + for kill in kill_house_request_without_clearance_code: + + fullname = '-', + mobile = '-', + poultry_request = PoultryRequest.objects.get( + key=kill['province_kill_request__province_request__poultry_request__key']) + date_of_kill = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + vet_farm = (VetFarm.objects.filter( + poultry=kill['province_kill_request__province_request__poultry_request__poultry']) + .select_related('vet__user').only('vet__user__fullname', 'vet__user__mobile').last()) + if vet_farm: + fullname = vet_farm.vet.user.fullname + mobile = vet_farm.vet.user.mobile + else: + fullname = '-' + mobile = '-' + + list1 = [ + m, + str(kill['bar_code']), + kill['killhouse_user__name'], + kill['killhouse_user__kill_house_operator__user__mobile'], + kill['province_request__poultry_request__poultry__unit_name'], + kill['province_request__poultry_request__poultry__user__mobile'], + str(date_of_kill), + kill['add_car__driver__type_car'], + kill['add_car__driver__driver_name'], + poultry_request.chicken_breed, + kill['quantity'], + kill['accepted_real_weight'], + round(kill['accepted_real_weight'] / kill['accepted_real_quantity'], 1), + kill['kill_request__slaughter_house__name'] if kill['kill_request__slaughter_house'] != None else + kill['kill_request__kill_house__name'], + fullname, + mobile, + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + elif sheet_name == 'بارهای تخلیه نشده': + worksheet['A2'] = f'بارهای تخلیه نشده' + worksheet['A4'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:C2' + merge_range = 'A4:C4' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet['A2'].fill = PatternFill(start_color="E26B0A", fill_type="solid") + + kill_house_request_without_vet_check = kill_house.filter(vet_state='pending').select_related( + 'add_car__driver', + 'province_kill_request__province_request__poultry_request', + 'province_kill_request__province_request__poultry_request__poultry', + 'killhouse_user__kill_house_operator__user').only( + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name', + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name').values( + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name', 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name') + + for kill in kill_house_request_without_vet_check: + + poultry_request = PoultryRequest.objects.get( + key=kill['province_kill_request__province_request__poultry_request__key']) + date_of_kill = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + kill_request = KillRequest.objects.get(key=kill['kill_request__key']) + if kill_request.slaughter_house != None: + kill_house_vet = KillHouseVet.objects.filter( + kill_house=kill_request.slaughter_house).select_related( + 'vet__user').first() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + 'vet__user').first() + if kill_house_vet: + fullname = kill_house_vet.vet.user.fullname + mobile = kill_house_vet.vet.user.mobile + else: + fullname = '-' + mobile = '-' + list1 = [ + m, + str(kill['bar_code']), + kill['killhouse_user__name'], + kill['killhouse_user__kill_house_operator__user__mobile'], + kill['province_request__poultry_request__poultry__unit_name'], + kill['province_request__poultry_request__poultry__user__mobile'], + str(date_of_kill), + kill['add_car__driver__type_car'], + kill['add_car__driver__driver_name'], + poultry_request.chicken_breed, + kill['quantity'], + kill['accepted_real_weight'], + round(kill['accepted_real_weight'] / kill['accepted_real_quantity'], 1), + kill['clearance_code'] if kill['clearance_code'] else '-', + fullname, + mobile, + + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + elif sheet_name == 'بارهای تکمیل نشده': + worksheet['A2'] = f'بارهای تکمیل نشده(بارگزاری سند باسکول و مستندات وزنی)' + worksheet['A4'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:E2' + merge_range = 'A4:C4' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet['A2'].fill = PatternFill(start_color="FFFF00", fill_type="solid") + + kill_house_request_without_bar_info = kill_house.filter( + vet_state='accepted', + assignment_state_archive='pending', + ).select_related('add_car__driver', + 'province_kill_request__province_request__poultry_request', + 'province_kill_request__province_request__poultry_request__poultry', + 'killhouse_user__kill_house_operator__user', 'kill_request').only( + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name', 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name').values( + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name', 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name') + + for kill in kill_house_request_without_bar_info: + poultry_request = PoultryRequest.objects.get( + key=kill['province_kill_request__province_request__poultry_request__key']) + date_of_kill = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + kill_request = KillRequest.objects.get(key=kill['kill_request__key']) + if kill_request.slaughter_house != None: + kill_house_vet = KillHouseVet.objects.filter( + kill_house=kill_request.slaughter_house).select_related( + 'vet__user').first() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_request.kill_house).select_related( + 'vet__user').first() + if kill_house_vet: + fullname = kill_house_vet.vet.user.fullname + mobile = kill_house_vet.vet.user.mobile + else: + fullname = '-' + mobile = '-' + list1 = [ + m, + str(kill['bar_code']), + kill['killhouse_user__name'], + kill['killhouse_user__kill_house_operator__user__mobile'], + kill['province_request__poultry_request__poultry__unit_name'], + kill['province_request__poultry_request__poultry__user__mobile'], + str(date_of_kill), + kill['add_car__driver__type_car'], + kill['add_car__driver__driver_name'], + poultry_request.chicken_breed, + kill['quantity'], + kill['accepted_real_weight'], + round(kill['accepted_real_weight'] / kill['accepted_real_quantity'], 1), + kill['clearance_code'] if kill['clearance_code'] else '-', + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + fullname, + mobile + + ] + + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + blue = Font(color="0070C0") + red = Font(color="C00000") + if cell.column in [11, 12]: + cell.font = blue + else: + if cell.column in [15, 16]: + cell.font = red + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + elif sheet_name == 'مغایرت در اطلاعات بار': + worksheet['A2'] = f'بارهای تکمیل نشده(بارگزاری سند باسکول و مستندات وزنی)' + worksheet['A4'] = f'در تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['A4'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:E2' + merge_range = 'A4:C4' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet['A2'].fill = PatternFill(start_color="92D050", fill_type="solid") + + kill_house_request_diffrent_bar_info = kill_house.filter( + Q(quantity__gt=F('vet_accepted_real_quantity')) | Q(quantity__lt=F('vet_accepted_real_quantity')) | Q( + quantity__gt=F('accepted_real_quantity')) | Q(quantity__lt=F('accepted_real_quantity')) | Q( + vet_accepted_real_quantity__gt=F('accepted_real_quantity')) | Q( + vet_accepted_real_quantity__lt=F('accepted_real_quantity')), + vet_state='accepted', assignment_state_archive='True', + ).select_related('add_car__driver', + 'province_kill_request__province_request__poultry_request', + 'province_kill_request__province_request__poultry_request__poultry', + 'killhouse_user__kill_house_operator__user', 'kill_request').only( + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name', 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight').values( + 'key', + 'province_request__poultry_request__Index_weight', + 'province_kill_request__province_request__poultry_request__key', + 'province_kill_request__province_request__poultry_request__poultry', + 'bar_code', 'killhouse_user__kill_house_operator__user__mobile', + 'add_car__driver__type_car', + 'add_car__driver__driver_name', 'quantity', 'accepted_real_quantity', 'accepted_real_weight', + 'kill_request__slaughter_house__name', 'kill_request__slaughter_house', 'kill_request__key', + 'clearance_code', 'killhouse_user__name', 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__unit_name', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight') + + for kill in kill_house_request_diffrent_bar_info: + assignment_info = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill['key']).first() + if assignment_info: + assingment_quantity = assignment_info.real_quantity + assingment_weight = assignment_info.net_weight + else: + assingment_quantity = 0 + assingment_weight = 0 + kill_house_vet_quantity = kill['vet_accepted_real_quantity'] + kill_house_vet_weight = kill['vet_accepted_real_weight'] + quantity = kill['quantity'] + weight = int(kill['quantity'] * kill['province_request__poultry_request__Index_weight']) + + poultry_request = PoultryRequest.objects.get( + key=kill['province_kill_request__province_request__poultry_request__key']) + date_of_kill = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + list1 = [ + m, + str(kill['bar_code']), + kill['killhouse_user__name'], + kill['killhouse_user__kill_house_operator__user__mobile'], + kill['province_request__poultry_request__poultry__unit_name'], + kill['province_request__poultry_request__poultry__user__mobile'], + str(date_of_kill), + kill['add_car__driver__type_car'], + kill['add_car__driver__driver_name'], + kill['clearance_code'] if kill['clearance_code'] else '-', + quantity, + weight, + kill_house_vet_quantity, + int(kill_house_vet_weight), + assingment_quantity, + assingment_weight + ] + + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + blue = Font(color="0070C0") + red = Font(color="C00000") + orange = Font(color="F47914") + + if cell.column in [11, 12]: + cell.font = blue + + elif cell.column in [13, 14]: + cell.font = orange + else: + if cell.column in [15, 16]: + cell.font = red + value = list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش مغایرت اطلاعات کشتار و عدم فعالیت نقش ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_for_each_persion_excel(request): + # date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + kill = KillHouseRequest.objects.filter(trash=False, bar_code=request.GET['code']).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity').values( + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + ).first() + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد وارد شده در قرنطینه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد (کشتارگاه)', + 'وزن بار (کشتارگاه)', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[4].height = 19 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + name = kill['killhouse_user__name'] + worksheet['B1'] = f'مدیریت بارهای کشتارگاه {name}' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + + l = 4 + m = 1 + + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + quarantine_quantity = kill['quarantine_quantity'] if kill['quarantine_quantity'] != None else '-' + list1 = [ + '1', + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('add_car__driver__health_code')), + quantity, + weight, + code, + quarantine_quantity, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filtered_poultry_reqs = PoultryRequest.objects.filter( + trash=False, + send_date__date__gte=date1, + send_date__date__lte=date2 + ).select_related('poultry', 'poultry__user', 'hatching', 'poultry__user__city').only('remain_quantity', 'amount', + 'key', 'poultry', + 'send_date', + 'hatching__date', + 'create_date', 'order_code', + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__user__city__name', + 'hatching__quantity', + 'quantity', + 'hatching__left_over', + 'hatching__chicken_breed', + 'poultry__address__province__name', + 'Index_weight', + 'hatching__quantity').values( + 'key', 'poultry', 'remain_quantity', + 'send_date', + 'hatching__date', + 'create_date', 'order_code', + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__user__city__name', + 'hatching__quantity', + 'quantity', + 'hatching__left_over', + 'hatching__chicken_breed', 'poultry__address__province__name', 'Index_weight', 'amount', + 'hatching__quantity').order_by( + '-send_date') + len_province_request = len(ProvinceKillRequest.objects.filter( + province_request__poultry_request__key__in=filtered_poultry_reqs.values('key'), trash=False, + state__in=('pending', 'accepted'))) + excel_options = [ + 'ردیف', + 'کد سفارش', + 'نام واحد', + 'نام و نام خانوادگی مرغدار', + 'موبایل', + 'آدرس', + 'تاریخ جوجه ریزی', + 'تعداد کل جوجه ریزی', + 'سن مرغ', + 'تعداد درخواست کشتار', + 'وزن درخواست کشتار', + 'میانگین وزنی', + 'قیمت مرغ زنده', + 'تعداد تخصیصی به خریدار', + 'مانده قابل تخصیص', + 'تعداد قطعه باقی مانده در سالن', + 'نژاد', + 'تاریخ درخواست کشتار', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'وضعیت درخواست', + 'خریدار', + 'تعداد تخصیصی قطعه', + 'وزن تخصیصی', + 'تاریخ تخصیص', + 'آدرس', + 'محل کشتار', + 'وضعییت تخصیص به خریدار', + 'تعداد بار ایجاد شده', + 'تعداد قطعه تخصیصی به بار', + 'وزن تخصیصی به بار', + 'مانده قطعه قابل تخصیص', + 'مانده وزن قابل تخصیص', + 'ماشین', + 'راننده', + 'تلفن', + 'کد بهداشتی حمل و نقل', + 'کد رهگیری سامانه قرنطینه', + 'تعداد ثبت شده در قرنطینه', + 'تعداد قطعه بار', + 'وزن بار', + 'وضعیت بار', + 'تعداد تخلیه', + 'وزن تخلیه', + 'تاریخ تخلیه کشتارگاه', + 'دامپزشک کشتارگاه', + 'تلفن دامپزشک کشتارگاه', + 'اطلاعات تکمیلی قطعه', + 'اطلاعات تکمیلی وزن', + 'کاربر کشتارگاه', + 'تلفن کاربرکشتارگاه', + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد درخواست های کشتار', + 'مجموع قطعه درخواست های کشتار', + 'مجموع وزن درخواست های کشتار', + 'تعداد تخصیص به خریداران', + 'تعداد قطعه تخصیصی به خریداران', + 'وزن تخصیصی به خریداران', + 'مانده قابل تخصیص', + 'تعداد بار ایجاد شده', + 'تعداد قطعه بار های ایجاد شده', + 'وزن بارهای ایجاد شده', + 'تعداد قطعه قابل تخصیص به بار', + 'تعداد بارهای تخلیه شده', + 'تعداد قطعه بارهای تخلیه شده', + 'وزن بارهای تخلیه شده', + 'تعداد بار های تکمیل شده', + 'تعداد قطعه بارهای تکمیل شده', + 'وزن بارهای تکمیل شده', + + ] + all_quantity = 0 + all_main_quantity = 0 + all_assignment_quantity = 0 + all_wight = 0 + all_wight_killer = 0 + sum_all_quantity_of_bar = 0 + sum_all_weight_of_bar = 0 + sum_all_remain_quantity_of_bar = 0 + vet_state_accepted = 0 + all_vet_quantity = 0 + all_vet_wight = 0 + all_assigment = 0 + all_assignment_weight = 0 + all_hatching = 0 + all_poultry_request_weight = 0 + all_hatching_left_over = 0 + all_reamin_province = 0 + all_qarantine = 0 + all_poultry_request = filtered_poultry_reqs.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_remain_quantity = filtered_poultry_reqs.aggregate( + total_quantity=Sum('remain_quantity')).get( + 'total_quantity', 0) + sum_province_to_kill_house = all_poultry_request - all_remain_quantity + # برای بالای هدر + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 17 + if filtered_poultry_reqs.exists(): + province = filtered_poultry_reqs.first()['poultry__address__province__name'] + worksheet['A2'] = f' استان {province}' + + worksheet['A1'] = f'گزارش روند پرونده های کشتار مرغ گوشتی' + worksheet['A3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + m = 1 + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 7 + bar_list = 0 + bar_list2 = 0 + for filtered_poultry_req in filtered_poultry_reqs: + # print(filtered_poultry_req.get('poultry__unit_name')) + all_poultry_request_weight += int( + filtered_poultry_req.get('quantity') * filtered_poultry_req.get('Index_weight')) + all_hatching += filtered_poultry_req['hatching__quantity'] + all_hatching_left_over += filtered_poultry_req['hatching__left_over'] + state_p = 'در انتظار تخصیص استان' + if filtered_poultry_req.get('quantity') != filtered_poultry_req.get('remain_quantity'): + state_p = 'تخصیص داده شد' + all_wight += int(filtered_poultry_req.get('quantity') * filtered_poultry_req.get('Index_weight')) + all_quantity += filtered_poultry_req.get('quantity') + try: + vet_farm = VetFarm.objects.get(poultry=filtered_poultry_req.get('poultry'), trash=False) + vet_farm_name = vet_farm.vet.user.fullname + vet_farm_mobile = vet_farm.vet.user.mobile + except: + vet_farm_name = '-' + vet_farm_mobile = '-' + + age = (filtered_poultry_req.get('send_date').date() - filtered_poultry_req.get( + "hatching__date").date()).days + 1 + gregorian_date = jdatetime.date.fromgregorian( + day=filtered_poultry_req.get("hatching__date").day, + month=filtered_poultry_req.get("hatching__date").month, + year=filtered_poultry_req.get("hatching__date").year + ) + date_of_kill = jdatetime.date.fromgregorian( + day=filtered_poultry_req.get('create_date').day, + month=filtered_poultry_req.get('create_date').month, + year=filtered_poultry_req.get('create_date').year + ) + + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request__key=filtered_poultry_req.get('key'), + trash=False).select_related( + 'kill_request__kill_house', 'killhouse_user__kill_house_operator', + 'killhouse_user__kill_house_operator__user', 'killhouse_user__kill_house_operator__address', + 'killhouse_user').only('kill_request__slaughter_house', 'kill_request__slaughter_house__name', 'state', + 'key', 'create_date', + 'kill_request__kill_house', 'main_quantity', 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', 'killhouse_user__killer', + 'province_request__poultry_request__Index_weight', 'quantity').values( + 'kill_request__slaughter_house', 'kill_request__slaughter_house__name', 'key', 'create_date', + 'kill_request__kill_house', + 'main_quantity', + 'killhouse_user__name', + 'killhouse_user__killer', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', + 'province_request__poultry_request__Index_weight', + 'state', 'quantity') + + list1 = [ + m, + filtered_poultry_req.get('order_code'), + filtered_poultry_req.get('poultry__unit_name'), + filtered_poultry_req.get('poultry__user__fullname'), + filtered_poultry_req.get('poultry__user__mobile'), + filtered_poultry_req.get('poultry__user__city__name'), + str(gregorian_date), + filtered_poultry_req.get('hatching__quantity'), + str(age), + filtered_poultry_req.get('quantity'), + int(filtered_poultry_req.get('quantity') * filtered_poultry_req.get('Index_weight')), + filtered_poultry_req.get('Index_weight'), + filtered_poultry_req.get('amount'), + filtered_poultry_req.get('quantity') - filtered_poultry_req.get('remain_quantity'), + filtered_poultry_req.get('remain_quantity'), + filtered_poultry_req.get('hatching__left_over'), + + filtered_poultry_req.get('hatching__chicken_breed'), + str(date_of_kill), + vet_farm_name, + vet_farm_mobile, + state_p, + + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + worksheet.row_dimensions[l + 1].height = 24 + + if m % 2 == 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + state_s = 'در انتظار تخصیص استان' + m += 1 + + if province_kill_reqs.exists(): + quantity_kill_house_request = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__key= + filtered_poultry_req['key']) + + if len(province_kill_reqs) > 1: + if len(quantity_kill_house_request) <= 1: + s = len(province_kill_reqs) - 1 + for col in range(ord('A'), ord('U') + 1): + # rng = chr(col) + '7:{}'.format(r) + rng = f'{chr(col)}{l}:{chr(col)}{l + s}' + worksheet.merge_cells(rng) + worksheet[chr(col) + f'{l}'].alignment = Alignment(horizontal='center', vertical='center') + # TODO : جایی که باید انجام بشه + if quantity_kill_house_request.exists(): + if len(quantity_kill_house_request) > 1: + for col in range(ord('A'), ord('U') + 1): + # rng = chr(col) + '7:{}'.format(r) + s = len(quantity_kill_house_request) - 1 + rng = f'{chr(col)}{l}:{chr(col)}{l + s}' + worksheet.merge_cells(rng) + worksheet[chr(col) + f'{l}'].alignment = Alignment(horizontal='center', vertical='center') + + for province_kill_req in province_kill_reqs: + + if province_kill_req['state'] == 'pending': + state_s = 'درانتظار تایید' + + elif province_kill_req['state'] == 'accepted': + state_s = ' تایید شده' + elif province_kill_req['state'] == 'rejected': + state_s = 'رد شده' + all_wight_killer += int(province_kill_req.get('main_quantity') * province_kill_req.get( + 'province_request__poultry_request__Index_weight')) + # o += 1 + all_main_quantity += province_kill_req.get('main_quantity') + + date_of_inner_bar = '-' + + code = '-' + + time = jdatetime.date.fromgregorian( + day=province_kill_req.get('create_date').day, + month=province_kill_req.get('create_date').month, + year=province_kill_req.get('create_date').year + ) + assignment_quantity = '-' + assignment_weight = '-' + + if province_kill_req.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + else: + killers = 'کشتارکن' + + kill_house_requests = KillHouseRequest.objects.filter( + province_kill_request__key=province_kill_req['key'], + trash=False).select_related('add_car__driver', + 'killhouse_user').only( + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__user__fullname', 'killhouse_user', + 'province_kill_request__province_request__poultry_request__Index_weight', 'key', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'traffic_code', 'create_date', + 'clearance_code', + 'killhouse_user__killer', + 'accepted_real_quantity', 'accepted_real_weight', + 'quantity', 'province_request__poultry_request__Index_weight', 'vet_state', + 'assignment_state_archive', 'vet_accepted_real_weight', 'vet_accepted_real_quantity', + 'vet_state').values('vet_state', 'vet_accepted_real_weight', 'vet_accepted_real_quantity', + 'quarantine_quantity', 'vet_state', 'assignment_state_archive', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'key', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'traffic_code', + 'create_date', + 'clearance_code', + 'killhouse_user__killer', + 'accepted_real_quantity', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user', + 'accepted_real_weight', + 'killhouse_user__kill_house_operator__user__mobile', + 'quantity', 'quarantine_quantity', + 'province_request__poultry_request__Index_weight') + bar_list += (len(kill_house_requests)) + all_quantity_of_bar = kill_house_requests.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + bar_weight = int(all_quantity_of_bar * province_kill_req[ + 'province_request__poultry_request__Index_weight']) if all_quantity_of_bar != None else 0 + remain_province = int(province_kill_req.get('quantity') * province_kill_req[ + 'province_request__poultry_request__Index_weight']) + all_reamin_province += int(province_kill_req.get('quantity') * province_kill_req[ + 'province_request__poultry_request__Index_weight']) + sum_all_quantity_of_bar += all_quantity_of_bar if all_quantity_of_bar != None else 0 + sum_all_weight_of_bar += bar_weight + sum_all_remain_quantity_of_bar += province_kill_req.get('quantity') + list1 = [ + killers + '(' + province_kill_req.get('killhouse_user__name') + ')', + province_kill_req.get('main_quantity'), + int(province_kill_req.get('main_quantity') * province_kill_req.get( + 'province_request__poultry_request__Index_weight')), + str(time), + province_kill_req.get('killhouse_user__kill_house_operator__address__city__name'), + province_kill_req.get('kill_request__slaughter_house__name') if province_kill_req.get( + 'kill_request__slaughter_house') is not None else '-', + state_s, + len(kill_house_requests), + all_quantity_of_bar if all_quantity_of_bar != None else 0, + bar_weight, + province_kill_req.get('quantity'), + remain_province, + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 22, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + if m % 2 != 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + + if kill_house_requests.exists(): + if len(kill_house_requests) > 1: + s = len(kill_house_requests) - 1 + + letters = ["V", "W", "X", "Y", "Z", "AA", "AB", "AC", "AD", "AE", "AF", "AG"] + for col in letters: + rng = f'{col}{l}:{col}{l + s}' + worksheet.merge_cells(rng) + worksheet[col + f'{l}'].alignment = Alignment(horizontal='center', vertical='center') + + for kill_house_request in kill_house_requests: + all_qarantine += kill_house_request['quarantine_quantity'] if kill_house_request[ + 'quarantine_quantity'] else 0 + if kill_house_request['vet_state'] == 'accepted': + vet_state_accepted += 1 + bar_list2 += 1 + kil_house_vet = KillHouseVet.objects.filter( + kill_house=kill_house_request.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + if (kill_house_request['assignment_state_archive'] == 'True' and kill_house_request[ + 'vet_state'] == 'pending') or kill_house_request[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + all_quantity_of_bar += kill_house_request['quantity'] + vet_quantity = kill_house_request['vet_accepted_real_quantity'] + vet_wight = kill_house_request['vet_accepted_real_weight'] + all_vet_quantity += vet_quantity + all_vet_wight += vet_wight + kill_house_driver_name = kill_house_request.get('add_car__driver__driver_name') + kill_house_driver_mobile = kill_house_request.get('add_car__driver__driver_mobile') + kill_house_driver_type_car = kill_house_request.get('add_car__driver__type_car') + kill_house_traffic_code = kill_house_request.get('traffic_code') + vet_checks = VetCheckRequest.objects.filter( + kill_house_request__key=kill_house_request.get('key')).only( + 'create_date').values('create_date').first() + + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill_house_request.get('key')).only('real_quantity', + 'net_weight', + 'create_date').values( + 'real_quantity', 'net_weight', 'create_date').first() + if assignment: + all_assigment += 1 + all_assignment_quantity += assignment.get('real_quantity') + assignment_quantity = assignment.get('real_quantity') + assignment_weight = assignment.get("net_weight") + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + all_assignment_weight += assignment_weight + if kill_house_request.get('clearance_code'): + code = kill_house_request.get('clearance_code') + + list1 = [ + kill_house_driver_type_car, + kill_house_driver_name, + kill_house_driver_mobile, + kill_house_traffic_code, + code, + kill_house_request['quarantine_quantity'] if kill_house_request[ + 'quarantine_quantity'] else '-', + kill_house_request['quantity'], + int(kill_house_request['quantity'] * kill_house_request[ + 'province_request__poultry_request__Index_weight']), + state, + vet_quantity, + vet_wight, + str(date_of_inner_bar), + kill_house_vet_name, + kill_house_vet_mobile, + assignment_quantity, + assignment_weight, + kill_house_request['killhouse_user__kill_house_operator__user__fullname'], + kill_house_request['killhouse_user__kill_house_operator__user__mobile'], + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 34, value=list1[item]) + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + if m % 2 != 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + + l += 1 + else: + list1 = [ + + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + + ] + # m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 34, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + if m % 2 != 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + if province_kill_req['state'] == 'pending' or province_kill_req['state'] == 'rejected': + l += 1 + + + else: + list1 = [ + '-', + '-', + '-', + '-', + '-', + '-', + state_s, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + + ] + # m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 22, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + if m % 2 != 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + l += 1 + print(vet_state_accepted) + value_header_list = [ + len(filtered_poultry_reqs), + all_quantity, + all_wight, + len_province_request, + all_main_quantity, + all_wight_killer, + all_remain_quantity, + bar_list, + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + sum_all_remain_quantity_of_bar, + vet_state_accepted, + all_vet_quantity, + all_vet_wight, + all_assigment, + all_assignment_quantity, + all_assignment_weight, + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 4, value=value_header_list[item]) + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value = value_header_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + all_hatching, + '', + all_poultry_request, + all_poultry_request_weight, + '', + '', + sum_province_to_kill_house, + all_remain_quantity, + all_hatching_left_over, + '', + '', + '', + '', + '', + '', + all_main_quantity, + all_wight_killer, + '', + '', + '', + '', + '', + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + sum_all_remain_quantity_of_bar, + all_reamin_province, + '', + '', + '', + '', + '', + all_qarantine, + sum_all_quantity_of_bar, + sum_all_weight_of_bar, + '', + all_vet_quantity, + all_vet_wight, + '', + '', + '', + all_assignment_quantity, + all_assignment_weight, + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="روند پرونده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_contradiction_of_quarantine_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, quarantine_quantity__isnull=False, + + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity').values( + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'مجموع تعداد قطعه ثبت شده در قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'گزارش مغایرت در بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if kill.get('quantity') != kill['quarantine_quantity']: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = kill['quarantine_quantity'] if kill['quarantine_quantity'] != None else '-' + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else 0, + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + else: + pass + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مغایرت بار ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def detail_of_killing_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + now_date_1 = separate.join(reversed_date) + + if 'role' in request.GET: + role = request.GET['role'] + else: + user = SystemUserProfile.objects.get(key=request.GET['key']) + user_token = ReportsUsers.objects.filter(user_token=request.GET['key']).first() + role = user_token.position + + if role == 'CityOperator': + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_poultry_hatch = PoultryHatching.objects.filter(archive=False, + allow_hatching='pending', + poultry__city_operator=city_operator.unit_name, + trash=False, left_over__gt=0, chicken_age__gt=50) + + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, + poultry__city_operator=city_operator.unit_name, + left_over__gt=F('quantity') * percent_of_losses, + chicken_age__range=(55, 90)).order_by('id') + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killer', 'killer__kill_house_operator__user__mobile', + 'killer__name', 'province_request__poultry_request__freezing', + 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date', 'message').values( + 'killer', 'killer__kill_house_operator__user__mobile', 'killer__name', + 'message', + 'province_request__poultry_request__freezing', 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, poultry__city_operator=city_operator.unit_name, + pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + poultry__city_operator=city_operator.unit_name, + out_province_request_cancel=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + province_state__in=('pending', 'accepted')) + else: + user = SystemUserProfile.objects.get(key=request.GET['key']) + city = ReportsUsers.objects.get(user_token=request.GET['key']) + filtered_poultry_hatch = PoultryHatching.objects.filter(archive=False, + allow_hatching='pending', + poultry__user__city__name=city.city, + trash=False, left_over__gt=0, chicken_age__gt=50) + + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, + poultry__user__city__name=city.city, + left_over__gt=F('quantity') * percent_of_losses, + chicken_age__range=(55, 90)).order_by('id') + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + province_request__poultry_request__poultry__user__city__name=city.city, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killer', 'killer__kill_house_operator__user__mobile', + 'killer__name', 'province_request__poultry_request__freezing', + 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date', 'message').values( + 'killer', 'killer__kill_house_operator__user__mobile', 'killer__name', + 'message', + 'province_request__poultry_request__freezing', 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, poultry__user__city__name=city.city, + pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + poultry__user__city__name=city.city, + out_province_request_cancel=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + province_state__in=('pending', 'accepted')) + elif role in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key']) + filtered_poultry_hatch = PoultryHatching.objects.filter(archive=False, poultry__address__city=user.city, + allow_hatching='pending', + trash=False, left_over__gt=0, chicken_age__gt=50) + + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, poultry__address__city=user.city, + left_over__gt=F('quantity') * percent_of_losses, + chicken_age__range=(55, 90)).order_by('id') + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + province_request__poultry_request__poultry__address__city=user.city, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killer', 'killer__kill_house_operator__user__mobile', + 'killer__name', 'province_request__poultry_request__freezing', + 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date', 'message').values( + 'killer', 'killer__kill_house_operator__user__mobile', 'killer__name', + 'message', + 'province_request__poultry_request__freezing', 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + poultry_request = (PoultryRequest.objects.filter(trash=False, poultry__address__city=user.city, + pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + poultry__address__city=user.city, + out_province_request_cancel=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + province_state__in=('pending', 'accepted')) + + else: + filtered_poultry_hatch = PoultryHatching.objects.filter(archive=False, + allow_hatching='pending', + trash=False, left_over__gt=0, chicken_age__gt=50) + + hatching_between_50_70 = PoultryHatching.objects.filter(trash=False, + left_over__gt=F('quantity') * percent_of_losses, + chicken_age__range=(55, 90)).order_by('id') + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('killer', 'killer__kill_house_operator__user__mobile', + 'killer__name', 'province_request__poultry_request__freezing', + 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date', 'message').values( + 'killer', 'killer__kill_house_operator__user__mobile', 'killer__name', + 'message', + 'province_request__poultry_request__freezing', 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__hatching__date', + 'province_request__poultry_request__send_date' + ) + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + out_true_poultry_request = PoultryRequest.objects.filter(trash=False, out=True, + out_province_request_cancel=False, + send_date__date__gte=date1, + send_date__date__lte=date2, + province_state__in=('pending', 'accepted')) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + filtered_kill_reqs_not_code_but_have_assigment = filtered_kill_reqs.filter( + Q(assignment_state_archive='True', vet_state='pending') + | Q(vet_state='accepted'), clearance_code__isnull=True) + all_age = [] + + excel_options = { + 'آمار کلی': [], + 'مدیریت بارها': [], + 'مانده در سالن بالای 50 روز': [], + 'بارهای احراز شده مغایرت دار': [], + 'بارهای فاقد قرنطینه تخلیه شده': [], + 'بارهای عدم احراز از قرنطینه': [], + 'بارهای تخلیه نشده با کد قرنطینه': [], + 'تخلیه نشده-تحویل گرفته شده': [], + 'تخلیه شده-عدم تکمیل': [], + 'بارهای تخلیه نشده-عدم تکمیل': [], + 'بارهای تخلیه شده- تکمیل شده': [], + } + output = BytesIO() + workbook = Workbook() + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + for name, options in excel_options.items(): + all_age1 = sorted(all_age) + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + # worksheet.column_dimensions[col_letter].width = 20.01 + # worksheet.row_dimensions[1].height = 22 + + if sheet_name == 'مدیریت بارها': + + filterset_class = KillHouseRequestFilterSet + filterset_fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', 'document_status', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'province_kill_request__province_request__poultry_request__out', + 'province_kill_request__kill_house_price', + 'price', + 'killer__name', + 'killhouse_user__type', 'killer', 'bar_document_status', + 'bar_document_status__title').values( + 'province_request__poultry_request__poultry__user__fullname', 'province_kill_request__kill_house_price', + 'kill_request__export_country', + 'province_request__poultry_request__direct_buying', + 'province_request__poultry_request__export', + 'province_request__poultry_request__freezing', + 'document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'province_kill_request__province_request__poultry_request__out', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', 'bar_document_status', + 'province_kill_request__kill_house_price', + 'price', + 'bar_document_status__title' + ) + + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(key=request.GET['key']) + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key']) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__address__city=user.city) + elif request.GET['role'] == 'VetFarm': + user = SystemUserProfile.objects.get(key=request.GET['key']) + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user__kill_house_operator__user=user) + else: + filtered_kill_reqs = filtered_kill_request + + if request.GET['role'] == 'KillHouse': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + + elif request.GET['role'] == 'KillHouseVet': + user = SystemUserProfile.objects.get(key=request.GET['key']) + kill_house_vets = KillHouseVet.objects.filter(vet__user=user, trash=False).select_related('kill_house') + kill_house = kill_house_vets.values_list('kill_house', flat=True).distinct() + + else: + kill_house = KillHouse.objects.filter(out_province=False, trash=False) + + if 'state' in request.GET: + if request.GET['state'] == 'completed': + filtered_kill_reqs = filtered_kill_reqs.filter(assignment_state_archive='True') + elif request.GET['state'] == 'bar_pending': + filtered_kill_reqs = filtered_kill_reqs.filter( + (Q(killhouse_user__in=kill_house) | Q(kill_request__slaughter_house__in=kill_house) | Q( + killer__in=kill_house)), assignment_state_archive='pending') + else: + filtered_kill_reqs = filtered_kill_reqs + else: + filtered_kill_reqs = filtered_kill_reqs + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_kill_reqs + + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_kill_reqs) + filtered_kill_reqs = ps.filter() + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'نوع کشتار', + 'کدسفارش مرغدار', + 'نام و نام خانوادگی مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'نام فارم', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + 'قیمت پیشنهادی کشتارگاه(ریال)', + 'قیمت تعاونی(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'قیمت کشتارگاه(ریال)', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت در لحظه', + 'درصد افت ورود به انبار', + 'کشور مقصد', + 'اختلاف مجوز', + + ] + + from_date_1 = shamsi_date(date1) + + to_date_1 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'حجم بارهای ایجاد شده', + 'وزن بارهای ایجاد شده', + 'میانگین وزن بارهای ایجاد شده', + 'کمترین سن', + 'بیشترین سن', + 'میانگین سنی', + 'تعداد بارهای دارای کد قرنطینه', + 'حجم بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد بار فاقد قرنطینه', + 'حجم بار فاقد قرنطینه', + ' تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'حجم بارها', + 'وزن بارها', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه ورود به انبار', + + ] + + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + header_list3 = [ + 'درصد بارهای دارای کد قرنطینه', + 'درصد تعداد بارهای احراز شده از قرنطینه', + 'درصد تعداد بارهای تکمیل شده کشتارگاه', + 'درصد وزن نهایی در کشتارگاه نسبت به وزن کل', + 'درصد بارهای فاقد کد قرنطینه', + 'درصد بارهای اختلاف دار در قرنطینه و رصدیار', + 'درصد تعداد بارهای ورودی به انبار', + 'درصد وزن لاشه ها در انبار نسبت به وزن کل', + 'درصد وزن لاشه در انبار نسبت به وزن نهایی در کشتارگاه', + + ] + create_header(worksheet, header_list, 9, 2, height=21.8) + + create_header(worksheet, header_list2, 6, 2, height=21.8, color='green') + + create_header(worksheet, header_list3, 6, 5, height=43, color='orange', text_color='0D0D0D') + create_header_freez(worksheet, excel_options, 1, 8, 9, height=21, len_with=True) + + excel_description(worksheet, 'B1', 'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی', color='red', + row2='D1') + + kill_keys = [kill.get('key') for kill in filtered_kill_reqs] + + vet_checks = VetCheckRequest.objects.filter( + trash=False, kill_house_request__key__in=kill_keys + ).only('create_date', 'kill_house_request__key').values( + 'create_date', 'kill_house_request__key') + + assignments = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key__in=kill_keys, trash=False + ).only('create_date', 'net_weight', 'real_quantity', 'kill_house_request__key') + + vet_check_mapping = {vc['kill_house_request__key']: vc['create_date'] for vc in vet_checks} + assignment_mapping = { + assignment.kill_house_request.key: ( + int(assignment.net_weight), assignment.real_quantity, assignment.create_date) + for assignment in assignments + } + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + excel_description(worksheet, 'B2', f'استان {name}', color='red', row2='D2') + excel_description(worksheet, 'B3', f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})', row2='D3') + + l = 8 + m = 1 + all_age = [] + + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + poultry_ids = [req.get('province_request__poultry_request__poultry') for req in filtered_kill_reqs] + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry_id: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + if age not in all_age: + all_age.append(age) + + if (kill['assignment_state_archive']) == 'True' or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + vet_farm_id = kill.get('province_request__poultry_request__poultry') + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = convert_to_shamsi(year=send_date.year, month=send_date.month, + day=send_date.day, ) + + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + key = kill.get('key') + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + if kill['assignment_state_archive'] == 'True' or kill['ware_house_confirmation'] == True: + net_weighte = kill['accepted_real_weight'] + real_quantity = kill['accepted_real_quantity'] + else: + net_weighte = 0 + real_quantity = 0 + net_weighte2, real_quantity2, vet_check_date = assignment_mapping.get(key, ('-', '-', None)) + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + vet_check_date = vet_check_mapping.get(key, vet_check_date) + date_of_inner_bar = convert_to_shamsi(datetime=vet_check_date) if vet_check_date else '-' + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + export_country = '-' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__out'] == True: + type = 'خارج از استان' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + elif kill['province_request__poultry_request__freezing'] == True: + type = 'انجماد' + elif kill['province_request__poultry_request__export'] == True: + type = 'صادرات' + export_country = kill['kill_request__export_country'] + else: + type = 'عادی' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_weighte += weight + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + + else: + state_ware_house_confirmation = '-' + + weight_loss1 = kill['accepted_real_weight'] - kill['ware_house_accepted_real_weight'] if kill[ + 'ware_house_accepted_real_weight'] > 0 else 0 + if weight_loss1 < 0: + weight_loss1 = weight_loss1 * -1 + total_weight_loss = (weight_loss1 / kill['accepted_real_weight']) * 100 if weight_loss1 != 0 else 0 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + type, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__user__fullname'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + kill.get('province_request__poultry_request__poultry__unit_name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + + kill.get('province_kill_request__kill_house_price') if kill.get( + 'province_kill_request__kill_house_price') else '-', + + kill.get('price') if kill.get( + 'price') else '-', + + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + kill.get('province_kill_request__kill_house_price'), + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + round(kill['accepted_real_weight'], 1), + state_delete, + kill['bar_document_status__title'] if kill['bar_document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'%{round(total_weight_loss, 2)}', + f'%{weight_loss}', + export_country, + kill['accepted_real_quantity'] - quarantine_quantity if kill[ + 'quarantine_quantity'] != None else quarantine_quantity + + ] + m += 1 + create_value(worksheet, list1, l, 1, height=20, different_cell=40, different_value='بار حذف شده') + killer_exclusive = len(filtered_kill_reqs.filter(killer__isnull=False)) + all_state_ware_house_confirmation = len(filtered_kill_reqs.filter(ware_house_confirmation=True)) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + + aggregate_filtered_kill_reqs = filtered_kill_reqs.aggregate( + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity=Sum('quantity'), + total_vet_accepted_real_quantity=Sum('vet_accepted_real_quantity'), + total_vet_accepted_real_weight=Sum('vet_accepted_real_weight'), + total_quarantine_quantity=Sum('quarantine_quantity'), + total_ware_house_accepted_real_quantity=Sum('ware_house_accepted_real_quantity'), + total_ware_house_accepted_real_weight=Sum('ware_house_accepted_real_weight'), + total_weight_loss=Sum('weight_loss'), + + ) + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + + accepted_real_quantity = aggregate_filtered_kill_reqs['total_accepted_real_quantity'] or 0 + + accepted_real_wight = aggregate_filtered_kill_reqs['total_accepted_real_weight'] or 0 + all_kill_request_quantity = aggregate_filtered_kill_reqs['total_quantity'] or 0 + all_quarantine_quantity = aggregate_filtered_kill_reqs['total_quarantine_quantity'] or 0 + all_vet_accepted_real_quantity = aggregate_filtered_kill_reqs['total_vet_accepted_real_quantity'] or 0 + all_vet_accepted_real_weight = aggregate_filtered_kill_reqs['total_vet_accepted_real_weight'] or 0 + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_quantity'] or 0 + all_ware_house_accepted_real_weight = aggregate_filtered_kill_reqs[ + 'total_ware_house_accepted_real_weight'] or 0 + all_weight_loss = aggregate_filtered_kill_reqs['total_weight_loss'] or 0 + has_code1 = filtered_kill_reqs.filter(clearance_code__isnull=False).aggregate( + total_quantity=Sum('quantity'), + ) + all_quarantine_quantity_has_code = has_code1['total_quantity'] or 0 + hasnt_code1 = filtered_kill_reqs.filter(clearance_code__isnull=True) + hasnt_code = hasnt_code1.aggregate( + total_quantity=Sum('quantity') + ) + all_quarantine_quantity_hasnt_code = hasnt_code['total_quantity'] or 0 + difference_bar = len(filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')))) + all_weight_loss = round(int(all_weight_loss) / all_state_ware_house_confirmation, + 2) if all_weight_loss > 0 else 0 + + all_age1 = sorted(all_age) + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + + province_kill_request = ProvinceKillRequest.objects.filter( + pk__in=filtered_kill_reqs.values( + 'province_kill_request')).aggregate( + total_quantity_melak=Sum('total_killed_quantity'), + total_weight_melak=Sum('total_killed_weight'), + ) + + # province_kill_request = filtered_kill_reqs.values_list( + # 'province_kill_request',flat=True).distinct().aggregate( + # total_quantity_melak=Sum('total_killed_quantity'), + # total_weight_melak=Sum('total_killed_weight'), + # ) + accepted_real_quantity_melak = province_kill_request['total_quantity_melak'] or 0 + + accepted_real_wight_melak = province_kill_request['total_weight_melak'] or 0 + value_header_list = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight), + len(filtered_kill_reqs), + killer_exclusive, + all_kill_request_quantity, + int(all_weighte), + round(all_weighte / all_kill_request_quantity, + 1) if all_weighte > 0 and all_kill_request_quantity > 0 else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + int((sum(all_age1)) / len(all_age1)) if len(all_age1) > 0 else '-', + has_code, + all_quarantine_quantity_has_code, + has_qarantine, + all_quarantine_quantity, + len(hasnt_code1), + all_quarantine_quantity_hasnt_code, + difference_bar, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity_melak, + accepted_real_wight_melak, + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + create_value(worksheet, value_header_list, 3, 6) + value_header_list2 = [ + f'%{round((has_code * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((has_qarantine * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((len(bar_complete) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_net_weighte) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((len(hasnt_code1) * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((difference_bar * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((all_state_ware_house_confirmation * 100) / len(filtered_kill_reqs), 2) if len(filtered_kill_reqs) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_weighte), 2) if int(all_weighte) > 0 else 0}', + f'%{round((int(all_ware_house_accepted_real_weight) * 100) / int(all_net_weighte), 2) if int(all_net_weighte) > 0 else 0}' + ] + create_value(worksheet, value_header_list2, 6, 6) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + elif sheet_name == 'مانده در سالن بالای 50 روز': + excel_options = [ + 'ردیف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + header_list = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + for poultry_hatching in filtered_poultry_hatch: + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + age = (datetime.datetime.now().date() - poultry_hatching.date.date()).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) - poultry_hatching.killed_quantity + all_left_over_ninty_percent += left_over_ninty_percent + list1 = [ + m, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(filtered_poultry_hatch), + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای احراز شده مغایرت دار': + filtered_kill_reqs_qarantine = filtered_kill_reqs.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')) + , quarantine_quantity__isnull=False) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای احراز شده دارای مغایرت', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارهای احراز شده دارای مغایرت', + 'مجموع وزن بارهای احراز شده دارای مغایرت', + 'تعداد بارهای احراز شده دارای مغایرت دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای احراز شده دارای مغایرت در قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ ({from_date_1}) تا تاریخ ({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_qarantine.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_qarantine.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_qarantine: + for kill in filtered_kill_reqs_qarantine: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_qarantine.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_qarantine.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs_qarantine.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_qarantine), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای فاقد قرنطینه تخلیه شده': + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای فاقد قرنطینه تخلیه شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارهای فاقد قرنطینه تخلیه شده', + 'مجموع وزن بارهای فاقد قرنطینه تخلیه شده', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای فاقد قرنطینه تخلیه شده' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_code_but_have_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_not_code_but_have_assigment: + for kill in filtered_kill_reqs_not_code_but_have_assigment: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_code_but_have_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_code_but_have_assigment), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای عدم احراز از قرنطینه': + filtered_kill_reqs_havent_qarantine_quantity = filtered_kill_reqs.filter(quarantine_quantity__isnull=True, + clearance_code__isnull=False) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای عدم احراز از قرنطینه', + 'تعداد بارهای دارای کشتارکن اختصاصی', + + 'مجموع تعداد قطعه بارهای عدم احراز از قرنطینه', + 'مجموع وزن بارهای عدم احراز از قرنطینه', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای عدم احراز از قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_havent_qarantine_quantity.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_havent_qarantine_quantity.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_havent_qarantine_quantity: + for kill in filtered_kill_reqs_havent_qarantine_quantity: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_havent_qarantine_quantity.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_havent_qarantine_quantity.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs_havent_qarantine_quantity.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_havent_qarantine_quantity), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'بارهای تخلیه نشده با کد قرنطینه': + filtered_kill_reqs_not_assigment_but_have_code = filtered_kill_reqs.filter( + Q(assignment_state_archive='pending') + | Q(vet_state='pending'), clearance_code__isnull=False) + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تخلیه نشده با کد قرنطینه', + 'تعداد بارهای دارای کشتارکن اختصاصی', + + 'مجموع تعداد قطعه بارهای تخلیه نشده با کد قرنطینه', + 'مجموع وزن بارهای تخلیه نشده با کد قرنطینه', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای تخلیه نشده با کد قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment_but_have_code.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_not_assigment_but_have_code: + for kill in filtered_kill_reqs_not_assigment_but_have_code: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment_but_have_code.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تخلیه نشده-تحویل گرفته شده': + filtered_kill_reqs_not_assigment_but_have_code = filtered_kill_reqs.filter( + vet_state='pending', assignment_state_archive='True') + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تخلیه نشده با کد قرنطینه', + 'تعداد بارهای دارای کشتارکن اختصاصی', + + 'مجموع تعداد قطعه بارهای تخلیه نشده با کد قرنطینه', + 'مجموع وزن بارهای تخلیه نشده با کد قرنطینه', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'تخلیه نشده/تحویل گرفته شده' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment_but_have_code.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_not_assigment_but_have_code: + for kill in filtered_kill_reqs_not_assigment_but_have_code: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment_but_have_code.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + elif sheet_name == 'تخلیه شده-عدم تکمیل': + filtered_kill_reqs_not_assigment = filtered_kill_reqs.filter(vet_state='accepted', + assignment_state_archive='pending') + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تکمیل نشده توسط کشتارگاه', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارهای تکمیل نشده توسط کشتارگاه', + 'مجموع وزن بارهای تکمیل نشده توسط کشتارگاه', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'تخلیه شده/عدم تکمیل' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_reqs_not_assigment: + for kill in filtered_kill_reqs_not_assigment: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs_not_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بارهای تخلیه نشده-عدم تکمیل': + filtered_kill_not_assigment = filtered_kill_reqs.filter(vet_state='pending', + assignment_state_archive='pending') + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تخلیه نشده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارهای تخلیه نشده', + 'مجموع وزن بارهای تخلیه نشده', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای بارهای تخلیه نشده' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_not_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_not_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_not_assigment.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_not_assigment: + for kill in filtered_kill_not_assigment: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_not_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_not_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_not_assigment), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بارهای تخلیه شده- تکمیل شده': + filtered_kill_not_assigment = filtered_kill_reqs.filter(vet_state='accepted', + assignment_state_archive='True') + + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + ' کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تخلیه نشده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + + 'مجموع تعداد قطعه بارهای تخلیه نشده', + 'مجموع وزن بارهای تخلیه نشده', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای تخلیه شده/ تکمیل شده' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_not_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_not_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_not_assigment.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + killer_exclusive = 0 + if filtered_kill_not_assigment: + for kill in filtered_kill_not_assigment: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_not_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_not_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_not_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_not_assigment), + killer_exclusive, + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + else: + worksheet[ + 'E2'] = 'گزارش کلی فارم های فعال و بایگانی شده مرغ گوشتی دارای مانده در سالن بیشتر از 11 درصد بین بازه سنی 55 روز تا 90 روز' + + worksheet['A2'] = f'این گزارش در مورخ {now_date_1} صادر شده است.' + + worksheet['E2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'E2:K2' + merge_range2 = 'A2:C2' + # merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + # worksheet['B1'].font = red_font + # worksheet['B3'].font = Font(size=11) + worksheet['E2'].font = Font(size=10) + worksheet['A2'].font = Font(size=10, color="C00000") + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم بایگانی شده', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کشتارشده', + 'جمع کل مانده در سالن(قطعه)', + 'جمع مانده در سال فارم فعال(قطعه)', + 'جمع مانده در سالن فارم بایگانی(قطعه)', + 'کمترین سن ', + 'بیشترین سن ', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + for col_num, option in enumerate(header_list, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFFFFF", fill_type="solid") + cell.font = Font(size=8, bold=True, color='538135') + worksheet.row_dimensions[3].height = 28.8 + worksheet.column_dimensions[col_letter].width = 11.95 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium', color='A8D08D'), + right=openpyxl.styles.Side(style='medium', color='A8D08D'), + top=openpyxl.styles.Side(style='medium', color='A8D08D'), + bottom=openpyxl.styles.Side(style='medium', color='A8D08D') + ) + + min_list = [] + all_left_over_ninty_percent = 0 + len_archive_hatch = 0 + len_hatch = 0 + left_over_archive = 0 + left_over = 0 + for poultry_hatching in hatching_between_50_70: + if poultry_hatching.archive == True and poultry_hatching.allow_hatching == 'True': + len_archive_hatch += 1 + left_over_archive += poultry_hatching.left_over + if poultry_hatching.archive == False and poultry_hatching.allow_hatching == 'pending': + len_hatch += 1 + left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + left_over_ninty_percent = (( + poultry_hatching.quantity * 90) / 100) - poultry_hatching.killed_quantity + all_left_over_ninty_percent += left_over_ninty_percent + + min_list = sorted(min_list) + all_total_commitment = hatching_between_50_70.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_poultry_hatching_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_poultry_hatching_quantity = hatching_between_50_70.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_poultry_hatching_left_over = hatching_between_50_70.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = hatching_between_50_70.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = hatching_between_50_70.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = hatching_between_50_70.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_age1 = sorted(all_age) + value_header_list = [ + len_hatch, + len_archive_hatch, + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + left_over_archive, + left_over, + + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=4, column=item + 1, value=value_header_list[item]) + cell.fill = PatternFill(start_color="E2EFD9", fill_type="solid") + + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium', color='A8D08D'), + right=openpyxl.styles.Side(style='medium', color='A8D08D'), + top=openpyxl.styles.Side(style='medium', color='A8D08D'), + bottom=openpyxl.styles.Side(style='medium', color='A8D08D') + ) + worksheet[ + 'A6'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + worksheet['A7'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['F7'] = f'اطلاعات کلی بارها' + worksheet['G11'] = f'تفکیک بارهای دولتی,آزاد و خارج از استان' + worksheet['E15'] = f'اطلاعات بارهای تخلیه شده و تکمیل شده توسط کشتارگاه' + worksheet['F19'] = f'اطلاعات بارهای تخلیه نشده و تکمیل نشده توسط کشتارگاه' + worksheet['F23'] = f'تعداد قطعه نهایی کم شده از سالن مرغدار(ملاک کشتار)' + worksheet['M11'] = f'درمجموع بارها محاسبه نمیشود*' + + worksheet['A6'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A7'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['F7'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G11'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['E15'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['F19'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['F23'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M11'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A6:D6' + merge_range2 = 'A7:D7' + merge_range3 = 'F7:J7' + merge_range4 = 'G11:J11' + merge_range5 = 'E15:K15' + merge_range6 = 'F19:I19' + merge_range7 = 'F23:I23' + merge_range8 = 'M11:N11' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet['A6'].font = Font(size=10) + worksheet['A7'].font = Font(size=9) + worksheet['F7'].font = Font(size=11) + worksheet['F11'].font = Font(size=11) + worksheet['D15'].font = Font(size=11) + worksheet['F19'].font = Font(size=10) + worksheet['F23'].font = Font(size=8) + worksheet['M11'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + worksheet['M11'].fill = PatternFill(start_color="E9CFAF", fill_type="solid") + header_list3 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + 'کمترین سن کشتار', + 'بیشترین سن کشتار', + 'میانگین سنی کشتار', + + ] + for col_num, option in enumerate(header_list3, 2): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=8, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + header_list2 = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارهای ایجاد شده', + 'مجموع وزن بارها ایجاد شده', + 'میانگین وزن', + + ] + for col_num, option in enumerate(header_list2, 8): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=8, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + header_list4 = [ + + 'تعداد بارهای دارای کد قرنطینه', + 'مجموع قطعه بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list4, 12): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="C5E0B3", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + header_list5 = [ + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + + ] + for col_num, option in enumerate(header_list5, 14): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="8EAADB", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + header_list6 = [ + 'تعداد بارهای فاقد کد قرنطینه', + 'مجموع قطعه بارهای فاقد کد قرنطینه', + 'تعداد بارهایی که در قرنطینه و رصدیار اختلاف دارند', + ] + for col_num, option in enumerate(header_list6, 16): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFF2CC", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + header_list7 = [ + 'حجم بارها', + 'وزن بارها', + + ] + for col_num, option in enumerate(header_list7, 19): + cell = worksheet.cell(row=8, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=8, bold=True, color='FFFFFF') + worksheet.row_dimensions[8].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + all_weighte = 0 + for kill in filtered_kill_reqs: + w = kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + weight = kill.get('quantity') * w + all_weighte += weight + + difference_bar = len(filtered_kill_reqs.filter(~Q(quantity=F('quarantine_quantity')))) + + hasnt_code = filtered_kill_reqs.filter(clearance_code__isnull=True) + all_quarantine_quantity_hasnt_code = hasnt_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + has_code = filtered_kill_reqs.filter(clearance_code__isnull=False) + all_quarantine_quantity_has_code = has_code.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + has_qarantine = filtered_kill_reqs.filter(quarantine_quantity__isnull=False) + all_has_qarantine = has_qarantine.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + value_header = [ + len(poultry_request), + total_requests_quantity if total_requests_quantity != None else 0, + total_requests_weight if total_requests_weight != None else 0, + all_age1[0] if len(all_age1) > 0 else '-', + all_age1[len(all_age1) - 1] if len(all_age1) > 0 else '-', + (sum(all_age1) / len(all_age1)) if len(all_age1) > 0 else '-', + len(filtered_kill_reqs), + all_quantity if all_quantity != None else 0, + all_weighte, + round(all_weighte / all_quantity, 1) if all_weighte > 0 and all_quantity > 0 else 0, + len(has_code), + all_quarantine_quantity_has_code if all_quarantine_quantity_has_code != None else 0, + len(has_qarantine), + all_has_qarantine if all_has_qarantine != None else 0, + len(hasnt_code), + all_quarantine_quantity_hasnt_code if all_quarantine_quantity_hasnt_code != None else 0, + difference_bar, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header)): + cell = worksheet.cell(row=9, column=item + 2, value=value_header[item]) + value = value_header[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + header_list7 = [ + 'تعداد بار دولتی', + 'مجموع قطعه بارهای دولتی', + 'مجموع وزن بارهای دولتی', + 'بارهای دولتی دارای احراز شده قرنطینه', + 'تعداد قطعه دولتی احراز شده از قرنطینه', + ] + + for col_num, option in enumerate(header_list7, 2): + cell = worksheet.cell(row=12, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=8, bold=True, color='FFFFFF') + worksheet.row_dimensions[12].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + header_list8 = [ + 'تعداد بارهای آزاد', + 'مجموع قطعه بارهای آزاد', + 'مجموع وزن بارهای آزاد', + 'بارهای آزاد احراز شده از قرنطینه', + 'مجموع تعداد قطعه بارهای آزاد احراز شده از قرنطینه', + 'کل بارهای آزاد دارای کد قرنطینه', + + ] + header_listx = [ + 'تعداد بارهای خارج از استان', + 'مجموع قطعه بارهای خارج از استان', + ] + for col_num, option in enumerate(header_list8, 7): + cell = worksheet.cell(row=12, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFE599", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[12].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_listx, 13): + cell = worksheet.cell(row=12, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="E9CFAF", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[12].height = 42.8 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + bar_government = filtered_kill_reqs.filter( + province_request__poultry_request__free_sale_in_province=False) + + accepted_real_quantity_bar_government = bar_government.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_bar_government = bar_government.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + bar_government_quarantine_quantity = bar_government.filter(quarantine_quantity__isnull=False) + + accepted_real_quantity_bar_government_quarantine_quantity = bar_government_quarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + + bar_free = filtered_kill_reqs.filter(province_request__poultry_request__free_sale_in_province=True) + accepted_real_quantity_bar_free = bar_free.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_bar_free = bar_free.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + bar_free_quarantine_quantity = bar_free.filter(quarantine_quantity__isnull=False) + + accepted_real_quantity_bar_free_quarantine_quantity = bar_free_quarantine_quantity.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + + bar_free_has_code = len(bar_free.filter(clearance_code__isnull=False)) + + quantity_out_true_poultry_request = out_true_poultry_request.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + value_header_free_and_goverment_bar = [ + len(bar_government), + accepted_real_quantity_bar_government if accepted_real_quantity_bar_government != None else 0, + accepted_real_wight_bar_government if accepted_real_wight_bar_government != None else 0, + len(bar_government_quarantine_quantity), + accepted_real_quantity_bar_government_quarantine_quantity if accepted_real_quantity_bar_government_quarantine_quantity != None else 0, + len(bar_free), + accepted_real_quantity_bar_free if accepted_real_quantity_bar_free != None else 0, + accepted_real_wight_bar_free if accepted_real_wight_bar_free != None else 0, + len(bar_free_quarantine_quantity), + accepted_real_quantity_bar_free_quarantine_quantity if accepted_real_quantity_bar_free_quarantine_quantity != None else 0, + bar_free_has_code, + len(out_true_poultry_request), + quantity_out_true_poultry_request if quantity_out_true_poultry_request != None else 0, + + ] + for item in range(len(value_header_free_and_goverment_bar)): + cell = worksheet.cell(row=13, column=item + 2, value=value_header_free_and_goverment_bar[item]) + value = value_header_free_and_goverment_bar[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + header_list_bar_complete = [ + + 'تعداد بارتخلیه شده دامپزشک', + 'مجموع تعداد قطعه تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + + ] + header_list_bar_completex2 = [f'وزن لاشه مرغ بعد از کسر {25} % افت', + ] + header_list_bar_completex = ['تعداد بار ورودی به کشتارگاه', + 'مجموع قطعه بارهای ورودی به کشتارگاه', + 'وزن بارهای ورودی به کشتارگاه', + 'میانگین وزن', + ] + for col_num, option in enumerate(header_list_bar_completex, 2): + cell = worksheet.cell(row=16, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="F3CC85", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[16].height = 42 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list_bar_completex2, 6): + cell = worksheet.cell(row=16, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FF7979", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[16].height = 42 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list_bar_complete, 7): + cell = worksheet.cell(row=16, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="F4B083", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[16].height = 42 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + header_list_bar_complete2 = [ + 'تعداد بارهای تکمیل شده کشتارگاه', + 'مجموع تعداد قطعه نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + + ] + header_list_bar_complete2x = ['بارهای تخلیه شده فاقد کد قرنطینه', + 'قطعه بارهای تخلیه شده فاقد کد قرنطینه', + 'وزن بارهای تخلیه شده فاقد کد قرنطینه', ] + for col_num, option in enumerate(header_list_bar_complete2, 10): + cell = worksheet.cell(row=16, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="BDD6EE", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[16].height = 42 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(header_list_bar_complete2x, 13): + cell = worksheet.cell(row=16, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="AEF8FE", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[16].height = 42 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + bar_complete_with_kill_house_and_vet = filtered_kill_reqs.filter( + ware_house_confirmation=True) + bar_complete_with_vet = filtered_kill_reqs.filter( + vet_state='accepted') + accepted_real_quantity_with_kill_house_and_vet = bar_complete_with_kill_house_and_vet.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_with_kill_house_and_vet = bar_complete_with_kill_house_and_vet.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity_with_kill_house_and_vet = bar_complete_with_vet.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight_with_kill_house_and_vet = bar_complete_with_vet.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + bar_complete_with_kill_house = filtered_kill_reqs.filter(Q(ware_house_confirmation=True)| + Q(assignment_state_archive='True')) + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + accepted_real_quantity_no_code = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_no_code = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + if accepted_real_wight_with_kill_house_and_vet != None: + less_25 = (accepted_real_wight_with_kill_house_and_vet * 75) / 100 + else: + less_25 = 0 + value_header_complete_bar = [ + len(bar_complete_with_kill_house_and_vet), + accepted_real_quantity_with_kill_house_and_vet if accepted_real_quantity_with_kill_house_and_vet != None else 0, + accepted_real_wight_with_kill_house_and_vet if accepted_real_wight_with_kill_house_and_vet != None else 0, + round(accepted_real_wight_with_kill_house_and_vet / accepted_real_quantity_with_kill_house_and_vet, + 1) if accepted_real_wight_with_kill_house_and_vet != None else 0, + less_25, + len(bar_complete_with_vet), + all_vet_accepted_real_quantity_with_kill_house_and_vet if all_vet_accepted_real_quantity_with_kill_house_and_vet != None else 0, + all_vet_accepted_real_weight_with_kill_house_and_vet if all_vet_accepted_real_weight_with_kill_house_and_vet != None else 0, + len(bar_complete_with_kill_house), + accepted_real_quantity_final if accepted_real_quantity_final != None else 0, + accepted_real_wight_final if accepted_real_wight_final != None else 0, + len(filtered_kill_reqs_not_code_but_have_assigment), + accepted_real_quantity_no_code if accepted_real_quantity_no_code != None else 0, + accepted_real_wight_no_code if accepted_real_wight_no_code != None else 0, + + ] + for item in range(len(value_header_complete_bar)): + cell = worksheet.cell(row=17, column=item + 2, value=value_header_complete_bar[item]) + value = value_header_complete_bar[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + filtered_kill_reqs_not_assigment_all = filtered_kill_reqs.filter( + assignment_state_archive='pending', vet_state='pending') + + accepted_real_quantity_not_assigment_all = filtered_kill_reqs_not_assigment_all.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_not_assigment_all = filtered_kill_reqs_not_assigment_all.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + filtered_kill_reqs_havent_kill_house = filtered_kill_reqs.filter( + assignment_state_archive='pending' + , vet_state='accepted') + + accepted_real_quantity_havent_kill_house = filtered_kill_reqs_havent_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight_havent_kill_house = filtered_kill_reqs_havent_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + header_list_not_assigment = [ + 'تعداد بار تخلیه نشده', + 'مجموع قطعه بار های تخلیه نشده', + 'وزن بارهای تخلیه نشده', + ] + + for col_num, option in enumerate(header_list_not_assigment, 5): + cell = worksheet.cell(row=20, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="DA9694", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[20].height = 57 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + header_list_not_assigment2 = [ + 'بارهای تخلیه شده و عدم تکمیل توسط کشتارگاه', + 'قطعه بارهای تخلیه شده و عدم تکمیل توسط کشتارگاه', + 'وزن بارهای تخلیه شده و عدم تکمیل توسط کشتارگاه', + ] + + for col_num, option in enumerate(header_list_not_assigment2, 8): + cell = worksheet.cell(row=20, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FABF8F", fill_type="solid") + cell.font = Font(size=8, bold=True) + worksheet.row_dimensions[20].height = 57 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + value_header_list_not_assigment = [ + len(filtered_kill_reqs_not_assigment_all), + accepted_real_quantity_not_assigment_all if accepted_real_quantity_not_assigment_all != None else 0, + accepted_real_wight_not_assigment_all if accepted_real_wight_not_assigment_all != None else 0, + len(filtered_kill_reqs_havent_kill_house), + accepted_real_quantity_havent_kill_house if accepted_real_quantity_havent_kill_house != None else 0, + accepted_real_wight_havent_kill_house if accepted_real_wight_havent_kill_house != None else 0, + + ] + for item in range(len(value_header_list_not_assigment)): + cell = worksheet.cell(row=21, column=item + 5, value=value_header_list_not_assigment[item]) + value = value_header_list_not_assigment[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + accepted_real_quantity_final = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_weight_final = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + header_final = [ + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + ] + + for col_num, option in enumerate(header_final, 7): + cell = worksheet.cell(row=24, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=8, bold=True, color='FFFFFF') + worksheet.row_dimensions[24].height = 31 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + value_header_final = [ + accepted_real_quantity_final if accepted_real_quantity_final != None else 0, + accepted_real_weight_final if accepted_real_weight_final != None else 0, + + ] + for item in range(len(value_header_final)): + cell = worksheet.cell(row=25, column=item + 7, value=value_header_final[item]) + value = value_header_final[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + names_list = [] + tomorrow_date1 = date1 + timedelta(days=1) + tomorrow_date2 = date2 + timedelta(days=1) + from_date = jdatetime.date.fromgregorian( + year=tomorrow_date1.year, + month=tomorrow_date1.month, + day=tomorrow_date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + tommorow_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=tomorrow_date2.year, + month=tomorrow_date2.month, + day=tomorrow_date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + tomorrow_date_2 = separate.join(reversed_date) + kill_house_ware_houses = KillHouseWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(free_weight_of_carcasses__gt=0) | Q( + pre_cold_weight_of_carcasses_to_ware_house__gt=0), date__date__gte=tomorrow_date1, + date__date__lte=tomorrow_date2, trash=False) + for kill in kill_house_ware_houses: + if kill.kill_house.name not in names_list: + names_list.append(kill.kill_house.name) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + ware_house__in=kill_house_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + steward_allocations_for_number_of_steward = steward_allocations.filter(steward__isnull=False, + trash=False) + number_of_steward = steward_allocations_for_number_of_steward.values( + 'steward').distinct().count() if steward_allocations_for_number_of_steward else 0 + + total_pre_cold_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_number_of_carcasses_to_ware_house'))[ + 'total'] + total_pre_cold_weight = \ + kill_house_ware_houses.aggregate(total=Sum('pre_cold_weight_of_carcasses_to_ware_house'))[ + 'total'] + total_number_of_free_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('free_weight_of_carcasses'))[ + 'total'] + total_number_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = kill_house_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + kill_house_ware_houses.aggregate(total=Sum('final_total_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + kill_house_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + abc_list = ['A', 'B', 'D', 'F', 'H', 'J', 'L', 'N', 'P', 'S', 'R'] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + worksheet.row_dimensions[27].height = 47 + # worksheet.row_dimensions[3].height = 30 + # worksheet.row_dimensions[5].height = 19.04 + # worksheet.row_dimensions[8].height = 32 + + for abc in abc_list: + worksheet[f'{abc}28'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + withe_font = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['A26'] = f'اطلاعات کلی توزیع و پخش مرغ از تاریخ {tommorow_date_1} تا {tomorrow_date_2}' + worksheet['G27'] = f'توزیع از کشتارگاه به مباشر و صنف' + worksheet['A28'] = f'تعداد خریداران' + worksheet['B28'] = f'ورودی از سردخانه' + worksheet['D28'] = f'پیش سرد' + worksheet['F28'] = f'خرید خارج از استان' + worksheet['H28'] = f'بارهای روزانه' + worksheet['J28'] = f'جمع کل انبار' + worksheet['L28'] = f'توزیع شده' + worksheet['N28'] = f'توزیع / تحویل شده' + worksheet['P28'] = f'مانده انبار' + worksheet['R28'] = f'تعداد مباشر تخصیص داده شده' + worksheet['S28'] = f'تعداد صنف تخصیص داده شده' + + worksheet['G27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A26'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['B28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['D28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['H28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['J28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['L28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['N28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['P28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['R28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['S28'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range12 = 'G27:L27' + merge_range0 = 'A26:D27' + merge_range1 = 'A28:A30' + merge_range2 = 'B28:C29' + merge_range3 = 'D28:E29' + merge_range4 = 'H28:I29' + merge_range5 = 'J28:K29' + merge_range6 = 'L28:M29' + merge_range7 = 'N28:O29' + merge_range8 = 'P28:Q29' + merge_range9 = 'R28:R30' + merge_range10 = 'S28:S30' + merge_range11 = 'F28:G29' + + worksheet.merge_cells(merge_range12) + worksheet.merge_cells(merge_range0) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + worksheet.merge_cells(merge_range11) + + worksheet['A26'].font = red_font + worksheet['G27'].font = red_font + worksheet['A28'].font = withe_font + worksheet['B28'].font = withe_font + worksheet['D28'].font = withe_font + worksheet['F28'].font = withe_font + worksheet['H28'].font = withe_font + worksheet['J28'].font = withe_font + worksheet['L28'].font = withe_font + worksheet['N28'].font = withe_font + worksheet['P28'].font = withe_font + worksheet['R28'].font = withe_font + worksheet['S28'].font = withe_font + + worksheet['A28'].fill = blue + worksheet['B28'].fill = blue + worksheet['D28'].fill = blue + worksheet['F28'].fill = blue + worksheet['H28'].fill = blue + worksheet['J28'].fill = blue + worksheet['L28'].fill = blue + worksheet['N28'].fill = blue + worksheet['P28'].fill = blue + worksheet['R28'].fill = blue + worksheet['S28'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=30, column=item + 2, value=list1[item]) + worksheet.row_dimensions[30].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + head_list1 = [len(names_list) + , 0, + 0, + total_pre_cold_quantity if total_pre_cold_quantity != None else 0, + total_pre_cold_weight if total_pre_cold_weight != None else 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_steward, + number_of_guild, + + ] + for item in range(len(head_list1)): + cell = worksheet.cell(row=31, column=item + 1, value=head_list1[item]) + worksheet.row_dimensions[31].height = 12 + value = head_list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + abc_list = ['A', 'B', 'D', 'F', 'H', 'J', 'L', 'N', 'P', 'R'] + + for abc in abc_list: + worksheet[f'{abc}36'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + withe_font = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['A34'] = f'اطلاعات کلی توزیع و پخش مرغ از تاریخ {tommorow_date_1} تا {tomorrow_date_2}' + worksheet['G34'] = f'توزیع از مباشر به صنف' + worksheet['A36'] = f'تعداد خریداران' + worksheet['B36'] = f'ورودی از سردخانه' + worksheet['D36'] = f'پیش سرد' + worksheet['F36'] = f'خرید خارج از استان' + worksheet['H36'] = f'بارهای روزانه' + worksheet['J36'] = f'جمع کل انبار' + worksheet['L36'] = f'توزیع شده' + worksheet['N36'] = f'توزیع / تحویل شده' + worksheet['P36'] = f'مانده انبار' + worksheet['R36'] = f'تعداد صنف تخصیص داده شده' + + worksheet['G34'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A34'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['B36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['D36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['H36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['J36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['L36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['N36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['P36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['R36'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range12 = 'G34:L34' + merge_range0 = 'A34:D35' + merge_range1 = 'A36:A38' + merge_range2 = 'B36:C37' + merge_range3 = 'D36:E37' + merge_range4 = 'H36:I37' + merge_range5 = 'J36:K37' + merge_range6 = 'L36:M37' + merge_range7 = 'N36:O37' + merge_range8 = 'P36:Q37' + merge_range9 = 'R36:R38' + merge_range11 = 'F36:G37' + + worksheet.merge_cells(merge_range12) + worksheet.merge_cells(merge_range0) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range11) + + worksheet['A34'].font = red_font + worksheet['G34'].font = red_font + worksheet['A36'].font = withe_font + worksheet['B36'].font = withe_font + worksheet['D36'].font = withe_font + worksheet['F36'].font = withe_font + worksheet['H36'].font = withe_font + worksheet['J36'].font = withe_font + worksheet['L36'].font = withe_font + worksheet['N36'].font = withe_font + worksheet['P36'].font = withe_font + worksheet['R36'].font = withe_font + + worksheet['A36'].fill = blue + worksheet['B36'].fill = blue + worksheet['D36'].fill = blue + worksheet['F36'].fill = blue + worksheet['H36'].fill = blue + worksheet['J36'].fill = blue + worksheet['L36'].fill = blue + worksheet['N36'].fill = blue + worksheet['P36'].fill = blue + worksheet['R36'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=38, column=item + 2, value=list1[item]) + worksheet.row_dimensions[38].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + head_list1 = [number_of_steward, + 0, + 0, + 0, + 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_guild, + + ] + for item in range(len(head_list1)): + cell = worksheet.cell(row=39, column=item + 1, value=head_list1[item]) + worksheet.row_dimensions[39].height = 12 + value = head_list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش جزئیات کشتار.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def pos_excel(request): + guilds = Guilds.objects.filter(trash=False, has_pos=False) + + if 'key' in request.GET: + poss = POSMachine.objects.filter(pos_company__user__key=request.GET['key'], trash=False).select_related('user', + 'guild', + 'user__province', + 'user__city') + else: + poss = POSMachine.objects.filter(trash=False).select_related('user', 'guild', 'user__province', 'user__city') + list1 = ['مشخصات کارتخوان ها', 'اصناف'] + + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + output = BytesIO() + workbook = Workbook() + for name in list1: + min_list = [] + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000") + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + if sheet_name == 'مشخصات کارتخوان ها': + excel_options = [ + 'ردیف', + 'نام واحد صنفی', + 'نام شخص(موبایل)', + 'کد ملی', + 'نوع فعالیت', + 'حوزه فعالیت', + 'استان شهر', + 'مباشر', + 'شرکت', + 'آی دی', + 'شماره پذیرنده', + 'شماره ترمینال', + ] + + # برای بالای هدر + + worksheet['A1'] = f'گزارش مدیریت کارتخوان ها' + worksheet['A3'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 21.01 + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 7 + m = 1 + for pos in poss: + company_name = '-' + if pos.pos_company is not None: + company_name = pos.pos_company.name + + if pos.guild.steward == True: + state = 'می باشد' + else: + state = 'نمی باشد' + receiver_number = '-' + national_id = '-' + if pos.receiver_number is not None: + receiver_number = pos.receiver_number + if pos.user.national_id is not None: + national_id = pos.user.national_id + list1 = [ + m, + pos.guild.guilds_name, + pos.user.fullname + '(' + pos.user.mobile + ')', + national_id, + pos.guild.type_activity, + pos.guild.area_activity, + pos.user.province.name + '/' + pos.user.city.name, + state, + company_name, + pos.pos_id, + receiver_number, + pos.terminal_number + + ] + + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + worksheet.row_dimensions[l + 1].height = 24 + l += 1 + m += 1 + else: + worksheet['A1'] = f'گزارش مدیریت اصناف فاقد کارتخوان' + worksheet['A3'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['A3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['A1'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'A1:B1' + merge_range2 = 'A2:B2' + merge_range = 'A3:B3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['A1'].font = red_font + worksheet['A3'].font = Font(size=11) + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'نام واحد صنفی', + 'نام شخص/شرکت', + 'موبایل', + 'کد ملی', + 'نوع فعالیت', + 'حوزه فعالیت', + 'کد پستی', + 'شماره مجوز', + 'استان/شهر', + 'آدرس', + 'مباشر', + 'حداکثر تخصیص', + 'محدودیت مباشر', + 'کشتارگاه انتخابی', + 'کارتخوان دارد/ندارد', + + ] + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[4].height = 25 + worksheet.freeze_panes = worksheet['A5'] + max_col = worksheet.max_column + range_str = f'A4:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 4 + m = 1 + for guild in guilds: + postal_code = guild.address.postal_code if guild.address.postal_code else '-' + national_code = guild.user.national_code if guild.user.national_code else '-' + steward = 'می باشد' if guild.steward == True else 'نمی باشد' + max_allocation = 0 + if guild.allocation_limit: + max_allocation = guild.allocation_limit + centers_allocations = '-' + kill_house_centers_allocations = '-' + if guild.centers_allocation != None: + for center_allocation in guild.centers_allocation: + centers_allocations = center_allocation['label'] + if guild.kill_house_centers_allocation != None: + for kill_house_centers_allocation in guild.kill_house_centers_allocation: + kill_house_centers_allocations = kill_house_centers_allocation['label'] + province = '-' + if guild.user.province: + province = guild.user.province.name + city = '-' + if guild.user.city: + city = guild.user.city.name + pos = 'دارد' if guild.has_pos == True else 'ندارد' + list1 = [ + m, + guild.guilds_id, + guild.guilds_name, + guild.user.fullname, + guild.user.mobile, + national_code, + guild.type_activity, + guild.area_activity, + postal_code, + guild.license_number, + province + '-' + city, + guild.address.address, + steward, + max_allocation, + centers_allocations, + kill_house_centers_allocations, + pos + + ] + l += 1 + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + worksheet.row_dimensions[l + 1].height = 24 + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="اکسل پوز.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_and_bar_daily_report_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + now_fa_date = separate.join(reversed_date) + filtered_poultry_hatch = (PoultryHatching.objects.filter( + trash=False).select_related('poultry__user') + .only('quantity', 'killed_quantity', 'total_killed_weight', 'left_over', + 'total_commitment' + , 'governmental_quantity', 'governmental_killed_quantity', + 'losses', 'free_killed_quantity', 'free_quantity', 'out_province_killed_quantity', + 'out_province_killed_weight', 'create_date', + 'date', 'registrar', 'poultry__user__fullname', 'poultry__unit_name', + 'poultry__user__mobile', 'poultry__breeding_unique_id', 'poultry__system_code', + 'hall', 'period', 'chicken_breed', 'killed_quantity', 'total_average_killed_weight', + 'poultry__epidemiological_code', 'chicken_age', 'poultry__key') + .values('quantity', 'killed_quantity', 'total_killed_weight', 'left_over', + 'total_commitment' + , 'governmental_quantity', 'governmental_killed_quantity', + 'losses', 'free_killed_quantity', 'free_quantity', 'out_province_killed_quantity', + 'out_province_killed_weight', 'create_date', + 'date', 'registrar', 'poultry__user__fullname', 'poultry__unit_name', + 'poultry__user__mobile', 'poultry__breeding_unique_id', 'poultry__system_code', + 'hall', 'period', 'chicken_breed', 'killed_quantity', + 'total_average_killed_weight', + 'poultry__epidemiological_code', 'chicken_age', 'poultry__key')).order_by('-date') + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', 'province_request', + 'province_request__poultry_request', + 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state').values( + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date', + 'province_request', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + ) + + header_list_gt_60_header = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + header_list_between_50_60 = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + header_list_between_40_50 = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + header_list_no_license1 = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان' + + ] + + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + excel_options = { + 'آمار کشتار روزانه': [], + 'فارم بالای 60 روز': [], + 'فارم بین 50 تا 60 روز': [], + 'فارم بین 40 تا 50 روز': [], + 'تخلیه فارم بدون مجوز': [], + 'دامپزشکان فارم مغایرت قرنطینه': [], + 'عدم تخلیه دامپزشک کشتارگاه': [], + 'بار های تخلیه نشده کشتارگاه': [], + 'بار های تخلیه شده فاقد قرنطینه': [], + + } + output = BytesIO() + workbook = Workbook() + + gte_60 = filtered_poultry_hatch.filter(archive=False, + allow_hatching='pending', chicken_age__gt=60) + + between_50_60 = filtered_poultry_hatch.filter(archive=False, + allow_hatching='pending', chicken_age__gt=50, + chicken_age__lte=60) + between_40_50 = filtered_poultry_hatch.filter(archive=False, + allow_hatching='pending', chicken_age__gte=40, + chicken_age__lte=50) + + no_license1 = filtered_poultry_hatch.filter(archive=False, + allow_hatching='pending') + + filtered_kill_reqs_not_code_but_have_assigment = filtered_kill_reqs.filter( + Q(clearance_code__isnull=True) | Q(quantity__gt=F('quarantine_quantity')) | Q( + quantity__lt=F('quarantine_quantity'))) + + filtered_kill_reqs_not_assigment_but_have_code = filtered_kill_reqs.filter( + vet_state='pending') + + filtered_kill_reqs_not_assigment_but_have_code1 = filtered_kill_reqs.filter( + assignment_state_archive='pending', vet_state='pending') + + filtered_kill_reqs__assigment_but_havent_code = filtered_kill_reqs.filter(Q(assignment_state_archive='True', + vet_state='pending') | Q( + vet_state='accepted'), clearance_code__isnull=True) + + for name, options in excel_options.items(): + min_list = [] + + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000") + + for col_num, option in enumerate(options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=1, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + # worksheet.column_dimensions[col_letter].width = 20.01 + # worksheet.row_dimensions[1].height = 22 + + if sheet_name == 'فارم بالای 60 روز': + + gt_60_header = [ + 'ردیف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + + for col_num, option in enumerate(header_list_gt_60_header, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {now_fa_date} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(gt_60_header, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + all_left_over_ninty_percent = 0 + for poultry_hatching in gte_60: + l += 1 + + all_poultry_hatching_quantity += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list: + min_list.append(poultry_hatching['chicken_age']) + + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching['create_date'].day, + month=poultry_hatching['create_date'].month, + year=poultry_hatching['create_date'].year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching['date'].day, + month=poultry_hatching['date'].month, + year=poultry_hatching['date'].year + ) + # date1 = datetime.datetime.strptime(str(poultry_hatching['date']), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now().date() - poultry_hatching['date'].date()).days + 1 + + creator = '-' + if poultry_hatching['registrar']: + if poultry_hatching['registrar']['fullname'] != '': + creator = poultry_hatching['registrar']['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent += left_over_ninty_percent + list1 = [ + m, + poultry_hatching['poultry__user__fullname'], + poultry_hatching['poultry__unit_name'], + poultry_hatching['poultry__user__mobile'], + poultry_hatching['poultry__breeding_unique_id'], + poultry_hatching['poultry__system_code'], + poultry_hatching['hall'], + poultry_hatching['period'], + str(create_date), + str(date), + poultry_hatching['chicken_breed'], + age, + poultry_hatching['quantity'], + poultry_hatching['losses'], + poultry_hatching['killed_quantity'], + poultry_hatching['total_killed_weight'], + poultry_hatching['left_over'], + left_over_ninty_percent, + poultry_hatching['total_commitment'], + poultry_hatching['governmental_quantity'], + poultry_hatching['governmental_killed_quantity'], + poultry_hatching['free_quantity'], + poultry_hatching['free_killed_quantity'], + str(poultry_hatching['total_average_killed_weight']), + creator, + poultry_hatching['poultry__epidemiological_code'] if poultry_hatching[ + 'poultry__epidemiological_code'] else '-', + poultry_hatching['out_province_killed_quantity'] if poultry_hatching[ + 'out_province_killed_quantity'] > 0 else '-', + poultry_hatching['out_province_killed_weight'] if poultry_hatching[ + 'out_province_killed_weight'] > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_quantity = gte_60.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = gte_60.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = gte_60.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = gte_60.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = gte_60.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = gte_60.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = gte_60.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = gte_60.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = gte_60.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = gte_60.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = gte_60.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = gte_60.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(gte_60), + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'فارم بین 50 تا 60 روز': + + between_50_60_header = [ + 'ردیف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + + for col_num, option in enumerate(header_list_between_50_60, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {now_fa_date} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(between_50_60_header, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + for poultry_hatching in between_50_60: + l += 1 + + all_poultry_hatching_quantity += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list: + min_list.append(poultry_hatching['chicken_age']) + + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching['create_date'].day, + month=poultry_hatching['create_date'].month, + year=poultry_hatching['create_date'].year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching['date'].day, + month=poultry_hatching['date'].month, + year=poultry_hatching['date'].year + ) + # date1 = datetime.datetime.strptime(str(poultry_hatching['date']), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now().date() - poultry_hatching['date'].date()).days + 1 + + creator = '-' + if poultry_hatching['registrar']: + if poultry_hatching['registrar']['fullname'] != '': + creator = poultry_hatching['registrar']['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent += left_over_ninty_percent + list1 = [ + m, + poultry_hatching['poultry__user__fullname'], + poultry_hatching['poultry__unit_name'], + poultry_hatching['poultry__user__mobile'], + poultry_hatching['poultry__breeding_unique_id'], + poultry_hatching['poultry__system_code'], + poultry_hatching['hall'], + poultry_hatching['period'], + str(create_date), + str(date), + poultry_hatching['chicken_breed'], + age, + poultry_hatching['quantity'], + poultry_hatching['losses'], + poultry_hatching['killed_quantity'], + poultry_hatching['total_killed_weight'], + poultry_hatching['left_over'], + left_over_ninty_percent, + poultry_hatching['total_commitment'], + poultry_hatching['governmental_quantity'], + poultry_hatching['governmental_killed_quantity'], + poultry_hatching['free_quantity'], + poultry_hatching['free_killed_quantity'], + str(poultry_hatching['total_average_killed_weight']), + creator, + poultry_hatching['poultry__epidemiological_code'] if poultry_hatching[ + 'poultry__epidemiological_code'] else '-', + poultry_hatching['out_province_killed_quantity'] if poultry_hatching[ + 'out_province_killed_quantity'] > 0 else '-', + poultry_hatching['out_province_killed_weight'] if poultry_hatching[ + 'out_province_killed_weight'] > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_quantity = between_50_60.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = between_50_60.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = between_50_60.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = between_50_60.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = between_50_60.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = between_50_60.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = between_50_60.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = between_50_60.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = between_50_60.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = between_50_60.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = between_50_60.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = between_50_60.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(between_50_60), + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'فارم بین 40 تا 50 روز': + + between_40_50_header = [ + 'ردیف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + + for col_num, option in enumerate(header_list_between_40_50, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(between_40_50_header, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + for poultry_hatching in between_40_50: + l += 1 + + all_poultry_hatching_quantity += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list: + min_list.append(poultry_hatching['chicken_age']) + + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching['create_date'].day, + month=poultry_hatching['create_date'].month, + year=poultry_hatching['create_date'].year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching['date'].day, + month=poultry_hatching['date'].month, + year=poultry_hatching['date'].year + ) + # date1 = datetime.datetime.strptime(str(poultry_hatching['date']), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now().date() - poultry_hatching['date'].date()).days + 1 + + creator = '-' + if poultry_hatching['registrar']: + if poultry_hatching['registrar']['fullname'] != '': + creator = poultry_hatching['registrar']['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent += left_over_ninty_percent + list1 = [ + m, + poultry_hatching['poultry__user__fullname'], + poultry_hatching['poultry__unit_name'], + poultry_hatching['poultry__user__mobile'], + poultry_hatching['poultry__breeding_unique_id'], + poultry_hatching['poultry__system_code'], + poultry_hatching['hall'], + poultry_hatching['period'], + str(create_date), + str(date), + poultry_hatching['chicken_breed'], + age, + poultry_hatching['quantity'], + poultry_hatching['losses'], + poultry_hatching['killed_quantity'], + poultry_hatching['total_killed_weight'], + poultry_hatching['left_over'], + left_over_ninty_percent, + poultry_hatching['total_commitment'], + poultry_hatching['governmental_quantity'], + poultry_hatching['governmental_killed_quantity'], + poultry_hatching['free_quantity'], + poultry_hatching['free_killed_quantity'], + str(poultry_hatching['total_average_killed_weight']), + creator, + poultry_hatching['poultry__epidemiological_code'] if poultry_hatching[ + 'poultry__epidemiological_code'] else '-', + poultry_hatching['out_province_killed_quantity'] if poultry_hatching[ + 'out_province_killed_quantity'] > 0 else '-', + poultry_hatching['out_province_killed_weight'] if poultry_hatching[ + 'out_province_killed_weight'] > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_quantity = between_40_50.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = between_40_50.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = between_40_50.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = between_40_50.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = between_40_50.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = between_40_50.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = between_40_50.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = between_40_50.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = between_40_50.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = between_40_50.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = between_40_50.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = between_40_50.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(between_40_50), + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'تخلیه فارم بدون مجوز': + + no_license1_header = [ + 'ردیف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + + for col_num, option in enumerate(header_list_no_license1, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(no_license1_header, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + no_license3 = [] + all_quantity = 0 + all_total_killed_weight = 0 + all_total_commitment = 0 + all_governmental_quantity = 0 + all_losses = 0 + all_governmental_killed_quantity = 0 + all_free_killed_quantity = 0 + all_free_quantity = 0 + all_out_province_killed_quantity = 0 + all_out_province_killed_weight = 0 + for no_license in no_license1: + if no_license['period'] > 1: + no_licence2 = (filtered_poultry_hatch.filter(left_over__gt=F('quantity') * 0.1, + poultry__key=no_license['poultry__key'] + , period=no_license['period'] - 1)) + no_license3.append(no_licence2) + + for p in no_license3: + for poultry_hatching in p: + + all_quantity += poultry_hatching['quantity'] + all_poultry_hatching_quantity += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity += poultry_hatching['killed_quantity'] + all_total_killed_weight += poultry_hatching['total_killed_weight'] + all_poultry_hatching_left_over += poultry_hatching['left_over'] + all_total_commitment += poultry_hatching['total_commitment'] + all_governmental_quantity += poultry_hatching['governmental_quantity'] + all_governmental_killed_quantity += poultry_hatching['governmental_killed_quantity'] + all_losses += poultry_hatching['losses'] + all_free_killed_quantity += poultry_hatching['free_killed_quantity'] + all_free_quantity += poultry_hatching['free_quantity'] + all_out_province_killed_quantity += poultry_hatching['out_province_killed_quantity'] + all_out_province_killed_weight += poultry_hatching['out_province_killed_weight'] + if poultry_hatching['chicken_age'] not in min_list: + min_list.append(poultry_hatching['chicken_age']) + + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching['create_date'].day, + month=poultry_hatching['create_date'].month, + year=poultry_hatching['create_date'].year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching['date'].day, + month=poultry_hatching['date'].month, + year=poultry_hatching['date'].year + ) + # date1 = datetime.datetime.strptime(str(poultry_hatching['date']), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now().date() - poultry_hatching['date'].date()).days + 1 + + creator = '-' + if poultry_hatching['registrar']: + if poultry_hatching['registrar']['fullname'] != '': + creator = poultry_hatching['registrar']['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent += left_over_ninty_percent + list1 = [ + m, + poultry_hatching['poultry__user__fullname'], + poultry_hatching['poultry__unit_name'], + poultry_hatching['poultry__user__mobile'], + poultry_hatching['poultry__breeding_unique_id'], + poultry_hatching['poultry__system_code'], + poultry_hatching['hall'], + poultry_hatching['period'], + str(create_date), + str(date), + poultry_hatching['chicken_breed'], + age, + poultry_hatching['quantity'], + poultry_hatching['losses'], + poultry_hatching['killed_quantity'], + poultry_hatching['total_killed_weight'], + poultry_hatching['left_over'], + left_over_ninty_percent, + poultry_hatching['total_commitment'], + poultry_hatching['governmental_quantity'], + poultry_hatching['governmental_killed_quantity'], + poultry_hatching['free_quantity'], + poultry_hatching['free_killed_quantity'], + str(poultry_hatching['total_average_killed_weight']), + creator, + poultry_hatching['poultry__epidemiological_code'] if poultry_hatching[ + 'poultry__epidemiological_code'] else '-', + poultry_hatching['out_province_killed_quantity'] if poultry_hatching[ + 'out_province_killed_quantity'] > 0 else '-', + poultry_hatching['out_province_killed_weight'] if poultry_hatching[ + 'out_province_killed_weight'] > 0 else '-', + ] + m += 1 + l += 1 + + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_left_over = all_poultry_hatching_left_over + + value_header_list = [ + len(no_license3), + all_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + all_killed_quantity = all_poultry_hatching_killed_quantity + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'دامپزشکان فارم مغایرت قرنطینه': + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs_not_code_but_have_assigment.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'دامپزشکان فارمی که گواهی قرنطینه ثبت نکرده اند یا مغایرت در تعداد قطعه دارند.' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:E1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_code_but_have_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs_not_code_but_have_assigment: + for kill in filtered_kill_reqs_not_code_but_have_assigment: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_code_but_have_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_code_but_have_assigment), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'عدم تخلیه دامپزشک کشتارگاه': + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs_not_assigment_but_have_code.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + worksheet['B1'] = f'بارهای تخلیه نشده با کد قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment_but_have_code.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs_not_assigment_but_have_code: + for kill in filtered_kill_reqs_not_assigment_but_have_code: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment_but_have_code.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment_but_have_code.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_assigment_but_have_code.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بار های تخلیه نشده کشتارگاه': + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, + pk__in=filtered_kill_reqs_not_assigment_but_have_code1.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + # worksheet['B1'] = f'بارهای تخلیه نشده با کد قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_assigment_but_have_code1.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_assigment_but_have_code1.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs_not_assigment_but_have_code1: + for kill in filtered_kill_reqs_not_assigment_but_have_code1: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs_not_assigment_but_have_code1.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_assigment_but_have_code1.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_assigment_but_have_code1.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code1), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'بار های تخلیه شده فاقد قرنطینه': + + poultry_request = ( + PoultryRequest.objects.filter(trash=False, + pk__in=filtered_kill_reqs__assigment_but_havent_code.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + all_quantity = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارها', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + # worksheet['B1'] = f'بارهای تخلیه نشده با کد قرنطینه' + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs__assigment_but_havent_code.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs__assigment_but_havent_code.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs__assigment_but_havent_code: + for kill in filtered_kill_reqs__assigment_but_havent_code: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only( + 'vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user')).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + + age = (kill['province_request__poultry_request__send_date'].date() - kill[ + 'province_request__poultry_request__hatching__date'].date()).days + 1 + + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs__assigment_but_havent_code.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs__assigment_but_havent_code.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs__assigment_but_havent_code.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs__assigment_but_havent_code), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + elif sheet_name == 'آمار کشتار روزانه': + + worksheet['A2'] = f'این گزارش در مورخ {now_fa_date} صادر شده است.' + worksheet['G3'] = f'فارم های بالای 60 روز' + worksheet['G3'] = f'فارم بین 50 تا 60 روز' + worksheet['F8'] = f'فارم بین 50 تا 60 روز' + worksheet['F12'] = f'فارم بین 40 تا 50 روز' + worksheet['F17'] = f'تخلیه مرغداران بدون مجوز' + worksheet['B21'] = f' گزارش مغایرت در اطلاعات از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + worksheet['F22'] = 'بارهای دارای مغایرت یا فاقد کد قرنطینه (مسئول فنی فارم )' + worksheet['G27'] = 'بارهای تخلیه نشده توسط دامپزشک کشتارگاه' + worksheet['G32'] = 'بارهای تکمیل نشده توسط کشتارگاه' + worksheet['F37'] = 'بارهای تخلیه شده یا تکمیل شده فاقد کد قرنطینه' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F12'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F17'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['B21'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F22'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G27'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G32'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['F37'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:F2' + merge_range2 = 'G3:M3' + merge_range3 = 'F8:N8' + merge_range4 = 'F12:N12' + merge_range5 = 'F17:N17' + merge_range6 = 'B21:E22' + merge_range7 = 'F22:L22' + merge_range8 = 'G27:J27' + merge_range9 = 'G32:J32' + merge_range10 = 'F37:J37' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + worksheet['A2'].font = red_font + worksheet['B21'].font = red_font + + for col_num, option in enumerate(header_list_gt_60_header, 3): + cell = worksheet.cell(row=4, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFFF00", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[4].height = 36 + all_poultry_hatching_quantity_gte_60 = 0 + all_poultry_hatching_killed_quantity_gte_60 = 0 + all_poultry_hatching_left_over_gte_60 = 0 + all_left_over_ninty_percent_gte_60 = 0 + min_list_gte_60 = [] + + for poultry_hatching in gte_60: + + all_poultry_hatching_quantity_gte_60 += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity_gte_60 += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over_gte_60 += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list_gte_60: + min_list_gte_60.append(poultry_hatching['chicken_age']) + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent_gte_60 += left_over_ninty_percent + min_list_gte_60 = sorted(min_list_gte_60) + all_total_commitment_gte_60 = gte_60.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity_gte_60 = gte_60.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity_gte_60 = gte_60.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight_gte_60 = gte_60.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity_gte_60 = gte_60.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity_gte_60 = gte_60.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity_gte_60 = gte_60.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight_gte_60 = gte_60.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list1 = [ + len(gte_60), + all_poultry_hatching_quantity_gte_60, + all_poultry_hatching_killed_quantity_gte_60, + all_total_killed_weight_gte_60, + all_poultry_hatching_left_over_gte_60, + all_left_over_ninty_percent_gte_60, + min_list_gte_60[0] if len(min_list_gte_60) > 0 else '-', + min_list_gte_60[len(min_list) - 1] if len(min_list_gte_60) > 0 else '-', + all_total_commitment_gte_60, + all_governmental_quantity_gte_60, + all_governmental_killed_quantity_gte_60, + all_free_quantity_gte_60, + all_free_killed_quantity_gte_60, + all_out_province_killed_quantity_gte_60, + all_out_province_killed_weight_gte_60 + ] + for item in range(len(value_header_list1)): + cell = worksheet.cell(row=5, column=item + 3, value=value_header_list1[item]) + value = value_header_list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list_between_50_60, 3): + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="92CDDC", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[9].height = 37 + + all_poultry_hatching_quantity_between_50_60 = 0 + all_poultry_hatching_killed_quantity_between_50_60 = 0 + all_poultry_hatching_left_over_between_50_60 = 0 + min_list_between_50_60 = [] + all_left_over_ninty_percent_between_50_60 = 0 + for poultry_hatching in between_50_60: + + all_poultry_hatching_quantity_between_50_60 += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity_between_50_60 += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over_between_50_60 += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list_between_50_60: + min_list_between_50_60.append(poultry_hatching['chicken_age']) + + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent_between_50_60 += left_over_ninty_percent + + min_list_between_50_60 = sorted(min_list_between_50_60) + all_total_commitment_between_50_60 = between_50_60.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight_between_50_60 = between_50_60.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(between_50_60), + all_poultry_hatching_quantity_between_50_60, + all_poultry_hatching_killed_quantity_between_50_60, + all_total_killed_weight_between_50_60, + all_poultry_hatching_left_over_between_50_60, + all_left_over_ninty_percent_between_50_60, + min_list_between_50_60[0] if len(min_list_between_50_60) > 0 else '-', + min_list_between_50_60[len(min_list) - 1] if len(min_list_between_50_60) > 0 else '-', + all_total_commitment_between_50_60, + all_governmental_quantity_between_50_60, + all_governmental_killed_quantity_between_50_60, + all_free_quantity_between_50_60, + all_free_killed_quantity_between_50_60, + all_out_province_killed_quantity_between_50_60, + all_out_province_killed_weight_between_50_60 + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=10, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list_between_40_50, 3): + cell = worksheet.cell(row=13, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="92D050", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[13].height = 37 + + all_poultry_hatching_quantity_between_40_50 = 0 + all_poultry_hatching_killed_quantity_between_40_50 = 0 + all_poultry_hatching_left_over_between_40_50 = 0 + min_list_between_40_50 = [] + all_left_over_ninty_percent_between_40_50 = 0 + for poultry_hatching in between_40_50: + all_poultry_hatching_quantity_between_40_50 += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity_between_40_50 += poultry_hatching['killed_quantity'] + all_poultry_hatching_left_over_between_40_50 += poultry_hatching['left_over'] + if poultry_hatching['chicken_age'] not in min_list_between_40_50: + min_list_between_40_50.append(poultry_hatching['chicken_age']) + + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent_between_40_50 += left_over_ninty_percent + + min_list_between_40_50 = sorted(min_list_between_40_50) + + all_total_commitment_between_40_50 = between_40_50.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight_between_40_50 = between_40_50.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(between_40_50), + all_poultry_hatching_quantity_between_40_50, + all_poultry_hatching_killed_quantity_between_40_50, + all_total_killed_weight_between_40_50, + all_poultry_hatching_left_over_between_40_50, + all_left_over_ninty_percent_between_40_50, + min_list_between_40_50[0] if len(min_list_between_40_50) > 0 else '-', + min_list_between_40_50[len(min_list) - 1] if len(min_list_between_40_50) > 0 else '-', + all_total_commitment_between_40_50, + all_governmental_quantity_between_40_50, + all_governmental_killed_quantity_between_40_50, + all_free_quantity_between_40_50, + all_free_killed_quantity_between_40_50, + all_out_province_killed_quantity_between_40_50, + all_out_province_killed_weight_between_40_50 + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=14, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list_no_license1, 3): + cell = worksheet.cell(row=18, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FCD5B4", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[18].height = 37 + + all_poultry_hatching_quantity_no_license1 = 0 + all_poultry_hatching_killed_quantity_no_license1 = 0 + all_poultry_hatching_left_over_no_license1 = 0 + min_list_no_license1 = [] + all_left_over_ninty_percent_no_license1 = 0 + no_license3_no_license1 = [] + all_quantity_no_license1 = 0 + all_total_killed_weight_no_license1 = 0 + all_total_commitment_no_license1 = 0 + all_governmental_quantity_no_license1 = 0 + all_losses_no_license1 = 0 + all_governmental_killed_quantity_no_license1 = 0 + all_free_killed_quantity_no_license1 = 0 + all_free_quantity_no_license1 = 0 + all_out_province_killed_quantity_no_license1 = 0 + all_out_province_killed_weight_no_license1 = 0 + for no_license in no_license1: + if no_license['period'] > 1: + no_licence2_no_license1 = (filtered_poultry_hatch.filter(left_over__gt=F('quantity') * 0.1, + poultry__key=no_license['poultry__key'] + , period=no_license['period'] - 1)) + no_license3_no_license1.append(no_licence2_no_license1) + + for p in no_license3_no_license1: + for poultry_hatching in p: + + all_quantity_no_license1 += poultry_hatching['quantity'] + all_poultry_hatching_quantity_no_license1 += poultry_hatching['quantity'] + all_poultry_hatching_killed_quantity_no_license1 += poultry_hatching['killed_quantity'] + all_total_killed_weight_no_license1 += poultry_hatching['total_killed_weight'] + all_poultry_hatching_left_over_no_license1 += poultry_hatching['left_over'] + all_total_commitment_no_license1 += poultry_hatching['total_commitment'] + all_governmental_quantity_no_license1 += poultry_hatching['governmental_quantity'] + all_governmental_killed_quantity_no_license1 += poultry_hatching['governmental_killed_quantity'] + all_losses_no_license1 += poultry_hatching['losses'] + all_free_killed_quantity_no_license1 += poultry_hatching['free_killed_quantity'] + all_free_quantity_no_license1 += poultry_hatching['free_quantity'] + all_out_province_killed_quantity_no_license1 += poultry_hatching['out_province_killed_quantity'] + all_out_province_killed_weight_no_license1 += poultry_hatching['out_province_killed_weight'] + if poultry_hatching['chicken_age'] not in min_list_no_license1: + min_list_no_license1.append(poultry_hatching['chicken_age']) + + left_over_ninty_percent = ((poultry_hatching['quantity'] * 90) / 100) - poultry_hatching[ + 'killed_quantity'] + all_left_over_ninty_percent_no_license1 += left_over_ninty_percent + + min_list_no_license1 = sorted(min_list_no_license1) + + value_header_list = [ + len(no_license3_no_license1), + all_quantity_no_license1, + all_poultry_hatching_killed_quantity_no_license1, + all_total_killed_weight_no_license1, + all_poultry_hatching_left_over_no_license1, + all_left_over_ninty_percent_no_license1, + min_list_no_license1[0] if len(min_list_no_license1) > 0 else '-', + min_list_no_license1[len(min_list) - 1] if len(min_list_no_license1) > 0 else '-', + all_total_commitment_no_license1, + all_governmental_quantity_no_license1, + all_governmental_killed_quantity_no_license1, + all_free_quantity_no_license1, + all_free_killed_quantity_no_license1, + all_out_province_killed_quantity_no_license1, + all_out_province_killed_weight_no_license1 + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=19, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list, 4): + cell = worksheet.cell(row=23, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFC000", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[23].height = 48.8 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs_not_code_but_have_assigment.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_vet_accepted_real_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs_not_code_but_have_assigment: + for kill in filtered_kill_reqs_not_assigment_but_have_code: + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + + has_code = len(filtered_kill_reqs_not_code_but_have_assigment.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs_not_code_but_have_assigment.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len( + filtered_kill_reqs_not_code_but_have_assigment.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_code_but_have_assigment), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=24, column=item + 4, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + for col_num, option in enumerate(header_list[:4], 7): + cell = worksheet.cell(row=28, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFC000", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[28].height = 48.8 + + all_quantity_2 = 0 + + all_weighte_2 = 0 + + if filtered_kill_reqs_not_assigment_but_have_code: + for kill in filtered_kill_reqs_not_assigment_but_have_code: + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity_2 += quantity + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte_2 += weight + + has_code_2 = len(filtered_kill_reqs_not_assigment_but_have_code.filter(clearance_code__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code), + all_quantity_2, + all_weighte_2, + has_code_2, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=29, column=item + 7, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list[:4], 7): + cell = worksheet.cell(row=33, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFC000", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[33].height = 48.8 + all_quantity_3 = 0 + all_real_quantity_3 = 0 + all_net_weighte_3 = 0 + all_weighte_3 = 0 + if filtered_kill_reqs_not_assigment_but_have_code1: + for kill in filtered_kill_reqs_not_assigment_but_have_code1: + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity_3 += quantity + + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte_3 += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity_3 += real_quantity + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte_3 += weight + + has_code_3 = len(filtered_kill_reqs_not_assigment_but_have_code1.filter(clearance_code__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs_not_assigment_but_have_code1), + all_quantity_3, + all_weighte_3, + has_code_3, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=34, column=item + 7, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + for col_num, option in enumerate(header_list[:3], 7): + cell = worksheet.cell(row=38, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="FFC000", fill_type="solid") + cell.font = Font(size=9, bold=True) + worksheet.row_dimensions[38].height = 48.8 + + all_quantity_4 = 0 + + all_weighte_4 = 0 + if filtered_kill_reqs__assigment_but_havent_code: + for kill in filtered_kill_reqs__assigment_but_havent_code: + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity_4 += quantity + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte_4 += weight + value_header_list = [ + len(filtered_kill_reqs__assigment_but_havent_code), + all_quantity_4, + all_weighte_4, + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=39, column=item + 7, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش روزانه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_free_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + state = request.GET['state'] + + name_bar = '' + if request.GET['role'] == 'VetFarm': + user = SystemUserProfile.objects.get(key=request.GET['key']) + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(key=request.GET['key']) + city_operator = CityOperator.objects.get(user=user) + if state == 'pending': + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + name_bar = 'حذف/رد شده' + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + name_bar = 'حذف/رد شده' + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + if request.GET['state'] == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'جدید' + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + name_bar = 'تایید شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + name_bar = 'رد شده' + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=poultry_requests) + poultry_requests = ps.filter() + + poultry_requests_accepted = poultry_requests.filter(province_state='accepted') + + excel_options = [ + 'ردیف', + 'وضعیت', + 'پرداخت کننده', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + ' شهر خریدار', + 'استان خریدار', + 'محل کشتار', + 'کد یکتای کشتارگاه', + 'شهر محل کشتار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'تعداد در قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای {name_bar} خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + + # if ProvinceKillRequest.objects.filter( + # province_request__city_request_Poultry__poultry_request=poultry_request, + # state='accepted').exists(): + # age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + # else: + age = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + + killing_place = '-' + killing_place_city = '-' + uniq_id = '-' + if poultry_request.out_province_poultry_request_buyer: + if poultry_request.out_province_poultry_request_buyer.type == 'killhouse': + is_killer = 'کشتارگاه' + uniq_id = poultry_request.out_province_poultry_request_buyer.kill_house_unique_id if poultry_request.out_province_poultry_request_buyer.kill_house_unique_id else '-' + + else: + is_killer = 'کشتارکن' + killing_place = poultry_request.killer_kill_house_unit_name \ + if poultry_request.killer_kill_house_unit_name is not None \ + else '-' + killing_place_city = poultry_request.killer_kill_house_province \ + + '(' + poultry_request.killer_kill_house_city \ + + ')' if poultry_request.killer_kill_house_province \ + and poultry_request.killer_kill_house_city is not None \ + else '-' + uniq_id = poultry_request.kill_house_unique_id if poultry_request.kill_house_unique_id else '-' + else: + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if PoultryRequestQuarantineCode.objects.filter(trash=False,poultry_request=poultry_request).exists(): + all_quanrantine=PoultryRequestQuarantineCode.objects.filter(trash=False,poultry_request=poultry_request) + quaranatine_quantity=all_quanrantine.aggregate(total=Sum('system_quarantine_quantity'))['total'] or 0 + all_code=all_quanrantine.values_list('quarantine_code',flat=True) + code='-'.join(all_code) + elif poultry_request.quarantine_code: + code = poultry_request.quarantine_code + quaranatine_quantity = poultry_request.quarantine_quantity + has_code += 1 + else: + code = '-' + quaranatine_quantity=0 + + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + + if poultry_request.out_province_poultry_request_buyer is not None: + full_name_buyer = poultry_request.out_province_poultry_request_buyer.fullname + mobile_buyer = poultry_request.out_province_poultry_request_buyer.user.mobile + city_buyer = poultry_request.out_province_poultry_request_buyer.user.city.name + province_buyer = poultry_request.out_province_poultry_request_buyer.user.province.name + + else: + full_name_buyer = poultry_request.buyer['firstName'] + mobile_buyer = poultry_request.buyer['mobile'] + city_buyer = poultry_request.buyer['city'] + province_buyer = poultry_request.buyer['province'] + + if poultry_request.province_state == 'rejected': + state1 = 'رد شده' + elif poultry_request.province_state == 'pending' and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار تایید' + + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'در انتظار پرداخت' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == False and poultry_request.wage_pay == False and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'تایید شده' + elif poultry_request.province_state == 'accepted' and poultry_request.has_wage == True and poultry_request.wage_pay == True and poultry_request.out_province_request_cancel == False and poultry_request.out_province_request_cancel == False: + state1 = 'پرداخت شده' + else: + state1 = 'لغو شده' + + list1 = [ + m, + state1, + poultry_request.payer_fullname if poultry_request.payer_fullname else '-', + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + full_name_buyer, + mobile_buyer, + city_buyer, + province_buyer, + killing_place, + uniq_id, + killing_place_city, + poultry_request.out_province_driver_info[ + 'driverCar'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverPelak'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverName'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverMobile'] if poultry_request.out_province_driver_info != None else '-', + poultry_request.out_province_driver_info[ + 'driverhealthCode'] if poultry_request.out_province_driver_info != None else '-', + code, + quaranatine_quantity, + full_name + '(' + mobile + ')', + str(date_of_create_code), + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="بار های خارج از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def steward_ware_house_total_report_daily_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + names_list = {'اطلاعات کلی': '0'} + + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + for kill in steward_allocations: + if kill.steward_ware_house: + if kill.steward_ware_house.steward.guilds.key not in names_list.values(): + names_list.update( + {kill.steward_ware_house.steward.guilds.guilds_name: kill.steward_ware_house.steward.key}) + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + abc_list = ['A', 'B', 'C', 'D', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S'] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + number_of_steward = Steward.objects.filter( + pk__in=steward_ware_houses.values('steward') + ) + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + for name, key in names_list.items(): + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + if sheet_name == 'اطلاعات کلی': + worksheet.row_dimensions[2].height = 24 + worksheet.row_dimensions[3].height = 30 + worksheet.row_dimensions[5].height = 19.04 + worksheet.row_dimensions[8].height = 32 + + worksheet['A2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + worksheet['G2'] = f'اطلاعات کلی توزیع و پخش مرغ گرم از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'A2:D2' + merge_range123 = 'G2:N2' + worksheet.merge_cells(merge_range122) + worksheet.merge_cells(merge_range123) + + worksheet['G2'].font = Font(size=12, color='FF0000') + + for abc in abc_list: + worksheet[f'{abc}8'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + for abc in abc_list[1:]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + withe_font = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + green = PatternFill(start_color="00B050", fill_type="solid") + worksheet['B3'] = f'تعداد خریداران' + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'بارهای روزانه' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + worksheet['S3'] = f'تعداد صنف تخصیص داده شده' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['S3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + merge_range9 = 'B3:B5' + merge_range10 = 'S3:S5' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + worksheet.merge_cells(merge_range10) + + worksheet['C3'].font = withe_font + worksheet['B3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + worksheet['S3'].font = withe_font + + worksheet['B3'].fill = blue + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + worksheet['S3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + worksheet['A8'] = f'ردیف' + worksheet['B8'] = f'خریدار' + worksheet['C8'] = f'شهرستان' + worksheet['D8'] = f'تعداد صنف تخصیصی' + worksheet['E8'] = f'ورودی از سردخانه' + worksheet['G8'] = f'پیش سرد' + worksheet['I8'] = f'خرید خارج از استان' + worksheet['K8'] = f'بارهای روزانه' + worksheet['M8'] = f'جمع کل انبار' + worksheet['O8'] = f'توزیع شده' + worksheet['Q8'] = f'توزیع / تحویل شده' + worksheet['S8'] = f'مانده انبار' + + worksheet['A8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['C8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['D8'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['K8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['O8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['Q8'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['S8'].alignment = Alignment(horizontal='center', vertical='center') + + merge_range11 = 'A8:A10' + merge_range12 = 'B8:B10' + merge_range13 = 'C8:C10' + merge_range14 = 'D8:D10' + merge_range1 = 'E8:F9' + merge_range2 = 'G8:H9' + merge_range3 = 'I8:J9' + merge_range4 = 'K8:L9' + merge_range5 = 'M8:N9' + merge_range6 = 'O8:P9' + merge_range7 = 'Q8:R9' + merge_range8 = 'S8:T9' + + worksheet.merge_cells(merge_range11) + worksheet.merge_cells(merge_range12) + worksheet.merge_cells(merge_range13) + worksheet.merge_cells(merge_range14) + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + + worksheet['A8'].font = withe_font + worksheet['B8'].font = withe_font + worksheet['C8'].font = withe_font + worksheet['D8'].font = withe_font + worksheet['E8'].font = withe_font + worksheet['G8'].font = withe_font + worksheet['I8'].font = withe_font + worksheet['K8'].font = withe_font + worksheet['M8'].font = withe_font + worksheet['O8'].font = withe_font + worksheet['Q8'].font = withe_font + worksheet['S8'].font = withe_font + + worksheet['A8'].fill = green + worksheet['B8'].fill = green + worksheet['C8'].fill = green + worksheet['D8'].fill = green + worksheet['E8'].fill = blue + worksheet['G8'].fill = blue + worksheet['I8'].fill = blue + worksheet['K8'].fill = blue + worksheet['M8'].fill = blue + worksheet['O8'].fill = blue + worksheet['Q8'].fill = blue + worksheet['S8'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + for item in range(len(list1)): + cell = worksheet.cell(row=10, column=item + 5, value=list1[item]) + worksheet.row_dimensions[5].height = 28 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + head_list1 = [len(number_of_steward), + 0, + 0, + 0, + 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_guild, + + ] + for item in range(len(head_list1)): + cell = worksheet.cell(row=6, column=item + 2, value=head_list1[item]) + worksheet.row_dimensions[6].height = 12 + value = head_list1[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + l = 11 + m = 1 + for steward in number_of_steward: + steward_ware_houses = StewardWareHouse.objects.filter( + Q(weight_of_carcasses__gt=0) | Q(weight_of_free_carcasses__gt=0), date__date__gte=date1, + date__date__lte=date2, steward=steward, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + list2 = [ + m, + steward.guilds.guilds_name, + steward.guilds.address.city.name, + number_of_guild, + 0, + 0, + 0, + 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + l += 1 + m += 1 + else: + worksheet['F2'] = f'اطلاعات کلی توزیع و پخش از مباشر به صنف از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['F2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'F2:N2' + worksheet.merge_cells(merge_range122) + + worksheet['F2'].font = Font(size=10) + + for abc in abc_list[2:]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + withe_font = Font(size=12, bold=True, color='D9FFFFFF') + withe_font1 = Font(size=10, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'مجموع بارها' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + worksheet['S3'] = f'تعداد صنف تخصیص داده شده' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + worksheet['S3'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + merge_range9 = 'S3:S5' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + worksheet.merge_cells(merge_range9) + + worksheet['C3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + worksheet['S3'].font = withe_font1 + + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + worksheet['S3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + steward = Steward.objects.get(key=key, trash=False) + + steward_ware_houses = StewardWareHouse.objects.filter(date__date__gte=date1, date__date__lte=date2, + steward=steward, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + list2 = [ + 0, + 0, + 0, + 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + number_of_guild, + + ] + + for item in range(len(list2)): + cell = worksheet.cell(row=6, column=item + 3, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه تخصیص', + 'وزن لاشه تخصیصی', + 'تعداد لاشه تحویلی', + 'وزن لاشه تحویلی', + 'وضعیت', + 'کد احراز', + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[9].height = 26 + worksheet.freeze_panes = worksheet['A10'] + max_col = worksheet.max_column - 1 + range_str = f'A9:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + m = 1 + l = 10 + + steward = Steward.objects.get(key=key, trash=False) + + steward_ware_house = steward_ware_houses.filter(steward=steward) + + for s in steward_ware_house: + stewards = (StewardAllocation.objects.filter(trash=False, + steward_ware_house=s, + date__date__gte=date1, + date__date__lte=date2).select_related('guilds', + 'guilds__user', + 'guilds__address__city', + 'kill_house', + 'kill_house__kill_house_operator').order_by( + 'id')) + + if stewards.exists(): + for steward_allocation in stewards: + create_date = jdatetime.date.fromgregorian( + day=steward_allocation.create_date.day, + month=steward_allocation.create_date.month, + year=steward_allocation.create_date.year + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + if steward_allocation.receiver_state == 'pending': + reciver_type = 'در انتظار تحویل' + register = '-' + elif steward_allocation.receiver_state == 'accepted': + reciver_type = 'تحویل گرفته شد' + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else 'وارد نشده' + + else: + reciver_type = 'رد شده' + register = '-' + + list2 = [ + m, + guilds_id, + str(create_date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + steward_allocation.receiver_real_number_of_carcasses, + steward_allocation.receiver_real_weight_of_carcasses, + reciver_type, + register, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + m += 1 + l += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش پخش لاشه مرغ گرم از مباشر به صنف.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def steward_ware_house_total_report_daily_detail_excel(request): + abc_list = ['A', 'B', 'C', 'D', 'E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S'] + + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + + steward = Steward.objects.get(key=request.GET['key'], trash=False) + + steward_ware_houses = StewardWareHouse.objects.filter(date__date__gte=date1, date__date__lte=date2, + steward=steward, trash=False) + + steward_allocations = StewardAllocation.objects.filter( + Q(type='manual') | Q(type='auto', system_registration_code=True), + steward_ware_house__in=steward_ware_houses, receiver_state__in=('pending', 'accepted'), + trash=False).order_by( + 'id') + name = steward.guilds.guilds_name + + guild_allocations = steward_allocations.filter(guilds__isnull=False, trash=False) + number_of_guild = guild_allocations.values('guilds').distinct().count() if guild_allocations else 0 + + total_number_of_free_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_free_carcasses'))[ + 'total'] + total_free_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_free_carcasses'))[ + 'total'] + total_number_of_carcasses = steward_ware_houses.aggregate(total=Sum('number_of_carcasses'))[ + 'total'] + total_weight_of_carcasses = steward_ware_houses.aggregate(total=Sum('weight_of_carcasses'))[ + 'total'] + + final_total_number_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + final_total_weight_of_carcasses = \ + steward_ware_houses.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_remain_quantity = \ + steward_ware_houses.aggregate(total=Sum('remain_total_number_of_carcasses'))[ + 'total'] + + total_remain_weight = \ + steward_ware_houses.aggregate(total=Sum('remain_total_weight_of_carcasses'))[ + 'total'] + + total_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('real_number_of_carcasses'))[ + 'total'] + + total_allocated_weight = \ + steward_allocations.aggregate(total=Sum('real_weight_of_carcasses'))[ + 'total'] + + total_accepted_allocated_quantity = \ + steward_allocations.aggregate(total=Sum('receiver_real_number_of_carcasses'))[ + 'total'] + + total_accepted_allocated_weight = \ + steward_allocations.aggregate(total=Sum('receiver_real_weight_of_carcasses'))[ + 'total'] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + names_list = [steward.guilds.guilds_name] + output = BytesIO() + workbook = Workbook() + for name in names_list: + sheet_name = name + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + worksheet['F2'] = f'اطلاعات کلی توزیع و پخش مرغ گرم از تاریخ {from_date_1} تا {to_date_1}' + + worksheet['F2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range122 = 'F2:N2' + worksheet.merge_cells(merge_range122) + + worksheet['F2'].font = Font(size=10) + + for abc in abc_list[2:11]: + worksheet[f'{abc}3'].border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + withe_font = Font(size=12, bold=True, color='D9FFFFFF') + blue = PatternFill(start_color="4472C4", fill_type="solid") + worksheet['C3'] = f'ورودی از سردخانه' + worksheet['E3'] = f'پیش سرد' + worksheet['G3'] = f'خرید خارج از استان' + worksheet['I3'] = f'بارهای روزانه' + worksheet['K3'] = f'جمع کل انبار' + worksheet['M3'] = f'توزیع شده' + worksheet['O3'] = f'توزیع / تحویل شده' + worksheet['Q3'] = f'مانده انبار' + + worksheet['C3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['E3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['G3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['I3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['K3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['M3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['O3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['Q3'].alignment = Alignment(horizontal='center', vertical='center') + + merge_range1 = 'C3:D4' + merge_range2 = 'E3:F4' + merge_range3 = 'G3:H4' + merge_range4 = 'I3:J4' + merge_range5 = 'K3:L4' + merge_range6 = 'M3:N4' + merge_range7 = 'O3:P4' + merge_range8 = 'Q3:R4' + + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range2) + worksheet.merge_cells(merge_range3) + worksheet.merge_cells(merge_range4) + worksheet.merge_cells(merge_range5) + worksheet.merge_cells(merge_range6) + worksheet.merge_cells(merge_range7) + worksheet.merge_cells(merge_range8) + + worksheet['C3'].font = withe_font + worksheet['E3'].font = withe_font + worksheet['G3'].font = withe_font + worksheet['I3'].font = withe_font + worksheet['K3'].font = withe_font + worksheet['M3'].font = withe_font + worksheet['O3'].font = withe_font + worksheet['Q3'].font = withe_font + + worksheet['C3'].fill = blue + worksheet['E3'].fill = blue + worksheet['G3'].fill = blue + worksheet['I3'].fill = blue + worksheet['K3'].fill = blue + worksheet['M3'].fill = blue + worksheet['O3'].fill = blue + worksheet['Q3'].fill = blue + + list1 = [' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن', ' تعداد', + 'وزن', ' تعداد', 'وزن', ' تعداد', 'وزن'] + + for item in range(len(list1)): + cell = worksheet.cell(row=5, column=item + 3, value=list1[item]) + worksheet.row_dimensions[5].height = 19 + + cell.fill = PatternFill(start_color="FFD966", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + list2 = [ + 0, + 0, + 0, + 0, + total_number_of_free_carcasses if total_number_of_free_carcasses != None else 0, + total_free_weight_of_carcasses if total_free_weight_of_carcasses != None else 0, + total_number_of_carcasses if total_number_of_carcasses != None else 0, + total_weight_of_carcasses if total_weight_of_carcasses != None else 0, + final_total_number_of_carcasses if final_total_number_of_carcasses != None else 0, + final_total_weight_of_carcasses if final_total_weight_of_carcasses != None else 0, + total_allocated_quantity if total_allocated_quantity != None else 0, + total_allocated_weight if total_allocated_weight != None else 0, + total_accepted_allocated_quantity if total_accepted_allocated_quantity != None else 0, + total_accepted_allocated_weight if total_accepted_allocated_weight != None else 0, + total_remain_quantity if total_remain_quantity != None else 0, + total_remain_weight if total_remain_weight != None else 0, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=6, column=item + 3, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.fill = PatternFill(start_color="E9EBF5", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.font = Font(size=10, bold=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='medium'), + right=openpyxl.styles.Side(style='medium'), + top=openpyxl.styles.Side(style='medium'), + bottom=openpyxl.styles.Side(style='medium') + ) + + excel_options = [ + 'ردیف', + 'شناسه صنف', + 'تاریخ ثبت', + 'ماهیت', + 'نوع تخصیص', + 'نام واحد صنفی', + 'نام شخص', + 'کد ملی', + 'موبایل', + 'نوع فعالیت', + 'حوزه فعالیت', + 'شماره مجوز', + 'شهرستان', + 'تعداد لاشه تخصیص', + 'وزن لاشه تخصیصی', + 'تعداد لاشه تحویلی', + 'وزن لاشه تحویلی', + 'وضعیت', + 'کد احراز', + ] + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=9, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[9].height = 26 + worksheet.freeze_panes = worksheet['A10'] + max_col = worksheet.max_column + range_str = f'A9:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + m = 1 + l = 10 + + stewards = (StewardAllocation.objects.filter(trash=False, + steward_ware_house__in=steward_ware_houses, + date__date__gte=date1, date__date__lte=date2).select_related( + 'guilds', + 'guilds__user', + 'guilds__address__city', + 'kill_house', + 'kill_house__kill_house_operator').order_by( + 'id')) + + if stewards.exists(): + for steward_allocation in stewards: + create_date = jdatetime.date.fromgregorian( + day=steward_allocation.create_date.day, + month=steward_allocation.create_date.month, + year=steward_allocation.create_date.year + ) + steward = 'مباشر' if steward_allocation.seller_type == 'steward' else 'صنف' + sell_type = 'اختصاصی' if steward_allocation.sell_type == 'exclusive' else 'آزاد' + type = 'دستی' if steward_allocation.type == 'manual' else 'اتوماتیک' + try: + guilds_name = steward_allocation.steward.guilds.guilds_name + guilds_id = steward_allocation.steward.guilds.guilds_id + fullname = steward_allocation.steward.guilds.user.fullname + national_id = steward_allocation.steward.guilds.user.national_id + mobile = steward_allocation.steward.guilds.user.mobile + type_activity = steward_allocation.steward.guilds.type_activity + area_activity = steward_allocation.steward.guilds.area_activity + license_number = steward_allocation.steward.guilds.license_number + city_name = steward_allocation.steward.guilds.address.city.name + except: + guilds_name = steward_allocation.guilds.guilds_name + guilds_id = steward_allocation.guilds.guilds_id + fullname = steward_allocation.guilds.user.fullname + national_id = steward_allocation.guilds.user.national_id + mobile = steward_allocation.guilds.user.mobile + type_activity = steward_allocation.guilds.type_activity + area_activity = steward_allocation.guilds.area_activity + license_number = steward_allocation.guilds.license_number + city_name = steward_allocation.guilds.address.city.name + if steward_allocation.receiver_state == 'pending': + reciver_type = 'در انتظار تحویل' + register = '-' + elif steward_allocation.receiver_state == 'accepted': + reciver_type = 'تحویل گرفته شد' + register = steward_allocation.logged_registration_code if steward_allocation.logged_registration_code else 'وارد نشده' + + else: + reciver_type = 'رد شده' + register = '-' + + list2 = [ + m, + guilds_id, + str(create_date), + steward, + f'{sell_type}({type})', + guilds_name, + fullname, + national_id, + mobile, + type_activity, + area_activity, + license_number, + city_name, + steward_allocation.number_of_carcasses, + steward_allocation.weight_of_carcasses, + steward_allocation.receiver_real_number_of_carcasses, + steward_allocation.receiver_real_weight_of_carcasses, + reciver_type, + register, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + m += 1 + l += 1 + workbook.remove_sheet(workbook.get_sheet_by_name('Sheet')) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="{name} در تاریخ {str(now)}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_by_age_range(request): + min_age = request.GET.get('min_age') + max_age = request.GET.get('max_age') + + # فیلتر اولیه برای تمام داده‌ها + base_filtered_poultry_hatch = PoultryHatching.objects.filter( + Q(left_over__gt=F('quantity') * percent_of_losses) | Q(violation=True), + trash=False + ).select_related('poultry', 'poultry__user') + + # تفکیک فعال‌ها: فیلتر براساس now_age (سن روز) + active_poultry_hatch = base_filtered_poultry_hatch.filter( + archive=False, + allow_hatching='pending' + ) + if min_age and max_age: + # محاسبه now_age برای هر رکورد و فیلتر + active_list = [] + for hatching in active_poultry_hatch: + now_age = (datetime.datetime.now().date() - hatching.date.date()).days + 1 + if int(min_age) <= now_age <= int(max_age): + active_list.append(hatching.id) + active_poultry_hatch = active_poultry_hatch.filter(id__in=active_list) + active_poultry_hatch = active_poultry_hatch.order_by('-date') + + # تفکیک بایگانی‌ها: فیلتر براساس chicken_age (سن بایگانی) با همان min_age و max_age + archive_poultry_hatch = base_filtered_poultry_hatch.filter( + archive=True, + allow_hatching='True' + ) + if min_age and max_age: + archive_poultry_hatch = archive_poultry_hatch.filter( + chicken_age__gte=int(min_age), + chicken_age__lte=int(max_age) + ) + archive_poultry_hatch = archive_poultry_hatch.order_by('-archive_date') + + excel_options = [ + 'ردیف', + 'وضعیت فارم', + 'وضعیت تخلف', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'شهرستان', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن بایگانی', + 'سن روز', + 'تعداد جوجه ریزی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'یازده درصد جوجه ریزی', + 'تعداد تخلف', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + 'دلیل تخلف', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(datetime.datetime.now().date()) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_names = ['فعال', 'بایگانی'] + sheets_data = [ + {'name': 'فعال', 'data': active_poultry_hatch, 'is_archive': False}, + {'name': 'بایگانی', 'data': archive_poultry_hatch, 'is_archive': True} + ] + + for sheet_info in sheets_data: + sheet_name = sheet_info['name'] + filtered_data = sheet_info['data'] + is_archive = sheet_info['is_archive'] + + worksheet = workbook.create_sheet(sheet_name) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد فارم', + 'تعداد فارم فعال', + 'تعداد فارم بایگانی شده', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کشتارشده', + 'جمع کل مانده در سالن(قطعه)', + 'جمع مانده در سال فارم فعال(قطعه)', + 'جمع مانده در سالن فارم بایگانی(قطعه)', + 'کمترین سن ', + 'بیشترین سن ', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های فعال متخلف', + 'تعداد فارم های بایگانی متخلف', + ] + + create_header(worksheet, header_list, 5, 2, height=20) + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است. بین بازه سنی {min_age} تا {max_age}' + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + worksheet.merge_cells(merge_range1) + worksheet['B2'].font = red_font + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22, width=20.1, different_cell='تعداد تخلف') + + l = 6 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation_count = 0 + len_archive_hatch = 0 + len_hatch = 0 + left_over_archive = 0 + left_over_active = 0 + all_eleven_percent = 0 + + for poultry_hatching in filtered_data: + now_age = (datetime.datetime.now().date() - poultry_hatching.date.date()).days + 1 + + reason = 'مانده بیش از حد مجاز در سالن' + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + + age = poultry_hatching.chicken_age + if age not in min_list: + min_list.append(age) + + if now_age not in min_list: + min_list.append(now_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + + if is_archive: + state = 'بایگانی' + len_archive_hatch += 1 + left_over_archive += poultry_hatching.left_over + else: + state = 'فعال' + len_hatch += 1 + left_over_active += poultry_hatching.left_over + creator = 'پنجره واحد' + left_over_ninty_percent = (poultry_hatching.quantity * percent_of_losses) + eleven_percent = (poultry_hatching.left_over - (poultry_hatching.quantity * percent_of_losses)) + all_left_over_ninty_percent += left_over_ninty_percent + all_eleven_percent += eleven_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + violation_count += 1 + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + + list1 = [ + m, + state, + farm_state, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.user.city.name, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + now_age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + eleven_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + reason, + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[2] == 'متخلف': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + + min_list = sorted(min_list) + all_quantity = filtered_data.aggregate(total_quantity=Sum('quantity')).get('total_quantity', 0) + all_losses = filtered_data.aggregate(total_quantity=Sum('losses')).get('total_quantity', 0) + all_direct_losses = filtered_data.aggregate(total_quantity=Sum('direct_losses')).get('total_quantity', 0) + all_total_losses = filtered_data.aggregate(total_quantity=Sum('total_losses')).get('total_quantity', 0) + all_killed_quantity = filtered_data.aggregate(total_quantity=Sum('killed_quantity')).get('total_quantity', 0) + all_left_over_total = filtered_data.aggregate(total_quantity=Sum('left_over')).get('total_quantity', 0) + all_total_commitment = filtered_data.aggregate(total_quantity=Sum('total_commitment')).get('total_quantity', 0) + all_governmental_killed_quantity = filtered_data.aggregate(total_quantity=Sum('governmental_killed_quantity')).get('total_quantity', 0) + all_free_killed_quantity = filtered_data.aggregate(total_quantity=Sum('free_killed_quantity')).get('total_quantity', 0) + all_total_killed_weight = filtered_data.aggregate(total_quantity=Sum('total_killed_weight')).get('total_quantity', 0) + all_governmental_quantity = filtered_data.aggregate(total_quantity=Sum('governmental_quantity')).get('total_quantity', 0) + all_free_quantity = filtered_data.aggregate(total_quantity=Sum('free_quantity')).get('total_quantity', 0) + all_out_province_killed_quantity = filtered_data.aggregate(total_quantity=Sum('out_province_killed_quantity')).get('total_quantity', 0) + all_out_province_killed_weight = filtered_data.aggregate(total_quantity=Sum('out_province_killed_weight')).get('total_quantity', 0) + + violation_count_in_filter = filtered_data.filter(violation=True).count() + + value_header_list = [ + len(filtered_data), + len_hatch, + len_archive_hatch, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + left_over_archive, + left_over_active, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + 0 if is_archive else violation_count_in_filter, + violation_count_in_filter if is_archive else 0 + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', + all_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over_total, + all_left_over_ninty_percent, + all_eleven_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', '', '', '', + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' + else: + cell.value = value + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" جوجه ریزی های متخلف بین بازه سنی {min_age} تا {max_age}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_for_detail_killing_excel(request): + filtered_poultry_hatch = PoultryHatching.objects.filter(trash=False, + left_over__gt=F('quantity') * percent_of_losses, + chicken_age__range=(55, 90)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + excel_options = [ + 'ردیف', + 'وضعیت فارم فعال/بایگانی', + 'وضعیت فارم', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'مانده در سالن از نود درصد', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد فارم', + 'تعداد فارم فعال', + 'تعداد فارم بایگانی شده', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کشتارشده', + 'جمع کل مانده در سالن(قطعه)', + 'جمع مانده در سال فارم فعال(قطعه)', + 'جمع مانده در سالن فارم بایگانی(قطعه)', + 'کمترین سن ', + 'بیشترین سن ', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های فعال متخلف', + 'تعداد فارم های بایگانی متخلف', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + len_archive_hatch = 0 + len_hatch = 0 + left_over_archive = 0 + left_over = 0 + for poultry_hatching in filtered_poultry_hatch: + age = '-' + if poultry_hatching.archive == True and poultry_hatching.allow_hatching == 'True': + if poultry_hatching.last_change: + date1 = datetime.datetime.strptime((poultry_hatching.last_change['date'].split(' ')[0]), + '%Y-%m-%d').date() + age = (date1 - poultry_hatching.date.date()).days + 1 + len_archive_hatch += 1 + left_over_archive += poultry_hatching.left_over + state = 'بایگانی' + elif poultry_hatching.archive == False and poultry_hatching.allow_hatching == 'pending': + age = (datetime.datetime.now().date() - poultry_hatching.date.date()).days + 1 + len_hatch += 1 + left_over += poultry_hatching.left_over + state = "فعال" + else: + state = '' + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) - poultry_hatching.killed_quantity + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'پیگیری' + violation += 1 + + list1 = [ + m, + state, + farm_state, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[2] == 'متخلف': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + cell.alignment = Alignment(horizontal='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + violation_archive = len(filtered_poultry_hatch.filter(violation=True, archive=True, allow_hatching='True')) + violation_active = len( + filtered_poultry_hatch.filter(violation=True, archive=False, allow_hatching='pending')) + value_header_list = [ + len(filtered_poultry_hatch), + len_hatch, + len_archive_hatch, + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + left_over_archive, + left_over, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation_active, + violation_archive + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="فارم های متخلف بین 55تا 90 روز.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_live_stock_support_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__freezing=True).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی منجمد' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارها(پشتیبانی امور دام).xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def successful_transactions_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if "date1" in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if "date2" in request.GET else now + if 'key' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='completed', + transaction_type='wage-gateway', + trash=False).order_by('id') + else: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + transaction_type='wage-gateway', + trash=False).order_by('id') + + excel_options = [ + 'ردیف', + 'تاریخ و زمان', + 'پرداخت کننده', + 'تعداد سفارشات', + 'تعداد کل(قطعه)', + 'وزن کل(کیلوگرم)', + 'شماره درخواست', + 'شماره پیگیری', + 'کد سفارش', + 'شماره کارت', + 'قیمت(ریال)', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + for transaction in transactions: + total_weight = 0 + total_quantity = 0 + total_request = 0 + wage_payment = WagePayment.objects.filter( + Q(orderId=transaction.orderId) | Q(tracking_code=transaction.saleReferenceId), + trash=False).first() + if wage_payment.province_kill_request != None: + total_request = len(wage_payment.province_kill_request) + for province_kill_req in wage_payment.province_kill_request: + province_kill = ProvinceKillRequest.objects.get(key=province_kill_req, trash=False) + total_weight += province_kill.total_killed_weight + total_quantity += province_kill.total_killed_quantity + date = transaction.date + date_create = convert_to_shamsi(datetime=date) + list1 = [ + m, + str(date_create), + transaction.payer, + total_request, + total_quantity, + total_weight, + str(transaction.refId) if transaction.refId != None else '-', + str(transaction.saleReferenceId) if transaction.saleReferenceId != None else '-', + str(transaction.orderId) if transaction.orderId != None else '-', + str(transaction.cardHolderPan) if transaction.cardHolderPan != None else '-', + transaction.amount + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 29 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های موفق.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def unsuccessful_transactions_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() if "date1" in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() if "date2" in request.GET else now + if 'key' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status='failed', + transaction_type='wage-gateway', + trash=False).order_by('id') + else: + transactions = ExternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='failed', + transaction_type='wage-gateway', + trash=False).order_by('id') + + excel_options = [ + 'ردیف', + 'تاریخ و زمان', + 'پرداخت کننده', + 'تعداد سفارشات', + 'تعداد کل(قطعه)', + 'وزن کل(کیلوگرم)', + 'شماره درخواست', + 'شماره پیگیری', + 'کد سفارش', + 'شماره کارت', + 'قیمت(ریال)', + 'متن خطا', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + for transaction in transactions: + total_weight = 0 + total_quantity = 0 + total_request = 0 + wage_payment = WagePayment.objects.filter( + Q(orderId=transaction.orderId) | Q(tracking_code=transaction.saleReferenceId), + trash=False).first() + if wage_payment.province_kill_request != None: + total_request = len(wage_payment.province_kill_request) + for province_kill_req in wage_payment.province_kill_request: + province_kill = ProvinceKillRequest.objects.get(key=province_kill_req, trash=False) + total_weight += province_kill.total_killed_weight + total_quantity += province_kill.total_killed_quantity + date = transaction.date + date_create = convert_to_shamsi(datetime=date) + message = transaction.message + if message == 'ﻛﺎرﺑﺮ_از_اﻧﺠﺎم_ﺗﺮاﻛﻨﺶ_ﻣﻨﺼﺮف_ﺷﺪه_اﺳﺖ': + message = 'ﻛﺎرﺑﺮ از اﻧﺠﺎم ﺗﺮاﻛﻨﺶ ﻣﻨﺼﺮف ﺷﺪه اﺳﺖ' + + list1 = [ + m, + str(date_create), + transaction.payer, + total_request, + total_quantity, + total_weight, + str(transaction.refId) if transaction.refId != None else '-', + str(transaction.saleReferenceId) if transaction.saleReferenceId != None else '-', + str(transaction.orderId) if transaction.orderId != None else '-', + str(transaction.cardHolderPan) if transaction.cardHolderPan != None else '-', + transaction.amount, + message + ] + m += 1 + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 29 + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="تراکنش های ناموفق.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_hatching_between_50age_70age_excel(request): + filtered_poultry_hatch = PoultryHatching.objects.filter(trash=False, left_over__gt=F('quantity') * 0.1, + chicken_age__range=(55, 90)).order_by('id') + + excel_options = [ + 'ردیف', + 'وضعیت فارم', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد فارم فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + # worksheet['A1'] = f' وضعیت پرونده ها' + worksheet['B2'] = f'این گزارش در مورخ {from_date_1} صادر شده است.' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B2:C3' + # merge_range2 = 'B2:C2' + + worksheet.merge_cells(merge_range1) + # worksheet.merge_cells(merge_range2) + worksheet['B2'].font = red_font + + # cell = worksheet.cell(row=1, column=1) + # cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + for poultry_hatching in filtered_poultry_hatch: + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + violation += 1 + + list1 = [ + m, + farm_state, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[1] == 'متخلف': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + cell.alignment = Alignment(horizontal='center') + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + value_header_list = [ + len(filtered_poultry_hatch), + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کلی فارم های فعال مرغ گوشتی دارای مانده در سالن بیشتر از 10 درصد و بازه سنی 55 تا 90 روزه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def number_of_times_with_quarantine_code_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + clearance_code__isnull=False).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای دارای کد قرنطینه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای دارای کد قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def the_burden_of_quarantine_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + quarantine_quantity__isnull=False).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای احراز شده از قرنطینه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای احراز شده از قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_without_quarantine_code_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter(trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + clearance_code__isnull=True).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای فاقد کد قرنطینه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای فاقد کد قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def loads_that_differ_in_quarantine_and_cooperation_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(quantity__gt=F('quarantine_quantity')) | Q(quantity__lt=F('quarantine_quantity')), trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهایی که در قرنطینه و رصدیار اختلاف دارند' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهایی که در قرنطینه و تعاون اختلاف دارند.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def government_burden_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__free_sale_in_province=False, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بار دولتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بار دولتی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def goverment_bar_state_with_a_certified_quarantine_code_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__free_sale_in_province=False, quarantine_quantity__isnull=False, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بار دولتی دارای کد قرنطینه احراز شده' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بار دولتی دارای کد قرنطینه احراز شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def free_loads_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__free_sale_in_province=True, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای آزاد' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای آزاد.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def free_cargoes_obtained_from_quarantine_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__free_sale_in_province=True, quarantine_quantity__isnull=False, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای آزاد احراز شده از قرنطینه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای آزاد احراز شده از قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def free_loads_with_quarantine_code_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + province_request__poultry_request__free_sale_in_province=True, clearance_code__isnull=False, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای آزاد دارای کد قرنطینه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای آزاد دارای کد قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def loads_outside_the_province_excel(request): + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() if 'date2' in request.GET else now + + poultry_requests = (PoultryRequest.objects.filter(trash=False, out=True, province_state='accepted', + out_province_request_cancel=False + , send_date__date__gte=date1 + , send_date__date__lte=date2).order_by( + '-send_date').select_related('poultry', 'poultry__user', 'hatching')) + + poultry_requests_accepted = poultry_requests.filter(province_state='accepted') + + excel_options = [ + 'ردیف', + 'کدسفارش مرغدار', + ' تاریخ ثبت درخواست', + ' تاریخ کشتار', + ' کشتار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + ' استان مرغدار', + 'سن مرغ', + ' نژاد', + 'تعداد درخواست', + 'میانگین وزنی', + 'وزن درخواست', + 'مانده در سالن', + 'جوجه ریزی اولیه', + + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' شهر خریدار', + ' استان خریدار', + + 'نوع خودرو', + 'پلاک', + + 'نام راننده', + 'موبایل راننده', + 'کد بهداشتی حمل و نقل', + + 'کد رهگیری سامانه قرنطینه', + 'ثبت کننده کد قرنطینه', + 'تاریخ ثبت کد قرنطینه', + 'وضعیت', + 'سازنده', + + ] + + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای تایید شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'کمترین سن مرغ', + 'بیشترین سن مرغ', + 'تعداد بارهای دارای کد قرنطینه', + + ] + for col_num, option in enumerate(header_list, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای خارج از استان' + if poultry_requests.exists(): + name = poultry_requests.first().poultry.user.province.name + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 6 + m = 1 + + all_weighte = 0 + all_chicken_quantity = 0 + all_age = [] + all_quantity = poultry_requests_accepted.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + + all_weighte = poultry_requests_accepted.aggregate( + total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] + + has_code = 0 + if poultry_requests: + for poultry_request in poultry_requests: + age = (poultry_request.send_date.date() - poultry_request.hatching.date.date()).days + 1 + all_age.append(age) + all_chicken_quantity += poultry_request.hatching.quantity + create_date_of_poultry_request = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + date_of_kill_request = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + if poultry_request.quarantine_code_registrar is not None: + date_code = poultry_request.quarantine_code_registrar['date'].split('-') + + date_of_create_code = jdatetime.date.fromgregorian( + day=int(date_code[2]), + month=int(date_code[1]), + year=int(date_code[0]) + ) + full_name = poultry_request.quarantine_code_registrar['fullname'] + mobile = poultry_request.quarantine_code_registrar['mobile'] + else: + date_of_create_code = '-' + full_name = '-' + mobile = '-' + is_killer = 'کشتارگاه' if poultry_request.buyer is not None and poultry_request.buyer[ + 'buyerType'] == 'killhouse' else 'کشتارکن' + if poultry_request.quarantine_code: + code = poultry_request.quarantine_code + has_code += 1 + else: + code = '-' + + if poultry_request.province_state == 'pending': + state = 'در انتظار تایید' + elif poultry_request.province_state == 'accepted': + state = 'تایید شده' + else: + state = 'حذف شده' + freez_state = 'منجمد' if poultry_request.freezing == True else 'عادی' + list1 = [ + m, + str(poultry_request.order_code), + str(create_date_of_poultry_request), + str(date_of_kill_request), + freez_state, + poultry_request.poultry.user.fullname, + poultry_request.poultry.user.mobile, + poultry_request.poultry.user.city.name, + poultry_request.poultry.user.province.name, + age, + poultry_request.hatching.chicken_breed, + poultry_request.quantity, + poultry_request.Index_weight, + int(poultry_request.quantity * poultry_request.Index_weight), + poultry_request.hatching.left_over, + poultry_request.hatching.quantity, + is_killer, + poultry_request.buyer['firstName'], + poultry_request.buyer['mobile'], + poultry_request.buyer['city'], + poultry_request.buyer['province'], + poultry_request.out_province_driver_info['driverCar'], + poultry_request.out_province_driver_info['driverPelak'], + poultry_request.out_province_driver_info['driverName'], + poultry_request.out_province_driver_info['driverMobile'], + poultry_request.out_province_driver_info['driverhealthCode'], + code, + full_name + '(' + mobile + ')', + str(date_of_create_code), + state, + poultry_request.registrar['fullname'] if poultry_request.registrar else '-' + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + l += 1 + + # last_age=sorted(reversed(all_age)) + all_age = sorted(all_age) + value_header_list2 = [ + len(poultry_requests_accepted), + all_quantity if all_quantity != None else 0, + all_weighte if all_weighte != None else 0, + all_age[0] if len(all_age) > 0 else None, + all_age[len(all_age) - 1] if len(all_age) > 0 else None, + has_code, + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity if all_quantity != None else 0, + '', + all_weighte, + '', + all_chicken_quantity, + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="بار های خارج از استان.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def loads_entering_the_slaughterhouse_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + ware_house_confirmation=True, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ورودی به کشتارگاه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای ورودی به کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def veterinarian_unloaded_load_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + vet_state='accepted', trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تخلیه شده دامپزشک' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت تخلیه شده دامپزشک.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def completed_slaughterhouse_loads_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + assignment_state_archive='True', trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تکمیل شده کشتارگاه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تکمیل شده کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def unloaded_cargo_without_quarantine_code_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + Q(assignment_state_archive='True', vet_state='pending') + | Q(vet_state='accepted'), clearance_code__isnull=True, trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تخلیه شده فاقد کد قرنطینه ' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تخلیه شده فاقد کد قرنطینه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def unloaded_load_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + assignment_state_archive='pending', vet_state='pending', trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تخلیه نشده' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تخلیه نشده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def loads_unloaded_and_not_completed_by_the_slaughterhouse_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + filtered_kill_reqs = KillHouseRequest.objects.filter( + assignment_state_archive='pending' + , vet_state='accepted', trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values( + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', 'province_request__poultry_request__hatching__date' + ) + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای تخلیه شده و عدم تکمیل توسط کشتارگاه' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] != None else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] != None else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای تخلیه شده و عدم تکمیل توسط کشتارگاه.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_date_range_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + filtered_poultry_hatch = PoultryHatching.objects.filter(date__date__gte=date1, date__date__lte=date2, archive=False, + allow_hatching='pending', + trash=False).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + excel_options = [ + 'ردیف', + 'وضعیت فارم', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + + from_date_1 = shamsi_date(date1) + from_date_2 = shamsi_date(date2) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'جوجه ریزی های فعال از تاریخ {from_date_1} تا {from_date_2}', color='red', + row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = poultry_hatching.chicken_age + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(وجود فارم فعال دیگر)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + + list1 = [ + m, + farm_state, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جوجه ریزی در بازه تاریخی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def wallete_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(key=request.GET['key']) + transactions = ExternalTransaction.objects.filter(type__isnull=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house_user=user, + status__in=('completed', 'failed'), + transaction_type='wallet', + trash=False).order_by('id') + + excel_options = [ + 'ردیف', + 'وضعیت پرداختی', + 'تاریخ و زمان', + 'پرداخت کننده', + 'شماره درخواست', + 'شماره پیگیری', + 'کدسفارش', + 'شماره کارت', + 'مبلغ', + 'متن خطا', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + from_date2 = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date2.split("-")) + separate = "-" + from_date_2 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد تراکنش ها', + 'تعداد تراکنش های موفق', + 'مبلغ تراکنش های موفق', + 'تعداد تراکنش های ناموفق', + 'مبلغ تراکنش های ناموفق', + + ] + + for col_num, option in enumerate(header_list, 5): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20 + + worksheet['B2'] = f'گزارش کیف پول کشتارگاه از تاریخ {from_date_1} تا {from_date_2}' + + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'B2:D3' + worksheet.merge_cells(merge_range1) + worksheet['B2'].font = red_font + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[6].height = 22 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + l = 5 + m = 1 + + for transaction in transactions: + l += 1 + state = 'موفق' if transaction.status == 'completed' else 'ناموفق' + date = convert_to_shamsi( + datetime=transaction.date + ) + list1 = [ + m, + state, + date, + transaction.payer, + transaction.orderId, + transaction.saleReferenceId if transaction.saleReferenceId is not None else '-', + transaction.orderId, + transaction.cardHolderPan if transaction.cardHolderPan is not None else '-', + transaction.amount, + transaction.message if transaction.message is not None else '-', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[1] == 'ناموفق': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + complete_trans = transactions.filter(status='completed') + complete_trans_amount = complete_trans.aggregate( + total_quantity=Sum('amount')).get( + 'total_quantity') or 0 + failed_trans = transactions.filter(status='failed') + failed_trans_amount = failed_trans.aggregate( + total_quantity=Sum('amount')).get( + 'total_quantity') or 0 + value_header_list = [ + m - 1, + len(complete_trans), + complete_trans_amount, + len(failed_trans), + failed_trans_amount, + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 5, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="گزارش کیف پول.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def kill_house_request_suspended_load_excel(request): + date1 = datetime.datetime.strptime(str(request.GET['start']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['end']), '%Y-%m-%d').date() + filtered_kill_request = KillHouseRequest.objects.filter( + Q(trash=False) | Q(trash=True, clearance_code__isnull=False), + + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, vet_state='pending', assignment_state_archive='pending').order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('message', 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date').values('message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date' + ) + if 'key' in request.GET: + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__user__city=user.city) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + filtered_kill_reqs = filtered_kill_request.filter( + province_request__poultry_request__poultry__in=poultries) + + elif request.GET['role'] == 'KillHouse': + filtered_kill_reqs = filtered_kill_request.filter(killhouse_user=user) + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + else: + filtered_kill_reqs = filtered_kill_request + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + ' محل کشتار ', + 'نوع تخصیص', + + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + + ] + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + to_date = jdatetime.date.fromgregorian( + year=date2.year, + month=date2.month, + day=date2.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(to_date.split("-")) + separate = "-" + to_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای معلق در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate(total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter(poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + all_quantity += quantity + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = assignment.get('net_weight') + all_net_weighte += net_weighte + real_quantity = assignment.get('real_quantity') + all_real_quantity += real_quantity + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = kill['vet_accepted_real_weight'] if kill['vet_accepted_real_weight'] else '-' + + weight = kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight') + all_weighte += weight + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + elif kill['quarantine_code_state'] == 'merge': + quarantine_quantity = 'ادغام' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + kill['accepted_real_weight'], + state_delete, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + + value_header_list = [ + len(filtered_kill_reqs), + all_quantity, + all_weighte, + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + len(bar_complete), + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0 + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + total_requests_weight + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + all_weighte, + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + all_vet_accepted_real_weight, + all_real_quantity, + all_net_weighte, + accepted_real_quantity if accepted_real_quantity != None else 0, + accepted_real_wight if accepted_real_wight != None else 0, + '' + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int, float)): + cell.number_format = '#,##0' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + name = filtered_kill_request.first()['killhouse_user__name'] + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت بارهای کشتارگاه {name}.xlsx"'.encode( + 'utf-8') + else: + response[ + 'Content-Disposition'] = f'attachment; filename=" مدیریت بارها معلق.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def chain_excel(request): + chain = ChainCompany.objects.filter(trash=False) + + excel_options = [ + 'ردیف', + 'نام شرکت', + 'نام مدیرعامل', + 'نام خانوادگی مدیرعامل', + 'موبایل', + 'شهر', + 'آدرس', + 'کد پستی', + + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 26.01 + worksheet.row_dimensions[3].height = 25 + worksheet.freeze_panes = worksheet['A4'] + max_col = worksheet.max_column + range_str = f'A3:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + worksheet['A2'] = f'مدیریت شرکت های استان {chain.first().address.province.name}' + + worksheet['A2'].font = Font(color="C00000", bold=True) + worksheet['A2'].alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + merge_range1 = 'A2:B2' + + worksheet.merge_cells(merge_range1) + l = 2 + m = 1 + + for user in chain: + + list1 = [ + m, + user.name, + user.user.first_name, + user.user.last_name, + user.user.mobile, + user.address.city.name, + user.address.address, + user.address.postal_code, + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + m += 1 + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت شرکت ها.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def test_excel(request): + start_excel() + return close_excel('nima') + + +def test_all_excel_functions(request): + from panel.VetFarm.excel_processing import technical_responsible_performance_excel, totoal_technical_responsible_performance_excel + from panel.ProvinceOperator.excel_processing import ( + kill_house_total_transactions_wage_payid_super_admin_excel, kill_house_total_transactions_wage_payid_excel, + payment_transactions_province_excel, general_free_bar_excel, out_province_poultry_request_buyers_excel, + chain_company_buyers_excel, bar_chain_excel, kill_house_total_transactions_wage_payid_admin_x_excel, + buy_outside_the_province_excel, poultry_request_report_excel, transacion_out_request_excel, + from_allocation_to_distribution_excel, login_user_excel, city_operator_for_sub_sector_excel, + vet_for_sub_sector_excel, guild_for_sub_sector_excel, all_guilds_transaction_excel, + detail_guilds_transaction_excel, management_hatching_excel, user_without_role_excel, + sub_section_of_cooperative_share_detail_with_date_excel, vet_for_sub_sector_with_date_excel, + dashboard_monitoring_bar_and_killing_excel, steward_allocation_excel, + sevrence_kill_house_steward_allocation_excel, free_sale_out_province_excel, + steward_free_sale_out_province_excel, total_steward_dashboard_excel, + detail_of_killing_and_warehouse_excel, market_requests_excel, return_province_request_excel, + guilds_without_allocation_excel + ) + from panel.poultry.excel_processing import ( + hatching_excel, archive_hatching_excel, hatching_age_range_excel, poultry_monitoring_excel, + poultry_hatching_prediction_chart_excel, hatching_report_from_age_excel, + poultry_hatching_prediction_excel, bar_difference_reques_excel + ) + from panel.KillHouse.excel_processing import ( + direct_purchase_excel, direct_purchase_archive_excel, kill_house_assignment_information_excel, + kill_house_user_excel, bar_excel, kill_house_total_wage_excel, slaughterhouse_export_excel, + export_kill_house_excel, monitor_loads_excel, kill_house_free_bar_excel, + comprehensive_report_of_the_slaughterhouse_excel, out_province_carcasses_buyer_kill_house_excel, + kill_house_free_sale_bar_information_for_excel_excel, kill_house_free_sale_bar_information_excel, + notentered_bars_for_kill_house_excel, entered_bars_for_kill_house_excel, + kill_house_free_bar_entered_for_warehouse_excel, kill_house_free_bar_carcasses_for_warehouse_excel, + steward_allocation_for_warehouse_excel, cold_house_excel, management_cold_house_excel, + create_guilds_or_stewards_from_excel, non_receipt_request_excel, return_kill_house_request_excel, + warehouse_archive_combined_excel + ) + from helper_eata import token, chat_id + from django.http import QueryDict + + class MockRequest: + def __init__(self, get_params=None): + if get_params: + self.GET = QueryDict(get_params) + else: + self.GET = QueryDict() + self.FILES = {} + self.data = {} + if adminx_user: + self.user = adminx_user.user + else: + self.user = None + + adminx_user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + adminx_key = adminx_user.key if adminx_user else None + adminx_token = None + if adminx_user: + access_token = AccessToken.objects.filter(user=adminx_user.user).first() + adminx_token = access_token.token if access_token else None + + today = datetime.datetime.now().date() + date1 = today - timedelta(days=1) + date2 = today + + date1_str = date1.strftime('%Y-%m-%d') + date2_str = date2.strftime('%Y-%m-%d') + + def add_params(base_params, use_start_end=False, use_date1_date2=False, use_token=False): + params = base_params.copy() if base_params else {} + if adminx_key: + params['key'] = adminx_key + params['role'] = 'AdminX' + if use_token and adminx_token: + params['token'] = adminx_token + if use_start_end: + params['start'] = date1_str + params['end'] = date2_str + elif use_date1_date2: + params['date1'] = date1_str + params['date2'] = date2_str + else: + params['date1'] = date1_str + params['date2'] = date2_str + return params + + excel_functions = [ + # (vet_check_excel, add_params({}, use_start_end=True)), + (kill_house_request_excel, add_params({}, use_start_end=True)), + # (request_report_excel, add_params({}, use_date1_date2=True)), + (allocated_excel, add_params({}, use_start_end=True)), + (allocated_trash_true_excel, add_params({}, use_start_end=True)), + (poultry_kill_request_excel, add_params({'token': adminx_token} if adminx_token else {}, use_start_end=True)), + (car_allocation_excel, add_params({}, use_start_end=True)), + (guilds_excel, add_params({})), + # (commerce_report_excel, add_params({}, use_start_end=True)), + # (commerce_bar_excel, add_params({}, use_start_end=True)), + (number_of_kills_weight_excel, add_params({'day': 1})), + (number_of_kills_excel, add_params({'day': 1})), + (single_hatching_age_range_excel, add_params({})), + # (total_poultry_request_dashboard_excel, add_params({})), + (total_poultry_hatching_dashboard_excel, add_params({})), + # (doughnut_left_hatching_excel, add_params({}, use_token=True)), + # (doughnut_hatching_excel, add_params({}, use_token=True)), + (forecast_hatching_left_over_excel, add_params({'age': 60})), + (manager_of_farm_excel, add_params({})), + (kill_house__request_vet_killing_process_excel, add_params({})), + (kill_house_percent_excel, add_params({})), + # (poultry_request_out_excel, add_params({'date': date1_str})), + (get_all_user_excel, add_params({})), + (stewards_excel, add_params({})), + (all_kill_house_total_wage_excel, add_params({'token': adminx_token})), + (kill_house_total_wage_not_payid_excel, add_params({'token': adminx_token})), + (slaughterhouse_fee_excel, add_params({})), + (slaughterhouse_fee_not_paid_excel, add_params({})), + (car_province_excel, add_params({})), + (kill_house_wage_archive_excel, add_params({})), + (kill_house_total_wage_archive_excel, add_params({})), + (bar_management_kill_house_excel, add_params({})), + (all_inventory_excel, add_params({})), + (daily_process_excel, add_params({})), + (daily_process_klling_proccess_excel, add_params({'date': date1_str})), + (killing_process_from_date_excel, add_params({}, use_start_end=True)), + (discrepancy_report_excel, add_params({})), + # (bar_for_each_persion_excel, add_params({'code': 'test_code'})), + # (poultry_excel, add_params({}, use_start_end=True)), + (bar_contradiction_of_quarantine_excel, add_params({}, use_start_end=True)), + (detail_of_killing_excel, add_params({})), + # (pos_excel, add_params({})), + (poultry_and_bar_daily_report_excel, add_params({})), + (bar_free_excel, add_params({'state': 'pending'})), + (steward_ware_house_total_report_daily_excel, add_params({})), + # (steward_ware_house_total_report_daily_detail_excel, add_params({}, use_date1_date2=True)), + (hatching_for_detail_killing_excel, add_params({})), + (bar_live_stock_support_excel, add_params({}, use_start_end=True)), + (successful_transactions_excel, add_params({})), + (unsuccessful_transactions_excel, add_params({})), + (poultry_hatching_between_50age_70age_excel, add_params({})), + (number_of_times_with_quarantine_code_excel, add_params({})), + (the_burden_of_quarantine_excel, add_params({})), + (bar_without_quarantine_code_excel, add_params({})), + (loads_that_differ_in_quarantine_and_cooperation_excel, add_params({})), + (government_burden_excel, add_params({})), + (goverment_bar_state_with_a_certified_quarantine_code_excel, add_params({})), + (free_loads_excel, add_params({})), + (free_cargoes_obtained_from_quarantine_excel, add_params({})), + (free_loads_with_quarantine_code_excel, add_params({})), + # (loads_outside_the_province_excel, add_params({})), + (loads_entering_the_slaughterhouse_excel, add_params({})), + (veterinarian_unloaded_load_excel, add_params({})), + (completed_slaughterhouse_loads_excel, add_params({})), + (unloaded_cargo_without_quarantine_code_excel, add_params({})), + (unloaded_load_excel, add_params({})), + (loads_unloaded_and_not_completed_by_the_slaughterhouse_excel, add_params({})), + (hatching_date_range_excel, add_params({}, use_date1_date2=True)), + (wallete_excel, add_params({})), + (kill_house_request_suspended_load_excel, add_params({}, use_start_end=True)), + # (chain_excel, add_params({})), + # (technical_responsible_performance_excel, add_params({})), + # (totoal_technical_responsible_performance_excel, add_params({}, use_date1_date2=True)), + (kill_house_total_transactions_wage_payid_super_admin_excel, add_params({})), + (kill_house_total_transactions_wage_payid_excel, add_params({})), + (payment_transactions_province_excel, add_params({})), + (general_free_bar_excel, add_params({})), + (out_province_poultry_request_buyers_excel, add_params({})), + (chain_company_buyers_excel, add_params({})), + (bar_chain_excel, add_params({'state': 'accepted'}, use_date1_date2=True)), + (kill_house_total_transactions_wage_payid_admin_x_excel, add_params({})), + (buy_outside_the_province_excel, add_params({})), + (poultry_request_report_excel, add_params({}, use_start_end=True)), + (transacion_out_request_excel, add_params({'type': 'poultry'}, use_date1_date2=True)), + (from_allocation_to_distribution_excel, add_params({})), + (login_user_excel, add_params({})), + (city_operator_for_sub_sector_excel, add_params({'type': 'city'})), + (vet_for_sub_sector_excel, add_params({'type': 'vet'})), + (guild_for_sub_sector_excel, add_params({'type': 'guild'}, use_date1_date2=True)), + (all_guilds_transaction_excel, add_params({})), + # (detail_guilds_transaction_excel, add_params({}, use_date1_date2=True)), + (management_hatching_excel, add_params({})), + (user_without_role_excel, add_params({})), + # (sub_section_of_cooperative_share_detail_with_date_excel, add_params({}, use_date1_date2=True)), + (vet_for_sub_sector_with_date_excel, add_params({}, use_date1_date2=True)), + (dashboard_monitoring_bar_and_killing_excel, add_params({})), + (steward_allocation_excel, add_params({})), + # (sevrence_kill_house_steward_allocation_excel, add_params({'type':'KillHouse'})), + (free_sale_out_province_excel, add_params({'type': 1})), + (steward_free_sale_out_province_excel, add_params({})), + (total_steward_dashboard_excel, add_params({})), + (detail_of_killing_and_warehouse_excel, add_params({})), + (market_requests_excel, add_params({})), + (return_province_request_excel, add_params({})), + (guilds_without_allocation_excel, add_params({})), + (hatching_excel, add_params({})), + (archive_hatching_excel, add_params({})), + (hatching_age_range_excel, add_params({})), + # (poultry_monitoring_excel, add_params({})), + # (poultry_hatching_prediction_chart_excel, add_params({})), + (hatching_report_from_age_excel, add_params({'age1': 50, 'age2': 60})), + # (poultry_hatching_prediction_excel, add_params({})), + # (bar_difference_reques_excel, add_params({'state':'pending'})), + (direct_purchase_excel, add_params({}, use_date1_date2=True)), + (direct_purchase_archive_excel, add_params({}, use_date1_date2=True)), + # (kill_house_assignment_information_excel, add_params({}, use_start_end=True)), + (kill_house_user_excel, add_params({})), + (bar_excel, add_params({}, use_start_end=True)), + (kill_house_total_wage_excel, add_params({})), + # (slaughterhouse_export_excel, add_params({}, use_date1_date2=True)), + (export_kill_house_excel, add_params({})), + (monitor_loads_excel, add_params({})), + (kill_house_free_bar_excel, add_params({'type': 'all'}, use_date1_date2=True)), + (comprehensive_report_of_the_slaughterhouse_excel, add_params({})), + # (out_province_carcasses_buyer_kill_house_excel, add_params({})), + # (kill_house_free_sale_bar_information_for_excel_excel, add_params({})), + # (kill_house_free_sale_bar_information_excel, add_params({}, use_date1_date2=True)), + (notentered_bars_for_kill_house_excel, add_params({})), + (entered_bars_for_kill_house_excel, add_params({})), + (kill_house_free_bar_entered_for_warehouse_excel, add_params({'type': 'all', 'bar_state': 'entered'})), + (kill_house_free_bar_carcasses_for_warehouse_excel, add_params({'type': 'all', 'bar_state': 'carcasses'})), + (steward_allocation_for_warehouse_excel, add_params({})), + # (cold_house_excel, add_params({}, use_date1_date2=True)), + (management_cold_house_excel, add_params({})), + (non_receipt_request_excel, add_params({})), + (return_kill_house_request_excel, add_params({})), + (warehouse_archive_combined_excel, add_params({})), + ] + + failed_functions = [] + + for func, params in excel_functions: + try: + if params: + query_string = '&'.join([f'{k}={v}' for k, v in params.items()]) + mock_request = MockRequest(query_string) + else: + mock_request = MockRequest() + response = func(mock_request) + if not response or not isinstance(response, HttpResponse): + failed_functions.append(func.__name__) + except Exception as e: + failed_functions.append(func.__name__) + + if failed_functions: + url = f'https://eitaayar.ir/api/{token}/sendMessage' + message = f'❌ توابع اکسل که خطا داشتند:\n\n' + message += f'❌ استان:{base_url_for_sms_report}\n\n' + for func_name in failed_functions: + + message += f'• {func_name}\n' + + data = { + 'chat_id': 10046800, + 'text': message, + } + requests.post(url, data=data, verify=False) + + return HttpResponse(f'تست انجام شد. تعداد توابع با خطا: {len(failed_functions)}') + + +def test_all_excel_functions_cron(): + from panel.VetFarm.excel_processing import technical_responsible_performance_excel, totoal_technical_responsible_performance_excel + from panel.ProvinceOperator.excel_processing import ( + kill_house_total_transactions_wage_payid_super_admin_excel, kill_house_total_transactions_wage_payid_excel, + payment_transactions_province_excel, general_free_bar_excel, out_province_poultry_request_buyers_excel, + chain_company_buyers_excel, bar_chain_excel, kill_house_total_transactions_wage_payid_admin_x_excel, + buy_outside_the_province_excel, poultry_request_report_excel, transacion_out_request_excel, + from_allocation_to_distribution_excel, login_user_excel, city_operator_for_sub_sector_excel, + vet_for_sub_sector_excel, guild_for_sub_sector_excel, all_guilds_transaction_excel, + detail_guilds_transaction_excel, management_hatching_excel, user_without_role_excel, + sub_section_of_cooperative_share_detail_with_date_excel, vet_for_sub_sector_with_date_excel, + dashboard_monitoring_bar_and_killing_excel, steward_allocation_excel, + sevrence_kill_house_steward_allocation_excel, free_sale_out_province_excel, + steward_free_sale_out_province_excel, total_steward_dashboard_excel, + detail_of_killing_and_warehouse_excel, market_requests_excel, return_province_request_excel, + guilds_without_allocation_excel + ) + from panel.poultry.excel_processing import ( + hatching_excel, archive_hatching_excel, hatching_age_range_excel, poultry_monitoring_excel, + poultry_hatching_prediction_chart_excel, hatching_report_from_age_excel, + poultry_hatching_prediction_excel, bar_difference_reques_excel + ) + from panel.KillHouse.excel_processing import ( + direct_purchase_excel, direct_purchase_archive_excel, kill_house_assignment_information_excel, + kill_house_user_excel, bar_excel, kill_house_total_wage_excel, slaughterhouse_export_excel, + export_kill_house_excel, monitor_loads_excel, kill_house_free_bar_excel, + comprehensive_report_of_the_slaughterhouse_excel, out_province_carcasses_buyer_kill_house_excel, + kill_house_free_sale_bar_information_for_excel_excel, kill_house_free_sale_bar_information_excel, + notentered_bars_for_kill_house_excel, entered_bars_for_kill_house_excel, + kill_house_free_bar_entered_for_warehouse_excel, kill_house_free_bar_carcasses_for_warehouse_excel, + steward_allocation_for_warehouse_excel, cold_house_excel, management_cold_house_excel, + create_guilds_or_stewards_from_excel, non_receipt_request_excel, return_kill_house_request_excel, + warehouse_archive_combined_excel + ) + from helper_eata import token, chat_id + from django.http import QueryDict + + class MockRequest: + def __init__(self, get_params=None): + if get_params: + self.GET = QueryDict(get_params) + else: + self.GET = QueryDict() + self.FILES = {} + self.data = {} + if adminx_user: + self.user = adminx_user.user + else: + self.user = None + + adminx_user = SystemUserProfile.objects.filter(trash=False, role__name='AdminX').first() + adminx_key = adminx_user.key if adminx_user else None + adminx_token = None + if adminx_user: + access_token = AccessToken.objects.filter(user=adminx_user.user).first() + adminx_token = access_token.token if access_token else None + + today = datetime.datetime.now().date() + date1 = today - timedelta(days=1) + date2 = today + + date1_str = date1.strftime('%Y-%m-%d') + date2_str = date2.strftime('%Y-%m-%d') + + def add_params(base_params, use_start_end=False, use_date1_date2=False, use_token=False): + params = base_params.copy() if base_params else {} + if adminx_key: + params['key'] = adminx_key + params['role'] = 'AdminX' + if use_token and adminx_token: + params['token'] = adminx_token + if use_start_end: + params['start'] = date1_str + params['end'] = date2_str + elif use_date1_date2: + params['date1'] = date1_str + params['date2'] = date2_str + else: + params['date1'] = date1_str + params['date2'] = date2_str + return params + + excel_functions = [ + # (vet_check_excel, add_params({}, use_start_end=True)), + (kill_house_request_excel, add_params({}, use_start_end=True)), + # (request_report_excel, add_params({}, use_date1_date2=True)), + (allocated_excel, add_params({}, use_start_end=True)), + (allocated_trash_true_excel, add_params({}, use_start_end=True)), + (poultry_kill_request_excel, add_params({'token': adminx_token} if adminx_token else {}, use_start_end=True)), + (car_allocation_excel, add_params({}, use_start_end=True)), + (guilds_excel, add_params({})), + # (commerce_report_excel, add_params({}, use_start_end=True)), + # (commerce_bar_excel, add_params({}, use_start_end=True)), + (number_of_kills_weight_excel, add_params({'day': 1})), + (number_of_kills_excel, add_params({'day': 1})), + (single_hatching_age_range_excel, add_params({})), + # (total_poultry_request_dashboard_excel, add_params({})), + (total_poultry_hatching_dashboard_excel, add_params({})), + # (doughnut_left_hatching_excel, add_params({}, use_token=True)), + # (doughnut_hatching_excel, add_params({}, use_token=True)), + (forecast_hatching_left_over_excel, add_params({'age': 60})), + (manager_of_farm_excel, add_params({})), + (kill_house__request_vet_killing_process_excel, add_params({})), + (kill_house_percent_excel, add_params({})), + # (poultry_request_out_excel, add_params({'date': date1_str})), + (get_all_user_excel, add_params({})), + (stewards_excel, add_params({})), + (all_kill_house_total_wage_excel, add_params({'token': adminx_token})), + (kill_house_total_wage_not_payid_excel, add_params({'token': adminx_token})), + (slaughterhouse_fee_excel, add_params({})), + (slaughterhouse_fee_not_paid_excel, add_params({})), + (car_province_excel, add_params({})), + (kill_house_wage_archive_excel, add_params({})), + (kill_house_total_wage_archive_excel, add_params({})), + (bar_management_kill_house_excel, add_params({})), + (all_inventory_excel, add_params({})), + (daily_process_excel, add_params({})), + (daily_process_klling_proccess_excel, add_params({'date': date1_str})), + (killing_process_from_date_excel, add_params({}, use_start_end=True)), + (discrepancy_report_excel, add_params({})), + # (bar_for_each_persion_excel, add_params({'code': 'test_code'})), + # (poultry_excel, add_params({}, use_start_end=True)), + (bar_contradiction_of_quarantine_excel, add_params({}, use_start_end=True)), + (detail_of_killing_excel, add_params({})), + # (pos_excel, add_params({})), + (poultry_and_bar_daily_report_excel, add_params({})), + (bar_free_excel, add_params({'state': 'pending'})), + (steward_ware_house_total_report_daily_excel, add_params({})), + # (steward_ware_house_total_report_daily_detail_excel, add_params({}, use_date1_date2=True)), + (hatching_for_detail_killing_excel, add_params({})), + (bar_live_stock_support_excel, add_params({}, use_start_end=True)), + (successful_transactions_excel, add_params({})), + (unsuccessful_transactions_excel, add_params({})), + (poultry_hatching_between_50age_70age_excel, add_params({})), + (number_of_times_with_quarantine_code_excel, add_params({})), + (the_burden_of_quarantine_excel, add_params({})), + (bar_without_quarantine_code_excel, add_params({})), + (loads_that_differ_in_quarantine_and_cooperation_excel, add_params({})), + (government_burden_excel, add_params({})), + (goverment_bar_state_with_a_certified_quarantine_code_excel, add_params({})), + (free_loads_excel, add_params({})), + (free_cargoes_obtained_from_quarantine_excel, add_params({})), + (free_loads_with_quarantine_code_excel, add_params({})), + # (loads_outside_the_province_excel, add_params({})), + (loads_entering_the_slaughterhouse_excel, add_params({})), + (veterinarian_unloaded_load_excel, add_params({})), + (completed_slaughterhouse_loads_excel, add_params({})), + (unloaded_cargo_without_quarantine_code_excel, add_params({})), + (unloaded_load_excel, add_params({})), + (loads_unloaded_and_not_completed_by_the_slaughterhouse_excel, add_params({})), + (hatching_date_range_excel, add_params({}, use_date1_date2=True)), + (wallete_excel, add_params({})), + (kill_house_request_suspended_load_excel, add_params({}, use_start_end=True)), + # (chain_excel, add_params({})), + # (technical_responsible_performance_excel, add_params({})), + # (totoal_technical_responsible_performance_excel, add_params({}, use_date1_date2=True)), + (kill_house_total_transactions_wage_payid_super_admin_excel, add_params({})), + (kill_house_total_transactions_wage_payid_excel, add_params({})), + (payment_transactions_province_excel, add_params({})), + (general_free_bar_excel, add_params({})), + (out_province_poultry_request_buyers_excel, add_params({})), + (chain_company_buyers_excel, add_params({})), + (bar_chain_excel, add_params({'state': 'accepted'}, use_date1_date2=True)), + (kill_house_total_transactions_wage_payid_admin_x_excel, add_params({})), + (buy_outside_the_province_excel, add_params({})), + (poultry_request_report_excel, add_params({}, use_start_end=True)), + (transacion_out_request_excel, add_params({'type': 'poultry'}, use_date1_date2=True)), + (from_allocation_to_distribution_excel, add_params({})), + (login_user_excel, add_params({})), + (city_operator_for_sub_sector_excel, add_params({'type': 'city'})), + (vet_for_sub_sector_excel, add_params({'type': 'vet'})), + (guild_for_sub_sector_excel, add_params({'type': 'guild'}, use_date1_date2=True)), + (all_guilds_transaction_excel, add_params({})), + # (detail_guilds_transaction_excel, add_params({}, use_date1_date2=True)), + (management_hatching_excel, add_params({})), + (user_without_role_excel, add_params({})), + # (sub_section_of_cooperative_share_detail_with_date_excel, add_params({}, use_date1_date2=True)), + (vet_for_sub_sector_with_date_excel, add_params({}, use_date1_date2=True)), + (dashboard_monitoring_bar_and_killing_excel, add_params({})), + (steward_allocation_excel, add_params({})), + # (sevrence_kill_house_steward_allocation_excel, add_params({'type':'KillHouse'})), + (free_sale_out_province_excel, add_params({'type': 1})), + (steward_free_sale_out_province_excel, add_params({})), + (total_steward_dashboard_excel, add_params({})), + (detail_of_killing_and_warehouse_excel, add_params({})), + (market_requests_excel, add_params({})), + (return_province_request_excel, add_params({})), + (guilds_without_allocation_excel, add_params({})), + (hatching_excel, add_params({})), + (archive_hatching_excel, add_params({})), + (hatching_age_range_excel, add_params({})), + # (poultry_monitoring_excel, add_params({})), + # (poultry_hatching_prediction_chart_excel, add_params({})), + (hatching_report_from_age_excel, add_params({'age1': 50, 'age2': 60})), + # (poultry_hatching_prediction_excel, add_params({})), + # (bar_difference_reques_excel, add_params({'state':'pending'})), + (direct_purchase_excel, add_params({}, use_date1_date2=True)), + (direct_purchase_archive_excel, add_params({}, use_date1_date2=True)), + # (kill_house_assignment_information_excel, add_params({}, use_start_end=True)), + (kill_house_user_excel, add_params({})), + (bar_excel, add_params({}, use_start_end=True)), + (kill_house_total_wage_excel, add_params({})), + # (slaughterhouse_export_excel, add_params({}, use_date1_date2=True)), + (export_kill_house_excel, add_params({})), + (monitor_loads_excel, add_params({})), + (kill_house_free_bar_excel, add_params({'type': 'all'}, use_date1_date2=True)), + (comprehensive_report_of_the_slaughterhouse_excel, add_params({})), + # (out_province_carcasses_buyer_kill_house_excel, add_params({})), + # (kill_house_free_sale_bar_information_for_excel_excel, add_params({})), + # (kill_house_free_sale_bar_information_excel, add_params({}, use_date1_date2=True)), + (notentered_bars_for_kill_house_excel, add_params({})), + (entered_bars_for_kill_house_excel, add_params({})), + (kill_house_free_bar_entered_for_warehouse_excel, add_params({'type': 'all', 'bar_state': 'entered'})), + (kill_house_free_bar_carcasses_for_warehouse_excel, add_params({'type': 'all', 'bar_state': 'carcasses'})), + (steward_allocation_for_warehouse_excel, add_params({})), + # (cold_house_excel, add_params({}, use_date1_date2=True)), + (management_cold_house_excel, add_params({})), + (non_receipt_request_excel, add_params({})), + (return_kill_house_request_excel, add_params({})), + (warehouse_archive_combined_excel, add_params({})), + ] + + failed_functions = [] + + for func, params in excel_functions: + try: + if params: + query_string = '&'.join([f'{k}={v}' for k, v in params.items()]) + mock_request = MockRequest(query_string) + else: + mock_request = MockRequest() + response = func(mock_request) + if not response or not isinstance(response, HttpResponse): + failed_functions.append(func.__name__) + except Exception as e: + failed_functions.append(func.__name__) + + if failed_functions: + url = f'https://eitaayar.ir/api/{token}/sendMessage' + message = f'❌ توابع اکسل که خطا داشتند:\n\n' + message += f'❌ استان:{base_url_for_sms_report}\n\n' + for func_name in failed_functions: + + message += f'• {func_name}\n' + + data = { + 'chat_id': 10046800, + 'text': message, + } + requests.post(url, data=data, verify=False) diff --git a/panel/filterset.py b/panel/filterset.py new file mode 100644 index 0000000..e7038eb --- /dev/null +++ b/panel/filterset.py @@ -0,0 +1,646 @@ +from url_filter.filtersets import ModelFilterSet +from django_filters import rest_framework as filters + +from django.contrib.auth.models import User + +from LiveStock.models import Cooperative +from authentication.models import UserProfile, SystemUserProfile +from panel.models import (CityOperatorCheckRequest, PoultryRequestExchange, Poultry, ProvinceOperator, + KillHouse, Vet, KillHouseOperator, CityOperator, KillHouseDriver, InspectorOperator, + PoultryHatching, Guilds, KillHouseRequest, ProvinceKillRequest, PoultryRequest, KillRequest, + WagePayment, ChainAllocation, InternalTransaction, ChainCompany, KillHouseFreeBarInformation, + OutProvincePoultryRequestBuyer, ReportsUsers, Dispenser, StewardAllocation, + OutProvinceCarcassesBuyer, KillHouseFreeSaleBarInformation, BaseOutProvinceCarcassesBuyer, + ColdHouseAllocations, ColdHouse, SubSectorTransactions, StewardFreeBarInformation, + PosSegmentation, PosMachineTransactions, BarDifferenceRequest, POSDeviceSession, + HatchingIncreaseRequest, CommonlyUsed, StewardFreeSaleBarInformation, DirectBuyingPayment, + PoultryScience, PoultryScienceReport, WarehouseArchive, POSMachine, EvacuationHatchingDetail, + DispenserInformation, Representative) +from authentication.models import City + +# test +from ticket.models import TicketSupport + + +class CityOperatorRequestFilterSet(ModelFilterSet): + class Meta: + model = CityOperatorCheckRequest + + +class CityOperatorFilterSet(ModelFilterSet): + class Meta: + model = CityOperator + + +class PoultryRequestExchangeFilterSet(ModelFilterSet): + class Meta: + model = PoultryRequestExchange + + +class PoultryRequestFilterSet(ModelFilterSet): + class Meta: + model = PoultryRequest + + +class OutProvincePoultryRequestBuyerFilterSet(ModelFilterSet): + class Meta: + model = OutProvincePoultryRequestBuyer + + +class PoultryFilterSet(ModelFilterSet): + class Meta: + model = Poultry + + +class ChainCompanyFilterSet(ModelFilterSet): + class Meta: + model = ChainCompany + + +class ChainAllocationFilterSet(ModelFilterSet): + class Meta: + model = ChainAllocation + + +class InternalTransactionFilterSet(ModelFilterSet): + class Meta: + model = InternalTransaction + + +class DispenserAllocationFilterSet(ModelFilterSet): + class Meta: + model = StewardAllocation + + +class StewardAllocationFilterSet(ModelFilterSet): + class Meta: + model = StewardAllocation + + +class StewardAllocationDashboardFilterSet(filters.FilterSet): + class Meta: + model = StewardAllocation + fields = [ + 'guilds__user__first_name', + 'guilds__user__last_name', + 'guilds__user__fullname', + 'guilds__user__mobile', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__fullname', + 'steward__user__mobile', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'to_guilds__user__first_name', + 'to_guilds__user__last_name', + 'to_guilds__user__fullname', + 'to_guilds__user__mobile', + 'to_steward__user__first_name', + 'to_steward__user__last_name', + 'to_steward__user__fullname', + 'to_steward__user__mobile', + 'to_kill_house__kill_house_operator__user__first_name', + 'to_kill_house__kill_house_operator__user__last_name', + 'to_kill_house__kill_house_operator__user__fullname', + 'to_kill_house__kill_house_operator__user__mobile', + 'to_kill_house__name', + ] + + +class StewardFreeBarInformationFilterSet(ModelFilterSet): + class Meta: + model = StewardFreeBarInformation + + +class StewardFreeSaleBarInformationFilterSet(ModelFilterSet): + class Meta: + model = StewardFreeSaleBarInformation + fields = [ + 'steward__user__fullname', + 'steward__user__first_name', + 'steward__user__last_name', + 'steward__user__mobile', + 'buyer__user__fullname', + 'buyer__user__first_name', + 'buyer__user__last_name', + 'buyer__user__mobile', + 'province', + 'city', + 'province' + 'buyer_name' + 'buyer_mobile' + + ] + + +class PosSegmentationFilterSet(ModelFilterSet): + class Meta: + model = PosSegmentation + + +class PosMachineTransactionsFilterSet(ModelFilterSet): + class Meta: + model = PosMachineTransactions + + +class POSMachineFilterSet(ModelFilterSet): + class Meta: + model = POSMachine + + +class ColdHouseFilterSet(ModelFilterSet): + class Meta: + model = ColdHouse + + +class ColdHouseAllocationsFilterSet(ModelFilterSet): + class Meta: + model = ColdHouseAllocations + + +class DispenserFilterSet(ModelFilterSet): + class Meta: + model = Dispenser + + +class RepresentativeFilterSet(ModelFilterSet): + class Meta: + model = Representative + + +class DispenserInformationFilterSet(ModelFilterSet): + class Meta: + model = DispenserInformation + + +class ReportsUsersFilterSet(ModelFilterSet): + class Meta: + model = ReportsUsers + + +class CooperativeFilterSet(ModelFilterSet): + class Meta: + model = Cooperative + fields = [ + 'user__fullname', + 'user__mobile', + 'name', + 'mobile', + ] + + +class GuildsFilterSet(filters.FilterSet): + kill_house = filters.ModelMultipleChoiceFilter( + queryset=KillHouse.objects.all(), + field_name='kill_house', + to_field_name='id' + ) + + # stewards = filters.ModelMultipleChoiceFilter( + # queryset=Guilds.objects.all(), + # field_name='stewards', + # to_field_name='id' + # ) + + class Meta: + model = Guilds + fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__city__name', + 'user__national_code', + 'user__national_id', + 'user__province__name', + 'address__city__name', + 'guilds_name', + 'type_activity', + 'area_activity', + 'guilds_id', + 'license_number', + 'kill_house__name', + 'stewards__user__mobile', + 'stewards__user__first_name', + 'stewards__user__last_name', + ] + + +class TestGuildsFilterSet(filters.FilterSet): + kill_house = filters.ModelMultipleChoiceFilter( + queryset=KillHouse.objects.all(), + field_name='kill_house', + to_field_name='id' + ) + + class Meta: + model = Guilds + fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__city__name', + 'user__province__name', + 'address__city__name', + 'guilds_name', + 'type_activity', + 'area_activity', + 'kill_house__name', + ] + + +class ProvinceKillRequestFilterSet(ModelFilterSet): + class Meta: + model = ProvinceKillRequest + + +class UserProfileFilterSet(ModelFilterSet): + class Meta: + model = UserProfile + + +class ProvinceOperatorFilterSet(ModelFilterSet): + class Meta: + model = ProvinceOperator + + +class InspectorOperatorFilterSet(ModelFilterSet): + class Meta: + model = InspectorOperator + + +class KillHouseFilterSet(ModelFilterSet): + class Meta: + model = KillHouse + + +class KillHouseFreeSaleBarInformationFilterSet(ModelFilterSet): + class Meta: + model = KillHouseFreeSaleBarInformation + + +class DirectBuyingPaymentFilterSet(ModelFilterSet): + class Meta: + model = DirectBuyingPayment + + +class KillHouseOperatorFilterSet(ModelFilterSet): + class Meta: + model = KillHouseOperator + + +class KillHouseDriverFilterSet(ModelFilterSet): + class Meta: + model = KillHouseDriver + + +class VetFilterSet(ModelFilterSet): + class Meta: + model = Vet + + +class KillHouseFreeBarInformationFilterSet(ModelFilterSet): + class Meta: + model = KillHouseFreeBarInformation + + +class PoultryHatchingFilterSet(ModelFilterSet): + class Meta: + model = PoultryHatching + fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'licence_number', + 'poultry__breeding_unique_id', + 'CertId', + 'PersonTypeName', + 'InteractTypeName', + 'UnionTypeName', + 'poultry__city_operator', + + ] + + +class EvacuationHatchingDetailFilterSet(ModelFilterSet): + class Meta: + model = EvacuationHatchingDetail + + +class KillHouseRequestFilterSet(ModelFilterSet): + class Meta: + model = KillHouseRequest + + +class BarDifferenceRequestFilterSet(ModelFilterSet): + class Meta: + model = BarDifferenceRequest + + +class KillRequestFilterSet(ModelFilterSet): + class Meta: + model = KillRequest + + +class WagePaymentFilterSet(ModelFilterSet): + class Meta: + model = WagePayment + + +class DashboardEnterLoadInformationFilterSet(filters.FilterSet): + class Meta: + model = KillHouseRequest + fields = [ + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__order_code', + 'bar_code', + ] + + +class DashboardPoultryRequestFilterSet(filters.FilterSet): + class Meta: + model = PoultryRequest + fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + +class DashboardKillHouseFreeBarInformationFilterSet(filters.FilterSet): + class Meta: + model = KillHouseFreeBarInformation + fields = [ + 'kill_house__name', + 'poultry_name', + 'poultry_mobile', + 'province', + 'city', + 'driver_name', + 'driver_mobile', + 'bar_clearance_code', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__kill_house_operator__user__fullname', + + ] + + +class VetFarmAndKillHouseFilterSet(ModelFilterSet): + class Meta: + model = Vet + fields = [ + 'user__national_id', + 'user__base_order', + 'user__mobile', + 'user__fullname' + + ] + + +class ProvinceKillRequestNewFilterSet(filters.FilterSet): + class Meta: + model = ProvinceKillRequest + fields = [ + 'province_request__poultry_request__order_code', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__fullname', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__kill_house_operator__address__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__fullname', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__poultry__address__city__name', + ] + + +class ReturnProvinceKillRequestFilterSet(ModelFilterSet): + class Meta: + model = ProvinceKillRequest + + +class PoultryManageFilterSet(filters.FilterSet): + class Meta: + model = Poultry + fields = [ + 'breeding_unique_id', + 'user__national_id', + 'user__base_order', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'address__city__name', + 'unit_name', + + ] + + +class DashboardKillRequestFilterSet(filters.FilterSet): + class Meta: + model = KillRequest + fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__first_name', + 'kill_house__kill_house_operator__user__last_name', + 'kill_house__kill_house_operator__user__mobile', + 'kill_house__name', + 'slaughter_house__name', + 'export_country', + 'export_code', + 'direct_buying_code', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + + ] + + +# class TicketsFilterSet(filters.FilterSet): +# to_user = filters.ModelMultipleChoiceFilter( +# queryset=SystemUserProfile.objects.all(), +# field_name='to_user', +# to_field_name='id' +# ) +# +# class Meta: +# model = TicketSupport +# fields = [ +# 'user__fullname', +# 'user__mobile', +# 'title', +# 'ticket_id', +# 'to_user__fullname', +# 'to_user__mobile', +# +# ] + + +class BaseOutProvinceCarcassesBuyerFilterSet(ModelFilterSet): + class Meta: + model = BaseOutProvinceCarcassesBuyer + + +class OutProvinceCarcassesBuyerFilterSet(ModelFilterSet): + class Meta: + model = OutProvinceCarcassesBuyer + + +class SubSectorTransactionsFilterSet(ModelFilterSet): + class Meta: + model = SubSectorTransactions + + +class CommonlyUsedFilterSet(ModelFilterSet): + class Meta: + model = CommonlyUsed + + +class TicketsFilterSet(filters.FilterSet): + class Meta: + model = TicketSupport + fields = [ + 'ticket_id', + 'user__fullname', + 'title', + + ] + + +class GuildsForPostationFilterSet(ModelFilterSet): + class Meta: + model = Guilds + fields = [ + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'guilds_name' + ] + + +class GuildsForArchiveFilterSet(ModelFilterSet): + class Meta: + model = Guilds + fields = [ + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'user__mobile', + 'guilds_name' + ] + + +class GuildsForGeneralConfigsFilterSet(ModelFilterSet): + class Meta: + model = Guilds + + fields = [ + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__city__name', + 'user__province__name', + 'address__city__name', + 'guilds_name', + 'type_activity', + 'area_activity', + ] + + +class POSDeviceSessionForCompanyFilterSet(ModelFilterSet): + class Meta: + model = POSDeviceSession + fields = [ + 'pos__terminal_number', + 'pos__pos_id', + 'pos__pos_company__name', + 'pos__guild__guilds_name', + 'pos__guild__user__fullname', + 'pos__guild__user__national_code', + + ] + + +class WarehouseArchiveFilterSet(ModelFilterSet): + class Meta: + model = WarehouseArchive + fields = [ + 'kill_house__kill_house_operator__user__fullname' + 'kill_house__kill_house_operator__user__mobile' + 'steward__user__fullname' + 'steward__user__mobile' + 'guild__user__fullname' + 'guild__user__mobile' + + ] + + +class HatchingIncreaseRequestFilterSet(ModelFilterSet): + class Meta: + model = HatchingIncreaseRequest + fields = [ + 'hatching__poultry__unit_name', + 'hatching__poultry__user__fullname', + 'hatching__poultry__user__mobile', + 'hatching__poultry__breeding_unique_id', + 'hatching__licence_number', + 'registerer_name', + 'registerer_mobile', + ] + + +class PoultryRequestDirectBuyingFilterSet(ModelFilterSet): + class Meta: + model = PoultryRequest + fields = [ + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__breeding_unique_id', + 'hatching__licence_number' + ] + + +class PoultryScienceFilterSet(ModelFilterSet): + class Meta: + model = PoultryScience + fields = [ + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__breeding_unique_id', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + ] + + +class PoultryScienceReportFilterSet(ModelFilterSet): + class Meta: + model = PoultryScienceReport + fields = [ + 'hatching__poultry__unit_name', + 'hatching__poultry__user__fullname', + 'hatching__poultry__user__mobile', + 'hatching__poultry__breeding_unique_id', + 'hatching__licence_number', + 'poultry_science__user__mobile', + 'poultry_science__user__first_name', + 'poultry_science__user__last_name', + 'poultry_science__user__fullname', + ] diff --git a/panel/helper.py b/panel/helper.py new file mode 100644 index 0000000..c36bb37 --- /dev/null +++ b/panel/helper.py @@ -0,0 +1,255 @@ +import re +from django.db.models import Q +from django.http import HttpResponse +from django.views.decorators.csrf import csrf_exempt +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny + +from authentication.models import SystemUserProfile, Province, BankCard, City, Group, SystemAddress +from authentication.serializer.serializer import BankCardSerializer +from authentication.serializers import SystemAddressSerializer +from rest_framework.response import Response +from rest_framework import status +from panel.models import Wallet + +COMPANY_NUMBER='09011110919' +COMPANY_NUMBER2='09169726704' +UNION_NUMBER='09011110919' +GUILD_NUMBER='09011110919' +UNION_SECOND_NUMBER=None +SUPPORTER_NUMBER='09165597588' +UNION_THIRD_NUMBER=None +UNION_FOURTH_NUMBER=None +UNION_NUMBER_2=None +UNION_FIFTH_NUMBER=None +UNION_SIXTH_NUMBER=None + +LIARA_STORAGE_URL='https://storage.c2.liara.space/ticket-rasadyar/' + +# Remove Null Fields From Request Body +def remove_null_fields(type=None, request=None, item=None): + if type == 'req': + null_fields = [] + for key, value in request.data.items(): + if value is None: + null_fields.append(key) + for item in null_fields: + request.data.pop(item) + elif type == 'item': + null_fields = [] + for key, value in request.data[item].items(): + if value is None: + null_fields.append(key) + for field in null_fields: + request.data[item].pop(field) + return request + + +def create_except_profile(request, queryset, serializer, role): + # get user profile object + userprofile = SystemUserProfile.objects.get(key=request.data['userprofile_key']) + request.data.pop('userprofile_key') + + # if not queryset.objects.filter(user=userprofile).exists(): + + # get group and set role for user + group = Group.objects.get(name=role) + userprofile.role.add(group) + + # get province object + province = Province.objects.get(key=request.data['province']) + request.data.pop("province") + + # get city object + city = City.objects.get(key=request.data['city']) + request.data.pop('city') + + # get user banking information + if 'user_bank_info' in request.data.keys(): + bank_card = BankCard.objects.create(**request.data['user_bank_info']) + request.data.pop('user_bank_info') + else: + bank_card = None + wallet = Wallet() + wallet.save() + + # create address object & operator object with serializers + address_serializer = SystemAddressSerializer(data=request.data) + if address_serializer.is_valid(): + address_obj = address_serializer.create(validated_data=request.data) + address_obj.province = province + address_obj.city = city + address_obj.save() + operator_object = queryset( + user=userprofile, + address=address_obj, + user_bank_info=bank_card, + wallet=wallet + ) + operator_object.save() + operator_serializer = serializer(operator_object) + return operator_serializer.data, status.HTTP_201_CREATED, operator_object + return address_serializer.errors, status.HTTP_400_BAD_REQUEST + # else: + # return "operator exists", status.HTTP_403_FORBIDDEN + + +def update_except_profile(model, serializer, request): + # remove null fields in address body + request = remove_null_fields(type='item', request=request, item='address') + # remove null fields in user bank info body + request = remove_null_fields(type='item', request=request, item='user_bank_info') + + userprofile = SystemUserProfile.objects.get(user=request.user) + operator = model.objects.get(user=userprofile) + + if 'address' in request.data.keys() or request.data['address'] is not None: + address_serializer = SystemAddressSerializer(data=request.data['address']) + if address_serializer.is_valid(): + addr_object = address_serializer.update( + instance=operator.address, + validated_data=request.data['address'] + ) + operator.address = addr_object + + if 'user_bank_info' in request.data.keys() or request.data['user_bank_info'] is not None: + bank_serializer = BankCardSerializer(data=request.data['user_bank_info']) + if bank_serializer.is_valid(): + bank_object = bank_serializer.update( + instance=operator.user_bank_info, + validated_data=request.data['user_bank_info'] + ) + operator.user_bank_info = bank_object + operator.save() + response_serializer = serializer(operator) + return response_serializer + + +def operator_update_except_profile(model, serializer, request): + # remove null fields in address body + request = remove_null_fields(type='item', request=request, item='address') + # remove null fields in user bank info body + request = remove_null_fields(type='item', request=request, item='user_bank_info') + + userprofile = SystemUserProfile.objects.get(key=request.data['userprofile_key']) + request.data.pop('userprofile_key') + if 'poultry_key' in request.data.keys(): + if 'unit_name' in request.data.keys(): + unit_name = request.data['unit_name'] + request.data.pop('unit_name') + + else: + unit_name = None + + if 'halls' in request.data.keys(): + halls = int(request.data['halls']) + request.data.pop('halls') + + else: + halls = None + + if 'breeding_unique_id' in request.data.keys(): + breeding_unique_id = request.data['breeding_unique_id'] + request.data.pop('breeding_unique_id') + + else: + breeding_unique_id = None + + operator = model.objects.get(key=request.data['poultry_key']) + + request.data.pop('poultry_key') + if halls != None: + operator.number_of_halls = halls + operator.save() + if unit_name != None: + operator.unit_name = unit_name + operator.save() + if breeding_unique_id != None: + operator.breeding_unique_id = breeding_unique_id + operator.save() + + + else: + operator = model.objects.get(user=userprofile) + + if 'address' in request.data.keys() or request.data['address'] is not None: + data = request.data['address'] + if 'city' in request.data['address']: + city = City.objects.get(key=request.data['address']['city']) # contains city object + data.pop('city') + else: + city = None + + if 'province' in request.data['address']: + province = Province.objects.get(key=request.data['address']['province']) # contains province object + data.pop('province') + else: + province = None + + address = SystemAddress.objects.get(key=operator.address.key) + if province != None: + address.province = province + if city != None: + address.city = city + address.save() + + address_serializer = SystemAddressSerializer(data=data) + if address_serializer.is_valid(): + addr_object = address_serializer.update( + instance=operator.address, + validated_data=request.data['address'] + ) + if city != None: + addr_object.city = city + if province != None: + addr_object.province = province + addr_object.save() + operator.address = addr_object + + if 'user_bank_info' in request.data.keys() or request.data['user_bank_info'] != "": + if operator.user_bank_info is not None: + bank_serializer = BankCardSerializer(data=request.data['user_bank_info']) + if bank_serializer.is_valid(): + bank_object = bank_serializer.update( + instance=operator.user_bank_info, + validated_data=request.data['user_bank_info'] + ) + operator.user_bank_info = bank_object + else: + bank_serializer = BankCardSerializer(data=request.data['user_bank_info']) + if bank_serializer.is_valid(): + bank_object = bank_serializer.create( + validated_data=request.data['user_bank_info'] + ) + operator.user_bank_info = bank_object + operator.save() + response_serializer = serializer(operator) + return response_serializer + + + +def check_mobile_number(s): + pattern = r'^09\d{9}$' + return bool(re.match(pattern, s)) + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def get_country(request): + asian_countries = { + 'Iraq': 'عراق', + 'Afghanistan': 'افغانستان', + 'Turkey': 'ترکیه', + + } + + persian_country_details = [{'en': eng_name, 'fa': persian_name} for eng_name, persian_name in + asian_countries.items()] + + return Response(persian_country_details) + +def build_query(filterset_class, value): + query = Q() + for field in filterset_class.Meta.fields: + query |= Q(**{f"{field}__icontains": value}) + return query diff --git a/panel/helper_excel.py b/panel/helper_excel.py new file mode 100644 index 0000000..3a0a94a --- /dev/null +++ b/panel/helper_excel.py @@ -0,0 +1,538 @@ +from datetime import datetime +from io import BytesIO + +import jdatetime +import openpyxl +from django.db.models import Q, Sum +from django.http import HttpResponse +from openpyxl import Workbook +from openpyxl.chart import LineChart, Reference, BarChart +from openpyxl.styles import PatternFill, Alignment, Font +from openpyxl.utils import get_column_letter + +from deposit_id import wage_counting_type +from panel.models import WageType, ProvinceKillRequest, KillHouseRequest, KillHouseFreeBarInformation, \ + KillHouseFreeSaleBarInformation, InternalTransaction, KillHouse, StewardAllocation + +blue_fill = PatternFill(start_color="277358", fill_type="solid") +Alignment_CELL = Alignment(horizontal='center', vertical='center', wrap_text=True) +red_font = Font(color="C00000", bold=True) +GREEN_CELL = PatternFill(start_color="00B050", fill_type="solid") +RED_CELL = PatternFill(start_color="FCDFDC", fill_type="solid") +YELLOW_CELL = PatternFill(start_color="FFFF00", fill_type="solid") +ORANGE_CELL = PatternFill(start_color="FFC000", fill_type="solid") +BLUE_CELL = PatternFill(start_color="538DD5", fill_type="solid") +LIGHT_GREEN_CELL = PatternFill(start_color="92D050", fill_type="solid") +VERY_LIGHT_GREEN_CELL = PatternFill(start_color="5AFC56", fill_type="solid") + +percent_of_losses = 0.11 + + +def shamsi_date(date, in_value=None, set_datetime=None): + if set_datetime: + sh_dt = jdatetime.datetime.fromgregorian(datetime=date) + return sh_dt.strftime('%Y/%m/%d (%H:%M)') + + if in_value: + sh_date = jdatetime.date.fromgregorian( + year=date.year, + month=date.month, + day=date.day + ) + else: + gh_date = jdatetime.date.fromgregorian( + year=date.year, + month=date.month, + day=date.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(gh_date.split("-")) + separate = "-" + sh_date = separate.join(reversed_date) + return sh_date + + +def create_header(worksheet, list, num, row, height=None, width=None, color=None, text_color=None, border_style=None): + for col_num, option in enumerate(list, num): + cell = worksheet.cell(row=row, column=col_num, value=option) + col_letter = get_column_letter(col_num) + cell.alignment = Alignment_CELL + if color is not None: + if color == 'green': + cell.fill = GREEN_CELL + elif color == 'orange': + cell.fill = ORANGE_CELL + elif color == 'blue': + cell.fill = BLUE_CELL + else: + cell.fill = PatternFill(start_color=color, fill_type="solid") + else: + cell.fill = blue_fill + if text_color is not None: + cell.font = Font(size=9, bold=True, color=text_color) + else: + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + if height is not None: + worksheet.row_dimensions[row].height = height + if width is not None: + worksheet.column_dimensions[col_letter].width = width + if border_style is not None: + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style=border_style), + right=openpyxl.styles.Side(style=border_style), + top=openpyxl.styles.Side(style=border_style), + bottom=openpyxl.styles.Side(style=border_style) + ) + + +def create_header_freez(worksheet, list, num, row, header_row, height=None, width=None, len_with=None, + different_cell=None): + for col_num, option in enumerate(list, num): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=row, column=col_num, value=option) + cell.alignment = Alignment_CELL + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + if height is not None: + worksheet.row_dimensions[row].height = height + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 2 + if width is not None: + worksheet.column_dimensions[col_letter].width = width + if len_with is not None: + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + if different_cell is not None: + if option == different_cell: + cell.fill = PatternFill(start_color="C00000", fill_type="solid") + worksheet.freeze_panes = worksheet[f'A{header_row}'] + max_col = worksheet.max_column + range_str = f'A{header_row - 1}:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + +def excel_description(worksheet, row1, description, size=None, color=None, my_color=None, row2=None): + worksheet[row1] = description + worksheet[row1].alignment = Alignment_CELL + if size is not None: + worksheet[row1].font = Font(size=size) + if color is not None: + worksheet[row1].font = red_font + if my_color is not None: + worksheet[row1].font = PatternFill(start_color=my_color, fill_type="solid") + + if row2 is not None: + merge_range = f'{row1}:{row2}' + worksheet.merge_cells(merge_range) + + +def create_value(worksheet, list, l, num, border_style=None, m=None, height=None, color=None, width=None, + different_cell=None, different_value=None, item_num=None, item_color=None): + color_dict = { + 'green': GREEN_CELL, + 'yellow': YELLOW_CELL, + 'blue': BLUE_CELL, + 'red': RED_CELL, + 'light_green': LIGHT_GREEN_CELL, + 'very_light_green': VERY_LIGHT_GREEN_CELL + } + + for item in range(len(list)): + cell = worksheet.cell(row=l, column=item + num, value=list[item]) + cell.alignment = Alignment_CELL + + if border_style: + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style=border_style), + right=openpyxl.styles.Side(style=border_style), + top=openpyxl.styles.Side(style=border_style), + bottom=openpyxl.styles.Side(style=border_style) + ) + + value = list[item] + if isinstance(value, (int, float)) and value != 0: + cell.number_format = '#,###' + else: + cell.value = value + + cell.font = Font(size=10, bold=True) + + if m is not None and m % 2 != 0: + cell.fill = PatternFill(start_color="D6F6FE", fill_type="solid") + + if height is not None: + worksheet.row_dimensions[l + 1].height = height + + if item_num is not None and item == item_num: + if item_color: + cell.fill = item_color + elif color in color_dict: + cell.fill = color_dict[color] + + if different_cell is not None and list[different_cell] == different_value: + cell.fill = RED_CELL + + if width is not None: + worksheet.column_dimensions[openpyxl.utils.get_column_letter(item + num)].width = width + + +def merge_cells(worksheet, l, s, cell1=None, cell2=None, lst=None): + if lst is not None: + for col in lst: + rng = f'{col}{l}:{col}{l + s}' + worksheet.merge_cells(rng) + worksheet[col + f'{l}'].alignment = Alignment_CELL + else: + for col in range(ord(f'{cell1}'), ord(f'{cell2}') + 1): + rng = f'{chr(col)}{l}:{chr(col)}{l + s}' + worksheet.merge_cells(rng) + worksheet[chr(col) + f'{l}'].alignment = Alignment_CELL + + +def add_header(worksheet): + worksheet.oddHeader.center.text = "سامانه رصدیار" + worksheet.oddHeader.center.size = 14 # تنظیم اندازه فونت + worksheet.oddHeader.center.font = "Arial,Bold" # تنظیم فونت و ضخامت + + # همچنین می‌توانید از هدرهای چپ و راست هم استفاده کنید + # worksheet.oddHeader.right.text = f"تاریخ: {shamsi_now_date}" + + +def cell_color_changer(worksheet, row, start_index, end_index, custom_color): + for item in range(start_index, end_index): + cell = worksheet.cell(row=row, column=item) + cell.fill = PatternFill(start_color=custom_color, fill_type="solid") + + +def get_kill_house_finance_info_by_date(kill_house, date1, date2): + total_wage_type = WageType.objects.filter(trash=False) + province_live_wage_type = total_wage_type.filter(en_name='province-kill-request', trash=False).first() + free_buying_live_weight_wage_type = total_wage_type.filter(en_name='live-buy', trash=False).first() + free_buying_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-buy', trash=False).first() + free_sell_carcesses_weight_wage_type = total_wage_type.filter(en_name='carcasse-sell', trash=False).first() + province_live_wage_type_amount = province_live_wage_type.amount if province_live_wage_type.status == True else 0 + free_buying_live_weight_wage_type_amount = free_buying_live_weight_wage_type.amount if free_buying_live_weight_wage_type.status == True else 0 + free_buying_carcesses_weight_wage_type_amount = free_buying_carcesses_weight_wage_type.amount if free_buying_carcesses_weight_wage_type.status == True else 0 + free_sell_carcesses_weight_wage_type_amount = free_sell_carcesses_weight_wage_type.amount if free_sell_carcesses_weight_wage_type.status == True else 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(killhouse_user=kill_house, trash=False, + archive_wage=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2).order_by( + 'id') + kill_house_requests = KillHouseRequest.objects.filter( + Q(Q(killhouse_user=kill_house) & Q(killer=kill_house)) | Q( + Q(killhouse_user=kill_house) & Q(killer__isnull=True)) | Q( + Q(killhouse_user=kill_house) | Q(killer=kill_house)), archive_wage=False, + trash=False, calculate_status=True, kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2 + ) + kill_house_requests = kill_house_requests.filter( + Q(killhouse_user=kill_house, killer__isnull=True) | Q(killhouse_user=kill_house, killer=kill_house) | Q( + killer=kill_house)) + kill_house_free_bar_info = KillHouseFreeBarInformation.objects.filter( + Q(kill_house=kill_house, exclusive_killer__isnull=True) | Q(exclusive_killer=kill_house), date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + calculate_status=True, + trash=False) + kill_house_free_sale_bar_info = KillHouseFreeSaleBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house=kill_house, + archive_wage=False, + calculate_status=True, + trash=False) + slaughter_transactions = InternalTransaction.objects.filter(date__date__gte=date1, + date__date__lte=date2, + kill_house=kill_house, status='completed', + trash=False) + + total_paid_wage = slaughter_transactions.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + total_province_live_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + total_province_live_weight += kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + total_out_selling_province_carcasses_weight = \ + kill_house_free_sale_bar_info.aggregate(total=Sum('real_weight_of_carcasses'))['total'] or 0 + if wage_counting_type == 'live': + total_province_carcasses_weight = total_province_live_weight + total_pure_province_carcasses_weight = total_province_carcasses_weight + else: + total_province_carcasses_weight = total_province_live_weight * 0.75 + total_out_carcasses_buying_for_pure_province_carcasses_weight = \ + kill_house_free_bar_info.aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + out_selling_out_carcasses_buying_difference = total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight if ( + total_out_selling_province_carcasses_weight - total_out_carcasses_buying_for_pure_province_carcasses_weight) > 0 else 0 + total_pure_province_carcasses_weight = total_province_carcasses_weight - out_selling_out_carcasses_buying_difference + total_out_live_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='live').aggregate(total=Sum('live_weight'))['total'] or 0 + total_out_carcasses_buying_province_carcasses_weight = \ + kill_house_free_bar_info.filter(buy_type='carcass').aggregate(total=Sum('weight_of_carcasses'))['total'] or 0 + + total_pure_province_carcasses_price = total_pure_province_carcasses_weight * province_live_wage_type_amount + total_out_selling_province_carcasses_price = total_out_selling_province_carcasses_weight * free_sell_carcesses_weight_wage_type_amount + total_out_live_buying_province_carcasses_price = total_out_live_buying_province_carcasses_weight * free_buying_live_weight_wage_type_amount + total_out_carcasses_buying_province_carcasses_price = total_out_carcasses_buying_province_carcasses_weight * free_buying_carcesses_weight_wage_type_amount + total_price = total_pure_province_carcasses_price + total_out_selling_province_carcasses_price + total_out_live_buying_province_carcasses_price + total_out_carcasses_buying_province_carcasses_price + + return { + "total_province_live_weight": total_province_live_weight, + "total_province_carcasses_weight": total_province_carcasses_weight, + "total_out_selling_province_carcasses_weight": total_out_selling_province_carcasses_weight, + "total_pure_province_carcasses_weight": total_pure_province_carcasses_weight, + "total_pure_province_carcasses_price": total_pure_province_carcasses_price, + "total_out_selling_province_carcasses_price": total_out_selling_province_carcasses_price, + "total_out_carcasses_buying_province_carcasses_weight": total_out_carcasses_buying_province_carcasses_weight, + "total_out_carcasses_buying_province_carcasses_price": total_out_carcasses_buying_province_carcasses_price, + "total_out_live_buying_province_carcasses_weight": total_out_live_buying_province_carcasses_weight, + "total_out_live_buying_province_carcasses_price": total_out_live_buying_province_carcasses_price, + "total_paid_wage": total_paid_wage, + "total_price": total_price, + "province_live_wage_amount": province_live_wage_type_amount, + "free_buying_live_weight_amount": free_buying_live_weight_wage_type_amount, + "free_buying_carcesses_weight_amount": free_buying_carcesses_weight_wage_type_amount, + "free_sell_carcesses_weight_amount": free_sell_carcesses_weight_wage_type_amount, + + } + + +def start_excel(): + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + return workbook, worksheet, output + + +def close_excel(name): + workbook, worksheet, output = start_excel() + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="{name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def get_kill_house_distribution_info(city, date1=None, date2=None): + kill_house_name = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + list1 = [city.name] + for kill_house in kill_house_name: + if date1: + allocations = StewardAllocation.objects.filter( + Q(to_steward__user__city=city) | Q(to_guilds__user__city=city), + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, date__date__gte=date1, receiver_state__in=('pending', 'accepted'), + date__date__lte=date2, calculate_status=True, kill_house=kill_house).order_by('id') + + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward__user__city=city) | Q(to_guilds__user__city=city), + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + receiver_state__in=('pending', 'accepted'), + trash=False, calculate_status=True, kill_house=kill_house).order_by('id') + + weight = allocations.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + list1.append(weight + + ) + return list1 + + +def get_kill_house_distribution_out_province_info(date1=None, date2=None): + kill_house_name = KillHouse.objects.filter(trash=False, out_province=False).order_by('id') + list1 = ['خارج استان'] + for kill_house in kill_house_name: + if date1: + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False, calculate_status=True, date__date__gte=date1, + date__date__lte=date2) + else: + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + kill_house=kill_house, + trash=False, calculate_status=True) + + weight_kill_house_free_sale_bars = kill_house_free_sale_bars.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + list1.append(weight_kill_house_free_sale_bars + ) + if date1: + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, calculate_status=True, date__date__gte=date1, + date__date__lte=date2) + else: + + kill_house_free_sale_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, calculate_status=True) + + weight_kill_house_free_sale_bars = kill_house_free_sale_bars.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + + list1.append(weight_kill_house_free_sale_bars + ) + return list1 + + +def all_get_kill_house_distribution_info(city, date1=None, date2=None): + if date1: + allocations = StewardAllocation.objects.filter( + Q(to_steward__user__city=city) | Q(to_guilds__user__city=city), + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + trash=False, date__date__gte=date1, receiver_state__in=('pending', 'accepted'), + date__date__lte=date2, calculate_status=True).order_by('id') + + else: + allocations = StewardAllocation.objects.filter( + Q(to_steward__user__city=city) | Q(to_guilds__user__city=city), + allocation_type__in=('killhouse_steward', 'killhouse_guild'), + receiver_state__in=('pending', 'accepted'), + trash=False, calculate_status=True).order_by('id') + + weight = allocations.aggregate( + total_quantity=Sum('real_weight_of_carcasses')).get( + 'total_quantity') or 0 + return weight + + +def add_chart( + worksheet, + chart_type, + data_columns, + category_column, + start_row, + end_row, + chart_position, + chart_title, + x_axis_title, + y_axis_title, + chart_width=25, # عرض نمودار پیش‌فرض (واحد: cm) + chart_height=15 +): + """ + افزودن نمودار به صفحه اکسل. + + ورودی: + worksheet (openpyxl.Worksheet): صفحه اکسل. + chart_type (str): نوع نمودار ("line" یا "bar"). + data_columns (list): لیستی از ستون‌های داده. + category_column (int): ستون دسته‌بندی‌ها. + start_row (int): ردیف شروع داده‌ها. + end_row (int): ردیف پایان داده‌ها. + chart_position (str): محل قرار گرفتن نمودار. + chart_title (str): عنوان نمودار. + x_axis_title (str): عنوان محور X. + y_axis_title (str): عنوان محور Y. + chart_width (float): عرض نمودار (واحد: cm). + chart_height (float): ارتفاع نمودار (واحد: cm). + """ + + if chart_type == 'line': + chart = LineChart() + chart.style = 20 + elif chart_type == 'bar': + chart = BarChart() + else: + raise ValueError("chart_type باید 'line' یا 'bar' باشد.") + + chart.title = chart_title + chart.y_axis.title = y_axis_title + chart.x_axis.title = x_axis_title + chart.width = chart_width + chart.height = chart_height + + categories = Reference(worksheet, min_col=category_column, min_row=start_row, max_row=end_row) + data = Reference(worksheet, min_col=data_columns, min_row=start_row - 1, max_row=end_row) + chart.add_data(data, titles_from_data=True) + chart.set_categories(categories) + for series in chart.series: + series.graphicalProperties.line.solidFill = "277358" + series.graphicalProperties.line.width = 30000 + + worksheet.add_chart(chart, chart_position) + # example + # add_chart( + # worksheet=worksheet, + # chart_type='line', + # data_columns=7, # ستون وزن وارد شده + # category_column=2, # ستون نام سردخانه‌ها + # start_row=7, + # end_row=l + 1, + # chart_position="A12", + # chart_title="نمودار تغییرات وزن در سردخانه‌ها", + # x_axis_title="سردخانه‌ها", + # y_axis_title="وزن (کیلوگرم)" + # ) + + +def to_locale_str(a): + return "{:,}".format(int(a)) + + +def convert_str_to_date(string, with_datetime=None): + """ + Convert a string to a datetime.date object. + + This function tries multiple common date formats, including ISO 8601 with or + without milliseconds, and plain 'YYYY-MM-DD'. If the string cannot be parsed, + it returns None. + + Parameters: + ----------- + string : str + The date string to convert. + + Returns: + -------- + datetime.date or None + A datetime.date object if conversion succeeds, otherwise None. + + Supported formats: + ------------------ + - 'YYYY-MM-DDTHH:MM:SS.sssZ' (ISO 8601 with milliseconds) + - 'YYYY-MM-DDTHH:MM:SSZ' (ISO 8601 without milliseconds) + - 'YYYY-MM-DD' (Simple date) + """ + string = str(string).strip() + + # فرمت‌های مختلف تاریخ + date_formats = [ + '%Y-%m-%dT%H:%M:%S.%fZ', + '%Y-%m-%dT%H:%M:%SZ', + '%Y-%m-%dT%H:%M:%S.%f%z', # ✅ با میلی‌ثانیه و تایم‌زون + '%Y-%m-%dT%H:%M:%S%z', # ✅ مثل: 2025-02-26T03:30:00+03:30 + '%Y-%m-%dT%H:%M:%S.%f', + '%Y-%m-%dT%H:%M:%S', + '%Y-%m-%d %H:%M:%S.%f', + '%Y-%m-%d %H:%M:%S', + '%Y-%m-%d' + ] + + for fmt in date_formats: + try: + if with_datetime: + date = datetime.strptime(string, fmt) + else: + date = datetime.strptime(string, fmt).date() + return date + except ValueError: + continue + + return None + diff --git a/panel/management/__init__.py b/panel/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/management/commands/__init__.py b/panel/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/management/commands/function_executor.py b/panel/management/commands/function_executor.py new file mode 100644 index 0000000..df6fc9c --- /dev/null +++ b/panel/management/commands/function_executor.py @@ -0,0 +1,215 @@ +from django.core.management.base import BaseCommand, CommandError +from notification.models import ( + NotificationToken, + NotificationType, +) +from notification.najva.send_notif_to_segments import send_notification_to_specific_segment +from authentication.models import UserMessageType +from authentication.sahandsms.sms import sms_reminder +from panel.models import OperatorLastTimeEnter +from panel.models import FunctionExecutor +from panel.models import * +import schedule +import time +import datetime + +from panel.poultry.views import Check_Poultry_Auction_request + +TITLE = "" +BODY = "" +CONTENT = "" +LINK_TEXT = "" +LINK = "" + + +def send_request_notification_to_city_operator(): + if CheckState.objects.filter(state__exact=True): + for item in CheckState.objects.filter(state__exact=True): + city_operator_user = UserProfile.objects.get(role__name__exact="CityOperator") + city_user_token = NotificationToken.objects.get(user__exact=city_operator_user).token + send_notification_to_specific_segment( + title=TITLE, + body=BODY, + content=CONTENT, + icon=None, + image=None, + subscriber_tokens=[city_user_token], + ) + notification = Notification( + title=TITLE, + content=CONTENT + ) + notification.notif_type = NotificationType.objects.get(name='poultry') + notification.notification_user = city_operator_user + notification.save() + item.notification = notification + item.state = False + item.city_state_notification = True + item.main_check = "pending" + item.save() + if CheckState.objects.filter(state__exact=False): + for item in CheckState.objects.filter(state__exact=False): + if item.city_state_notification is True and item.main_check == "pending": + city_operator_user = UserProfile.objects.get(role__name__exact="CityOperator") + last_enter_obj = OperatorLastTimeEnter.objects.get(operator__exact=city_operator_user) + if item.notification.create_date < last_enter_obj.city_operator_last_time_check < item.notification.create_date + datetime.timedelta( + hours=5): + item.notification.status = "read" + item.main_check = "city_end" + item.notification.save() + else: + user_message = UserMessage( + heading=TITLE, + message=CONTENT, + link_text=LINK_TEXT, + link=LINK, + ) + user_message.message_type = UserMessageType.objects.get(name="modal") + user_message.save() + user_message.users.add(city_operator_user) + item.user_message = user_message + item.city_state_notification = False + item.city_state_modal = True + item.main_check = 'pending' + item.save() + if CheckState.objects.filter(city_state_modal=True, main_check="pending"): + for item in CheckState.objects.filter(city_state_modal=True, main_check="pending"): + city_operator_user = UserProfile.objects.get(role__name__exact="CityOperator") + last_enter_obj = OperatorLastTimeEnter.objects.get(operator__exact=city_operator_user) + if item.user_message.create_date < last_enter_obj.city_operator_last_time_check < item.user_message.create_date + datetime.timedelta( + hours=5): + item.user_message.state = "read" + item.main_check = "city_end" + item.notification.save() + else: + sms_reminder( + receptor=city_operator_user.mobile, + title=TITLE, + content=CONTENT, + link_text=LINK_TEXT, + link=LINK, + time=datetime.datetime.now() + ) + user_message = UserMessage( + heading=TITLE, + message=CONTENT, + link_text=LINK_TEXT, + link=LINK, + ) + user_message.message_type = UserMessageType.objects.get(name="sms") + user_message.save() + user_message.users.add(city_operator_user) + item.user_message = user_message + item.city_state_modal = False + item.city_state_sms = True + item.city_state = True + item.main_check = "city_end" + item.save() + + +def send_request_notification_to_province_operator(): + if CheckState.objects.filter(city_state=True): + for item in CheckState.objects.filter(city_state=True): + province_operator_user = UserProfile.objects.get(role__name__exact="ProvinceOperator") + province_user_token = NotificationToken.objects.get(user__exact=province_operator_user).token + send_notification_to_specific_segment( + title=TITLE, + body=BODY, + content=CONTENT, + icon=None, + image=None, + subscriber_tokens=[province_user_token], + ) + notification = Notification( + title=TITLE, + content=CONTENT + ) + notification.notif_type = NotificationType.objects.get(name='poultry') + notification.notification_user = province_operator_user + notification.save() + item.notification = notification + item.province_state_notification = True + item.main_check = "pending" + item.save() + if CheckState.objects.filter(city_state=True): + for item in CheckState.objects.filter(city_state=True): + if item.province_state_notification is True and item.main_check == "pending": + province_operator_user = UserProfile.objects.get(role__name__exact="ProvinceOperator") + last_enter_obj = OperatorLastTimeEnter.objects.get(operator__exact=province_operator_user) + if item.notification.create_date < last_enter_obj.province_operator_last_time_check < item.notification.create_date + datetime.timedelta( + hours=5): + item.notification.status = "read" + item.main_check = "province_end" + item.notification.save() + else: + user_message = UserMessage( + heading=TITLE, + message=CONTENT, + link_text=LINK_TEXT, + link=LINK, + ) + user_message.message_type = UserMessageType.objects.get(name="modal") + user_message.save() + user_message.users.add(province_operator_user) + item.user_message = user_message + item.province_state_notification = False + item.province_state_modal = True + item.main_check = 'pending' + item.save() + if CheckState.objects.filter(province_state_modal=True, main_check="pending"): + for item in CheckState.objects.filter(province_state_modal=True, main_check="pending"): + province_operator_user = UserProfile.objects.get(role__name__exact="ProvinceOperator") + last_enter_obj = OperatorLastTimeEnter.objects.get(operator__exact=province_operator_user) + if item.user_message.create_date < last_enter_obj.province_operator_last_time_check < item.user_message.create_date + datetime.timedelta( + hours=5): + item.user_message.state = "read" + item.main_check = "province_end" + item.notification.save() + else: + sms_reminder( + receptor=province_operator_user.mobile, + title=TITLE, + content=CONTENT, + link_text=LINK_TEXT, + link=LINK, + time=datetime.datetime.now() + ) + user_message = UserMessage( + heading=TITLE, + message=CONTENT, + link_text=LINK_TEXT, + link=LINK, + ) + user_message.message_type = UserMessageType.objects.get(name="sms") + user_message.save() + user_message.users.add(province_operator_user) + item.user_message = user_message + item.province_state_modal = False + item.province_state_sms = True + item.province_state = True + item.main_check = "province_end" + item.save() + + +def send_request_notification_to_poultry_from_killhouse(): + pass + + +class Command(BaseCommand): + help = 'Closes the specified poll for voting' + + def add_arguments(self, parser): + pass + + def handle(self, *args, **options): + # schedule.every(2).hours.do() + # schedule.every(5).hours.do() + # schedule.every(10).minutes.do(job) + # schedule.every().hour.do(job) + # schedule.every().day.at("10:30").do(job) + # schedule.every().monday.do(job) + # schedule.every().wednesday.at("13:15").do(job) + while (True): + schedule.every(1).minutes.do(Check_Poultry_Auction_request) + schedule.run_pending() + print("function run !!!") diff --git a/panel/management/timing_function.py b/panel/management/timing_function.py new file mode 100644 index 0000000..5c6b9b8 --- /dev/null +++ b/panel/management/timing_function.py @@ -0,0 +1,26 @@ +from panel.models import FunctionExecutor +from datetime import timezone +import datetime +import jdatetime +import schedule + + +def timing_function(function_name): + func_obj = FunctionExecutor.objects.get( + function_name=function_name + ) + func_dict = { + + } + if func_obj.time_type == "year": + func_dict['']() + elif func_obj.time_type == "month": + func_dict['']() + elif func_obj.time_type == "day": + func_dict['']() + elif func_obj.time_type == "hour": + func_dict['']() + elif func_obj.time_type == "minute": + func_dict['']() + elif func_obj.time_type == "second": + func_dict['']() diff --git a/panel/merge_database.py b/panel/merge_database.py new file mode 100644 index 0000000..cc83fa0 --- /dev/null +++ b/panel/merge_database.py @@ -0,0 +1,402 @@ +from authentication.models import Province, City, CityUnit, SystemAddress, SystemUserProfile +from panel.models import Poultry, PoultryHatching, CityOperator, PoultryRequest, KillHouseOperator, \ + KillHouseAllowVet, KillHousePercentage, KillHouseDriver, CityOperatorCheckRequest, KillHouseADDCAR, \ + ProvinceOperator, ProvinceCheckOperatorOutRequest, ProvinceCheckOperatorRequest, ShareOfAllocation, KillRequest, \ + KillRequestFactor, KillRequestFactorPayment, ProvinceKillRequest, KillHouseRequest, KillHouseCheckRequest, \ + KillHouseAssignmentInformation, ProvinceCheckInformation, ProvinceFactorToKillHouse, KillHouseFactorToProvince, \ + ProvinceCheckKillHouseFactor, DepositAllocation, InspectorOperator, PovinceInspector, Vet, KillHouseVet, \ + VetCheckRequest, VetFarm, VetFarmInspection, Admin, Jahad, CityJahad, ProvincialGovernment, VetSupervisor, \ + ProvinceAllowKillHouseRegisterCar, ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultrySellFree, \ + KillHouseDailyQuota, ProvinceAutoAllocation + + +def update_database(): + from panel.models import KillHouse + provinces = Province.objects.all() + cities = City.objects.all() + city_units = CityUnit.objects.all() + adresses = SystemAddress.objects.all() + profiles = SystemUserProfile.objects.all() + poultries = Poultry.objects.all() + hatchings = PoultryHatching.objects.all() + city_operators = CityOperator.objects.all() + poultry_requests = PoultryRequest.objects.all() + kill_house_operators = KillHouseOperator.objects.all() + KillHouses = KillHouse.objects.all() + killhouseallowvets = KillHouseAllowVet.objects.all() + killhousepercentages = KillHousePercentage.objects.all() + drivers = KillHouseDriver.objects.all() + add_cars = KillHouseADDCAR.objects.all() + city_check_requests = CityOperatorCheckRequest.objects.all() + province_operators = ProvinceOperator.objects.all() + province_check_out_requests = ProvinceCheckOperatorOutRequest.objects.all() + province_check_requests = ProvinceCheckOperatorRequest.objects.all() + share_of_allocations = ShareOfAllocation.objects.all() + kill_requests = KillRequest.objects.all() + kill_request_factors = KillRequestFactor.objects.all() + kill_request_payment_factors = KillRequestFactorPayment.objects.all() + province_kill_requests = ProvinceKillRequest.objects.all() + kill_house_requests = KillHouseRequest.objects.all() + kill_house_check_requests = KillHouseCheckRequest.objects.all() + assignment_informations = KillHouseAssignmentInformation.objects.all() + province_check_informations = ProvinceCheckInformation.objects.all() + province_factors = ProvinceFactorToKillHouse.objects.all() + kill_house_factors = KillHouseFactorToProvince.objects.all() + province_check_kill_house_factors = ProvinceCheckKillHouseFactor.objects.all() + deposit_allocations = DepositAllocation.objects.all() + inspectors = InspectorOperator.objects.all() + inspector_checks = PovinceInspector.objects.all() + vets = Vet.objects.all() + kill_house_vets = KillHouseVet.objects.all() + vet_check_requests = VetCheckRequest.objects.all() + vet_farms = VetFarm.objects.all() + vet_farm_inspections = VetFarmInspection.objects.all() + admins = Admin.objects.all() + jahads = Jahad.objects.all() + city_jahads = CityJahad.objects.all() + goverments = ProvincialGovernment.objects.all() + vet_supervisers = VetSupervisor.objects.all() + province_allow_kill_house_registers = ProvinceAllowKillHouseRegisterCar.objects.all() + province_allow_poultry_choose_kill_houses = ProvinceAllowPoultryChooseKillHouse.objects.all() + province_allow_poultry_auto_sell = ProvinceAllowPoultrySellFree.objects.all() + kill_house_daily_quotas = KillHouseDailyQuota.objects.all() + province_auto_allocations = ProvinceAutoAllocation.objects.all() + + for province in provinces: + province.province_number = province.id + province.province_name = province.name + province.save() + + for city in cities: + city.province_number = city.province.id + city.province_name = city.province.name + city.city_number = city.id + city.city_name = city.name + city.save() + + for cityunit in city_units: + cityunit.province_number = cityunit.city.province.id + cityunit.province_name = cityunit.city.province.name + cityunit.city_number = cityunit.city.id + cityunit.city_name = cityunit.city.name + cityunit.save() + + for address in adresses: + address.province_number = address.province.id + address.province_name = address.province.name + address.city_number = address.city.id + address.city_name = address.city.name + address.save() + + for profile in profiles: + profile.province_number = profile.province.id + profile.province_name = profile.province.name + profile.city_number = profile.city.id + profile.city_name = profile.city.name + profile.save() + + for poultry in poultries: + poultry.city_number = poultry.address.city.id + poultry.city_name = poultry.address.city.name + poultry.province_number = poultry.address.province.id + poultry.province_name = poultry.address.province.name + poultry.save() + + for hatching in hatchings: + hatching.city_number = hatching.poultry.address.city.id + hatching.city_name = hatching.poultry.address.city.name + hatching.province_number = hatching.poultry.address.province.id + hatching.province_name = hatching.poultry.address.province.name + hatching.save() + + for city_operator in city_operators: + city_operator.city_number = city_operator.address.city.id + city_operator.city_name = city_operator.address.city.name + city_operator.province_number = city_operator.address.province.id + city_operator.province_name = city_operator.address.province.name + city_operator.save() + + for poultry_request in poultry_requests: + poultry_request.city_number = poultry_request.poultry.address.city.id + poultry_request.city_name = poultry_request.poultry.address.city.name + poultry_request.province_number = poultry_request.poultry.address.province.id + poultry_request.province_name = poultry_request.poultry.address.province.name + poultry_request.save() + + for kill_house_operator in kill_house_operators: + kill_house_operator.city_number = kill_house_operator.address.city.id + kill_house_operator.city_name = kill_house_operator.address.city.name + kill_house_operator.province_number = kill_house_operator.address.province.id + kill_house_operator.province_name = kill_house_operator.address.province.name + kill_house_operator.save() + + for KillHouse in KillHouses: + KillHouse.city_number = KillHouse.system_address.city.id + KillHouse.city_name = KillHouse.system_address.city.name + KillHouse.province_number = KillHouse.system_address.province.id + KillHouse.province_name = KillHouse.system_address.province.name + KillHouse.save() + + for killhouseallowvet in killhouseallowvets: + killhouseallowvet.city_number = killhouseallowvet.kill_house.system_address.city.id + killhouseallowvet.city_name = killhouseallowvet.kill_house.system_address.city.name + killhouseallowvet.province_number = killhouseallowvet.kill_house.system_address.province.id + killhouseallowvet.province_name = killhouseallowvet.kill_house.system_address.province.name + killhouseallowvet.save() + + for killhousepercentage in killhousepercentages: + killhousepercentage.city_number = killhousepercentage.kill_house.system_address.city.id + killhousepercentage.city_name = killhousepercentage.kill_house.system_address.city.name + killhousepercentage.province_number = killhousepercentage.kill_house.system_address.province.id + killhousepercentage.province_name = killhousepercentage.kill_house.system_address.province.name + killhousepercentage.save() + + for driver in drivers: + driver.city_number = driver.user.city.id + driver.city_name = driver.user.city.name + driver.province_number = driver.user.province.id + driver.province_name = driver.user.province.name + driver.save() + + for add_car in add_cars: + add_car.city_number = add_car.driver.user.city.id + add_car.city_name = add_car.driver.user.city.name + add_car.province_number = add_car.driver.user.province.id + add_car.province_name = add_car.driver.user.province.name + add_car.save() + + for city_check_request in city_check_requests: + city_check_request.city_number = city_check_request.city_operator_system.user.city.id + city_check_request.city_name = city_check_request.city_operator_system.user.city.name + city_check_request.province_number = city_check_request.city_operator_system.user.province.id + city_check_request.province_name = city_check_request.city_operator_system.user.province.name + city_check_request.save() + + for province_operator in province_operators: + province_operator.city_number = province_operator.user.city.id + province_operator.city_name = province_operator.user.city.name + province_operator.province_number = province_operator.user.province.id + province_operator.province_name = province_operator.user.province.name + province_operator.save() + + for province_check_out_request in province_check_out_requests: + province_check_out_request.city_number = province_check_out_request.province_operator_system.user.city.id + province_check_out_request.city_name = province_check_out_request.province_operator_system.user.city.name + province_check_out_request.province_number = province_check_out_request.province_operator_system.user.province.id + province_check_out_request.province_name = province_check_out_request.province_operator_system.user.province.name + province_check_out_request.save() + + for province_check_request in province_check_requests: + province_check_request.city_number = province_check_request.province_operator_system.user.city.id + province_check_request.city_name = province_check_request.province_operator_system.user.city.name + province_check_request.province_number = province_check_request.province_operator_system.user.province.id + province_check_request.province_name = province_check_request.province_operator_system.user.province.name + province_check_request.save() + + for share_of_allocation in share_of_allocations: + share_of_allocation.province_number = share_of_allocation.province.id + share_of_allocation.province_name = share_of_allocation.province.name + share_of_allocation.save() + + for kill_request in kill_requests: + kill_request.city_number = kill_request.kill_house.system_address.city.id + kill_request.city_name = kill_request.kill_house.system_address.city.name + kill_request.province_number = kill_request.kill_house.system_address.province.id + kill_request.province_name = kill_request.kill_house.system_address.province.name + kill_request.save() + + for kill_request_factor in kill_request_factors: + kill_request_factor.city_number = kill_request_factor.kill_request.kill_house.system_address.city.id + kill_request_factor.city_name = kill_request_factor.kill_request.kill_house.system_address.city.name + kill_request_factor.province_number = kill_request_factor.kill_request.kill_house.system_address.province.id + kill_request_factor.province_name = kill_request_factor.kill_request.kill_house.system_address.province.name + kill_request_factor.save() + + for kill_request_payment_factor in kill_request_payment_factors: + kill_request_payment_factor.city_number = kill_request_payment_factor.kill_request_factor.kill_request.kill_house.system_address.city.id + kill_request_payment_factor.city_name = kill_request_payment_factor.kill_request_factor.kill_request.kill_house.system_address.city.name + kill_request_payment_factor.province_number = kill_request_payment_factor.kill_request_factor.kill_request.kill_house.system_address.province.id + kill_request_payment_factor.province_name = kill_request_payment_factor.kill_request_factor.kill_request.kill_house.system_address.province.name + kill_request_payment_factor.save() + + for province_kill_request in province_kill_requests: + province_kill_request.city_number = province_kill_request.kill_request.kill_house.system_address.city.id + province_kill_request.city_name = province_kill_request.kill_request.kill_house.system_address.city.name + province_kill_request.province_number = province_kill_request.kill_request.kill_house.system_address.province.id + province_kill_request.province_name = province_kill_request.kill_request.kill_house.system_address.province.name + province_kill_request.save() + + for kill_house_request in kill_house_requests: + kill_house_request.city_number = kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + kill_house_request.city_name = kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + kill_house_request.province_number = kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + kill_house_request.province_name = kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + kill_house_request.save() + + for kill_house_check_request in kill_house_check_requests: + kill_house_check_request.city_number = kill_house_check_request.province_kill_request.kill_request.kill_house.system_address.city.id + kill_house_check_request.city_name = kill_house_check_request.province_kill_request.kill_request.kill_house.system_address.city.name + kill_house_check_request.province_number = kill_house_check_request.province_kill_request.kill_request.kill_house.system_address.province.id + kill_house_check_request.province_name = kill_house_check_request.province_kill_request.kill_request.kill_house.system_address.province.name + kill_house_check_request.save() + + for assignment_information in assignment_informations: + assignment_information.city_number = assignment_information.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + assignment_information.city_name = assignment_information.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + assignment_information.province_number = assignment_information.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + assignment_information.province_name = assignment_information.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + assignment_information.save() + + for province_check_information in province_check_informations: + province_check_information.city_number = province_check_information.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + province_check_information.city_name = province_check_information.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + province_check_information.province_number = province_check_information.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + province_check_information.province_name = province_check_information.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + province_check_information.save() + + for province_factor in province_factors: + province_factor.city_number = province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + province_factor.city_name = province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + province_factor.province_number = province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + province_factor.province_name = province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + province_factor.save() + + for kill_house_factor in kill_house_factors: + kill_house_factor.city_number = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + kill_house_factor.city_name = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + kill_house_factor.province_number = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + kill_house_factor.province_name = kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + kill_house_factor.save() + + for province_check_kill_house_factor in province_check_kill_house_factors: + province_check_kill_house_factor.city_number = province_check_kill_house_factor.kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.id + province_check_kill_house_factor.city_name = province_check_kill_house_factor.kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.city.name + province_check_kill_house_factor.province_number = province_check_kill_house_factor.kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.id + province_check_kill_house_factor.province_name = province_check_kill_house_factor.kill_house_factor.province_factor.province_check_info.kill_house_assignment.kill_house_request.province_kill_request.kill_request.kill_house.system_address.province.name + province_check_kill_house_factor.save() + + for deposit_allocation in deposit_allocations: + deposit_allocation.city_number = deposit_allocation.poultry.poultry.address.city.id + deposit_allocation.city_name = deposit_allocation.poultry.poultry.address.city.name + deposit_allocation.province_number = deposit_allocation.poultry.poultry.address.province.id + deposit_allocation.province_name = deposit_allocation.poultry.poultry.address.province.name + deposit_allocation.save() + + for inspector in inspectors: + inspector.city_number = inspector.address.city.id + inspector.city_name = inspector.address.city.name + inspector.province_number = inspector.address.province.id + inspector.province_name = inspector.address.province.name + inspector.save() + + for inspector_check in inspector_checks: + inspector_check.city_number = inspector_check.poultry_request.poultry.address.city.id + inspector_check.city_name = inspector_check.poultry_request.poultry.address.city.name + inspector_check.province_number = inspector_check.poultry_request.poultry.address.province.id + inspector_check.province_name = inspector_check.poultry_request.poultry.address.province.name + inspector_check.save() + + for vet in vets: + vet.city_number = vet.user.city.id + vet.city_name = vet.user.city.name + vet.province_number = vet.user.province.id + vet.province_name = vet.user.province.name + vet.save() + + for kill_house_vet in kill_house_vets: + kill_house_vet.city_number = kill_house_vet.vet.user.city.id + kill_house_vet.city_name = kill_house_vet.vet.user.city.name + kill_house_vet.province_number = kill_house_vet.vet.user.province.id + kill_house_vet.province_name = kill_house_vet.vet.user.province.name + kill_house_vet.save() + + for vet_check_request in vet_check_requests: + vet_check_request.city_number = vet_check_request.kill_house_vet.vet.user.city.id + vet_check_request.city_name = vet_check_request.kill_house_vet.vet.user.city.name + vet_check_request.province_number = vet_check_request.kill_house_vet.vet.user.province.id + vet_check_request.province_name = vet_check_request.kill_house_vet.vet.user.province.name + vet_check_request.save() + + for vet_farm in vet_farms: + vet_farm.city_number = vet_farm.poultry.address.city.id + vet_farm.city_name = vet_farm.poultry.address.city.name + vet_farm.province_number = vet_farm.poultry.address.province.id + vet_farm.province_name = vet_farm.poultry.address.province.name + vet_farm.save() + + for vet_farm_inspection in vet_farm_inspections: + vet_farm_inspection.city_number = vet_farm_inspection.poultry_hatching.poultry.address.city.id + vet_farm_inspection.city_name = vet_farm_inspection.poultry_hatching.poultry.address.city.name + vet_farm_inspection.province_number = vet_farm_inspection.poultry_hatching.poultry.address.province.id + vet_farm_inspection.province_name = vet_farm_inspection.poultry_hatching.poultry.address.province.name + vet_farm_inspection.save() + + for admin in admins: + admin.city_number = admin.user.city.id + admin.city_name = admin.user.city.name + admin.province_number = admin.user.province.id + admin.province_name = admin.user.province.name + admin.save() + + for jahad in jahads: + jahad.city_number = jahad.user.city.id + jahad.city_name = jahad.user.city.name + jahad.province_number = jahad.user.province.id + jahad.province_name = jahad.user.province.name + jahad.save() + + for city_jahad in city_jahads: + city_jahad.city_number = city_jahad.user.city.id + city_jahad.city_name = city_jahad.user.city.name + city_jahad.province_number = city_jahad.user.province.id + city_jahad.province_name = city_jahad.user.province.name + city_jahad.save() + + for goverment in goverments: + goverment.city_number = goverment.user.city.id + goverment.city_name = goverment.user.city.name + goverment.province_number = goverment.user.province.id + goverment.province_name = goverment.user.province.name + goverment.save() + + for vet_superviser in vet_supervisers: + vet_superviser.city_number = vet_superviser.user.city.id + vet_superviser.city_name = vet_superviser.user.city.name + vet_superviser.province_number = vet_superviser.user.province.id + vet_superviser.province_name = vet_superviser.user.province.name + vet_superviser.save() + + for province_allow_kill_house_register in province_allow_kill_house_registers: + province_allow_kill_house_register.city_number = province_allow_kill_house_register.kill_house.system_address.city.id + province_allow_kill_house_register.city_name = province_allow_kill_house_register.kill_house.system_address.city.name + province_allow_kill_house_register.province_number = province_allow_kill_house_register.kill_house.system_address.province.id + province_allow_kill_house_register.province_name = province_allow_kill_house_register.kill_house.system_address.province.name + province_allow_kill_house_register.save() + + for province_allow_poultry_choose_kill_house in province_allow_poultry_choose_kill_houses: + province_allow_poultry_choose_kill_house.city_number = province_allow_poultry_choose_kill_house.poultry.address.city.id + province_allow_poultry_choose_kill_house.city_name = province_allow_poultry_choose_kill_house.poultry.address.city.name + province_allow_poultry_choose_kill_house.province_number = province_allow_poultry_choose_kill_house.poultry.address.province.id + province_allow_poultry_choose_kill_house.province_name = province_allow_poultry_choose_kill_house.poultry.address.province.name + province_allow_poultry_choose_kill_house.save() + + for province_allow_poultry_auto in province_allow_poultry_auto_sell: + province_allow_poultry_auto.city_number = province_allow_poultry_auto.poultry.address.city.id + province_allow_poultry_auto.city_name = province_allow_poultry_auto.poultry.address.city.name + province_allow_poultry_auto.province_number = province_allow_poultry_auto.poultry.address.province.id + province_allow_poultry_auto.province_name = province_allow_poultry_auto.poultry.address.province.name + province_allow_poultry_auto.save() + + for kill_house_daily_quota in kill_house_daily_quotas: + kill_house_daily_quota.city_number = kill_house_daily_quota.kill_house.system_address.city.id + kill_house_daily_quota.city_name = kill_house_daily_quota.kill_house.system_address.city.name + kill_house_daily_quota.province_number = kill_house_daily_quota.kill_house.system_address.province.id + kill_house_daily_quota.province_name = kill_house_daily_quota.kill_house.system_address.province.name + kill_house_daily_quota.save() + + for province_auto_allocation in province_auto_allocations: + province_auto_allocation.city_number = province_auto_allocation.daily_quota.kill_house.system_address.city.id + province_auto_allocation.city_name = province_auto_allocation.daily_quota.kill_house.system_address.city.name + province_auto_allocation.province_number = province_auto_allocation.daily_quota.kill_house.system_address.province.id + province_auto_allocation.province_name = province_auto_allocation.daily_quota.kill_house.system_address.province.name + province_auto_allocation.save() diff --git a/panel/migrations/0001_initial.py b/panel/migrations/0001_initial.py new file mode 100644 index 0000000..f01c322 --- /dev/null +++ b/panel/migrations/0001_initial.py @@ -0,0 +1,3101 @@ +# Generated by Django 3.2.13 on 2023-09-18 19:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('notification', '0001_initial'), + ('auth', '0012_alter_user_first_name_max_length'), + ('authentication', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='CityOperator', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('city_operator_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('phone', models.CharField(max_length=20, null=True)), + ('unit_name', models.CharField(max_length=50, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_system_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityoperator_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityoperator_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_operator_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_operator_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CityOperatorCheckRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('city_operator_system_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('city_operator_check_request_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('allow_hatching', models.BooleanField(null=True)), + ('show_province', models.BooleanField(default=True)), + ('province_accept', models.BooleanField(default=False)), + ('province_state', models.CharField(default='pending', max_length=20)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('city_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_city_operator', to='authentication.userprofile')), + ('city_operator_system', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_city_operator', to='panel.cityoperator')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityoperatorcheckrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityoperatorcheckrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Guilds', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('provincial_government_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('guilds_id', models.CharField(max_length=50, null=True)), + ('license_number', models.CharField(max_length=50, null=True)), + ('guilds_name', models.CharField(max_length=100, null=True)), + ('type_activity', models.CharField(max_length=100, null=True)), + ('area_activity', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('steward', models.BooleanField(default=False)), + ('centers_allocation', models.JSONField(null=True)), + ('kill_house_centers_allocation', models.JSONField(null=True)), + ('allocation_limit', models.BigIntegerField(null=True)), + ('limitation_allocation', models.BooleanField(default=False)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Hall', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('hall_number', models.IntegerField(default=1)), + ], + ), + migrations.CreateModel( + name='InspectorOperator', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('inspector_operator_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('active', models.BooleanField(default=True)), + ('identity_documents', models.JSONField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('id_number', models.IntegerField(default=1)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspector_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspectoroperator_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspectoroperator_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspector_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_inspector_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Itransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('transfer_amount', models.FloatField(null=True)), + ('transaction_type', models.CharField(max_length=20, null=True)), + ('payment_code', models.BigIntegerField(default=0, null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('make_location_state', models.CharField(max_length=20, null=True)), + ('file_id', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='itransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='itransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('system_address_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_operator_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_id_key', models.IntegerField(null=True)), + ('shift_work_from', models.CharField(max_length=50, null=True)), + ('shift_work_to', models.CharField(max_length=50, null=True)), + ('name', models.CharField(max_length=50, null=True)), + ('car', models.JSONField(default=dict, null=True)), + ('capacity', models.FloatField(default=0)), + ('killing_race', models.CharField(max_length=20, null=True)), + ('phone', models.CharField(max_length=20, null=True)), + ('killer', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouse_address', to='authentication.address')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouse_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseADDCAR', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('driver_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_add_car_id_key', models.IntegerField(null=True)), + ('status', models.CharField(default='inactive', max_length=50)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseaddcar_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseAssignmentInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_check_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_request_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_kill_house_assingment_information_id_key', models.IntegerField(null=True)), + ('car_weight_without_load', models.FloatField(default=0)), + ('car_weight_without_load_image', models.CharField(max_length=500, null=True)), + ('car_weight_with_load', models.FloatField(default=0)), + ('car_weight_with_load_image', models.CharField(max_length=500, null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('net_weight', models.FloatField(default=0)), + ('exploited_carcass', models.FloatField(default=0)), + ('state', models.CharField(default='pending', max_length=15)), + ('poultry', models.BooleanField(default=False)), + ('city', models.BooleanField(default=False)), + ('province', models.BooleanField(default=False)), + ('unusual_casualties', models.BooleanField(default=False)), + ('real_quantity', models.IntegerField(default=0)), + ('importer', models.JSONField(default=dict, null=True)), + ('protest_time', models.DateTimeField(null=True)), + ('weight_withs_losses', models.FloatField(default=0, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentinformation_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseDailyQuota', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_id_foreign_key', models.IntegerField(null=True)), + ('killer_kill_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_daily_quota_id_key', models.IntegerField(null=True)), + ('percent', models.FloatField(default=0)), + ('quantity', models.BigIntegerField(default=0)), + ('remain_quantity', models.BigIntegerField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousedailyquota_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percent_killhouse_daily_quota', to='panel.killhouse')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseFactorToPoultry', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('payment_code', models.CharField(max_length=100, null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('payment_state', models.CharField(max_length=50, null=True)), + ('payment_method', models.CharField(max_length=50, null=True)), + ('factor_image', models.CharField(max_length=500, null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('importer', models.CharField(max_length=100, null=True)), + ('archive_state', models.CharField(default='pending', max_length=50)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefactortopoultry_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefactortopoultry_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseFactorToProvince', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_factor_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_factor_to_province_id_key', models.IntegerField(null=True)), + ('payment_code', models.CharField(max_length=100, null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('payment_state', models.CharField(max_length=50, null=True)), + ('payment_method', models.CharField(max_length=50, null=True)), + ('factor_image', models.CharField(max_length=500, null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('importer', models.CharField(max_length=100, null=True)), + ('archive_state', models.CharField(default='pending', max_length=50)), + ('first_payment', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefactortoprovince_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefactortoprovince_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('killhouse_user_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_id_foreign_key', models.IntegerField(null=True)), + ('province_request_id_foreign_key', models.IntegerField(null=True)), + ('province_kill_request_id_foreign_key', models.IntegerField(null=True)), + ('add_car_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_request_id_key', models.IntegerField(null=True)), + ('capacity', models.BigIntegerField(default=0)), + ('quantity', models.BigIntegerField(default=0)), + ('bar_code', models.BigIntegerField(null=True)), + ('fee', models.FloatField(default=0, null=True)), + ('time', models.CharField(max_length=20, null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('vet_state', models.CharField(default='pending', max_length=20)), + ('active_state', models.CharField(default='active', max_length=20)), + ('assignment_state_archive', models.CharField(default='pending', max_length=20)), + ('show_kill_house', models.CharField(default='pending', max_length=20)), + ('car', models.JSONField(default=dict, null=True)), + ('kill_house_message', models.TextField(max_length=1000, null=True)), + ('allocation_state', models.CharField(max_length=20, null=True)), + ('auction', models.BooleanField(default=False)), + ('role', models.JSONField(null=True)), + ('clearance_code', models.CharField(max_length=200, null=True)), + ('traffic_code', models.CharField(max_length=200, null=True)), + ('registrar_clearance_code', models.JSONField(null=True)), + ('editor_traffic_code', models.JSONField(null=True)), + ('bar_remover', models.JSONField(null=True)), + ('accepted_real_quantity', models.BigIntegerField(default=0)), + ('accepted_real_weight', models.FloatField(default=0)), + ('message', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('add_car', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_add_car', to='panel.killhouseaddcar')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequest_createdby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseRequestAction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fee', models.FloatField(default=0, null=True)), + ('date', models.DateTimeField(null=True)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestaction_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_auction_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseRequestExchangeReserve', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchangereserve_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_exchange_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchangereserve_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseVet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('vet_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_vet_id_key', models.IntegerField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousevet_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_vet', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousevet_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseWareHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('bar_quantity', models.BigIntegerField(default=0)), + ('allocated_quantity', models.BigIntegerField(default=0)), + ('bar_live_weight', models.FloatField(default=0)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('updated_number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('updated_weight_of_carcasses', models.FloatField(default=0)), + ('ave_weight_of_carcasses', models.FloatField(default=0)), + ('update_ave_weight_of_carcasses', models.FloatField(default=0)), + ('free_bar_quantity', models.BigIntegerField(default=0)), + ('number_of_free_carcasses', models.BigIntegerField(default=0)), + ('free_weight_of_carcasses', models.FloatField(default=0)), + ('total_bar_quantity', models.BigIntegerField(default=0)), + ('total_number_of_carcasses', models.BigIntegerField(default=0)), + ('update_total_number_of_carcasses', models.BigIntegerField(default=0)), + ('total_weight_of_carcasses', models.FloatField(default=0)), + ('update_total_weight_of_carcasses', models.FloatField(default=0)), + ('allocated_total_number_of_carcasses', models.BigIntegerField(default=0)), + ('allocated_total_weight_of_carcasses', models.FloatField(default=0)), + ('remain_total_number_of_carcasses', models.BigIntegerField(default=0)), + ('remain_total_weight_of_carcasses', models.FloatField(default=0)), + ('final_registration', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousewarehouse_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ware_house_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousewarehouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('slaughter_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_id_key', models.IntegerField(null=True)), + ('kill_capacity', models.IntegerField(null=True)), + ('remain_quantity_for_poultry', models.IntegerField(default=0)), + ('remain_quantity', models.IntegerField(null=True)), + ('recive_time', models.CharField(max_length=50, null=True)), + ('recive_date', models.DateTimeField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('province_state', models.CharField(default='pending', max_length=20)), + ('province_quantity', models.IntegerField(null=True)), + ('cars', models.JSONField(default=dict)), + ('buy_type', models.JSONField(default=dict, null=True)), + ('weight', models.CharField(max_length=200, null=True)), + ('weight_type', models.JSONField(default=dict, null=True)), + ('chicken_breed', models.CharField(max_length=200, null=True)), + ('old_chicken_breed', models.CharField(max_length=200, null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('Index_weight', models.FloatField(null=True)), + ('first_average_weight', models.FloatField(default=0)), + ('second_average_weight', models.FloatField(default=0)), + ('factor_amount', models.FloatField(default=0)), + ('allocated_number', models.FloatField(default=0)), + ('factor_deposit', models.FloatField(default=0)), + ('debt', models.BooleanField(default=False)), + ('priority', models.BooleanField(default=False)), + ('debt_amount', models.FloatField(default=0)), + ('sms_payment', models.BooleanField(default=False)), + ('automatic', models.BooleanField(default=False)), + ('automatic_debt', models.BooleanField(default=False)), + ('payment_info', models.JSONField(null=True)), + ('registrar', models.JSONField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('slaughter_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughter_kill_req', to='panel.killhouse')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillRequestFactor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_request_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_factor_id_key', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('amount', models.FloatField(default=0)), + ('minimum_amount', models.FloatField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactor_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='factor_kill_req', to='panel.killrequest')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactor_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LastUpdate', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('poultry_hatching', models.JSONField(null=True)), + ], + ), + migrations.CreateModel( + name='Poultry', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('owner_id_foreign_key', models.IntegerField(null=True)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('city_operator', models.CharField(max_length=150, null=True)), + ('unit_name', models.CharField(max_length=100, null=True)), + ('password', models.CharField(max_length=100, null=True)), + ('gis_code', models.CharField(max_length=30, null=True)), + ('operating_licence_capacity', models.BigIntegerField(default=0)), + ('number_of_halls', models.IntegerField(default=0)), + ('tenant', models.BooleanField(default=False, null=True)), + ('has_tenant', models.BooleanField(default=False, null=True)), + ('person_type', models.CharField(max_length=10, null=True)), + ('economic_code', models.CharField(max_length=30, null=True)), + ('system_code', models.CharField(max_length=20, null=True)), + ('epidemiological_code', models.CharField(max_length=20, null=True)), + ('breeding_unique_id', models.CharField(max_length=20, null=True)), + ('total_capacity', models.BigIntegerField(default=0)), + ('licence_number', models.CharField(max_length=20, null=True)), + ('health_certificate_number', models.CharField(max_length=20, null=True)), + ('number_of_requests', models.BigIntegerField(default=0)), + ('hatching_date', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 605532))), + ('last_party_date', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 605532))), + ('number_of_incubators', models.BigIntegerField(default=0)), + ('herd_age_by_day', models.IntegerField(default=0)), + ('herd_age_by_week', models.IntegerField(default=0)), + ('number_of_party', models.IntegerField(default=0)), + ('communication_type', models.CharField(max_length=30, null=True)), + ('cooperative', models.CharField(max_length=50, null=True)), + ('date_of_register', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 605532))), + ('unit_status', models.CharField(max_length=20, null=True)), + ('active', models.BooleanField(default=True)), + ('identity_documents', models.JSONField(null=True)), + ('samasat_user_code', models.CharField(max_length=20, null=True)), + ('base_order', models.BigIntegerField(null=True)), + ('incubation_date', models.DateTimeField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('city', models.IntegerField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('wallet_id_foreign_key', models.IntegerField(default=1)), + ('poultry_id_key', models.IntegerField(default=1)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_system_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_modifiedby', to=settings.AUTH_USER_MODEL)), + ('owner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_owner', to='panel.poultry')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryAssignmentInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('car_weight_without_load', models.FloatField(default=0)), + ('car_weight_without_load_image', models.CharField(max_length=500, null=True)), + ('car_weight_with_load', models.FloatField(default=0)), + ('car_weight_with_load_image', models.CharField(max_length=500, null=True)), + ('net_weight', models.FloatField(default=0)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryassignmentinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryassignmentinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryHatching', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('poultry_hatching_id_key', models.IntegerField(null=True)), + ('quantity', models.BigIntegerField(default=0)), + ('losses', models.BigIntegerField(default=0)), + ('left_over', models.BigIntegerField(null=True)), + ('request_left_over', models.BigIntegerField(default=0)), + ('hall', models.IntegerField(default=0)), + ('date', models.DateTimeField(null=True)), + ('chicken_breed', models.CharField(max_length=200, null=True)), + ('period', models.BigIntegerField(default=0, null=True)), + ('allow_hatching', models.CharField(default='pending', max_length=20)), + ('state', models.CharField(default='pending', max_length=50)), + ('archive', models.BooleanField(default=False)), + ('message', models.CharField(max_length=500, null=True)), + ('registrar', models.JSONField(null=True)), + ('breed', models.JSONField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('last_change', models.JSONField(null=True)), + ('chicken_age', models.IntegerField(default=1)), + ('latest_hatching_change', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryhatching_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryhatching_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_hatching_user', to='panel.poultry')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('city_operator_id_foreign_key', models.IntegerField(null=True)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('poultry_hatching_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_key', models.IntegerField(null=True)), + ('quantity', models.BigIntegerField(default=0)), + ('previous_quantity', models.BigIntegerField(default=0)), + ('remain_quantity', models.BigIntegerField(default=0)), + ('first_quantity', models.BigIntegerField(default=0)), + ('losses', models.BigIntegerField(default=0)), + ('send_date', models.DateTimeField(null=True)), + ('chicken_breed', models.CharField(max_length=200, null=True)), + ('Index_weight', models.FloatField(null=True)), + ('state', models.JSONField(default=dict, null=True)), + ('state_process', models.CharField(default='pending', max_length=50)), + ('province_state', models.CharField(default='pending', max_length=50)), + ('order_code', models.BigIntegerField(null=True)), + ('general_order_code', models.BigIntegerField(null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('inspector', models.CharField(max_length=30, null=True)), + ('union', models.BooleanField(default=False)), + ('awaiting_payment', models.BooleanField(default=False)), + ('assignment', models.BooleanField(default=False)), + ('auction', models.BooleanField(default=False)), + ('fee', models.FloatField(default=0)), + ('final_state', models.CharField(default='pending', max_length=50)), + ('cell_type', models.JSONField(default=dict, null=True)), + ('kill_house_list', models.JSONField(null=True)), + ('registrar', models.JSONField(null=True)), + ('buyer', models.JSONField(null=True)), + ('out', models.BooleanField(default=False)), + ('vet', models.BooleanField(default=False)), + ('archive', models.BooleanField(default=False)), + ('selling_without_city', models.BooleanField(default=False)), + ('clearance_code', models.BigIntegerField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('city_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_city_operator', to='panel.cityoperator')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_hatching', to='panel.poultryhatching')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_poultry', to='panel.poultry')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryRequestExchange', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0, null=True)), + ('send_date', models.DateTimeField(null=True)), + ('hatching_date', models.DateTimeField(null=True)), + ('chicken_breed', models.CharField(max_length=20, null=True)), + ('Index_weight', models.FloatField(null=True)), + ('fee', models.FloatField(null=True)), + ('order_code', models.IntegerField(null=True)), + ('longitude', models.FloatField(default=0)), + ('latitude', models.FloatField(default=0)), + ('address', models.TextField()), + ('age', models.IntegerField(default=0, null=True)), + ('inspector', models.CharField(max_length=30, null=True)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestexchange_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestexchange_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_exchange', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PriceAnalysis', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('corn_percent', models.FloatField(default=0, null=True)), + ('corn_free_price', models.FloatField(default=0, null=True)), + ('corn_Ration_free_price', models.FloatField(default=0, null=True)), + ('corn_total_free_price', models.FloatField(default=0, null=True)), + ('Soy_free_price', models.FloatField(default=0, null=True)), + ('Soy_total_free_price', models.FloatField(default=0, null=True)), + ('Soy_Ration_free_price', models.FloatField(default=0, null=True)), + ('Soy_percent', models.FloatField(default=0, null=True)), + ('Oil_percent', models.FloatField(default=0, null=True)), + ('Oil_free_price', models.FloatField(default=0, null=True)), + ('Oil_total_free_price', models.FloatField(default=0, null=True)), + ('Oil_Ration_free_price', models.FloatField(default=0, null=True)), + ('Dicalcium_free_price', models.FloatField(default=0, null=True)), + ('Dicalcium_total_free_price', models.FloatField(default=0, null=True)), + ('Dicalcium_Ration_free_price', models.FloatField(default=0, null=True)), + ('Dicalcium_percent', models.FloatField(default=0, null=True)), + ('Carbonate_free_price', models.FloatField(default=0, null=True)), + ('Carbonate_total_free_price', models.FloatField(default=0, null=True)), + ('Carbonate_Ration_free_price', models.FloatField(default=0, null=True)), + ('Carbonate_percent', models.FloatField(default=0, null=True)), + ('mineral_supplement_percent', models.FloatField(default=0, null=True)), + ('mineral_Ration_supplement_free_price', models.FloatField(default=0, null=True)), + ('mineral_supplement_free_price', models.FloatField(default=0, null=True)), + ('mineral_supplement_total_free_price', models.FloatField(default=0, null=True)), + ('vitamin_supplement_free_price', models.FloatField(default=0, null=True)), + ('vitamin_supplement_total_free_price', models.FloatField(default=0, null=True)), + ('vitamin_supplement_percent', models.FloatField(default=0, null=True)), + ('vitamin_Ration_free_supplement_percent', models.FloatField(default=0, null=True)), + ('baking_soda_free_price', models.FloatField(default=0, null=True)), + ('baking_soda_total_free_price', models.FloatField(default=0, null=True)), + ('baking_Ration_soda_free_price', models.FloatField(default=0, null=True)), + ('baking_soda_percent', models.FloatField(default=0, null=True)), + ('Salt_Ration_free_price', models.FloatField(default=0, null=True)), + ('Salt_Ration_total_free_price', models.FloatField(default=0, null=True)), + ('Salt_free_total_price', models.FloatField(default=0, null=True)), + ('Salt_free_price', models.FloatField(default=0, null=True)), + ('Salt_percent', models.FloatField(default=0, null=True)), + ('metiunin_Ration_free_price', models.FloatField(default=0, null=True)), + ('metiunin_free_price', models.FloatField(default=0, null=True)), + ('metiunin_total_free_price', models.FloatField(default=0, null=True)), + ('metiunin_percent', models.FloatField(default=0, null=True)), + ('Lysine_Ration_free_price', models.FloatField(default=0, null=True)), + ('Lysine_free_price', models.FloatField(default=0, null=True)), + ('Lysine_total_free_price', models.FloatField(default=0, null=True)), + ('Lysine_percent', models.FloatField(default=0, null=True)), + ('threonine_free_price', models.FloatField(default=0, null=True)), + ('threonine_total_free_price', models.FloatField(default=0, null=True)), + ('threonine_Ration_free_price', models.FloatField(default=0, null=True)), + ('threonine_percent', models.FloatField(default=0, null=True)), + ('Antifungal_free_price', models.FloatField(default=0, null=True)), + ('Antifungal_total_free_price', models.FloatField(default=0, null=True)), + ('Antifungal_Ration_free_price', models.FloatField(default=0, null=True)), + ('Antifungal_percent', models.FloatField(default=0, null=True)), + ('inulin_free_price', models.FloatField(default=0, null=True)), + ('inulin_total_free_price', models.FloatField(default=0, null=True)), + ('inulin_Ration_free_price', models.FloatField(default=0, null=True)), + ('inulin_percent', models.FloatField(default=0, null=True)), + ('Fire_emulsion_free_price', models.FloatField(default=0, null=True)), + ('Fire_total_emulsion_free_price', models.FloatField(default=0, null=True)), + ('Fire_emulsion_Ration_free_price', models.FloatField(default=0, null=True)), + ('Fire_emulsion_percent', models.FloatField(default=0, null=True)), + ('Colleen_free_price', models.FloatField(default=0, null=True)), + ('Colleen_total_free_price', models.FloatField(default=0, null=True)), + ('Colleen_Ration_free_price', models.FloatField(default=0, null=True)), + ('Colleen_percent', models.FloatField(default=0, null=True)), + ('total_price', models.FloatField(default=0, null=True)), + ('total_Ration_free_price', models.FloatField(default=0, null=True)), + ('Vaccination_period', models.FloatField(default=0, null=True)), + ('Multivitamin_course', models.FloatField(default=0, null=True)), + ('period_chicken', models.FloatField(default=0, null=True)), + ('directors_office', models.FloatField(default=0, null=True)), + ('Water_gas_electricity_period', models.FloatField(default=0, null=True)), + ('Water_gas_the_current_cost_of_the_period_unit', models.FloatField(default=0, null=True)), + ('Course_repairs', models.FloatField(default=0, null=True)), + ('Course_loss', models.FloatField(default=0, null=True)), + ('motfar_ga_durah', models.FloatField(default=0, null=True)), + ('Paper_reel', models.FloatField(default=0, null=True)), + ('Course_disinfection', models.FloatField(default=0, null=True)), + ('Lamp', models.FloatField(default=0, null=True)), + ('total_percent', models.FloatField(default=0, null=True)), + ('total_ration', models.FloatField(default=0, null=True)), + ('chicken_price', models.FloatField(default=0, null=True)), + ], + ), + migrations.CreateModel( + name='ProvinceCheckInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_assignment_id_foreign_key', models.IntegerField(null=True)), + ('province_operator_id_foreign_key', models.IntegerField(null=True)), + ('province_check_information_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_assignment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_assign', to='panel.killhouseassignmentinformation')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_assignment', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_assign', to='panel.poultryassignmentinformation')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceCheckOperatorRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_operator_system_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('city_request_poultry_id_foreign_key', models.IntegerField(null=True)), + ('province_operator_check_request_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=50, null=True)), + ('quantity', models.BigIntegerField(default=0, null=True)), + ('fee', models.FloatField(null=True)), + ('total_weight_at_end', models.FloatField(default=0, null=True)), + ('total_cost_at_end', models.FloatField(null=True)), + ('paid_state', models.CharField(default='pending', max_length=20)), + ('province_show_kill_house', models.CharField(default='pending', max_length=20)), + ('factor_state', models.CharField(default='pending', max_length=20)), + ('message', models.CharField(max_length=200, null=True)), + ('financial_archive', models.CharField(default='pending', max_length=20)), + ('deposit_allocation_archive', models.CharField(default='pending', max_length=20)), + ('end_state', models.CharField(default='active', max_length=20)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('city_request_Poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='Poultry_city_request_to_province', to='panel.cityoperatorcheckrequest')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckoperatorrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckoperatorrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_poultry_request', to='panel.poultryrequest')), + ('province_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_province_operator', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceFactorToKillHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('total_weight', models.FloatField(default=0)), + ('weight', models.FloatField(default=0)), + ('factor_fee', models.FloatField(default=0)), + ('factor_bar_code', models.BigIntegerField(null=True)), + ('factor_date', models.DateTimeField(null=True)), + ('total_price', models.FloatField(default=0)), + ('province_input_amount', models.FloatField(default=0)), + ('province_input_amount_type', models.CharField(max_length=20, null=True)), + ('province_wage', models.FloatField(default=0)), + ('previous_amount', models.FloatField(default=0)), + ('decreasing_amount', models.FloatField(default=0)), + ('today_price', models.FloatField(default=0)), + ('kill_house_factor_payment_remain', models.FloatField(default=0)), + ('real_weight', models.FloatField(default=0)), + ('shares', models.JSONField(default=dict, null=True)), + ('paid_state', models.CharField(default='pending', max_length=20)), + ('pay_for', models.CharField(max_length=20, null=True)), + ('kill_house_factor_info', models.CharField(default='pending', max_length=20)), + ('reason', models.TextField(null=True)), + ('sum_state', models.CharField(default='pending', max_length=20)), + ('factor_person_type', models.CharField(default='pending', max_length=20)), + ('province_check_info_id_foreign_key', models.IntegerField(null=True)), + ('province_check_req_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('province_factor_to_kill_house_id_key', models.IntegerField(null=True)), + ('out', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('bank', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bank_card_province', to='authentication.bankcard')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincefactortokillhouse_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincefactortokillhouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceFactorToKillHouseForPoultry', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('total_weight', models.FloatField(default=0)), + ('weight', models.FloatField(default=0)), + ('factor_fee', models.FloatField(default=0)), + ('factor_bar_code', models.BigIntegerField(null=True)), + ('factor_date', models.DateTimeField(null=True)), + ('total_price', models.FloatField(default=0)), + ('today_price', models.FloatField(default=0)), + ('real_weight', models.FloatField(default=0)), + ('shares', models.JSONField(default=dict, null=True)), + ('paid_state', models.CharField(default='pending', max_length=20)), + ('pay_for', models.CharField(max_length=20, null=True)), + ('kill_house_factor_info', models.CharField(default='pending', max_length=20)), + ('sum_state', models.CharField(default='pending', max_length=20)), + ('out', models.BooleanField(default=False)), + ('bank', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bank_card_poultry', to='authentication.bankcard')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincefactortokillhouseforpoultry_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincefactortokillhouseforpoultry_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province_check_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_info_poultry', to='panel.provincecheckinformation')), + ('province_check_req', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_poultry', to='panel.provincecheckoperatorrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceOperator', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('province_operator_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('phone', models.CharField(max_length=20, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_system_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceoperator_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceoperator_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_operator_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_operator_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Steward', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=True)), + ('allocation_limit', models.BigIntegerField(null=True)), + ('limitation_allocation', models.BooleanField(default=False)), + ('centers_allocation', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_createdby', to=settings.AUTH_USER_MODEL)), + ('guilds', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_guilds', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Vet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('vet_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_profile_vet', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='VetFarm', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('vet_id_foreign_key', models.IntegerField(null=True)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('vet_farm_id_key', models.IntegerField(null=True)), + ('hall', models.IntegerField(default=0)), + ('vetfarm_losses', models.BigIntegerField(default=0)), + ('state', models.CharField(default='pending', max_length=20)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarm_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarm_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_farm_poultry', to='panel.poultry')), + ('vet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_farm_vet', to='panel.vet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='WareHouseFactor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('customer', models.CharField(max_length=50, null=True)), + ('national_code', models.CharField(max_length=20, null=True)), + ('letter_number', models.BigIntegerField(null=True)), + ('letter_number_jahad', models.BigIntegerField(null=True)), + ('date', models.DateTimeField(null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('product_type', models.JSONField(default=dict, null=True)), + ('weight', models.FloatField(default=0, null=True)), + ('fee', models.FloatField(default=0, null=True)), + ('wage', models.FloatField(default=0, null=True)), + ('total_wage', models.FloatField(default=0, null=True)), + ('total_fee', models.FloatField(default=0, null=True)), + ('total_cost', models.FloatField(default=0, null=True)), + ('Complications', models.FloatField(default=0, null=True)), + ('tax', models.FloatField(default=0, null=True)), + ('discount', models.FloatField(default=0, null=True)), + ('name_of_bank_user', models.CharField(max_length=200, null=True)), + ('card', models.CharField(max_length=16, null=True)), + ('shaba', models.CharField(max_length=100, null=True)), + ('state', models.CharField(default='pending', max_length=100)), + ('account', models.CharField(max_length=100, null=True)), + ('mark', models.CharField(default='pending', max_length=100)), + ('considerations', models.TextField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='warehousefactor_createdby', to=settings.AUTH_USER_MODEL)), + ('first_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_first_operator', to='authentication.userprofile')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='warehousefactor_modifiedby', to=settings.AUTH_USER_MODEL)), + ('second_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_second_operator', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Wallet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('inventory', models.FloatField(default=0)), + ('state', models.CharField(default='active', max_length=120)), + ('province_name', models.CharField(max_length=50, null=True)), + ('id_number', models.IntegerField(default=1)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wallet_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wallet_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='WagePayment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_kill_request', models.JSONField(null=True)), + ('payment_type', models.CharField(max_length=50, null=True)), + ('total_amount', models.BigIntegerField(default=0)), + ('payer', models.JSONField(null=True)), + ('tracking_code', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wagepayment_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wagepayment_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='VetSupervisor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('vet_id_foreign_key', models.IntegerField(null=True)), + ('vet_superviser_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supervisor_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetsupervisor_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetsupervisor_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supervisor_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supervisor_bank_info', to='authentication.bankcard')), + ('vet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_supervisor', to='panel.vet')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supervisor_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='VetFarmInspection', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('vet_farm_id_foreign_key', models.IntegerField(null=True)), + ('poultry_hatching_id_foreign_key', models.IntegerField(null=True)), + ('vet_farm_inspection_id_key', models.IntegerField(null=True)), + ('hall', models.IntegerField(default=0)), + ('topic', models.CharField(max_length=500, null=True)), + ('description', models.TextField(null=True)), + ('Losses', models.BigIntegerField(default=0)), + ('image', models.JSONField(null=True)), + ('longitude', models.FloatField(default=0)), + ('latitude', models.FloatField(default=0)), + ('state', models.CharField(default='pending', max_length=20)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarminspection_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarminspection_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_farm_inspection_poultry_hatching', to='panel.poultryhatching')), + ('vet_farm', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_farm_inspection', to='panel.vetfarm')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='VetCheckRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_vet_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_request_id_foreign_key', models.IntegerField(null=True)), + ('vet_check_request_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetcheckrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_vet', to='panel.killhouserequest')), + ('kill_house_vet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_user_vet', to='panel.killhousevet')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetcheckrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='VetCheckAllocations', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('vet_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_request_id_foreign_key', models.IntegerField(null=True)), + ('vet_chick_allocations_id_key', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=50)), + ('reviewer', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetcheckallocations_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='check_kill_house_request', to='panel.killhouserequest')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetcheckallocations_modifiedby', to=settings.AUTH_USER_MODEL)), + ('vet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_check', to='panel.vet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='vet', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='TotalPoultryRequestQuantity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0)), + ('accepted_quantity', models.BigIntegerField(default=0)), + ('first_quantity', models.BigIntegerField(default=0)), + ('city_accepted_quantity', models.BigIntegerField(default=0)), + ('allocated_quantity', models.BigIntegerField(default=0)), + ('number_of_poultry', models.BigIntegerField(default=0)), + ('rejected_quantity', models.BigIntegerField(default=0)), + ('waiting_quantity', models.BigIntegerField(default=0)), + ('number_of_kill_house', models.BigIntegerField(default=0)), + ('input_quantity', models.BigIntegerField(default=0)), + ('assignableQuantity', models.BigIntegerField(default=0)), + ('kill_requests_quantity', models.BigIntegerField(default=0)), + ('date', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 612526))), + ('age_up_45', models.BigIntegerField(default=0, null=True)), + ('total_poultry_request_quantity_id_key', models.IntegerField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalpoultryrequestquantity_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalpoultryrequestquantity_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='StewardWareHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('bar_quantity', models.BigIntegerField(default=0)), + ('allocated_quantity', models.BigIntegerField(default=0)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('real_number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('real_weight_of_carcasses', models.FloatField(default=0)), + ('ave_weight_of_carcasses', models.FloatField(default=0)), + ('allocated_total_number_of_carcasses', models.BigIntegerField(default=0)), + ('allocated_total_weight_of_carcasses', models.FloatField(default=0)), + ('remain_total_number_of_carcasses', models.BigIntegerField(default=0)), + ('remain_total_weight_of_carcasses', models.FloatField(default=0)), + ('final_registration', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardwarehouse_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardwarehouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ware_house_steward', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='StewardAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('real_number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('real_weight_of_carcasses', models.FloatField(default=0)), + ('sell_type', models.CharField(max_length=100, null=True)), + ('seller_type', models.CharField(max_length=100, null=True)), + ('final_registration', models.BooleanField(default=False)), + ('system_registration_code', models.BooleanField(default=False)), + ('registration_code', models.IntegerField(null=True)), + ('logged_registration_code', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=50)), + ('date', models.DateTimeField(null=True)), + ('role', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('guilds', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_allocation_guilds', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_steward_allocation', to='panel.steward')), + ('ware_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ware_house_steward_allocation', to='panel.killhousewarehouse')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SmsLicense', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('hatching', models.BooleanField(default=False)), + ('poultry_request', models.BooleanField(default=False)), + ('city_approval', models.BooleanField(default=False)), + ('province_approval', models.BooleanField(default=False)), + ('kill_request', models.BooleanField(default=False)), + ('province_kill_request', models.BooleanField(default=False)), + ('farm_veterinarian_approval', models.BooleanField(default=False)), + ('kill_house_request', models.BooleanField(default=False)), + ('kill_house_house_veterinarian_approval', models.BooleanField(default=False)), + ('assingment_information', models.BooleanField(default=False)), + ('confirmation_of_assingment_information', models.BooleanField(default=False)), + ('invoicing', models.BooleanField(default=False)), + ('invoice_payment', models.BooleanField(default=False)), + ('invoice_payment_confirmation', models.BooleanField(default=False)), + ('inspector_approval', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='smslicense_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='smslicense_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ShareOfAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_id_foreign_key', models.IntegerField(null=True)), + ('share_of_allocation_id_key', models.IntegerField(null=True)), + ('central_union', models.FloatField(default=0, null=True)), + ('province_union', models.FloatField(default=0, null=True)), + ('city_union', models.FloatField(default=0, null=True)), + ('fanava', models.FloatField(default=0, null=True)), + ('central_control_system', models.FloatField(default=0, null=True)), + ('company', models.FloatField(default=0, null=True)), + ('vet', models.FloatField(default=0, null=True)), + ('total', models.FloatField(default=0, null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('date', models.DateTimeField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shareofallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='shareofallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='share_province', to='authentication.province')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SearchFields', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(max_length=100, null=True)), + ('field_name', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='searchfields_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='searchfields_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ReportingFieldRoleLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fields', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportingfieldrolelimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportingfieldrolelimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('role_name', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='report_role', to='auth.group')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvincialGovernment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('provincial_government_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='government_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincialgovernment_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincialgovernment_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='government_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='government_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='government_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceRequestAction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincerequestaction_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincerequestaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_request_auction_poultry', to='panel.poultryrequest')), + ('province_operator_system', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_province_operator_auction', to='panel.provinceoperator')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvincePercentLeftOver', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincepercentleftover_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincepercentleftover_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='provinceoperator', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='ProvinceKillRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('killhouse_user_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_id_foreign_key', models.IntegerField(null=True)), + ('province_request_id_foreign_key', models.IntegerField(null=True)), + ('province_kill_request_id_key', models.IntegerField(null=True)), + ('quantity', models.BigIntegerField(default=0)), + ('main_quantity', models.BigIntegerField(default=0)), + ('fee', models.FloatField(default=0, null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('vet_state', models.CharField(default='pending', max_length=20)), + ('payment_type', models.CharField(max_length=20, null=True)), + ('payment_dead_line', models.DateTimeField(null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('clearance_code', models.BigIntegerField(null=True)), + ('automatic', models.BooleanField(default=False)), + ('dont_show_kill_house', models.BooleanField(default=False)), + ('reviewer', models.JSONField(null=True)), + ('delete_message', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('wage_pay', models.BooleanField(default=False)), + ('depositor', models.JSONField(null=True)), + ('archive_by_province', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincekillrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_request', to='panel.killrequest')), + ('killhouse_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_user', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincekillrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_province', to='panel.provincecheckoperatorrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceImportKillHouseOutFactors', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('image', models.CharField(max_length=500, null=True)), + ('amount', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceimportkillhouseoutfactors_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_factor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_out', to='panel.provincefactortokillhouse')), + ('kill_house_factor_poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_poultry_out', to='panel.provincefactortokillhouseforpoultry')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceimportkillhouseoutfactors_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province_check', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_request', to='panel.provincecheckoperatorrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='poultry_factor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_factor_poultry', to='panel.provincefactortokillhouseforpoultry'), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_check_info', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_info', to='panel.provincecheckinformation'), + ), + migrations.AddField( + model_name='provincefactortokillhouse', + name='province_check_req', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_province', to='panel.provincecheckoperatorrequest'), + ), + migrations.AddField( + model_name='provincecheckoperatorrequest', + name='province_operator_system', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_province_operator', to='panel.provinceoperator'), + ), + migrations.CreateModel( + name='ProvinceCheckOperatorOutRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_operator_system_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('province_operator_check_out_request_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=50, null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckoperatoroutrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckoperatoroutrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_poultry_out_request', to='panel.poultryrequest')), + ('province_operator_system', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_province_operator_out', to='panel.provinceoperator')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceCheckKillHouseFactor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_factor_id_foreign_key', models.IntegerField(null=True)), + ('province_check_kill_house_factor_id_key', models.IntegerField(null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=500, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckkillhousefactor_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_factor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor', to='panel.killhousefactortoprovince')), + ('kill_house_factor_poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_check_factor_poultry', to='panel.killhousefactortopoultry')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincecheckkillhousefactor_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='provincecheckinformation', + name='province_operator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinc_operator_check_info', to='panel.provinceoperator'), + ), + migrations.CreateModel( + name='ProvinceAutoAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('daily_quota_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('province_kill_request_id_foreign_key', models.IntegerField(null=True)), + ('province_auto_allocation_id_key', models.IntegerField(null=True)), + ('unauthorized_number', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0)), + ('allocation_order_code', models.BigIntegerField(default=0)), + ('state', models.CharField(default='temporary', max_length=50)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceautoallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('daily_quota', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percent_auto_killhouse_daily_quota_province', to='panel.killhousedailyquota')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceautoallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_auto_quantity_province', to='panel.poultryrequest')), + ('province_kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_kill_request_auto_quantity_province', to='panel.provincekillrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowPoultrySellFreeTotal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrysellfreetotal_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrysellfreetotal_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowPoultrySellFree', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('province_allow_poultry_sell_free_id_key', models.IntegerField(null=True)), + ('allow', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrysellfree_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrysellfree_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_poultry_sell_free', to='panel.poultry')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowPoultryChooseKillHouseTotal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('mandatory', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrychoosekillhousetotal_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrychoosekillhousetotal_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowPoultryChooseKillHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('province_allow_poultry_choose_kill_house_id_key', models.IntegerField(null=True)), + ('allow', models.BooleanField(default=False)), + ('mandatory', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrychoosekillhouse_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowpoultrychoosekillhouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_kill_house_register', to='panel.poultry')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseRegisterCar', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('province_allow_kill_house_register_car_id_key', models.IntegerField(null=True)), + ('allow', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregistercar_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_kill_house_register', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregistercar_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseChooseStewardGuilds', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('steward', models.BooleanField(default=False)), + ('guilds', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousechoosestewardguilds_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allow_kill_house_steward_guilds', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousechoosestewardguilds_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Pricing', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('live_chicken_price', models.FloatField(null=True)), + ('dead_chicken_price', models.FloatField(null=True)), + ('major_seller_price', models.FloatField(null=True)), + ('retail_seller_price', models.FloatField(null=True)), + ('floor_price', models.FloatField(null=True)), + ('ceiling_price', models.FloatField(null=True)), + ('role', models.CharField(max_length=20, null=True)), + ('lock', models.BooleanField(default=False)), + ('pricing_id_key', models.IntegerField(null=True)), + ('operator_id_foreign_key', models.IntegerField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pricing_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pricing_modifiedby', to=settings.AUTH_USER_MODEL)), + ('operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pricing_operator', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PovinceInspector', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('inspector_operator_id_foreign_key', models.IntegerField(null=True)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('province_inspector_id_key', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('message', models.CharField(max_length=500, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='povinceinspector_createdby', to=settings.AUTH_USER_MODEL)), + ('inspector_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspector', to='panel.inspectoroperator')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='povinceinspector_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_inspector', to='panel.poultryrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryTenant', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fullname', models.CharField(max_length=150, null=True)), + ('first_name', models.CharField(max_length=200, null=True)), + ('last_name', models.CharField(max_length=200, null=True)), + ('natinal_id', models.CharField(max_length=10, null=True)), + ('mobile', models.CharField(default='', max_length=11, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultrytenant_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultrytenant_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_tenant', to='panel.poultry')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_tenant_bank_info', to='authentication.bankcard')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryRequestExchangeAccept', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(default='pending', max_length=15)), + ('message', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestexchangeaccept_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request_exchange_reserve', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_exchange_kill_house_accept', to='panel.killhouserequestexchangereserve')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestexchangeaccept_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request_exchange', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_exchange_accept', to='panel.poultryrequestexchange')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryRequestAuction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fee', models.FloatField(default=0, null=True)), + ('hour', models.CharField(max_length=10, null=True)), + ('auction_date', models.DateTimeField(null=True)), + ('state', models.CharField(default='inactive', max_length=10)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestauction_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestauction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_auction', to='panel.poultryrequest')), + ('pricing', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_auction_pricing', to='panel.pricing')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PoultryHallProfile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('start_date', models.DateTimeField(null=True)), + ('end_date', models.DateTimeField(null=True)), + ('hall', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hall_poultry_profile', to='panel.hall')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_poultry_profile', to='authentication.systemuserprofile')), + ], + ), + migrations.AddField( + model_name='poultryassignmentinformation', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_assignment', to='panel.poultryrequest'), + ), + migrations.CreateModel( + name='PoultryAllowCityProvince', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_id_foreign_key', models.IntegerField(null=True)), + ('poultry_allow_city_province_id_key', models.IntegerField(null=True)), + ('city', models.BooleanField(default=False)), + ('province', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryallowcityprovince_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryallowcityprovince_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_allow', to='panel.poultry')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='poultry', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='PercentageOfLosses', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('houre', models.IntegerField(default=0)), + ('percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentageoflosses_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentageoflosses_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Penalty', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('cost', models.IntegerField(null=True)), + ('description', models.TextField(null=True)), + ('image', models.CharField(max_length=300, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='penalty_createdby', to=settings.AUTH_USER_MODEL)), + ('itransaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='penalty_itransaction', to='panel.itransaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='penalty_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PaymentDeadLine', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('days', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='paymentdeadline_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='paymentdeadline_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='OperatorLastTimeEnter', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('city_operator_last_time_check', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 603532))), + ('province_operator_last_time_check', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 603532))), + ('kill_house_last_time_check', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 603532))), + ('assignment_last_time_check', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 603532))), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='operatorlasttimeenter_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='operatorlasttimeenter_modifiedby', to=settings.AUTH_USER_MODEL)), + ('operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='operator_last_time_check', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='MostSearch', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('searched_items', models.CharField(max_length=200, null=True)), + ('count', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mostsearch_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mostsearch_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='MonthlyProfitPercentage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('days', models.IntegerField(default=0)), + ('percent', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='monthlyprofitpercentage_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='monthlyprofitpercentage_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillRequestFactorPayment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_request_factor_id_foreign_key', models.IntegerField(null=True)), + ('kill_request_factor_payment_id_key', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('image', models.CharField(max_length=200, null=True)), + ('payment_code', models.BigIntegerField(default=0)), + ('amount', models.FloatField(default=0)), + ('remain_amount', models.FloatField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactorpayment_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_request_factor', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_req_factor', to='panel.killrequestfactor')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killrequestfactorpayment_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhousevet', + name='vet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_vet_user', to='panel.vet'), + ), + migrations.CreateModel( + name='KillHouseRequestExchangeAddCar', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('cars', models.JSONField(default=dict, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchangeaddcar_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_reserve', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_accept_reserve', to='panel.killhouserequestexchangereserve')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchangeaddcar_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseRequestExchange', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0, null=True)), + ('send_date1', models.DateTimeField(null=True)), + ('send_date2', models.DateTimeField(null=True)), + ('chicken_breed', models.JSONField(default=[], null=True)), + ('Index_weight', models.FloatField(default=0, null=True)), + ('fee', models.FloatField(default=0, null=True)), + ('longitude', models.FloatField(default=0)), + ('latitude', models.FloatField(default=0)), + ('address', models.TextField()), + ('age1', models.IntegerField(default=0, null=True)), + ('age2', models.IntegerField(default=0, null=True)), + ('state', models.CharField(default='pending', max_length=15)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchange_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_exchange_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestexchange_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_exchange', to='authentication.userprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseRequestActionWinner', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fee', models.FloatField(default=0, null=True)), + ('quantity', models.BigIntegerField(default=0, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestactionwinner_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request_auction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_auction_kill_house', to='panel.killhouserequestaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequestactionwinner_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhouserequestaction', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_auction_poultry', to='panel.poultryrequest'), + ), + migrations.AddField( + model_name='killhouserequest', + name='kill_house_request_auction_winner', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_winner', to='panel.killhouserequestactionwinner'), + ), + migrations.AddField( + model_name='killhouserequest', + name='kill_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_request_kill_house', to='panel.killrequest'), + ), + migrations.AddField( + model_name='killhouserequest', + name='killhouse_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_user', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouserequest', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouserequest_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_kill_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_kill_house_request', to='panel.provincekillrequest'), + ), + migrations.AddField( + model_name='killhouserequest', + name='province_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_province_request', to='panel.provincecheckoperatorrequest'), + ), + migrations.CreateModel( + name='KillHousePercentageOfLosses', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentageoflosses_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentageoflosses_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHousePercentage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_for_killer_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_percentage_id_key', models.IntegerField(null=True)), + ('percent', models.FloatField(default=0)), + ('last_guilds_update_date', models.CharField(max_length=100, null=True)), + ('guilds_quantity', models.IntegerField(default=0)), + ('guilds_weight', models.FloatField(default=0)), + ('quantity', models.BigIntegerField(default=0)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentage_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percent_killhouse', to='panel.killhouse')), + ('kill_house_for_killer', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killer_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepercentage_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseOperator', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_operator_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('killer', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_system_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseoperator_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseoperator_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_operator_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseFreeBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_name', models.CharField(max_length=100, null=True)), + ('poultry_mobile', models.CharField(max_length=11, null=True)), + ('province', models.CharField(max_length=50, null=True)), + ('city', models.CharField(max_length=50, null=True)), + ('vet_farm_name', models.CharField(max_length=100, null=True)), + ('vet_farm_mobile', models.CharField(max_length=11, null=True)), + ('driver_name', models.CharField(max_length=100, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('car', models.JSONField(null=True)), + ('clearance_code', models.JSONField(null=True)), + ('quantity', models.BigIntegerField(default=0)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('live_weight', models.FloatField(default=0)), + ('bar_image', models.CharField(max_length=200, null=True)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefreebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefreebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhousefactortoprovince', + name='province_factor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_factor_info', to='panel.provincefactortokillhouse'), + ), + migrations.AddField( + model_name='killhousefactortopoultry', + name='province_factor', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_factor_info_poultry', to='panel.provincefactortokillhouseforpoultry'), + ), + migrations.CreateModel( + name='KillHouseDriver', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('driver_name', models.CharField(max_length=500, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('type_car', models.CharField(max_length=50, null=True)), + ('type', models.CharField(max_length=50, null=True)), + ('pelak', models.CharField(max_length=200, null=True)), + ('capocity', models.CharField(max_length=50, null=True)), + ('weight_without_load', models.CharField(max_length=50, null=True)), + ('health_code', models.CharField(max_length=100, null=True)), + ('status', models.CharField(default='inactive', max_length=50)), + ('active', models.BooleanField(default=True)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_driver_id_key', models.IntegerField(null=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('phone', models.CharField(max_length=20, null=True)), + ('registrar', models.JSONField(null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousedriver_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousedriver_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_driver', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driver_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driver_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhousedailyquota', + name='kill_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percent_kill_request_daily_quota', to='panel.killrequest'), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='killer_kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killer_kill_house_daily_quota', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhousedailyquota', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousedailyquota_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.CreateModel( + name='KillHouseCreditors', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('amount', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecreditors_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_creditors', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecreditors_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseComplaint', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=200, null=True)), + ('description', models.TextField()), + ('image', models.JSONField(null=True)), + ('percent', models.FloatField(default=0)), + ('state', models.CharField(default='pending', max_length=20)), + ('message', models.CharField(max_length=20, null=True)), + ('registrar', models.JSONField(null=True)), + ('bar', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bar_information', to='panel.killhouseassignmentinformation')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecomplaint_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecomplaint_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseCheckRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province_kill_request_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_check_request_id_key', models.IntegerField(null=True)), + ('role', models.JSONField(null=True)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=200, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecheckrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousecheckrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('province_kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_kill_house_check', to='panel.provincekillrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='kill_house_check', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_check_req', to='panel.killhousecheckrequest'), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='kill_house_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_assignment', to='panel.killhouserequest'), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentinformation_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.CreateModel( + name='KillHouseAssignmentImages', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('health_certificate_image', models.CharField(max_length=500, null=True)), + ('national_card_image', models.CharField(max_length=500, null=True)), + ('birth_certificate_image', models.CharField(max_length=500, null=True)), + ('police_clearance_image', models.CharField(max_length=500, null=True)), + ('no_addiction_image', models.CharField(max_length=500, null=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentimages_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_images', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseassignmentimages_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='KillHouseAllowVet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_id_foreign_key', models.IntegerField(null=True)), + ('kill_house_allow_vet_id_key', models.IntegerField(null=True)), + ('allow', models.BooleanField(default=False)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseallowvet_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_allow', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseallowvet_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='killhouseaddcar', + name='driver', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_add_car_driver', to='panel.killhousedriver'), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_add_car', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouseaddcar', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouseaddcar_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhouse', + name='kill_house_operator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_kill_house_operator', to='panel.killhouseoperator'), + ), + migrations.AddField( + model_name='killhouse', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouse_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='killhouse', + name='system_address', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhouse_system_address', to='authentication.systemaddress'), + ), + migrations.AddField( + model_name='killhouse', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_killhouse', to='authentication.userprofile'), + ), + migrations.AddField( + model_name='killhouse', + name='userprofile', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_user_kill_house', to='authentication.systemuserprofile'), + ), + migrations.CreateModel( + name='Jahad', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('jahad_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='itransaction', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='itranseaction_wallet', to='panel.wallet'), + ), + migrations.AddField( + model_name='inspectoroperator', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inspector_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='HourLimit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('hour', models.IntegerField(null=True)), + ('active', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hourlimit_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hourlimit_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='HatchingLossesPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchinglossespermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchinglossespermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='hall', + name='poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_hall', to='panel.poultry'), + ), + migrations.CreateModel( + name='GuildsWareHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('bar_quantity', models.BigIntegerField(default=0)), + ('allocated_quantity', models.BigIntegerField(default=0)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('real_number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('real_weight_of_carcasses', models.FloatField(default=0)), + ('ave_weight_of_carcasses', models.FloatField(default=0)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildswarehouse_createdby', to=settings.AUTH_USER_MODEL)), + ('guilds', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ware_house_guilds', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildswarehouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='guilds', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='FunctionExecutor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('func_name', models.CharField(max_length=200, null=True)), + ('time_type', models.CharField(max_length=100, null=True)), + ('cycle', models.IntegerField(default=0)), + ('compare_time', models.DateTimeField(default=datetime.datetime(2023, 9, 18, 19, 32, 12, 656484))), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='functionexecutor_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='functionexecutor_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='FinancialTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(max_length=50, null=True)), + ('cost', models.IntegerField(null=True)), + ('description', models.TextField(null=True)), + ('image', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financialtransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('itransaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financial_transaction', to='panel.itransaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financialtransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='FinancialDocument', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('transaction_details', models.JSONField(null=True)), + ('type', models.CharField(max_length=30, null=True)), + ('cost', models.FloatField(null=True)), + ('description', models.TextField(null=True)), + ('payment_code', models.IntegerField(null=True)), + ('image', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financialdocument_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financialdocument_modifiedby', to=settings.AUTH_USER_MODEL)), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='financial_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='DriverRequestCancel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('message', models.TextField(null=True)), + ('Kill_house_add_car', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cancel_request_car', to='panel.killhouseaddcar')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driverrequestcancel_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cancel_request', to='panel.killhouserequest')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='driverrequestcancel_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='DepositAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_request_id_foreign_key', models.IntegerField(null=True)), + ('deposit_allocation_id_key', models.IntegerField(null=True)), + ('poultry_share', models.FloatField(default=0, null=True)), + ('poultry_share_payment', models.FloatField(default=0, null=True)), + ('poultry_share_payment_info', models.JSONField(default=list, null=True)), + ('city_share', models.FloatField(default=0, null=True)), + ('city_share_payment', models.FloatField(default=0, null=True)), + ('city_share_payment_info', models.JSONField(default=list, null=True)), + ('province_share', models.FloatField(default=0, null=True)), + ('province_share_payment', models.FloatField(default=0, null=True)), + ('province_share_payment_info', models.JSONField(default=list, null=True)), + ('poultry_bank', models.JSONField(default=dict, null=True)), + ('city_bank', models.JSONField(default=dict, null=True)), + ('poultry_image', models.CharField(max_length=200, null=True)), + ('city_image', models.CharField(max_length=200, null=True)), + ('company_share', models.FloatField(default=0, null=True)), + ('company_share_payment', models.FloatField(default=0, null=True)), + ('company_share_payment_info', models.JSONField(default=list, null=True)), + ('company_bank', models.JSONField(default=dict, null=True)), + ('central_union_share', models.FloatField(default=0, null=True)), + ('central_union_share_payment', models.FloatField(default=0, null=True)), + ('central_union_share_payment_info', models.JSONField(default=list, null=True)), + ('fanava_share', models.FloatField(default=0, null=True)), + ('fanava_share_payment', models.FloatField(default=0, null=True)), + ('fanava_share_payment_info', models.JSONField(default=list, null=True)), + ('deposit_allocation_state', models.CharField(default='pending', max_length=20)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='depositallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='depositallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocations_poultry', to='panel.poultryrequest')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Deposit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('cost', models.IntegerField(null=True)), + ('description', models.TextField(null=True)), + ('image', models.CharField(max_length=300, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='deposit_createdby', to=settings.AUTH_USER_MODEL)), + ('itransaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='deposit_itransaction', to='panel.itransaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='deposit_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Debt', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('cost', models.IntegerField(null=True)), + ('description', models.TextField(null=True)), + ('image', models.CharField(max_length=300, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='debt_createdby', to=settings.AUTH_USER_MODEL)), + ('itransaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='debtor_itransaction', to='panel.itransaction')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='debt_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Commerce', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commerce_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_check', to='panel.poultryrequest'), + ), + migrations.AddField( + model_name='cityoperator', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_wallet', to='panel.wallet'), + ), + migrations.CreateModel( + name='CityJahad', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('city_jahad_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_jahad_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityjahad_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityjahad_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_jahad_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_jahad_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_jahad_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CityCommerce', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_commerce_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citycommerce_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citycommerce_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_commerce_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_commerce_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_commerce_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CheckUnusualCasualties', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(max_length=50, null=True)), + ('message', models.TextField(null=True)), + ('role', models.JSONField(null=True)), + ('complaint', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='losses', to='panel.killhousecomplaint')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkunusualcasualties_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkunusualcasualties_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CheckState', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.BooleanField(default=False)), + ('city_state', models.BooleanField(default=False)), + ('city_state_notification', models.BooleanField(default=False)), + ('city_state_modal', models.BooleanField(default=False)), + ('city_state_sms', models.BooleanField(default=False)), + ('province_state', models.BooleanField(default=False)), + ('province_state_notification', models.BooleanField(default=False)), + ('province_state_modal', models.BooleanField(default=False)), + ('province_state_sms', models.BooleanField(default=False)), + ('kill_house_state_notification', models.BooleanField(default=False)), + ('kill_house_state_modal', models.BooleanField(default=False)), + ('kill_house_state_sms', models.BooleanField(default=False)), + ('assignment_state_notification', models.BooleanField(default=False)), + ('assignment_state_modal', models.BooleanField(default=False)), + ('assignment_state_sms', models.BooleanField(default=False)), + ('main_check', models.CharField(max_length=50, null=True)), + ('city_operator_check', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_operator_check_state', to='panel.cityoperatorcheckrequest')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkstate_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkstate_modifiedby', to=settings.AUTH_USER_MODEL)), + ('notification', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='check_notification', to='notification.notification')), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request', to='panel.poultryrequest')), + ('province_operator_check', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_operator_check_state', to='panel.provincecheckoperatorrequest')), + ('user_message', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='message_check', to='authentication.usermessage')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CheckKillHouseComplaint', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(max_length=20, null=True)), + ('message', models.CharField(max_length=20, null=True)), + ('camplaint', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='check_complaint', to='panel.killhousecomplaint')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkkillhousecomplaint_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='checkkillhousecomplaint_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='AutomaticKillRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automatickillrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automatickillrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='AutoMakeKillHouseRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automakekillhouserequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automakekillhouserequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='AutoAcceptProvinceKillRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='autoacceptprovincekillrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='autoacceptprovincekillrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='Admin', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('admin_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_profile_admin', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0002_auto_20230918_2031.py b/panel/migrations/0002_auto_20230918_2031.py new file mode 100644 index 0000000..7d2e45a --- /dev/null +++ b/panel/migrations/0002_auto_20230918_2031.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2023-09-18 20:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0001_initial'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultry', + name='address_id_foreign_key', + ), + migrations.RemoveField( + model_name='poultry', + name='city', + ), + migrations.RemoveField( + model_name='poultry', + name='city_name', + ), + migrations.RemoveField( + model_name='poultry', + name='city_number', + ), + migrations.RemoveField( + model_name='poultry', + name='poultry_id_key', + ), + migrations.RemoveField( + model_name='poultry', + name='province_name', + ), + migrations.RemoveField( + model_name='poultry', + name='province_number', + ), + migrations.RemoveField( + model_name='poultry', + name='user_bank_id_foreign_key', + ), + migrations.RemoveField( + model_name='poultry', + name='user_id_foreign_key', + ), + migrations.RemoveField( + model_name='poultry', + name='wallet_id_foreign_key', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 577980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 528026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 528026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 528026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 528026)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 529025)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 529025)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 529025)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 31, 10, 536019)), + ), + ] diff --git a/panel/migrations/0003_auto_20230918_2035.py b/panel/migrations/0003_auto_20230918_2035.py new file mode 100644 index 0000000..d6d1b10 --- /dev/null +++ b/panel/migrations/0003_auto_20230918_2035.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2023-09-18 20:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0002_auto_20230918_2031'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultry', + name='owner_id_foreign_key', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 757571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 704621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 704621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 704621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 704621)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 706619)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 706619)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 706619)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 20, 35, 11, 714612)), + ), + ] diff --git a/panel/migrations/0004_auto_20230918_2110.py b/panel/migrations/0004_auto_20230918_2110.py new file mode 100644 index 0000000..c7bfc35 --- /dev/null +++ b/panel/migrations/0004_auto_20230918_2110.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2023-09-18 21:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0003_auto_20230918_2035'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='address_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='city', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='city_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultry', + name='city_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='owner_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='poultry_id_key', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='poultry', + name='province_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultry', + name='province_number', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='user_bank_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='user_id_foreign_key', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='wallet_id_foreign_key', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 329099)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 277148)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 277148)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 277148)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 277148)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 279147)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 279147)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 279147)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 18, 21, 10, 45, 287138)), + ), + ] diff --git a/panel/migrations/0005_auto_20230919_0035.py b/panel/migrations/0005_auto_20230919_0035.py new file mode 100644 index 0000000..94ea175 --- /dev/null +++ b/panel/migrations/0005_auto_20230919_0035.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-19 00:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0004_auto_20230918_2110'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 338656)), + ), + migrations.AlterField( + model_name='killrequest', + name='cars', + field=models.JSONField(default=dict, null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 288701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 288701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 288701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 288701)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 290700)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 290700)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 290700)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 19, 0, 35, 16, 297695)), + ), + ] diff --git a/panel/migrations/0006_auto_20230923_1311.py b/panel/migrations/0006_auto_20230923_1311.py new file mode 100644 index 0000000..b51220d --- /dev/null +++ b/panel/migrations/0006_auto_20230923_1311.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2023-09-23 13:11 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0005_auto_20230919_0035'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='direct_buying_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='killrequest', + name='poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_kill_req', to='panel.poultry'), + ), + migrations.AddField( + model_name='poultryrequest', + name='direct_buying', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 261372)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 126962)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 23, 13, 11, 16, 155895)), + ), + ] diff --git a/panel/migrations/0007_auto_20230926_0954.py b/panel/migrations/0007_auto_20230926_0954.py new file mode 100644 index 0000000..db56b4d --- /dev/null +++ b/panel/migrations/0007_auto_20230926_0954.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-26 09:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0006_auto_20230923_1311'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='direct_buying_message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 115194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 68321)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 9, 54, 54, 83946)), + ), + ] diff --git a/panel/migrations/0008_auto_20230926_1440.py b/panel/migrations/0008_auto_20230926_1440.py new file mode 100644 index 0000000..c71fe2e --- /dev/null +++ b/panel/migrations/0008_auto_20230926_1440.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-26 14:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0007_auto_20230926_0954'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='previous_kill_capacity', + field=models.IntegerField(default=0, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 552927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 499533)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 26, 14, 40, 28, 515161)), + ), + ] diff --git a/panel/migrations/0009_auto_20230927_1033.py b/panel/migrations/0009_auto_20230927_1033.py new file mode 100644 index 0000000..36ecea3 --- /dev/null +++ b/panel/migrations/0009_auto_20230927_1033.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-27 10:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0008_auto_20230926_1440'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='direct_buying_kill_place', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 575717)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 513217)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 33, 23, 528842)), + ), + ] diff --git a/panel/migrations/0010_auto_20230927_1047.py b/panel/migrations/0010_auto_20230927_1047.py new file mode 100644 index 0000000..df638c1 --- /dev/null +++ b/panel/migrations/0010_auto_20230927_1047.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-27 10:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0009_auto_20230927_1033'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='direct_buying_buyer_info', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 701654)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 10, 47, 42, 654775)), + ), + ] diff --git a/panel/migrations/0011_auto_20230927_1416.py b/panel/migrations/0011_auto_20230927_1416.py new file mode 100644 index 0000000..2139bb4 --- /dev/null +++ b/panel/migrations/0011_auto_20230927_1416.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-09-27 14:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0010_auto_20230927_1047'), + ] + + operations = [ + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='direct_buying_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 791384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 14, 16, 34, 744510)), + ), + ] diff --git a/panel/migrations/0012_auto_20230927_1554.py b/panel/migrations/0012_auto_20230927_1554.py new file mode 100644 index 0000000..66c0a39 --- /dev/null +++ b/panel/migrations/0012_auto_20230927_1554.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2023-09-27 15:54 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0011_auto_20230927_1416'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 625956)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 563458)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 27, 15, 54, 7, 579081)), + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseDirectBuyingTotal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousedirectbuyingtotal_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousedirectbuyingtotal_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseDirectBuying', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousedirectbuying_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_kill_house_direct_buying', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhousedirectbuying_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0013_auto_20230928_1502.py b/panel/migrations/0013_auto_20230928_1502.py new file mode 100644 index 0000000..5d528e1 --- /dev/null +++ b/panel/migrations/0013_auto_20230928_1502.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-09-28 15:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0012_auto_20230927_1554'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='direct_buying_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='input_direct_buying_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 218683)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 171807)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 9, 28, 15, 2, 12, 187435)), + ), + ] diff --git a/panel/migrations/0014_auto_20231002_1157.py b/panel/migrations/0014_auto_20231002_1157.py new file mode 100644 index 0000000..67e8b73 --- /dev/null +++ b/panel/migrations/0014_auto_20231002_1157.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-02 11:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0013_auto_20230928_1502'), + ] + + operations = [ + migrations.AddField( + model_name='killhouseaddcar', + name='active_state', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousedriver', + name='active_state', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 350958)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 11, 56, 57, 304086)), + ), + ] diff --git a/panel/migrations/0015_auto_20231002_1201.py b/panel/migrations/0015_auto_20231002_1201.py new file mode 100644 index 0000000..ff7ab1f --- /dev/null +++ b/panel/migrations/0015_auto_20231002_1201.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-02 12:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0014_auto_20231002_1157'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 229711)), + ), + migrations.AlterField( + model_name='killhouseaddcar', + name='active_state', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='killhousedriver', + name='active_state', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 167213)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 2, 12, 0, 55, 182837)), + ), + ] diff --git a/panel/migrations/0016_auto_20231004_1101.py b/panel/migrations/0016_auto_20231004_1101.py new file mode 100644 index 0000000..07df2cf --- /dev/null +++ b/panel/migrations/0016_auto_20231004_1101.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2023-10-04 11:01 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0015_auto_20231002_1201'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 182015)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 135141)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 11, 1, 27, 150766)), + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseRegisterGuildsTotal', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregisterguildstotal_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregisterguildstotal_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ProvinceAllowKillHouseRegisterGuilds', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregisterguilds_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_allow_kill_house_register_guilds', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provinceallowkillhouseregisterguilds_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0017_auto_20231004_1452.py b/panel/migrations/0017_auto_20231004_1452.py new file mode 100644 index 0000000..b7f1680 --- /dev/null +++ b/panel/migrations/0017_auto_20231004_1452.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-04 14:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0016_auto_20231004_1101'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='province_accept', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='steward', + name='province_accept', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 991184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 14, 51, 58, 944316)), + ), + ] diff --git a/panel/migrations/0018_auto_20231004_1508.py b/panel/migrations/0018_auto_20231004_1508.py new file mode 100644 index 0000000..bc7c439 --- /dev/null +++ b/panel/migrations/0018_auto_20231004_1508.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-04 15:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0017_auto_20231004_1452'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='province_accept_state', + field=models.CharField(default='accepted', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 44, 27001)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 964504)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 8, 43, 980131)), + ), + ] diff --git a/panel/migrations/0019_auto_20231004_1528.py b/panel/migrations/0019_auto_20231004_1528.py new file mode 100644 index 0000000..ac8fe75 --- /dev/null +++ b/panel/migrations/0019_auto_20231004_1528.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2023-10-04 15:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0018_auto_20231004_1508'), + ] + + operations = [ + migrations.RemoveField( + model_name='guilds', + name='province_accept', + ), + migrations.RemoveField( + model_name='steward', + name='province_accept', + ), + migrations.AddField( + model_name='guilds', + name='kill_house_register', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='kill_house_register', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='province_accept_state', + field=models.CharField(default='accepted', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 201644)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 154770)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 28, 7, 170396)), + ), + ] diff --git a/panel/migrations/0020_auto_20231004_1539.py b/panel/migrations/0020_auto_20231004_1539.py new file mode 100644 index 0000000..1632bee --- /dev/null +++ b/panel/migrations/0020_auto_20231004_1539.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-10-04 15:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0019_auto_20231004_1528'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 603497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 39, 39, 556620)), + ), + ] diff --git a/panel/migrations/0021_auto_20231004_1552.py b/panel/migrations/0021_auto_20231004_1552.py new file mode 100644 index 0000000..76a7750 --- /dev/null +++ b/panel/migrations/0021_auto_20231004_1552.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-04 15:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0020_auto_20231004_1539'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='province_message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 368774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 321899)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 4, 15, 52, 15, 337526)), + ), + ] diff --git a/panel/migrations/0022_auto_20231005_0439.py b/panel/migrations/0022_auto_20231005_0439.py new file mode 100644 index 0000000..5563659 --- /dev/null +++ b/panel/migrations/0022_auto_20231005_0439.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2023-10-05 04:39 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0002_auto_20231005_0439'), + ('panel', '0021_auto_20231004_1552'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 935289)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 5, 4, 39, 40, 888413)), + ), + migrations.CreateModel( + name='CityVet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_vet_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityvet_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityvet_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_vet_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_vet_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_vet_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0023_auto_20231007_1338.py b/panel/migrations/0023_auto_20231007_1338.py new file mode 100644 index 0000000..cdcdce3 --- /dev/null +++ b/panel/migrations/0023_auto_20231007_1338.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-07 13:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0022_auto_20231005_0439'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='alternate_number', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 780858)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 615499)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 615499)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 615499)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 615499)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 631124)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 631124)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 631124)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 7, 13, 38, 17, 662370)), + ), + ] diff --git a/panel/migrations/0024_auto_20231009_1240.py b/panel/migrations/0024_auto_20231009_1240.py new file mode 100644 index 0000000..71387d4 --- /dev/null +++ b/panel/migrations/0024_auto_20231009_1240.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2023-10-09 12:40 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0023_auto_20231007_1338'), + ] + + operations = [ + migrations.AddField( + model_name='cityvet', + name='vet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_city_vet', to='panel.vet'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 822908)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 742983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 742983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 742983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 742983)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 745980)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 745980)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 745980)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 9, 12, 40, 34, 756970)), + ), + ] diff --git a/panel/migrations/0025_auto_20231010_1249.py b/panel/migrations/0025_auto_20231010_1249.py new file mode 100644 index 0000000..a24c0dc --- /dev/null +++ b/panel/migrations/0025_auto_20231010_1249.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2023-10-10 12:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0024_auto_20231009_1240'), + ] + + operations = [ + migrations.AddField( + model_name='hourlimit', + name='kill_house_active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='hourlimit', + name='kill_house_hour', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='hourlimit', + name='poultry_active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='hourlimit', + name='poultry_hour', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 289962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 231019)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 230024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 231019)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 231019)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 233016)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 233016)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 233016)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 10, 12, 49, 54, 243005)), + ), + ] diff --git a/panel/migrations/0026_auto_20231011_1337.py b/panel/migrations/0026_auto_20231011_1337.py new file mode 100644 index 0000000..b7520ba --- /dev/null +++ b/panel/migrations/0026_auto_20231011_1337.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2023-10-11 13:37 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0025_auto_20231010_1249'), + ] + + operations = [ + migrations.RemoveField( + model_name='hourlimit', + name='kill_house_active', + ), + migrations.RemoveField( + model_name='hourlimit', + name='kill_house_hour', + ), + migrations.RemoveField( + model_name='hourlimit', + name='poultry_active', + ), + migrations.RemoveField( + model_name='hourlimit', + name='poultry_hour', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 249531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 186592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 186592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 186592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 186592)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 189589)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 189589)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 189589)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 11, 13, 37, 15, 198580)), + ), + migrations.CreateModel( + name='KillHouseHourLimit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('hour', models.IntegerField(null=True)), + ('active', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousehourlimit_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousehourlimit_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0027_auto_20231015_1349.py b/panel/migrations/0027_auto_20231015_1349.py new file mode 100644 index 0000000..d8db8bc --- /dev/null +++ b/panel/migrations/0027_auto_20231015_1349.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-15 13:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0026_auto_20231011_1337'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='prev_total_amount', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_amount', + field=models.FloatField(default=0, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 896790)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 844839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 844839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 844839)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 844839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 846837)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 846837)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 846837)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 15, 13, 49, 5, 854829)), + ), + ] diff --git a/panel/migrations/0028_auto_20231016_1211.py b/panel/migrations/0028_auto_20231016_1211.py new file mode 100644 index 0000000..268d190 --- /dev/null +++ b/panel/migrations/0028_auto_20231016_1211.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-10-16 12:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0027_auto_20231015_1349'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='total_amount_editor', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 280667)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 227714)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 227714)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 227714)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 227714)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 229712)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 229712)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 229712)), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='prev_total_amount', + field=models.FloatField(null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 16, 12, 11, 6, 237707)), + ), + ] diff --git a/panel/migrations/0029_auto_20231017_1511.py b/panel/migrations/0029_auto_20231017_1511.py new file mode 100644 index 0000000..941a9cc --- /dev/null +++ b/panel/migrations/0029_auto_20231017_1511.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-17 15:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0028_auto_20231016_1211'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='wage', + field=models.FloatField(default=0, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 22, 197275)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 991467)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 991467)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 991467)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 991467)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 994465)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 994465)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 21, 994465)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 17, 15, 11, 22, 9451)), + ), + ] diff --git a/panel/migrations/0030_auto_20231028_1327.py b/panel/migrations/0030_auto_20231028_1327.py new file mode 100644 index 0000000..8be132d --- /dev/null +++ b/panel/migrations/0030_auto_20231028_1327.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2023-10-28 13:27 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0029_auto_20231017_1511'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 441830)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 379334)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 28, 13, 27, 36, 394960)), + ), + migrations.CreateModel( + name='KillHousePurchaseRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=True)), + ('limitation', models.BooleanField(default=False)), + ('limitation_number', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepurchaserequest_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_purchase_request', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepurchaserequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0031_auto_20231031_1233.py b/panel/migrations/0031_auto_20231031_1233.py new file mode 100644 index 0000000..88abdb2 --- /dev/null +++ b/panel/migrations/0031_auto_20231031_1233.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-10-31 12:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0030_auto_20231028_1327'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='orderId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='wagepayment', + name='refId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='wagepayment', + name='state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 566059)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 12, 33, 27, 519185)), + ), + ] diff --git a/panel/migrations/0032_auto_20231031_1509.py b/panel/migrations/0032_auto_20231031_1509.py new file mode 100644 index 0000000..99fe7e8 --- /dev/null +++ b/panel/migrations/0032_auto_20231031_1509.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-10-31 15:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0031_auto_20231031_1233'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 924368)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 872421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 871420)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 871420)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 871420)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 873418)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 873418)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 873418)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 10, 31, 15, 9, 19, 881411)), + ), + ] diff --git a/panel/migrations/0033_auto_20231101_1240.py b/panel/migrations/0033_auto_20231101_1240.py new file mode 100644 index 0000000..f7f27ab --- /dev/null +++ b/panel/migrations/0033_auto_20231101_1240.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-01 12:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0032_auto_20231031_1509'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='archive_message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='archiver', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 880289)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 811352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 811352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 811352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 811352)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 814351)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 814351)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 814351)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 1, 12, 40, 25, 824340)), + ), + ] diff --git a/panel/migrations/0034_auto_20231103_1509.py b/panel/migrations/0034_auto_20231103_1509.py new file mode 100644 index 0000000..dc07de7 --- /dev/null +++ b/panel/migrations/0034_auto_20231103_1509.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-03 15:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0033_auto_20231101_1240'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 208327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 140869)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 3, 15, 8, 57, 161453)), + ), + ] diff --git a/panel/migrations/0035_auto_20231104_1118.py b/panel/migrations/0035_auto_20231104_1118.py new file mode 100644 index 0000000..b804645 --- /dev/null +++ b/panel/migrations/0035_auto_20231104_1118.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-04 11:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0034_auto_20231103_1509'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='return_archive_message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='returner', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 803443)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 748494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 748494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 748494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 748494)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 750493)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 750493)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 750493)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 4, 11, 18, 30, 758485)), + ), + ] diff --git a/panel/migrations/0036_auto_20231105_1224.py b/panel/migrations/0036_auto_20231105_1224.py new file mode 100644 index 0000000..54de86b --- /dev/null +++ b/panel/migrations/0036_auto_20231105_1224.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-05 12:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0035_auto_20231104_1118'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='temp_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 101805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 49852)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 49852)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 49852)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 49852)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 51853)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 51853)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 51853)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 5, 12, 24, 31, 58846)), + ), + ] diff --git a/panel/migrations/0037_auto_20231106_1225.py b/panel/migrations/0037_auto_20231106_1225.py new file mode 100644 index 0000000..ea2f90e --- /dev/null +++ b/panel/migrations/0037_auto_20231106_1225.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2023-11-06 12:25 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0036_auto_20231105_1224'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 53, 144644)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 942831)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 942831)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 942831)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 942831)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 945828)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 945828)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 945828)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 12, 24, 52, 959815)), + ), + migrations.CreateModel( + name='AutomaticStewardAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('real_number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('real_weight_of_carcasses', models.FloatField(default=0)), + ('final_registration', models.BooleanField(default=False)), + ('registration_code', models.IntegerField(null=True)), + ('logged_registration_code', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=50)), + ('date', models.DateTimeField(null=True)), + ('role', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automaticstewardallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('guilds', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automatic_guilds_allocation', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automaticstewardallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automatic_steward_allocation', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0038_auto_20231106_1546.py b/panel/migrations/0038_auto_20231106_1546.py new file mode 100644 index 0000000..3a9518b --- /dev/null +++ b/panel/migrations/0038_auto_20231106_1546.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2023-11-06 15:46 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0037_auto_20231106_1225'), + ] + + operations = [ + migrations.AddField( + model_name='automaticstewardallocation', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_automatic_allocation', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 195216)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 145263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 145263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 145263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 145263)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 146262)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 146262)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 146262)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 6, 15, 45, 59, 154254)), + ), + ] diff --git a/panel/migrations/0039_auto_20231108_1156.py b/panel/migrations/0039_auto_20231108_1156.py new file mode 100644 index 0000000..9a4dfd5 --- /dev/null +++ b/panel/migrations/0039_auto_20231108_1156.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2023-11-08 11:56 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0038_auto_20231106_1546'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_steward_allocation', to='panel.killhouse'), + ), + migrations.AddField( + model_name='stewardallocation', + name='type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 771486)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 708986)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 708986)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 708986)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 708986)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 724610)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 724610)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 724610)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 8, 11, 56, 3, 724610)), + ), + ] diff --git a/panel/migrations/0040_auto_20231111_1426.py b/panel/migrations/0040_auto_20231111_1426.py new file mode 100644 index 0000000..6f1b21b --- /dev/null +++ b/panel/migrations/0040_auto_20231111_1426.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-11 14:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0039_auto_20231108_1156'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='wagepayment', + name='payer_info', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 655751)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 602802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 602802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 602802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 602802)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 604801)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 604801)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 604801)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 11, 14, 26, 19, 611793)), + ), + ] diff --git a/panel/migrations/0041_auto_20231112_2305.py b/panel/migrations/0041_auto_20231112_2305.py new file mode 100644 index 0000000..f3570c9 --- /dev/null +++ b/panel/migrations/0041_auto_20231112_2305.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-12 23:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0040_auto_20231111_1426'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='allocation_state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 584619)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 531896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 531896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 531896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 531896)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 533894)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 533894)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 533894)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 12, 23, 5, 43, 540887)), + ), + ] diff --git a/panel/migrations/0042_auto_20231114_0930.py b/panel/migrations/0042_auto_20231114_0930.py new file mode 100644 index 0000000..4cf279d --- /dev/null +++ b/panel/migrations/0042_auto_20231114_0930.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-11-14 09:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0041_auto_20231112_2305'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 983203)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 915235)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 14, 9, 30, 34, 930881)), + ), + ] diff --git a/panel/migrations/0043_auto_20231122_1203.py b/panel/migrations/0043_auto_20231122_1203.py new file mode 100644 index 0000000..4e4a113 --- /dev/null +++ b/panel/migrations/0043_auto_20231122_1203.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-22 12:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0042_auto_20231114_0930'), + ] + + operations = [ + migrations.AddField( + model_name='killhousewarehouse', + name='final_total_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='final_total_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 526302)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 473350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 473350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 473350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 473350)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 475349)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 475349)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 475349)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 22, 12, 2, 59, 483344)), + ), + ] diff --git a/panel/migrations/0044_auto_20231126_1221.py b/panel/migrations/0044_auto_20231126_1221.py new file mode 100644 index 0000000..13ad1c7 --- /dev/null +++ b/panel/migrations/0044_auto_20231126_1221.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2023-11-26 12:21 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0043_auto_20231122_1203'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryhatching', + name='temp_killed_quantity', + ), + migrations.AddField( + model_name='poultryhatching', + name='free_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='governmental_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_commitment', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='free_sale_in_province', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 570938)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 501003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 501003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 501003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 501003)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 505001)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 504001)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 505001)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 12, 21, 4, 514990)), + ), + migrations.CreateModel( + name='FreeSaleWithinprovince', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='freesalewithinprovince_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='freesalewithinprovince_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0045_auto_20231126_2005.py b/panel/migrations/0045_auto_20231126_2005.py new file mode 100644 index 0000000..3a810c3 --- /dev/null +++ b/panel/migrations/0045_auto_20231126_2005.py @@ -0,0 +1,67 @@ +# Generated by Django 3.2.13 on 2023-11-26 20:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0044_auto_20231126_1221'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryhatching', + name='free_killed_quantity', + ), + migrations.RemoveField( + model_name='poultryhatching', + name='governmental_killed_quantity', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 380554)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 308094)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 5, 30, 320170)), + ), + ] diff --git a/panel/migrations/0046_auto_20231126_2030.py b/panel/migrations/0046_auto_20231126_2030.py new file mode 100644 index 0000000..439fe5e --- /dev/null +++ b/panel/migrations/0046_auto_20231126_2030.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-11-26 20:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0045_auto_20231126_2005'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='free_killed_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='governmental_killed_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 626120)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 562102)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 26, 20, 30, 13, 577734)), + ), + ] diff --git a/panel/migrations/0047_auto_20231127_1018.py b/panel/migrations/0047_auto_20231127_1018.py new file mode 100644 index 0000000..f7fd7fa --- /dev/null +++ b/panel/migrations/0047_auto_20231127_1018.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-27 10:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0046_auto_20231126_2030'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='total_average_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 934409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 828509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 828509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 828509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 828509)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 832504)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 831506)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 831506)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 10, 18, 33, 847490)), + ), + ] diff --git a/panel/migrations/0048_auto_20231127_1404.py b/panel/migrations/0048_auto_20231127_1404.py new file mode 100644 index 0000000..9f159be --- /dev/null +++ b/panel/migrations/0048_auto_20231127_1404.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-11-27 14:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0047_auto_20231127_1018'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='receiver_state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 25, 17643)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 964693)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 964693)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 964693)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 964693)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 966691)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 966691)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 966691)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 14, 4, 24, 974684)), + ), + ] diff --git a/panel/migrations/0049_auto_20231127_1506.py b/panel/migrations/0049_auto_20231127_1506.py new file mode 100644 index 0000000..d1775b1 --- /dev/null +++ b/panel/migrations/0049_auto_20231127_1506.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-27 15:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0048_auto_20231127_1404'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='receiver_real_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='receiver_real_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 546659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 435762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 435762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 435762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 435762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 439759)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 438759)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 438759)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 27, 15, 6, 41, 455744)), + ), + ] diff --git a/panel/migrations/0050_auto_20231129_1029.py b/panel/migrations/0050_auto_20231129_1029.py new file mode 100644 index 0000000..c2e8a23 --- /dev/null +++ b/panel/migrations/0050_auto_20231129_1029.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2023-11-29 10:29 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0049_auto_20231127_1506'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='allocation_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='steward_ware_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_ware_house_steward_guilds_allocation', to='panel.stewardwarehouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 97087)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 10, 29, 36, 50216)), + ), + ] diff --git a/panel/migrations/0051_auto_20231129_1452.py b/panel/migrations/0051_auto_20231129_1452.py new file mode 100644 index 0000000..0d49a5a --- /dev/null +++ b/panel/migrations/0051_auto_20231129_1452.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-11-29 14:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0050_auto_20231129_1029'), + ] + + operations = [ + migrations.AddField( + model_name='freesalewithinprovince', + name='percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='freesalewithinprovince', + name='type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_commitment_quantity', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 881629)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 819131)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 14, 52, 3, 834754)), + ), + ] diff --git a/panel/migrations/0052_auto_20231129_1539.py b/panel/migrations/0052_auto_20231129_1539.py new file mode 100644 index 0000000..59162a0 --- /dev/null +++ b/panel/migrations/0052_auto_20231129_1539.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-11-29 15:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0051_auto_20231129_1452'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='free_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='governmental_quantity', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 548717)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 419838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 419838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 419838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 419838)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 423833)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 423833)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 423833)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 11, 29, 15, 39, 28, 443815)), + ), + ] diff --git a/panel/migrations/0053_auto_20231201_1759.py b/panel/migrations/0053_auto_20231201_1759.py new file mode 100644 index 0000000..66b31e8 --- /dev/null +++ b/panel/migrations/0053_auto_20231201_1759.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-12-01 17:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0052_auto_20231129_1539'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='total_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 471855)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 409358)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 17, 59, 25, 424982)), + ), + ] diff --git a/panel/migrations/0053_auto_20231202_1108.py b/panel/migrations/0053_auto_20231202_1108.py new file mode 100644 index 0000000..025a069 --- /dev/null +++ b/panel/migrations/0053_auto_20231202_1108.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2023-12-02 11:08 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0010_auto_20231202_1108'), + ('panel', '0052_auto_20231129_1539'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 325032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 282604)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 282604)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 282604)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 282604)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 283601)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 283601)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 283601)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 11, 8, 44, 290600)), + ), + migrations.CreateModel( + name='Observatory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='observatory_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0054_auto_20231201_2242.py b/panel/migrations/0054_auto_20231201_2242.py new file mode 100644 index 0000000..6d26d26 --- /dev/null +++ b/panel/migrations/0054_auto_20231201_2242.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-12-01 22:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0053_auto_20231201_1759'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='extra_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='extra_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='extra_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 998490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 946537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 946537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 946537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 946537)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 948535)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 948535)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 948535)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 1, 22, 42, 4, 956529)), + ), + ] diff --git a/panel/migrations/0055_merge_0053_auto_20231202_1108_0054_auto_20231201_2242.py b/panel/migrations/0055_merge_0053_auto_20231202_1108_0054_auto_20231201_2242.py new file mode 100644 index 0000000..f019563 --- /dev/null +++ b/panel/migrations/0055_merge_0053_auto_20231202_1108_0054_auto_20231201_2242.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.13 on 2023-12-02 11:19 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0053_auto_20231202_1108'), + ('panel', '0054_auto_20231201_2242'), + ] + + operations = [ + ] diff --git a/panel/migrations/0056_auto_20231202_2323.py b/panel/migrations/0056_auto_20231202_2323.py new file mode 100644 index 0000000..0c405cb --- /dev/null +++ b/panel/migrations/0056_auto_20231202_2323.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-12-02 23:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0055_merge_0053_auto_20231202_1108_0054_auto_20231201_2242'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='extra_killed_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='extra_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 175116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 123028)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 2, 23, 23, 10, 138655)), + ), + ] diff --git a/panel/migrations/0057_auto_20231205_1256.py b/panel/migrations/0057_auto_20231205_1256.py new file mode 100644 index 0000000..e4141e9 --- /dev/null +++ b/panel/migrations/0057_auto_20231205_1256.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2023-12-05 12:56 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0011_auto_20231205_1256'), + ('panel', '0056_auto_20231202_2323'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 967156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 916204)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 916204)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 916204)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 916204)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 918202)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 918202)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 918202)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 5, 12, 56, 11, 925195)), + ), + migrations.CreateModel( + name='ProvinceSupervisor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_supervisor_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincesupervisor_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='provincesupervisor_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_supervisor_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_supervisor_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='province_supervisor_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0058_auto_20231210_1253.py b/panel/migrations/0058_auto_20231210_1253.py new file mode 100644 index 0000000..4f9797f --- /dev/null +++ b/panel/migrations/0058_auto_20231210_1253.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-10 12:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0057_auto_20231205_1256'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='amount', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 789173)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 736223)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 735224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 735224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 735224)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 737222)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 737222)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 737222)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 12, 53, 2, 745214)), + ), + ] diff --git a/panel/migrations/0059_auto_20231210_1400.py b/panel/migrations/0059_auto_20231210_1400.py new file mode 100644 index 0000000..bfe5463 --- /dev/null +++ b/panel/migrations/0059_auto_20231210_1400.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-10 14:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0058_auto_20231210_1253'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='financial_operation', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 690711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 638762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 638762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 638762)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 638762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 640760)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 640760)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 640760)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 10, 14, 0, 53, 647754)), + ), + ] diff --git a/panel/migrations/0060_auto_20231211_0917.py b/panel/migrations/0060_auto_20231211_0917.py new file mode 100644 index 0000000..a8bc806 --- /dev/null +++ b/panel/migrations/0060_auto_20231211_0917.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2023-12-11 09:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0059_auto_20231210_1400'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='vet_accepted_real_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='vet_accepted_real_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='total_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 852727)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 9, 17, 42, 805854)), + ), + ] diff --git a/panel/migrations/0061_auto_20231211_1102.py b/panel/migrations/0061_auto_20231211_1102.py new file mode 100644 index 0000000..1153361 --- /dev/null +++ b/panel/migrations/0061_auto_20231211_1102.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2023-12-11 11:02 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0012_auto_20231211_1102'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0060_auto_20231211_0917'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 914703)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 855757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 855757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 855757)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 855757)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 857755)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 857755)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 857755)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 11, 2, 7, 865750)), + ), + migrations.CreateModel( + name='Car', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('driver_name', models.CharField(max_length=500, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('type_car', models.CharField(max_length=50, null=True)), + ('type', models.CharField(max_length=50, null=True)), + ('transport_type', models.CharField(max_length=50, null=True)), + ('pelak', models.CharField(max_length=200, null=True)), + ('capocity', models.CharField(max_length=50, null=True)), + ('weight_without_load', models.CharField(max_length=50, null=True)), + ('health_code', models.CharField(max_length=100, null=True)), + ('status', models.CharField(default='inactive', max_length=50)), + ('active', models.BooleanField(default=True)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('identity_documents', models.JSONField(null=True)), + ('phone', models.CharField(max_length=20, null=True)), + ('registrar', models.JSONField(null=True)), + ('active_state', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='car_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='car_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_car', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='car_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='car_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='guilds', + name='cars', + field=models.ManyToManyField(blank=True, null=True, related_name='guild_car', to='panel.Car'), + ), + migrations.AddField( + model_name='killhouse', + name='cars', + field=models.ManyToManyField(blank=True, null=True, related_name='kill_house_car', to='panel.Car'), + ), + ] diff --git a/panel/migrations/0062_auto_20231211_1209.py b/panel/migrations/0062_auto_20231211_1209.py new file mode 100644 index 0000000..1411711 --- /dev/null +++ b/panel/migrations/0062_auto_20231211_1209.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-11 12:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0061_auto_20231211_1102'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='steward_register', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 680878)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 625930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 625930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 625930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 625930)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 627928)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 627928)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 627928)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 11, 12, 9, 50, 634921)), + ), + ] diff --git a/panel/migrations/0063_auto_20231212_1000.py b/panel/migrations/0063_auto_20231212_1000.py new file mode 100644 index 0000000..6fbae13 --- /dev/null +++ b/panel/migrations/0063_auto_20231212_1000.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2023-12-12 10:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0062_auto_20231211_1209'), + ] + + operations = [ + migrations.AddField( + model_name='guildswarehouse', + name='allocated_total_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='guildswarehouse', + name='allocated_total_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guildswarehouse', + name='final_registration', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guildswarehouse', + name='remain_total_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='guildswarehouse', + name='remain_total_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 298255)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 182363)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 182363)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 182363)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 182363)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 186360)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 186360)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 186360)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 0, 45, 213334)), + ), + ] diff --git a/panel/migrations/0064_auto_20231212_1035.py b/panel/migrations/0064_auto_20231212_1035.py new file mode 100644 index 0000000..31601c4 --- /dev/null +++ b/panel/migrations/0064_auto_20231212_1035.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2023-12-12 10:35 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0063_auto_20231212_1000'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='car', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_allocation_car', to='panel.car'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 598566)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 545614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 545614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 545614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 545614)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 547613)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 547613)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 547613)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 12, 10, 35, 46, 554608)), + ), + ] diff --git a/panel/migrations/0065_auto_20231214_1409.py b/panel/migrations/0065_auto_20231214_1409.py new file mode 100644 index 0000000..cf49a9c --- /dev/null +++ b/panel/migrations/0065_auto_20231214_1409.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2023-12-14 14:09 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0064_auto_20231212_1035'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 725892)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 663950)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 662951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 663950)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 663950)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 664949)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 664949)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 664949)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 9, 4, 672941)), + ), + migrations.CreateModel( + name='POSMachine', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('pos_id', models.CharField(max_length=12, null=True)), + ('token', models.CharField(max_length=36, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posmachine_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_pos', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_pos', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posmachine_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_pos', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0066_auto_20231214_1418.py b/panel/migrations/0066_auto_20231214_1418.py new file mode 100644 index 0000000..85b6c51 --- /dev/null +++ b/panel/migrations/0066_auto_20231214_1418.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2023-12-14 14:18 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0013_auto_20231214_1418'), + ('panel', '0065_auto_20231214_1409'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_pos', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 739096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 656175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 656175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 656175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 656175)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 660171)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 660171)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 660171)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 14, 14, 18, 27, 673157)), + ), + ] diff --git a/panel/migrations/0067_auto_20231216_1015.py b/panel/migrations/0067_auto_20231216_1015.py new file mode 100644 index 0000000..6560632 --- /dev/null +++ b/panel/migrations/0067_auto_20231216_1015.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2023-12-16 10:15 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0066_auto_20231214_1418'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 141771)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 94896)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 15, 43, 110520)), + ), + migrations.CreateModel( + name='Product', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0)), + ('name', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0068_auto_20231216_1030.py b/panel/migrations/0068_auto_20231216_1030.py new file mode 100644 index 0000000..1f40344 --- /dev/null +++ b/panel/migrations/0068_auto_20231216_1030.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2023-12-16 10:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0067_auto_20231216_1015'), + ] + + operations = [ + migrations.AddField( + model_name='guildswarehouse', + name='product', + field=models.ManyToManyField(blank=True, null=True, related_name='guilds_ware_house_product', to='panel.Product'), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='product', + field=models.ManyToManyField(blank=True, null=True, related_name='kill_house_ware_house_product', to='panel.Product'), + ), + migrations.AddField( + model_name='stewardwarehouse', + name='product', + field=models.ManyToManyField(blank=True, null=True, related_name='steward_ware_house_product', to='panel.Product'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 519080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 472205)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 10, 30, 28, 487828)), + ), + ] diff --git a/panel/migrations/0069_auto_20231216_1448.py b/panel/migrations/0069_auto_20231216_1448.py new file mode 100644 index 0000000..28282ac --- /dev/null +++ b/panel/migrations/0069_auto_20231216_1448.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2023-12-16 14:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0068_auto_20231216_1030'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='out_province_killed_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='out_province_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 376009)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 255680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 255680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 255680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 255680)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 259677)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 259677)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 259677)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 14, 48, 26, 274893)), + ), + ] diff --git a/panel/migrations/0070_auto_20231216_2041.py b/panel/migrations/0070_auto_20231216_2041.py new file mode 100644 index 0000000..ea0df40 --- /dev/null +++ b/panel/migrations/0070_auto_20231216_2041.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-16 20:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0069_auto_20231216_1448'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='first_car_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 881001)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 787252)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 16, 20, 41, 23, 802880)), + ), + ] diff --git a/panel/migrations/0071_auto_20231225_1502.py b/panel/migrations/0071_auto_20231225_1502.py new file mode 100644 index 0000000..60c766a --- /dev/null +++ b/panel/migrations/0071_auto_20231225_1502.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-25 15:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0070_auto_20231216_2041'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='quarantine_quantity', + field=models.BigIntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 43, 254109)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 292004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 238054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 292004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 238054)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 300995)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 300995)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 300995)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 25, 15, 1, 42, 436869)), + ), + ] diff --git a/panel/migrations/0072_auto_20231226_1543.py b/panel/migrations/0072_auto_20231226_1543.py new file mode 100644 index 0000000..01b6bfa --- /dev/null +++ b/panel/migrations/0072_auto_20231226_1543.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-26 15:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0071_auto_20231225_1502'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='return_to_province', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 623992)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 337259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 337259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 337259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 337259)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 341256)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 340257)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 340257)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 26, 15, 43, 13, 357240)), + ), + ] diff --git a/panel/migrations/0073_auto_20231227_1020.py b/panel/migrations/0073_auto_20231227_1020.py new file mode 100644 index 0000000..158deda --- /dev/null +++ b/panel/migrations/0073_auto_20231227_1020.py @@ -0,0 +1,132 @@ +# Generated by Django 3.2.13 on 2023-12-27 10:20 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0072_auto_20231226_1543'), + ] + + operations = [ + migrations.RemoveField( + model_name='guildswarehouse', + name='product', + ), + migrations.RemoveField( + model_name='killhousewarehouse', + name='product', + ), + migrations.RemoveField( + model_name='stewardwarehouse', + name='product', + ), + migrations.AddField( + model_name='product', + name='extra_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='product', + name='extra_sale_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='product', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_product', to='panel.guilds'), + ), + migrations.AddField( + model_name='product', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='product', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_product', to='panel.killhouse'), + ), + migrations.AddField( + model_name='product', + name='remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='product', + name='remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='product', + name='sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='product', + name='sale_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='product', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_product', to='panel.steward'), + ), + migrations.AddField( + model_name='product', + name='unit_of_measurement', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='product', + name='weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 361981)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 10, 20, 42, 315105)), + ), + ] diff --git a/panel/migrations/0074_auto_20231227_1520.py b/panel/migrations/0074_auto_20231227_1520.py new file mode 100644 index 0000000..b71053f --- /dev/null +++ b/panel/migrations/0074_auto_20231227_1520.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-27 15:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0073_auto_20231227_1020'), + ] + + operations = [ + migrations.AddField( + model_name='totalpoultryrequestquantity', + name='returned_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 907802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 780920)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 779922)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 779922)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 779922)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 784917)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 784917)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 784917)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 27, 15, 20, 31, 802900)), + ), + ] diff --git a/panel/migrations/0075_auto_20231228_1158.py b/panel/migrations/0075_auto_20231228_1158.py new file mode 100644 index 0000000..ed25f60 --- /dev/null +++ b/panel/migrations/0075_auto_20231228_1158.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2023-12-28 11:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0074_auto_20231227_1520'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='product_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 391890)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 329394)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 28, 11, 58, 12, 345019)), + ), + ] diff --git a/panel/migrations/0076_auto_20231230_0919.py b/panel/migrations/0076_auto_20231230_0919.py new file mode 100644 index 0000000..28e2a3b --- /dev/null +++ b/panel/migrations/0076_auto_20231230_0919.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2023-12-30 09:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0075_auto_20231228_1158'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 764921)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2023, 12, 30, 9, 19, 39, 718045)), + ), + ] diff --git a/panel/migrations/0077_auto_20240102_0907.py b/panel/migrations/0077_auto_20240102_0907.py new file mode 100644 index 0000000..f13ca46 --- /dev/null +++ b/panel/migrations/0077_auto_20240102_0907.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-01-02 09:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0076_auto_20231230_0919'), + ] + + operations = [ + migrations.AddField( + model_name='product', + name='price', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='product', + name='selling_approved_price', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='product', + name='selling_free_price', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='product', + name='selling_more_than_inventory', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='product', + name='selling_other_products', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 18, 470433)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 912953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 912953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 912953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 912953)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 924942)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 923943)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 17, 923943)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 9, 7, 18, 6865)), + ), + ] diff --git a/panel/migrations/0078_auto_20240102_1009.py b/panel/migrations/0078_auto_20240102_1009.py new file mode 100644 index 0000000..1bc3609 --- /dev/null +++ b/panel/migrations/0078_auto_20240102_1009.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-01-02 10:09 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0077_auto_20240102_0907'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='real_add_car', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_real_add_car', to='panel.killhouseaddcar'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 700242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 345571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 345571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 345571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 345571)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 352566)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 352566)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 352566)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 10, 8, 59, 400520)), + ), + ] diff --git a/panel/migrations/0079_auto_20240102_1253.py b/panel/migrations/0079_auto_20240102_1253.py new file mode 100644 index 0000000..4679b61 --- /dev/null +++ b/panel/migrations/0079_auto_20240102_1253.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-01-02 12:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0078_auto_20240102_1009'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='quarantine_code_state', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='ware_house_accepted_real_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='ware_house_accepted_real_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='ware_house_confirmation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 752056)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 594204)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 593205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 593205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 593205)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 599203)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 599203)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 599203)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 2, 12, 53, 34, 622177)), + ), + ] diff --git a/panel/migrations/0080_auto_20240103_1246.py b/panel/migrations/0080_auto_20240103_1246.py new file mode 100644 index 0000000..ba1ce7b --- /dev/null +++ b/panel/migrations/0080_auto_20240103_1246.py @@ -0,0 +1,97 @@ +# Generated by Django 3.2.13 on 2024-01-03 12:46 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0079_auto_20240102_1253'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 238874)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 182927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 182927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 182927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 182927)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 184926)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 183926)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 183926)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 12, 46, 6, 191919)), + ), + migrations.CreateModel( + name='PosVersion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('build_id', models.BigIntegerField(default=0)), + ('latest_downloadlink', models.TextField()), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posversion_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posversion_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PosItem', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('value', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='positem_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='positem_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0081_auto_20240103_1417.py b/panel/migrations/0081_auto_20240103_1417.py new file mode 100644 index 0000000..12ff6f3 --- /dev/null +++ b/panel/migrations/0081_auto_20240103_1417.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-03 14:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0080_auto_20240103_1246'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='out_province_driver_info', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 360034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 305084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 305084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 305084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 305084)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 307082)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 307082)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 307082)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 17, 2, 315077)), + ), + ] diff --git a/panel/migrations/0082_auto_20240103_1455.py b/panel/migrations/0082_auto_20240103_1455.py new file mode 100644 index 0000000..3244105 --- /dev/null +++ b/panel/migrations/0082_auto_20240103_1455.py @@ -0,0 +1,68 @@ +# Generated by Django 3.2.13 on 2024-01-03 14:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0081_auto_20240103_1417'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryrequest', + name='clearance_code', + ), + migrations.AddField( + model_name='poultryrequest', + name='quarantine_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 153900)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 98951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 98951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 98951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 98951)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 100949)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 100949)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 100949)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 3, 14, 55, 1, 108943)), + ), + ] diff --git a/panel/migrations/0083_auto_20240107_1039.py b/panel/migrations/0083_auto_20240107_1039.py new file mode 100644 index 0000000..23d7cce --- /dev/null +++ b/panel/migrations/0083_auto_20240107_1039.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-01-07 10:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0082_auto_20240103_1455'), + ] + + operations = [ + migrations.AddField( + model_name='killhousewarehouse', + name='pre_cold_number_of_carcasses_self_ware_house', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='pre_cold_number_of_carcasses_to_ware_house', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='pre_cold_weight_of_carcasses_self_ware_house', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='pre_cold_weight_of_carcasses_to_ware_house', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 366821)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 313869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 313869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 313869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 313869)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 315868)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 315868)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 315868)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 10, 39, 44, 322863)), + ), + ] diff --git a/panel/migrations/0084_auto_20240107_1133.py b/panel/migrations/0084_auto_20240107_1133.py new file mode 100644 index 0000000..0e9a23e --- /dev/null +++ b/panel/migrations/0084_auto_20240107_1133.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2024-01-07 11:33 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0014_auto_20240107_1133'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0083_auto_20240107_1039'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 331179)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 270869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 270869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 270869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 270869)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 272868)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 272868)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 272868)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 11, 32, 59, 281867)), + ), + migrations.CreateModel( + name='GuildRoom', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('city_jahad_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_room_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildroom_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildroom_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_room_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_room_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_room_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0085_auto_20240107_1325.py b/panel/migrations/0085_auto_20240107_1325.py new file mode 100644 index 0000000..001acdf --- /dev/null +++ b/panel/migrations/0085_auto_20240107_1325.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-01-07 13:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0084_auto_20240107_1133'), + ] + + operations = [ + migrations.RemoveField( + model_name='guildroom', + name='city_jahad_id_key', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 242925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 189925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 189925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 189925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 189925)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 191926)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 191926)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 191926)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 13, 25, 5, 199926)), + ), + ] diff --git a/panel/migrations/0086_auto_20240107_2228.py b/panel/migrations/0086_auto_20240107_2228.py new file mode 100644 index 0000000..17e247c --- /dev/null +++ b/panel/migrations/0086_auto_20240107_2228.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-01-07 22:28 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0015_auto_20240107_2228'), + ('panel', '0085_auto_20240107_1325'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 608407)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 553455)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 553455)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 553455)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 553455)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 555453)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 555453)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 555453)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 28, 10, 562447)), + ), + migrations.CreateModel( + name='PosCompany', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poscompany_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poscompany_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pos_company_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0087_auto_20240107_2243.py b/panel/migrations/0087_auto_20240107_2243.py new file mode 100644 index 0000000..2704448 --- /dev/null +++ b/panel/migrations/0087_auto_20240107_2243.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-01-07 22:43 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0086_auto_20240107_2228'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='pos_company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='company_pos', to='panel.poscompany'), + ), + migrations.AddField( + model_name='posmachine', + name='receiver_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='posmachine', + name='terminal_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 498312)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 442365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 442365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 442365)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 442365)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 444366)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 444366)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 444366)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 7, 22, 43, 23, 452357)), + ), + ] diff --git a/panel/migrations/0088_auto_20240108_0954.py b/panel/migrations/0088_auto_20240108_0954.py new file mode 100644 index 0000000..5fb365f --- /dev/null +++ b/panel/migrations/0088_auto_20240108_0954.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 09:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0087_auto_20240107_2243'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='quarantine_code_registrar', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 209664)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 45818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 45818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 45818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 45818)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 51812)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 50813)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 51812)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 9, 53, 54, 74790)), + ), + ] diff --git a/panel/migrations/0089_auto_20240108_1100.py b/panel/migrations/0089_auto_20240108_1100.py new file mode 100644 index 0000000..1fdfd28 --- /dev/null +++ b/panel/migrations/0089_auto_20240108_1100.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-01-08 11:00 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0088_auto_20240108_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 455878)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 301023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 301023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 301023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 301023)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 306018)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 306018)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 306018)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 0, 13, 326999)), + ), + migrations.CreateModel( + name='POSId', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('pos_id', models.CharField(max_length=12, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posid_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posid_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0090_auto_20240108_1137.py b/panel/migrations/0090_auto_20240108_1137.py new file mode 100644 index 0000000..115c085 --- /dev/null +++ b/panel/migrations/0090_auto_20240108_1137.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 11:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0089_auto_20240108_1100'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 802242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 610425)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 610425)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 610425)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 610425)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 616419)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 616419)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 616419)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 11, 37, 2, 639394)), + ), + ] diff --git a/panel/migrations/0091_auto_20240108_2134.py b/panel/migrations/0091_auto_20240108_2134.py new file mode 100644 index 0000000..8424b06 --- /dev/null +++ b/panel/migrations/0091_auto_20240108_2134.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 21:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0090_auto_20240108_1137'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='has_pos', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 198740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 73746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 73746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 73746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 73746)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 89370)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 89370)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 89370)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 21, 34, 40, 104992)), + ), + ] diff --git a/panel/migrations/0092_auto_20240108_2257.py b/panel/migrations/0092_auto_20240108_2257.py new file mode 100644 index 0000000..656b747 --- /dev/null +++ b/panel/migrations/0092_auto_20240108_2257.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-08 22:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0091_auto_20240108_2134'), + ] + + operations = [ + migrations.AddField( + model_name='product', + name='general', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 656515)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 550615)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 550615)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 550615)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 550615)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 553612)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 553612)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 553612)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 22, 57, 21, 568598)), + ), + ] diff --git a/panel/migrations/0093_auto_20240108_2352.py b/panel/migrations/0093_auto_20240108_2352.py new file mode 100644 index 0000000..7fda14e --- /dev/null +++ b/panel/migrations/0093_auto_20240108_2352.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-01-08 23:52 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0092_auto_20240108_2257'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 299730)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 120897)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 120897)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 120897)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 120897)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 124893)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 124893)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 124893)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 8, 23, 52, 35, 140879)), + ), + migrations.CreateModel( + name='AdditionalProducts', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('image', models.CharField(max_length=500, null=True)), + ('unit_of_measurement', models.CharField(max_length=20, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='additionalproducts_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='additionalproducts_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0094_auto_20240109_1042.py b/panel/migrations/0094_auto_20240109_1042.py new file mode 100644 index 0000000..1e306b6 --- /dev/null +++ b/panel/migrations/0094_auto_20240109_1042.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-01-09 10:42 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0093_auto_20240108_2352'), + ] + + operations = [ + migrations.AddField( + model_name='additionalproducts', + name='price', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='additionalproducts', + name='selling_approved_price', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='additionalproducts', + name='selling_free_price', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='additionalproducts', + name='selling_more_than_inventory', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='additionalproducts', + name='selling_other_products', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='posmachine', + name='Lat', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='posmachine', + name='Long', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='product', + name='priority', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 101678)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 45728)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 45728)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 45728)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 45728)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 48728)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 47727)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 47727)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 9, 10, 42, 19, 55721)), + ), + ] diff --git a/panel/migrations/0095_auto_20240110_0238.py b/panel/migrations/0095_auto_20240110_0238.py new file mode 100644 index 0000000..0bf3b99 --- /dev/null +++ b/panel/migrations/0095_auto_20240110_0238.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2024-01-10 02:38 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0016_auto_20240110_0238'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0094_auto_20240109_1042'), + ] + + operations = [ + migrations.AddField( + model_name='posid', + name='info', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 994126)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 939178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 939178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 939178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 939178)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 941176)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 941176)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 941176)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 10, 2, 38, 17, 948169)), + ), + migrations.CreateModel( + name='POSTransactions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('cart', models.CharField(max_length=20, null=True)), + ('mobile', models.CharField(max_length=20, null=True)), + ('terminal', models.CharField(max_length=100, null=True)), + ('posid', models.CharField(max_length=100, null=True)), + ('result', models.CharField(max_length=500, null=True)), + ('refnum', models.CharField(max_length=200, null=True)), + ('resnum', models.CharField(max_length=200, null=True)), + ('natcode', models.CharField(max_length=20, null=True)), + ('fullname', models.CharField(max_length=200, null=True)), + ('buy_date', models.BigIntegerField(null=True)), + ('date', models.BigIntegerField(null=True)), + ('product', models.JSONField(null=True)), + ('state', models.IntegerField(null=True)), + ('amount', models.FloatField(null=True)), + ('price', models.FloatField(null=True)), + ('lng', models.FloatField(null=True)), + ('lot', models.FloatField(null=True)), + ('checkout', models.BooleanField(null=True)), + ('registered', models.BooleanField(null=True)), + ('paid', models.BooleanField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='postransactions_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_pos_transaction', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_pos_transaction', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='postransactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ('pos_machine', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pos_machine_transaction', to='panel.posmachine')), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_pos_transaction', to='panel.steward')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_pos_transaction', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0096_auto_20240111_1559.py b/panel/migrations/0096_auto_20240111_1559.py new file mode 100644 index 0000000..99a2c5c --- /dev/null +++ b/panel/migrations/0096_auto_20240111_1559.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-11 15:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0095_auto_20240110_0238'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='phone', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 1, 117356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 905552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 905552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 905552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 905552)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 909549)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 909549)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 909549)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 11, 15, 59, 0, 928532)), + ), + ] diff --git a/panel/migrations/0097_auto_20240114_1305.py b/panel/migrations/0097_auto_20240114_1305.py new file mode 100644 index 0000000..147a6a4 --- /dev/null +++ b/panel/migrations/0097_auto_20240114_1305.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-14 13:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0096_auto_20240111_1559'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='condition', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 796933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 714012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 714012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 714012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 714012)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 717006)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 717006)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 717006)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 5, 11, 730995)), + ), + ] diff --git a/panel/migrations/0098_auto_20240114_1343.py b/panel/migrations/0098_auto_20240114_1343.py new file mode 100644 index 0000000..9dc9ca8 --- /dev/null +++ b/panel/migrations/0098_auto_20240114_1343.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-14 13:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0097_auto_20240114_1305'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='description_condition', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='product', + name='show', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 21, 567513)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 276719)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 276719)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 276719)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 276719)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 280713)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 280713)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 280713)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 14, 13, 43, 20, 376623)), + ), + ] diff --git a/panel/migrations/0099_auto_20240115_1039.py b/panel/migrations/0099_auto_20240115_1039.py new file mode 100644 index 0000000..ed4221b --- /dev/null +++ b/panel/migrations/0099_auto_20240115_1039.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-15 10:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0098_auto_20240114_1343'), + ] + + operations = [ + migrations.AddField( + model_name='additionalproducts', + name='priority', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 50, 92083)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 747447)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 747447)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 747447)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 747447)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 749476)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 749476)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 749476)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 15, 10, 38, 49, 769020)), + ), + ] diff --git a/panel/migrations/0100_auto_20240118_1118.py b/panel/migrations/0100_auto_20240118_1118.py new file mode 100644 index 0000000..8273c64 --- /dev/null +++ b/panel/migrations/0100_auto_20240118_1118.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-01-18 11:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0099_auto_20240115_1039'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 999815)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 950776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 950776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 950776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 950776)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 952774)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 952774)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 952774)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 18, 11, 18, 22, 960773)), + ), + ] diff --git a/panel/migrations/0101_auto_20240121_1159.py b/panel/migrations/0101_auto_20240121_1159.py new file mode 100644 index 0000000..2472184 --- /dev/null +++ b/panel/migrations/0101_auto_20240121_1159.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-21 11:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0100_auto_20240118_1118'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='out_province_request_cancel', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='out_province_request_canceller', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 360992)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 306041)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 306041)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 306041)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 306041)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 308039)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 308039)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 308039)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 21, 11, 59, 41, 316032)), + ), + ] diff --git a/panel/migrations/0102_auto_20240123_1234.py b/panel/migrations/0102_auto_20240123_1234.py new file mode 100644 index 0000000..bcb85f7 --- /dev/null +++ b/panel/migrations/0102_auto_20240123_1234.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2024-01-23 12:34 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0101_auto_20240121_1159'), + ] + + operations = [ + migrations.AddField( + model_name='stewardwarehouse', + name='free_bar_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardwarehouse', + name='number_of_free_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardwarehouse', + name='weight_of_free_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 907240)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 796344)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 796344)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 796344)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 796344)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 800340)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 800340)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 800340)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 23, 12, 34, 18, 815326)), + ), + migrations.CreateModel( + name='StewardFreeBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_name', models.CharField(max_length=100, null=True)), + ('kill_house_mobile', models.CharField(max_length=11, null=True)), + ('kill_house_vet_name', models.CharField(max_length=100, null=True)), + ('kill_house_vet_mobile', models.CharField(max_length=11, null=True)), + ('province', models.CharField(max_length=50, null=True)), + ('city', models.CharField(max_length=50, null=True)), + ('driver_name', models.CharField(max_length=100, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('car', models.CharField(max_length=100, null=True)), + ('pelak', models.CharField(max_length=100, null=True)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('bar_image', models.CharField(max_length=200, null=True)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardfreebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardfreebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_steward', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0103_auto_20240127_0916.py b/panel/migrations/0103_auto_20240127_0916.py new file mode 100644 index 0000000..ba93622 --- /dev/null +++ b/panel/migrations/0103_auto_20240127_0916.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-01-27 09:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0102_auto_20240123_1234'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='accepted_assignment_real_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='accepted_assignment_real_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 200069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 137574)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 27, 9, 16, 9, 153198)), + ), + ] diff --git a/panel/migrations/0104_auto_20240130_1008.py b/panel/migrations/0104_auto_20240130_1008.py new file mode 100644 index 0000000..1a91431 --- /dev/null +++ b/panel/migrations/0104_auto_20240130_1008.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2024-01-30 10:08 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0103_auto_20240127_0916'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 988915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 930968)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 930968)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 930968)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 930968)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 932965)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 932965)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 932965)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 1, 30, 10, 8, 13, 941957)), + ), + migrations.CreateModel( + name='TypeActivity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='typeactivity_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='typeactivity_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='AreaActivity', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('tilte', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='areaactivity_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='areaactivity_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0105_auto_20240205_1011.py b/panel/migrations/0105_auto_20240205_1011.py new file mode 100644 index 0000000..28441e2 --- /dev/null +++ b/panel/migrations/0105_auto_20240205_1011.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-05 10:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0104_auto_20240130_1008'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='server_register', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 292479)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 238528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 238528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 238528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 238528)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 240528)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 240528)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 240528)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 5, 10, 11, 40, 248520)), + ), + ] diff --git a/panel/migrations/0106_auto_20240206_1500.py b/panel/migrations/0106_auto_20240206_1500.py new file mode 100644 index 0000000..1053a6c --- /dev/null +++ b/panel/migrations/0106_auto_20240206_1500.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-02-06 15:00 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0105_auto_20240205_1011'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='guild_area_activity', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_area_activity', to='panel.areaactivity'), + ), + migrations.AddField( + model_name='guilds', + name='guild_type_activity', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guilds_type_activity', to='panel.typeactivity'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 34, 36868)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 973927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 973927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 973927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 973927)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 975925)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 975925)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 975925)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 0, 33, 983920)), + ), + ] diff --git a/panel/migrations/0107_auto_20240206_1510.py b/panel/migrations/0107_auto_20240206_1510.py new file mode 100644 index 0000000..0e1e3c9 --- /dev/null +++ b/panel/migrations/0107_auto_20240206_1510.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-06 15:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0106_auto_20240206_1500'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='guilds_room_register', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 772792)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 694865)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 694865)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 694865)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 694865)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 698862)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 697862)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 697862)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 6, 15, 9, 53, 711849)), + ), + ] diff --git a/panel/migrations/0108_auto_20240207_1006.py b/panel/migrations/0108_auto_20240207_1006.py new file mode 100644 index 0000000..378cfb7 --- /dev/null +++ b/panel/migrations/0108_auto_20240207_1006.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2024-02-07 10:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0107_auto_20240206_1510'), + ] + + operations = [ + migrations.RemoveField( + model_name='areaactivity', + name='tilte', + ), + migrations.AddField( + model_name='areaactivity', + name='title', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='guilds', + name='pos_company_register', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 978338)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 919395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 919395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 919395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 919395)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 921395)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 921395)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 921395)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 7, 10, 5, 53, 929386)), + ), + ] diff --git a/panel/migrations/0109_auto_20240214_0923.py b/panel/migrations/0109_auto_20240214_0923.py new file mode 100644 index 0000000..f0e6cb6 --- /dev/null +++ b/panel/migrations/0109_auto_20240214_0923.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-02-14 09:23 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0108_auto_20240207_1006'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 970894)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 839590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 839590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 839590)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 839590)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 849658)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 849658)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 849658)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 9, 23, 19, 859733)), + ), + migrations.CreateModel( + name='EvacuationPermit', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(default='optional', max_length=100)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evacuationpermit_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evacuationpermit_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0110_auto_20240214_1029.py b/panel/migrations/0110_auto_20240214_1029.py new file mode 100644 index 0000000..08f031a --- /dev/null +++ b/panel/migrations/0110_auto_20240214_1029.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-14 10:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0109_auto_20240214_0923'), + ] + + operations = [ + migrations.AddField( + model_name='lastupdate', + name='update_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 949183)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 902867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 902867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 902867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 902867)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 904867)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 904867)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 904867)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 14, 10, 29, 27, 910867)), + ), + ] diff --git a/panel/migrations/0111_auto_20240220_0856.py b/panel/migrations/0111_auto_20240220_0856.py new file mode 100644 index 0000000..e1d2410 --- /dev/null +++ b/panel/migrations/0111_auto_20240220_0856.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-02-20 08:56 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0110_auto_20240214_1029'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='freezing', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 137436)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 74939)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 8, 56, 42, 90564)), + ), + migrations.CreateModel( + name='SellForFreezing', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('permission', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sellforfreezing_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sellforfreezing_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0112_auto_20240220_1341.py b/panel/migrations/0112_auto_20240220_1341.py new file mode 100644 index 0000000..985d744 --- /dev/null +++ b/panel/migrations/0112_auto_20240220_1341.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-02-20 13:41 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0020_auto_20240220_1341'), + ('panel', '0111_auto_20240220_0856'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 261383)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 139497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 138498)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 139497)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 139497)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 143493)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 142493)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 142493)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 20, 13, 41, 7, 159478)), + ), + migrations.CreateModel( + name='LiveStockSupport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_support_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestocksupport_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livestocksupport_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_support_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_support_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='live_stock_support_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0113_auto_20240221_1105.py b/panel/migrations/0113_auto_20240221_1105.py new file mode 100644 index 0000000..e8c4734 --- /dev/null +++ b/panel/migrations/0113_auto_20240221_1105.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-02-21 11:05 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0112_auto_20240220_1341'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 773865)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 659972)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 659972)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 659972)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 659972)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 663969)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 663969)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 663969)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 11, 5, 0, 680953)), + ), + migrations.CreateModel( + name='ColdHouse', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('total_quantity', models.BigIntegerField(default=0)), + ('total_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhouse_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_kill_house', to='panel.killhouse')), + ('live_stock_support', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_live_stock_support', to='panel.livestocksupport')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhouse_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0114_auto_20240221_1306.py b/panel/migrations/0114_auto_20240221_1306.py new file mode 100644 index 0000000..d0040a0 --- /dev/null +++ b/panel/migrations/0114_auto_20240221_1306.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-02-21 13:06 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0113_auto_20240221_1105'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 908387)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 797490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 797490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 797490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 797490)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 801486)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 801486)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 801486)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 5, 58, 817470)), + ), + migrations.CreateModel( + name='ColdHouseAllocations', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0)), + ('accepted_quantity', models.BigIntegerField(default=0)), + ('weight', models.FloatField(default=0)), + ('accepted_weight', models.FloatField(default=0)), + ('cold_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_cold_house', to='panel.coldhouse')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhouseallocations_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_kill_house_request', to='panel.killhouserequest')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhouseallocations_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_poultry_request', to='panel.poultryrequest')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0115_auto_20240221_1314.py b/panel/migrations/0115_auto_20240221_1314.py new file mode 100644 index 0000000..ef9bddc --- /dev/null +++ b/panel/migrations/0115_auto_20240221_1314.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-21 13:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0114_auto_20240221_1306'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 530465)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 473517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 473517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 473517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 473517)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 475515)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 475515)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 475515)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 13, 54, 484506)), + ), + ] diff --git a/panel/migrations/0116_auto_20240221_1317.py b/panel/migrations/0116_auto_20240221_1317.py new file mode 100644 index 0000000..c746987 --- /dev/null +++ b/panel/migrations/0116_auto_20240221_1317.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-02-21 13:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0115_auto_20240221_1314'), + ] + + operations = [ + migrations.AddField( + model_name='killhousewarehouse', + name='freezing_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='freezing_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 576264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 520316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 520316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 520316)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 520316)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 522315)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 522315)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 522315)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 13, 17, 43, 530307)), + ), + ] diff --git a/panel/migrations/0117_auto_20240221_1520.py b/panel/migrations/0117_auto_20240221_1520.py new file mode 100644 index 0000000..c69bdd8 --- /dev/null +++ b/panel/migrations/0117_auto_20240221_1520.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-02-21 15:20 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0116_auto_20240221_1317'), + ] + + operations = [ + migrations.RemoveField( + model_name='coldhouseallocations', + name='poultry_request', + ), + migrations.AddField( + model_name='coldhouseallocations', + name='kill_house_ware_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_kill_house_ware_house', to='panel.killhousewarehouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 470195)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 402259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 402259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 402259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 402259)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 405256)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 405256)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 405256)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 21, 15, 20, 43, 415246)), + ), + ] diff --git a/panel/migrations/0118_auto_20240222_1235.py b/panel/migrations/0118_auto_20240222_1235.py new file mode 100644 index 0000000..e2fc801 --- /dev/null +++ b/panel/migrations/0118_auto_20240222_1235.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-22 12:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0117_auto_20240221_1520'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 259376)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 12, 35, 8, 212501)), + ), + ] diff --git a/panel/migrations/0119_auto_20240222_1346.py b/panel/migrations/0119_auto_20240222_1346.py new file mode 100644 index 0000000..b3b7b79 --- /dev/null +++ b/panel/migrations/0119_auto_20240222_1346.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-22 13:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0118_auto_20240222_1235'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 249494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 193545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 193545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 193545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 193545)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 195543)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 195543)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 195543)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 13, 46, 20, 203538)), + ), + ] diff --git a/panel/migrations/0120_auto_20240222_1432.py b/panel/migrations/0120_auto_20240222_1432.py new file mode 100644 index 0000000..588c27b --- /dev/null +++ b/panel/migrations/0120_auto_20240222_1432.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-22 14:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0119_auto_20240222_1346'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='freezing', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 754026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 637136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 637136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 637136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 637136)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 641133)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 640134)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 640134)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 22, 14, 32, 30, 657118)), + ), + ] diff --git a/panel/migrations/0121_auto_20240226_1343.py b/panel/migrations/0121_auto_20240226_1343.py new file mode 100644 index 0000000..79741aa --- /dev/null +++ b/panel/migrations/0121_auto_20240226_1343.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-02-26 13:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0120_auto_20240222_1432'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='reviewer', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 133661)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 78711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 78711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 78711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 78711)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 80711)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 80711)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 80711)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 13, 43, 9, 88703)), + ), + ] diff --git a/panel/migrations/0122_auto_20240226_1524.py b/panel/migrations/0122_auto_20240226_1524.py new file mode 100644 index 0000000..c52378e --- /dev/null +++ b/panel/migrations/0122_auto_20240226_1524.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-02-26 15:24 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0121_auto_20240226_1343'), + ] + + operations = [ + migrations.AddField( + model_name='killhousewarehouse', + name='free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousewarehouse', + name='free_sale_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 586216)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 527269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 527269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 527269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 527269)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 529267)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 529267)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 529267)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 26, 15, 24, 30, 537261)), + ), + migrations.CreateModel( + name='KillHouseFreeSaleBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('buyer_name', models.CharField(max_length=100, null=True)), + ('buyer_mobile', models.CharField(max_length=11, null=True)), + ('province', models.CharField(max_length=50, null=True)), + ('city', models.CharField(max_length=50, null=True)), + ('driver_name', models.CharField(max_length=100, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('clearance_code', models.CharField(max_length=50, null=True)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefreesalebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousefreesalebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0123_auto_20240227_1159.py b/panel/migrations/0123_auto_20240227_1159.py new file mode 100644 index 0000000..8ba9e7e --- /dev/null +++ b/panel/migrations/0123_auto_20240227_1159.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-02-27 11:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0122_auto_20240226_1524'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='pelak', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='type_car', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 680109)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 624160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 624160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 624160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 624160)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 626158)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 626158)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 626158)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 2, 27, 11, 59, 11, 634152)), + ), + ] diff --git a/panel/migrations/0124_auto_20240303_1034.py b/panel/migrations/0124_auto_20240303_1034.py new file mode 100644 index 0000000..950a5a4 --- /dev/null +++ b/panel/migrations/0124_auto_20240303_1034.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-03 10:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0123_auto_20240227_1159'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='weight_loss', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 44, 58141)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 822978)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 34, 43, 838602)), + ), + ] diff --git a/panel/migrations/0125_auto_20240303_1044.py b/panel/migrations/0125_auto_20240303_1044.py new file mode 100644 index 0000000..72da5d6 --- /dev/null +++ b/panel/migrations/0125_auto_20240303_1044.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-03 10:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0124_auto_20240303_1034'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='ware_house_input_type', + field=models.CharField(default='input_weight', max_length=100), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 106811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 59937)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 10, 44, 41, 75562)), + ), + ] diff --git a/panel/migrations/0126_auto_20240303_1103.py b/panel/migrations/0126_auto_20240303_1103.py new file mode 100644 index 0000000..4342fb8 --- /dev/null +++ b/panel/migrations/0126_auto_20240303_1103.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-03 11:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0125_auto_20240303_1044'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 537947)), + ), + migrations.AlterField( + model_name='killhouserequest', + name='ware_house_input_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 441814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 441814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 441814)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 441814)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 445887)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 445887)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 445887)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 3, 11, 3, 7, 461102)), + ), + ] diff --git a/panel/migrations/0127_auto_20240309_1046.py b/panel/migrations/0127_auto_20240309_1046.py new file mode 100644 index 0000000..d3efc6d --- /dev/null +++ b/panel/migrations/0127_auto_20240309_1046.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-03-09 10:46 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0126_auto_20240303_1103'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 920306)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 857803)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 9, 10, 46, 3, 873429)), + ), + migrations.CreateModel( + name='OperationLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('vet_farm_out_province_limitation', models.BooleanField(default=False)), + ('province_allocation_limitation', models.BooleanField(default=False)), + ('kill_house_allocation_limitation', models.BooleanField(default=False)), + ('kill_house_assignment_limitation', models.BooleanField(default=False)), + ('kill_house_input_bar_limitation', models.BooleanField(default=False)), + ('kill_house_steward_guild_allocation_limitation', models.BooleanField(default=False)), + ('kill_house_freezing_limitation', models.BooleanField(default=False)), + ('kill_house_free_sale_limitation', models.BooleanField(default=False)), + ('kill_house_free_buy_limitation', models.BooleanField(default=False)), + ('kill_house_vet_limitation', models.BooleanField(default=False)), + ('vet_farm_limitation', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='operationlimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='operationlimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0128_auto_20240311_1159.py b/panel/migrations/0128_auto_20240311_1159.py new file mode 100644 index 0000000..77c62d7 --- /dev/null +++ b/panel/migrations/0128_auto_20240311_1159.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-11 11:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0127_auto_20240309_1046'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='out_province', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 454957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 370034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 370034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 370034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 370034)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 373031)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 373031)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 373031)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 11, 59, 5, 382023)), + ), + ] diff --git a/panel/migrations/0129_auto_20240311_1555.py b/panel/migrations/0129_auto_20240311_1555.py new file mode 100644 index 0000000..c0342d8 --- /dev/null +++ b/panel/migrations/0129_auto_20240311_1555.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-03-11 15:55 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0128_auto_20240311_1159'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 219145)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 104252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 104252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 104252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 104252)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 108248)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 108248)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 108248)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 11, 15, 55, 44, 127230)), + ), + migrations.CreateModel( + name='ApprovedPrice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('approved', models.BooleanField(default=False)), + ('lowest_price', models.FloatField(default=0)), + ('highest_price', models.FloatField(default=0)), + ('lowest_weight', models.FloatField(default=0)), + ('highest_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='approvedprice_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='approvedprice_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0130_auto_20240312_1158.py b/panel/migrations/0130_auto_20240312_1158.py new file mode 100644 index 0000000..17d6e16 --- /dev/null +++ b/panel/migrations/0130_auto_20240312_1158.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-12 11:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0129_auto_20240311_1555'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='approved_price', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 441865)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 387912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 387912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 387912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 387912)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 389910)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 389910)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 389910)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 12, 11, 58, 3, 397903)), + ), + ] diff --git a/panel/migrations/0131_auto_20240315_2202.py b/panel/migrations/0131_auto_20240315_2202.py new file mode 100644 index 0000000..467482b --- /dev/null +++ b/panel/migrations/0131_auto_20240315_2202.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-03-15 22:02 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0130_auto_20240312_1158'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 686640)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 501812)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 501812)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 501812)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 501812)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 505809)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 505809)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 505809)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 15, 22, 1, 58, 522792)), + ), + migrations.CreateModel( + name='Announcements', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, null=True, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('description', models.TextField(max_length=2000, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='announcements_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='announcements_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0132_auto_20240318_1139.py b/panel/migrations/0132_auto_20240318_1139.py new file mode 100644 index 0000000..cbcaa42 --- /dev/null +++ b/panel/migrations/0132_auto_20240318_1139.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-03-18 11:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0131_auto_20240315_2202'), + ] + + operations = [ + migrations.AddField( + model_name='operationlimitation', + name='vet_check_kill_house_assignment_limitation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 322571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 195689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 195689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 195689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 195689)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 199687)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 199687)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 199687)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 3, 18, 11, 39, 33, 227659)), + ), + ] diff --git a/panel/migrations/0133_auto_20240409_1145.py b/panel/migrations/0133_auto_20240409_1145.py new file mode 100644 index 0000000..ecd5fa1 --- /dev/null +++ b/panel/migrations/0133_auto_20240409_1145.py @@ -0,0 +1,770 @@ +# Generated by Django 3.2.13 on 2024-04-09 11:45 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0132_auto_20240318_1139'), + ] + + operations = [ + migrations.AlterField( + model_name='additionalproducts', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='admin', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='announcements', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='approvedprice', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='areaactivity', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='autoacceptprovincekillrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='automakekillhouserequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='automatickillrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='automaticstewardallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='car', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='checkkillhousecomplaint', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='checkstate', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='checkunusualcasualties', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='citycommerce', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityjahad', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityoperator', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityoperatorcheckrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='cityvet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='coldhouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='coldhouseallocations', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='commerce', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='debt', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='deposit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='depositallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='driverrequestcancel', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='evacuationpermit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='financialdocument', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='financialtransaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='freesalewithinprovince', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 945205)), + ), + migrations.AlterField( + model_name='functionexecutor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='guildroom', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='guilds', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='guildswarehouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='hatchinglossespermission', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='hourlimit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='inspectoroperator', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='itransaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='jahad', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouseaddcar', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouseallowvet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouseassignmentimages', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouseassignmentinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousecheckrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousecomplaint', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousecreditors', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousedailyquota', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousedriver', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousefactortopoultry', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousefactortoprovince', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousefreebarinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousefreesalebarinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousehourlimit', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouseoperator', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousepercentage', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousepercentageoflosses', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousepurchaserequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequestaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequestactionwinner', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequestexchange', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequestexchangeaddcar', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhouserequestexchangereserve', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousevet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killhousewarehouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killrequestfactor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='killrequestfactorpayment', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='livestocksupport', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='monthlyprofitpercentage', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='mostsearch', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='observatory', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='operationlimitation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 824528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 824528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 824528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 824528)), + ), + migrations.AlterField( + model_name='paymentdeadline', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='penalty', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='percentageoflosses', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poscompany', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='posid', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='positem', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='posmachine', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='posversion', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 831593)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 831593)), + ), + migrations.AlterField( + model_name='poultry', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 831593)), + ), + migrations.AlterField( + model_name='poultryallowcityprovince', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryassignmentinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryhatching', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryrequestauction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryrequestexchange', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultryrequestexchangeaccept', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultrytenant', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='povinceinspector', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='pricing', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='product', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhousechoosestewardguilds', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuying', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhousedirectbuyingtotal', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregistercar', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguilds', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowkillhouseregisterguildstotal', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowpoultrychoosekillhousetotal', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfree', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceallowpoultrysellfreetotal', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceautoallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincecheckinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincecheckkillhousefactor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincecheckoperatoroutrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincecheckoperatorrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincefactortokillhouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincefactortokillhouseforpoultry', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceimportkillhouseoutfactors', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provinceoperator', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincepercentleftover', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincerequestaction', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincesupervisor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='provincialgovernment', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='reportingfieldrolelimitation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='searchfields', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='sellforfreezing', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='shareofallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='smslicense', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='steward', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='stewardallocation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='stewardfreebarinformation', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='stewardwarehouse', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 11, 44, 54, 843781)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='typeactivity', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vetcheckallocations', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vetcheckrequest', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vetfarm', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vetfarminspection', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='vetsupervisor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='wagepayment', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='wallet', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='warehousefactor', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.CreateModel( + name='ChickenAgeRange', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('maximum', models.IntegerField(default=0)), + ('minimum', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chickenagerange_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chickenagerange_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0134_auto_20240409_1202.py b/panel/migrations/0134_auto_20240409_1202.py new file mode 100644 index 0000000..7311693 --- /dev/null +++ b/panel/migrations/0134_auto_20240409_1202.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-04-09 12:02 + +import datetime +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0133_auto_20240409_1145'), + ] + + operations = [ + migrations.AddField( + model_name='chickenagerange', + name='mid', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 343073)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 284068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 284068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 284068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 284068)), + ), + migrations.AlterField( + model_name='postransactions', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 286068)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 286068)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 286068)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 2, 13, 294068)), + ), + ] diff --git a/panel/migrations/0135_auto_20240409_1220.py b/panel/migrations/0135_auto_20240409_1220.py new file mode 100644 index 0000000..6400044 --- /dev/null +++ b/panel/migrations/0135_auto_20240409_1220.py @@ -0,0 +1,68 @@ +# Generated by Django 3.2.13 on 2024-04-09 12:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0134_auto_20240409_1202'), + ] + + operations = [ + migrations.RemoveField( + model_name='chickenagerange', + name='mid', + ), + migrations.AddField( + model_name='chickenagerange', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 280042)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 222039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 222039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 222039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 222039)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 224041)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 224041)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 224041)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 9, 12, 20, 41, 232039)), + ), + ] diff --git a/panel/migrations/0136_auto_20240413_1322.py b/panel/migrations/0136_auto_20240413_1322.py new file mode 100644 index 0000000..c43b516 --- /dev/null +++ b/panel/migrations/0136_auto_20240413_1322.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.13 on 2024-04-13 13:22 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0135_auto_20240409_1220'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 410655)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 270031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 270031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 270031)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 270031)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 285656)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 285656)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 285656)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 13, 13, 22, 33, 285656)), + ), + migrations.CreateModel( + name='TimeRange', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_request_start_hour', models.IntegerField(default=0)), + ('poultry_request_end_hour', models.IntegerField(default=0)), + ('kill_request_start_hour', models.IntegerField(default=0)), + ('kill_request_end_hour', models.IntegerField(default=0)), + ('province_kill_request_start_hour', models.IntegerField(default=0)), + ('province_kill_request_end_hour', models.IntegerField(default=0)), + ('kill_house_request_start_hour', models.IntegerField(default=0)), + ('kill_house_request_end_hour', models.IntegerField(default=0)), + ('vet_farm_check_start_hour', models.IntegerField(default=0)), + ('vet_farm_check_end_hour', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='timerange_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='timerange_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0137_auto_20240414_1050.py b/panel/migrations/0137_auto_20240414_1050.py new file mode 100644 index 0000000..0dcc163 --- /dev/null +++ b/panel/migrations/0137_auto_20240414_1050.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-14 10:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0136_auto_20240413_1322'), + ] + + operations = [ + migrations.AddField( + model_name='timerange', + name='time_range', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 71645)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 23895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 23895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 23895)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 23895)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 24758)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 24758)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 24758)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 10, 50, 14, 24758)), + ), + ] diff --git a/panel/migrations/0138_auto_20240414_1206.py b/panel/migrations/0138_auto_20240414_1206.py new file mode 100644 index 0000000..d5927ef --- /dev/null +++ b/panel/migrations/0138_auto_20240414_1206.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-04-14 12:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0137_auto_20240414_1050'), + ] + + operations = [ + migrations.RemoveField( + model_name='timerange', + name='kill_house_request_end_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='kill_house_request_start_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='kill_request_end_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='kill_request_start_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='poultry_request_end_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='poultry_request_start_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='province_kill_request_end_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='province_kill_request_start_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='vet_farm_check_end_hour', + ), + migrations.RemoveField( + model_name='timerange', + name='vet_farm_check_start_hour', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 921323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 846327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 846327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 846327)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 846327)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 849327)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 849327)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 849327)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 14, 12, 6, 13, 862325)), + ), + ] diff --git a/panel/migrations/0139_auto_20240416_1440.py b/panel/migrations/0139_auto_20240416_1440.py new file mode 100644 index 0000000..ea4524d --- /dev/null +++ b/panel/migrations/0139_auto_20240416_1440.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2024-04-16 14:40 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0025_auto_20240416_1440'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0138_auto_20240414_1206'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 998350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 820349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 820349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 820349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 820349)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 824348)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 824348)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 824348)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 16, 14, 40, 32, 841347)), + ), + migrations.CreateModel( + name='JahadInspector', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_inspector_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahadinspector_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahadinspector_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_inspector_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_inspector_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='jahad_inspector_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CitySupervisor', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_supervisor_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citysupervisor_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citysupervisor_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_supervisor_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_supervisor_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_supervisor_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0140_auto_20240417_1103.py b/panel/migrations/0140_auto_20240417_1103.py new file mode 100644 index 0000000..a1ad144 --- /dev/null +++ b/panel/migrations/0140_auto_20240417_1103.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-04-17 11:03 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0139_auto_20240416_1440'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 912674)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 760737)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 11, 2, 49, 791983)), + ), + migrations.CreateModel( + name='SystemWallet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('balance', models.BigIntegerField(default=0)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemwallet_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_wallet_guild', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_wallet_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='systemwallet_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='system_wallet_steward', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0141_auto_20240417_1257.py b/panel/migrations/0141_auto_20240417_1257.py new file mode 100644 index 0000000..b5baaac --- /dev/null +++ b/panel/migrations/0141_auto_20240417_1257.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-17 12:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0140_auto_20240417_1103'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 273113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 185111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 185111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 185111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 185111)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 187113)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 187113)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 187113)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 17, 12, 56, 50, 197113)), + ), + ] diff --git a/panel/migrations/0142_auto_20240418_1428.py b/panel/migrations/0142_auto_20240418_1428.py new file mode 100644 index 0000000..38f24fa --- /dev/null +++ b/panel/migrations/0142_auto_20240418_1428.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-18 14:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0141_auto_20240417_1257'), + ] + + operations = [ + migrations.AddField( + model_name='announcements', + name='role', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 857470)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 722478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 722478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 722478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 722478)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 726477)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 726477)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 726477)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 14, 28, 28, 742474)), + ), + ] diff --git a/panel/migrations/0143_auto_20240418_1550.py b/panel/migrations/0143_auto_20240418_1550.py new file mode 100644 index 0000000..6d19cbb --- /dev/null +++ b/panel/migrations/0143_auto_20240418_1550.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-18 15:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0142_auto_20240418_1428'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='wallet_pay', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 677160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 477163)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 477163)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 477163)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 477163)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 481163)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 481163)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 481163)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 18, 15, 50, 22, 508162)), + ), + ] diff --git a/panel/migrations/0144_auto_20240420_0033.py b/panel/migrations/0144_auto_20240420_0033.py new file mode 100644 index 0000000..6da3bdb --- /dev/null +++ b/panel/migrations/0144_auto_20240420_0033.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-04-20 00:33 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0027_auto_20240420_0033'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0143_auto_20240418_1550'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 978658)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 920652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 920652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 920652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 920652)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 922652)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 922652)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 922652)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 0, 33, 3, 930653)), + ), + migrations.CreateModel( + name='SuperAdmin', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='super_admin_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='superadmin_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='superadmin_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='super_admin_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='super_admin_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='super_admin_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0145_auto_20240420_1517.py b/panel/migrations/0145_auto_20240420_1517.py new file mode 100644 index 0000000..1c0fc4a --- /dev/null +++ b/panel/migrations/0145_auto_20240420_1517.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-04-20 15:17 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0144_auto_20240420_0033'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 475825)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 303828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 303828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 303828)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 303828)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 307824)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 307824)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 307824)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 20, 15, 17, 36, 322824)), + ), + migrations.CreateModel( + name='PaymentGatewayPercentage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('company', models.IntegerField(default=0)), + ('union', models.IntegerField(default=0)), + ('guilds', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='paymentgatewaypercentage_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='paymentgatewaypercentage_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0146_auto_20240427_1357.py b/panel/migrations/0146_auto_20240427_1357.py new file mode 100644 index 0000000..52a3ec3 --- /dev/null +++ b/panel/migrations/0146_auto_20240427_1357.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-27 13:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0145_auto_20240420_1517'), + ] + + operations = [ + migrations.AddField( + model_name='wagepayment', + name='total_amount_with_tax', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 370773)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 134772)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 133773)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 134772)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 134772)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 138774)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 138774)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 138774)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 27, 13, 57, 15, 157772)), + ), + ] diff --git a/panel/migrations/0147_auto_20240428_1211.py b/panel/migrations/0147_auto_20240428_1211.py new file mode 100644 index 0000000..ad95cdd --- /dev/null +++ b/panel/migrations/0147_auto_20240428_1211.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-04-28 12:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0146_auto_20240427_1357'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='type', + field=models.CharField(default='public', max_length=100), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 117270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 52269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 52269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 52269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 52269)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 54269)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 54269)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 54269)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 28, 12, 11, 41, 61269)), + ), + ] diff --git a/panel/migrations/0148_auto_20240429_1110.py b/panel/migrations/0148_auto_20240429_1110.py new file mode 100644 index 0000000..c81387f --- /dev/null +++ b/panel/migrations/0148_auto_20240429_1110.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-04-29 11:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0147_auto_20240428_1211'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 343206)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 233210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 233210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 233210)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 233210)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 237211)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 237211)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 237211)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 10, 43, 254208)), + ), + ] diff --git a/panel/migrations/0149_auto_20240429_1131.py b/panel/migrations/0149_auto_20240429_1131.py new file mode 100644 index 0000000..4217824 --- /dev/null +++ b/panel/migrations/0149_auto_20240429_1131.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-04-29 11:31 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0148_auto_20240429_1110'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='killer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_killer', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 463070)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 332072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 332072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 332072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 332072)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 336072)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 336072)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 336072)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 29, 11, 31, 37, 354076)), + ), + ] diff --git a/panel/migrations/0150_auto_20240430_1203.py b/panel/migrations/0150_auto_20240430_1203.py new file mode 100644 index 0000000..892cad7 --- /dev/null +++ b/panel/migrations/0150_auto_20240430_1203.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-04-30 12:03 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0149_auto_20240429_1131'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 989588)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 827586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 827586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 827586)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 827586)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 831584)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 831584)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 831584)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 12, 3, 16, 849590)), + ), + migrations.CreateModel( + name='SlaughterHouseTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('amount', models.BigIntegerField(default=0)), + ('amount_with_tax', models.BigIntegerField(default=0)), + ('type', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughterhousetransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughter_house_transaction_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughterhousetransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent_kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='slaughter_house_transaction_parent_kill_house', to='panel.killhouse')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0151_auto_20240430_1327.py b/panel/migrations/0151_auto_20240430_1327.py new file mode 100644 index 0000000..4981331 --- /dev/null +++ b/panel/migrations/0151_auto_20240430_1327.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-04-30 13:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0150_auto_20240430_1203'), + ] + + operations = [ + migrations.AddField( + model_name='slaughterhousetransaction', + name='state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='transaction', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 661630)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 584627)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 584627)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 584627)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 584627)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 586627)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 586627)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 586627)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 4, 30, 13, 27, 31, 596626)), + ), + ] diff --git a/panel/migrations/0152_auto_20240506_1344.py b/panel/migrations/0152_auto_20240506_1344.py new file mode 100644 index 0000000..09c8716 --- /dev/null +++ b/panel/migrations/0152_auto_20240506_1344.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-05-06 13:44 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0151_auto_20240430_1327'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 884857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 759857)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 13, 44, 23, 775483)), + ), + migrations.CreateModel( + name='WageType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('amount', models.BigIntegerField(default=0)), + ('status', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wagetype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wagetype_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PercentageOfWageType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('name', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentageofwagetype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentageofwagetype_modifiedby', to=settings.AUTH_USER_MODEL)), + ('wage_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wage_type_percentage', to='panel.wagetype')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0153_auto_20240506_1401.py b/panel/migrations/0153_auto_20240506_1401.py new file mode 100644 index 0000000..65974ca --- /dev/null +++ b/panel/migrations/0153_auto_20240506_1401.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-06 14:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0152_auto_20240506_1344'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 52, 30523)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 803520)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 803520)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 803520)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 803520)), + ), + migrations.AlterField( + model_name='percentageofwagetype', + name='name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 808522)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 807521)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 808522)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 14, 0, 51, 826521)), + ), + migrations.AlterField( + model_name='wagetype', + name='name', + field=models.CharField(max_length=500, null=True), + ), + ] diff --git a/panel/migrations/0154_auto_20240506_1502.py b/panel/migrations/0154_auto_20240506_1502.py new file mode 100644 index 0000000..e571254 --- /dev/null +++ b/panel/migrations/0154_auto_20240506_1502.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-05-06 15:02 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0153_auto_20240506_1401'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 471274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 414274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 414274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 414274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 414274)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 416274)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 416274)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 416274)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 6, 15, 2, 11, 423274)), + ), + migrations.CreateModel( + name='ShareType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=500, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sharetype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sharetype_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0155_auto_20240507_1044.py b/panel/migrations/0155_auto_20240507_1044.py new file mode 100644 index 0000000..80b0b40 --- /dev/null +++ b/panel/migrations/0155_auto_20240507_1044.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-07 10:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0154_auto_20240506_1502'), + ] + + operations = [ + migrations.AddField( + model_name='sharetype', + name='account_id', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 949142)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 10, 44, 11, 902257)), + ), + ] diff --git a/panel/migrations/0156_auto_20240507_1105.py b/panel/migrations/0156_auto_20240507_1105.py new file mode 100644 index 0000000..4263eb6 --- /dev/null +++ b/panel/migrations/0156_auto_20240507_1105.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-05-07 11:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0155_auto_20240507_1044'), + ] + + operations = [ + migrations.RemoveField( + model_name='sharetype', + name='account_id', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 359953)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 227302)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 227302)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 227302)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 227302)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 231301)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 231301)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 231301)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 5, 49, 247302)), + ), + ] diff --git a/panel/migrations/0157_auto_20240507_1110.py b/panel/migrations/0157_auto_20240507_1110.py new file mode 100644 index 0000000..0a0387f --- /dev/null +++ b/panel/migrations/0157_auto_20240507_1110.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-07 11:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0156_auto_20240507_1105'), + ] + + operations = [ + migrations.AddField( + model_name='sharetype', + name='account_id', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 936524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 811528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 811528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 811528)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 811528)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 814523)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 814523)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 814523)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 11, 10, 33, 831525)), + ), + ] diff --git a/panel/migrations/0158_auto_20240507_2243.py b/panel/migrations/0158_auto_20240507_2243.py new file mode 100644 index 0000000..031ec3e --- /dev/null +++ b/panel/migrations/0158_auto_20240507_2243.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-07 22:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0157_auto_20240507_1110'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='buy_type', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 634426)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 431538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 431538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 431538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 431538)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 436646)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 436606)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 436646)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 22, 43, 42, 453971)), + ), + ] diff --git a/panel/migrations/0159_auto_20240507_2343.py b/panel/migrations/0159_auto_20240507_2343.py new file mode 100644 index 0000000..6262cf1 --- /dev/null +++ b/panel/migrations/0159_auto_20240507_2343.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-07 23:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0158_auto_20240507_2243'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='ware_house', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 9, 69324)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 918128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 918128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 918128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 918128)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 922207)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 922207)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 922207)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 7, 23, 43, 8, 933661)), + ), + ] diff --git a/panel/migrations/0160_auto_20240508_1019.py b/panel/migrations/0160_auto_20240508_1019.py new file mode 100644 index 0000000..4d2fd27 --- /dev/null +++ b/panel/migrations/0160_auto_20240508_1019.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-08 10:19 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0159_auto_20240507_2343'), + ] + + operations = [ + migrations.RemoveField( + model_name='percentageofwagetype', + name='name', + ), + migrations.AddField( + model_name='percentageofwagetype', + name='share_type', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='share_type_percentage', to='panel.sharetype'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 875040)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 812533)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 10, 19, 26, 828163)), + ), + ] diff --git a/panel/migrations/0161_auto_20240508_1203.py b/panel/migrations/0161_auto_20240508_1203.py new file mode 100644 index 0000000..65994d8 --- /dev/null +++ b/panel/migrations/0161_auto_20240508_1203.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-08 12:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0160_auto_20240508_1019'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='seller_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='seller_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 378806)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 255810)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 255810)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 255810)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 255810)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 259808)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 259808)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 259808)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 8, 12, 3, 10, 275807)), + ), + ] diff --git a/panel/migrations/0162_auto_20240511_1129.py b/panel/migrations/0162_auto_20240511_1129.py new file mode 100644 index 0000000..132951b --- /dev/null +++ b/panel/migrations/0162_auto_20240511_1129.py @@ -0,0 +1,106 @@ +# Generated by Django 3.2.13 on 2024-05-11 11:29 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0029_auto_20240511_1129'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0161_auto_20240508_1203'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='has_chain_company', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryhatching', + name='chain_killed_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='chain_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='has_chain_company', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 804034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 11, 29, 47, 741534)), + ), + migrations.CreateModel( + name='ChainCompany', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chaincompany_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chaincompany_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='poultry', + name='chain_company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_chain_company', to='panel.chaincompany'), + ), + ] diff --git a/panel/migrations/0163_auto_20240511_1312.py b/panel/migrations/0163_auto_20240511_1312.py new file mode 100644 index 0000000..7e1475c --- /dev/null +++ b/panel/migrations/0163_auto_20240511_1312.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.13 on 2024-05-11 13:12 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0030_auto_20240511_1312'), + ('panel', '0162_auto_20240511_1129'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompany', + name='address', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_address', to='authentication.systemaddress'), + ), + migrations.AddField( + model_name='chaincompany', + name='user_bank_info', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_bank_info', to='authentication.bankcard'), + ), + migrations.AddField( + model_name='chaincompany', + name='wallet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_wallet', to='panel.wallet'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 833975)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 677976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 677976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 677976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 677976)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 684978)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 684978)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 684978)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 11, 13, 11, 48, 704976)), + ), + ] diff --git a/panel/migrations/0164_auto_20240512_1109.py b/panel/migrations/0164_auto_20240512_1109.py new file mode 100644 index 0000000..b5c05a4 --- /dev/null +++ b/panel/migrations/0164_auto_20240512_1109.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-12 11:09 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0163_auto_20240511_1312'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultry', + name='chain_company', + ), + migrations.AddField( + model_name='poultryhatching', + name='chain_company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_hatching_chain_company', to='panel.chaincompany'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 55, 89534)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 873402)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 873402)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 873402)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 873402)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 889025)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 889025)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 889025)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 12, 11, 8, 54, 904650)), + ), + ] diff --git a/panel/migrations/0165_auto_20240513_1219.py b/panel/migrations/0165_auto_20240513_1219.py new file mode 100644 index 0000000..0578309 --- /dev/null +++ b/panel/migrations/0165_auto_20240513_1219.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-05-13 12:19 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0164_auto_20240512_1109'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 17, 78483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 846222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 846222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 846222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 846222)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 861874)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 861874)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 861874)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 19, 16, 893124)), + ), + migrations.CreateModel( + name='ChainAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.BigIntegerField(default=0)), + ('weight', models.FloatField(default=0)), + ('chain_company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_allocation', to='panel.chaincompany')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chainallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chainallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_hatching_chain_allocation', to='panel.poultryhatching')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0166_auto_20240513_1255.py b/panel/migrations/0166_auto_20240513_1255.py new file mode 100644 index 0000000..a3aaec8 --- /dev/null +++ b/panel/migrations/0166_auto_20240513_1255.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-13 12:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0165_auto_20240513_1219'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='state', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 353947)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 193392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 193392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 193392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 193392)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 199387)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 199387)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 199387)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 55, 44, 218391)), + ), + ] diff --git a/panel/migrations/0167_auto_20240513_1256.py b/panel/migrations/0167_auto_20240513_1256.py new file mode 100644 index 0000000..671668a --- /dev/null +++ b/panel/migrations/0167_auto_20240513_1256.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-13 12:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0166_auto_20240513_1255'), + ] + + operations = [ + migrations.AlterField( + model_name='chainallocation', + name='state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 629353)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 507352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 507352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 507352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 507352)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 513349)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 513349)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 513349)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 13, 12, 56, 51, 530352)), + ), + ] diff --git a/panel/migrations/0168_auto_20240515_1153.py b/panel/migrations/0168_auto_20240515_1153.py new file mode 100644 index 0000000..0cd81f8 --- /dev/null +++ b/panel/migrations/0168_auto_20240515_1153.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-05-15 11:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0167_auto_20240513_1256'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='quarantine_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='remover', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='vet_farm_state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 841022)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 782005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 782005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 782005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 782005)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 786100)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 786100)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 786100)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 11, 52, 58, 786100)), + ), + ] diff --git a/panel/migrations/0169_auto_20240515_1301.py b/panel/migrations/0169_auto_20240515_1301.py new file mode 100644 index 0000000..e445193 --- /dev/null +++ b/panel/migrations/0169_auto_20240515_1301.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-15 13:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0168_auto_20240515_1153'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='quarantine_code_registrar', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 245526)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 100189)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 100189)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 100189)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 100189)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 102248)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 102248)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 102248)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 13, 1, 40, 126742)), + ), + ] diff --git a/panel/migrations/0170_auto_20240515_1453.py b/panel/migrations/0170_auto_20240515_1453.py new file mode 100644 index 0000000..fc64349 --- /dev/null +++ b/panel/migrations/0170_auto_20240515_1453.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-05-15 14:53 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0169_auto_20240515_1301'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 811795)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 383796)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 383796)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 383796)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 383796)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 389790)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 389790)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 389790)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 14, 52, 47, 421793)), + ), + migrations.CreateModel( + name='ShareTypeWage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('amount', models.BigIntegerField(default=0)), + ('date', models.DateTimeField(null=True)), + ('Province_kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wage_province_kill_request', to='panel.provincekillrequest')), + ('chain_allocation', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wage_chain_allocation', to='panel.chainallocation')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sharetypewage_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house_free_bar', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wage_kill_house_free_bar', to='panel.killhousefreebarinformation')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sharetypewage_modifiedby', to=settings.AUTH_USER_MODEL)), + ('share_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='wage_share_type', to='panel.sharetype')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0171_auto_20240515_1549.py b/panel/migrations/0171_auto_20240515_1549.py new file mode 100644 index 0000000..e54288c --- /dev/null +++ b/panel/migrations/0171_auto_20240515_1549.py @@ -0,0 +1,62 @@ +# Generated by Django 3.2.13 on 2024-05-15 15:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0170_auto_20240515_1453'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 247387)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 179388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 179388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 179388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 179388)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 183388)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 182388)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 182388)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 15, 49, 38, 192387)), + ), + migrations.DeleteModel( + name='ShareTypeWage', + ), + ] diff --git a/panel/migrations/0172_auto_20240515_2306.py b/panel/migrations/0172_auto_20240515_2306.py new file mode 100644 index 0000000..e989345 --- /dev/null +++ b/panel/migrations/0172_auto_20240515_2306.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-05-15 23:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0171_auto_20240515_1549'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='total_wage_amount', + field=models.FloatField(default=0, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 769223)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 706818)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 6, 25, 722340)), + ), + ] diff --git a/panel/migrations/0173_auto_20240515_2310.py b/panel/migrations/0173_auto_20240515_2310.py new file mode 100644 index 0000000..48ad8cd --- /dev/null +++ b/panel/migrations/0173_auto_20240515_2310.py @@ -0,0 +1,139 @@ +# Generated by Django 3.2.13 on 2024-05-15 23:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0172_auto_20240515_2306'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='total_wage_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='wage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='total_wage_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='wage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 624599)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 562080)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 10, 28, 577713)), + ), + ] diff --git a/panel/migrations/0174_auto_20240515_2326.py b/panel/migrations/0174_auto_20240515_2326.py new file mode 100644 index 0000000..20932e0 --- /dev/null +++ b/panel/migrations/0174_auto_20240515_2326.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-15 23:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0173_auto_20240515_2310'), + ] + + operations = [ + migrations.AddField( + model_name='wagetype', + name='en_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 975274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 912275)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 912275)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 912275)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 912275)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 915275)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 915275)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 915275)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 15, 23, 26, 35, 924278)), + ), + ] diff --git a/panel/migrations/0175_auto_20240516_0015.py b/panel/migrations/0175_auto_20240516_0015.py new file mode 100644 index 0000000..07769fb --- /dev/null +++ b/panel/migrations/0175_auto_20240516_0015.py @@ -0,0 +1,154 @@ +# Generated by Django 3.2.13 on 2024-05-16 00:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0174_auto_20240515_2326'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='chainallocation', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='sharetype', + name='en_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 833489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 769491)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 769491)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 769491)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 769491)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 772492)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 772492)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 772492)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 0, 15, 40, 782493)), + ), + ] diff --git a/panel/migrations/0176_auto_20240516_1132.py b/panel/migrations/0176_auto_20240516_1132.py new file mode 100644 index 0000000..93ec82c --- /dev/null +++ b/panel/migrations/0176_auto_20240516_1132.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-05-16 11:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0175_auto_20240516_0015'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 899929)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 761925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 760926)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 761925)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 760926)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 767926)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 767926)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 767926)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 11, 31, 51, 787927)), + ), + migrations.CreateModel( + name='TotalWageInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('total_amount', models.BigIntegerField(default=0)), + ('total_unpaid_amount', models.BigIntegerField(default=0)), + ('total_paid_amount', models.BigIntegerField(default=0)), + ('total_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalwageinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalwageinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0177_auto_20240516_1320.py b/panel/migrations/0177_auto_20240516_1320.py new file mode 100644 index 0000000..dcb1434 --- /dev/null +++ b/panel/migrations/0177_auto_20240516_1320.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-05-16 13:20 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0176_auto_20240516_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 305672)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 168673)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 168673)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 168673)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 168673)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 176672)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 176672)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 176672)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 16, 13, 20, 37, 197668)), + ), + migrations.CreateModel( + name='ChainCompanyTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('amount', models.BigIntegerField(default=0)), + ('amount_with_tax', models.BigIntegerField(default=0)), + ('transaction', models.IntegerField(null=True)), + ('state', models.CharField(default='pending', max_length=20)), + ('chain_company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_chain_company', to='panel.chaincompany')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chaincompanytransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chaincompanytransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0178_auto_20240517_1337.py b/panel/migrations/0178_auto_20240517_1337.py new file mode 100644 index 0000000..f8f5e4f --- /dev/null +++ b/panel/migrations/0178_auto_20240517_1337.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2024-05-17 13:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0177_auto_20240516_1320'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompanytransaction', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 537561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 470560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 470560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 470560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 470560)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 475560)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 475560)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 475560)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 37, 27, 484561)), + ), + ] diff --git a/panel/migrations/0179_auto_20240517_1352.py b/panel/migrations/0179_auto_20240517_1352.py new file mode 100644 index 0000000..728d81e --- /dev/null +++ b/panel/migrations/0179_auto_20240517_1352.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2024-05-17 13:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0178_auto_20240517_1337'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompanytransaction', + name='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='orderId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='pay_type', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='refId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chaincompanytransaction', + name='saleReferenceId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='cardHolderPan', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='orderId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='pay_type', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='refId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='slaughterhousetransaction', + name='saleReferenceId', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 476016)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 403012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 403012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 403012)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 403012)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 408017)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 408017)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 408017)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 13, 52, 6, 426016)), + ), + ] diff --git a/panel/migrations/0180_auto_20240517_2240.py b/panel/migrations/0180_auto_20240517_2240.py new file mode 100644 index 0000000..20bf350 --- /dev/null +++ b/panel/migrations/0180_auto_20240517_2240.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-05-17 22:40 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0179_auto_20240517_1352'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 370382)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 279378)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 279378)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 279378)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 279378)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 283380)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 283380)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 283380)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 17, 22, 40, 13, 296380)), + ), + migrations.CreateModel( + name='InternalTransaction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(auto_now_add=True)), + ('amount', models.BigIntegerField(default=0)), + ('amount_with_tax', models.BigIntegerField(default=0)), + ('status', models.CharField(default='pending', max_length=100)), + ('transaction_type', models.CharField(max_length=100, null=True)), + ('type', models.CharField(max_length=100, null=True)), + ('payer_type', models.CharField(max_length=100, null=True)), + ('message', models.TextField(null=True)), + ('saleReferenceId', models.CharField(max_length=100, null=True)), + ('refId', models.CharField(max_length=100, null=True)), + ('orderId', models.CharField(max_length=100, null=True)), + ('cardHolderPan', models.CharField(max_length=100, null=True)), + ('union_share', models.BigIntegerField(default=0)), + ('company_share', models.BigIntegerField(default=0)), + ('guilds_share', models.BigIntegerField(default=0)), + ('city_share', models.BigIntegerField(default=0)), + ('wallet_share', models.BigIntegerField(default=0)), + ('other_share', models.BigIntegerField(default=0)), + ('chain_company', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_chain_company_user', to='panel.chaincompany')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internaltransaction_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_kill_house_user', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internaltransaction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent_kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_parent_kill_house', to='panel.killhouse')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0181_auto_20240521_1033.py b/panel/migrations/0181_auto_20240521_1033.py new file mode 100644 index 0000000..0c8e525 --- /dev/null +++ b/panel/migrations/0181_auto_20240521_1033.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-21 10:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0180_auto_20240517_2240'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 42, 154728)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 725624)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 724545)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 725547)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 724545)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 751750)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 750547)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 750547)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 32, 41, 825332)), + ), + ] diff --git a/panel/migrations/0182_auto_20240521_1054.py b/panel/migrations/0182_auto_20240521_1054.py new file mode 100644 index 0000000..4a30cc6 --- /dev/null +++ b/panel/migrations/0182_auto_20240521_1054.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-21 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0181_auto_20240521_1033'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 664091)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 336007)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 336007)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 336007)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 336007)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 351633)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 351633)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 351633)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 21, 10, 53, 42, 382887)), + ), + ] diff --git a/panel/migrations/0183_auto_20240523_1653.py b/panel/migrations/0183_auto_20240523_1653.py new file mode 100644 index 0000000..5c02832 --- /dev/null +++ b/panel/migrations/0183_auto_20240523_1653.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-05-23 16:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0182_auto_20240521_1054'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='show_exclusive', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 929848)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 742837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 742837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 742837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 742837)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 749838)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 749838)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 749838)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 23, 16, 53, 4, 768838)), + ), + ] diff --git a/panel/migrations/0184_auto_20240525_1028.py b/panel/migrations/0184_auto_20240525_1028.py new file mode 100644 index 0000000..24c330c --- /dev/null +++ b/panel/migrations/0184_auto_20240525_1028.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-25 10:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0183_auto_20240523_1653'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='authority', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='wagepayment', + name='authority', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 37, 239441)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 795354)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 25, 10, 27, 36, 895690)), + ), + ] diff --git a/panel/migrations/0185_auto_20240528_1234.py b/panel/migrations/0185_auto_20240528_1234.py new file mode 100644 index 0000000..ec32669 --- /dev/null +++ b/panel/migrations/0185_auto_20240528_1234.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-05-28 12:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0184_auto_20240525_1028'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='link_pay', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='wagepayment', + name='link_pay', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 606743)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 418746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 418746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 418746)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 418746)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 427739)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 427739)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 427739)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 5, 28, 12, 34, 14, 448743)), + ), + ] diff --git a/panel/migrations/0186_auto_20240604_1332.py b/panel/migrations/0186_auto_20240604_1332.py new file mode 100644 index 0000000..84a3511 --- /dev/null +++ b/panel/migrations/0186_auto_20240604_1332.py @@ -0,0 +1,110 @@ +# Generated by Django 3.2.13 on 2024-06-04 13:32 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0185_auto_20240528_1234'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='buyer_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='buyer_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='city', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='driver_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='driver_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chain_company_allocation_kill_house', to='panel.killhouse'), + ), + migrations.AddField( + model_name='chainallocation', + name='out_province', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='chainallocation', + name='pelak', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='province', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='type_car', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 761792)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 699357)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 4, 13, 32, 29, 714997)), + ), + ] diff --git a/panel/migrations/0187_auto_20240605_1034.py b/panel/migrations/0187_auto_20240605_1034.py new file mode 100644 index 0000000..5db6657 --- /dev/null +++ b/panel/migrations/0187_auto_20240605_1034.py @@ -0,0 +1,134 @@ +# Generated by Django 3.2.13 on 2024-06-05 10:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0186_auto_20240604_1332'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='total_wage_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='wage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 253165)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 175033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 175033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 175033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 175033)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 190662)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 190662)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 190662)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 10, 33, 53, 190662)), + ), + ] diff --git a/panel/migrations/0188_auto_20240605_1220.py b/panel/migrations/0188_auto_20240605_1220.py new file mode 100644 index 0000000..69b0abd --- /dev/null +++ b/panel/migrations/0188_auto_20240605_1220.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-05 12:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0187_auto_20240605_1034'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='wage_pay', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 672712)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 544711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 544711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 544711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 544711)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 552713)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 552713)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 552713)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 12, 19, 45, 569712)), + ), + ] diff --git a/panel/migrations/0189_auto_20240605_1844.py b/panel/migrations/0189_auto_20240605_1844.py new file mode 100644 index 0000000..531592b --- /dev/null +++ b/panel/migrations/0189_auto_20240605_1844.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-05 18:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0188_auto_20240605_1220'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='now_age', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 253313)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 60162)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 60162)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 60162)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 60162)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 68160)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 68160)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 68160)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 5, 18, 44, 3, 85162)), + ), + ] diff --git a/panel/migrations/0190_auto_20240606_1050.py b/panel/migrations/0190_auto_20240606_1050.py new file mode 100644 index 0000000..c6ffc55 --- /dev/null +++ b/panel/migrations/0190_auto_20240606_1050.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-06 10:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0189_auto_20240605_1844'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='index_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 149769)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 4620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 4620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 4620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 4620)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 20263)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 20263)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 20263)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 10, 49, 54, 35892)), + ), + ] diff --git a/panel/migrations/0191_auto_20240606_1122.py b/panel/migrations/0191_auto_20240606_1122.py new file mode 100644 index 0000000..1c43415 --- /dev/null +++ b/panel/migrations/0191_auto_20240606_1122.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-06 11:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0190_auto_20240606_1050'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='seconder', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 675873)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 543869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 543869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 543869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 543869)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 552080)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 551078)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 551078)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 6, 11, 22, 17, 570480)), + ), + ] diff --git a/panel/migrations/0192_auto_20240608_1038.py b/panel/migrations/0192_auto_20240608_1038.py new file mode 100644 index 0000000..6dc39aa --- /dev/null +++ b/panel/migrations/0192_auto_20240608_1038.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-06-08 10:38 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0191_auto_20240606_1122'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_poultry_request', to='panel.poultryrequest'), + ), + migrations.AddField( + model_name='poultryrequest', + name='payer_fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='payer_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 399972)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 10, 38, 17, 337462)), + ), + ] diff --git a/panel/migrations/0193_auto_20240608_2310.py b/panel/migrations/0193_auto_20240608_2310.py new file mode 100644 index 0000000..84f7f62 --- /dev/null +++ b/panel/migrations/0193_auto_20240608_2310.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-08 23:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0192_auto_20240608_1038'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='health_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 598287)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 401057)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 401057)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 401057)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 401057)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 410272)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 410272)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 410272)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 10, 14, 429716)), + ), + ] diff --git a/panel/migrations/0194_auto_20240608_2326.py b/panel/migrations/0194_auto_20240608_2326.py new file mode 100644 index 0000000..061837d --- /dev/null +++ b/panel/migrations/0194_auto_20240608_2326.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-06-08 23:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0193_auto_20240608_2310'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 759054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 665294)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 8, 23, 25, 47, 680930)), + ), + migrations.CreateModel( + name='TotalPaymentGatewayPercentage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('company', models.IntegerField(default=0)), + ('union', models.IntegerField(default=0)), + ('guilds', models.IntegerField(default=0)), + ('type', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalpaymentgatewaypercentage_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='totalpaymentgatewaypercentage_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0195_auto_20240611_0019.py b/panel/migrations/0195_auto_20240611_0019.py new file mode 100644 index 0000000..5538868 --- /dev/null +++ b/panel/migrations/0195_auto_20240611_0019.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-06-11 00:19 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0194_auto_20240608_2326'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='poultry', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_poultry', to='panel.poultry'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 853496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 742494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 742494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 742494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 742494)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 746496)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 746496)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 746496)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 11, 0, 19, 34, 760494)), + ), + ] diff --git a/panel/migrations/0196_auto_20240612_0051.py b/panel/migrations/0196_auto_20240612_0051.py new file mode 100644 index 0000000..2a3c6ba --- /dev/null +++ b/panel/migrations/0196_auto_20240612_0051.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-06-12 00:51 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0195_auto_20240611_0019'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 343329)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 280826)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 0, 50, 51, 296452)), + ), + migrations.CreateModel( + name='OutProvincePoultryRequestBuyer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(max_length=100, null=True)), + ('fullname', models.CharField(max_length=300, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('unit_name', models.CharField(max_length=300, null=True)), + ('city', models.CharField(max_length=300, null=True)), + ('province', models.CharField(max_length=300, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincepoultryrequestbuyer_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincepoultryrequestbuyer_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0197_auto_20240612_1118.py b/panel/migrations/0197_auto_20240612_1118.py new file mode 100644 index 0000000..25d008f --- /dev/null +++ b/panel/migrations/0197_auto_20240612_1118.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2024-06-12 11:18 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0196_auto_20240612_0051'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 998321)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 924317)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 924317)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 924317)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 924317)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 929320)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 929320)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 929320)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 17, 56, 938321)), + ), + migrations.CreateModel( + name='StewardFreeSaleBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('buyer_name', models.CharField(max_length=100, null=True)), + ('buyer_mobile', models.CharField(max_length=11, null=True)), + ('province', models.CharField(max_length=50, null=True)), + ('city', models.CharField(max_length=50, null=True)), + ('driver_name', models.CharField(max_length=100, null=True)), + ('driver_mobile', models.CharField(max_length=11, null=True)), + ('type_car', models.CharField(max_length=100, null=True)), + ('pelak', models.CharField(max_length=100, null=True)), + ('clearance_code', models.CharField(max_length=50, null=True)), + ('number_of_carcasses', models.BigIntegerField(default=0)), + ('weight_of_carcasses', models.FloatField(default=0)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardfreesalebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardfreesalebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_steward', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0198_auto_20240612_1230.py b/panel/migrations/0198_auto_20240612_1230.py new file mode 100644 index 0000000..5e1fabd --- /dev/null +++ b/panel/migrations/0198_auto_20240612_1230.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-06-12 12:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0197_auto_20240612_1118'), + ] + + operations = [ + migrations.AddField( + model_name='stewardwarehouse', + name='free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardwarehouse', + name='free_sale_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 34, 51361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 988361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 988361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 988361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 988361)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 992361)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 992361)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 33, 992361)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 12, 30, 34, 361)), + ), + ] diff --git a/panel/migrations/0199_auto_20240612_1137.py b/panel/migrations/0199_auto_20240612_1137.py new file mode 100644 index 0000000..12df402 --- /dev/null +++ b/panel/migrations/0199_auto_20240612_1137.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2024-06-12 11:37 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0036_auto_20240612_1137'), + ('panel', '0198_auto_20240612_1230'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 566738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 516738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 516738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 516738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 516738)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 519737)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 519737)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 519737)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 12, 11, 36, 51, 526737)), + ), + migrations.CreateModel( + name='CityLivestock', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('user_id_foreign_key', models.IntegerField(null=True)), + ('address_id_foreign_key', models.IntegerField(null=True)), + ('user_bank_id_foreign_key', models.IntegerField(null=True)), + ('wallet_id_foreign_key', models.IntegerField(null=True)), + ('city_jahad_id_key', models.IntegerField(null=True)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('city_number', models.IntegerField(default=0)), + ('city_name', models.CharField(max_length=100, null=True)), + ('province_number', models.IntegerField(default=0)), + ('province_name', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_livestock_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citylivestock_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citylivestock_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_livestock_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_livestock_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_livestock_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0200_auto_20240613_1037.py b/panel/migrations/0200_auto_20240613_1037.py new file mode 100644 index 0000000..bf59311 --- /dev/null +++ b/panel/migrations/0200_auto_20240613_1037.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-13 10:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0199_auto_20240612_1137'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='has_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 702592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 640085)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 36, 54, 655711)), + ), + ] diff --git a/panel/migrations/0201_auto_20240613_1106.py b/panel/migrations/0201_auto_20240613_1106.py new file mode 100644 index 0000000..de7c6f1 --- /dev/null +++ b/panel/migrations/0201_auto_20240613_1106.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-06-13 11:06 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0200_auto_20240613_1037'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='out_province_poultry_request_buyer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_hatching', to='panel.outprovincepoultryrequestbuyer'), + ), + migrations.AddField( + model_name='poultryrequest', + name='sms', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 518278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 455774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 455774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 455774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 455774)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 471404)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 471404)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 471404)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 6, 19, 471404)), + ), + ] diff --git a/panel/migrations/0202_auto_20240613_1043.py b/panel/migrations/0202_auto_20240613_1043.py new file mode 100644 index 0000000..2296a00 --- /dev/null +++ b/panel/migrations/0202_auto_20240613_1043.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-13 10:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0201_auto_20240613_1106'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='user_gate_way_id', + field=models.CharField(max_length=6, null=True, unique=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 235421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 183811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 183811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 183811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 183811)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 186810)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 186810)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 186810)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 10, 42, 52, 193809)), + ), + ] diff --git a/panel/migrations/0203_auto_20240613_1101.py b/panel/migrations/0203_auto_20240613_1101.py new file mode 100644 index 0000000..316d268 --- /dev/null +++ b/panel/migrations/0203_auto_20240613_1101.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-06-13 11:01 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0038_auto_20240613_1101'), + ('panel', '0202_auto_20240613_1043'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryrequest', + name='user_gate_way_id', + ), + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='out_province_poultry_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 869432)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 819388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 819388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 819388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 819388)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 822432)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 822432)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 822432)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 13, 11, 1, 44, 829436)), + ), + ] diff --git a/panel/migrations/0204_auto_20240616_0110.py b/panel/migrations/0204_auto_20240616_0110.py new file mode 100644 index 0000000..d7662a9 --- /dev/null +++ b/panel/migrations/0204_auto_20240616_0110.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-06-16 01:10 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0203_auto_20240613_1101'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='out_province_poultry_request_buyer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_out_province_poultry_request_buyer', to='panel.outprovincepoultryrequestbuyer'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 175278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 83276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 82277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 83276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 83276)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 87277)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 87277)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 87277)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 1, 10, 10, 100277)), + ), + ] diff --git a/panel/migrations/0205_auto_20240616_0956.py b/panel/migrations/0205_auto_20240616_0956.py new file mode 100644 index 0000000..8e37261 --- /dev/null +++ b/panel/migrations/0205_auto_20240616_0956.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-06-16 09:56 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0039_auto_20240616_0956'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0204_auto_20240616_0110'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 832131)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 779621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 779621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 779621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 779621)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 782620)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 782620)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 782620)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 16, 9, 56, 22, 789621)), + ), + migrations.CreateModel( + name='ImprovingLivestock', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improving_livestock_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improvinglivestock_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improvinglivestock_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improving_livestock_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improving_livestock_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='improving_livestock_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0206_auto_20240617_1954.py b/panel/migrations/0206_auto_20240617_1954.py new file mode 100644 index 0000000..0856967 --- /dev/null +++ b/panel/migrations/0206_auto_20240617_1954.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-17 19:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0205_auto_20240616_0956'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 144088)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 3461)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 17, 19, 54, 33, 34713)), + ), + ] diff --git a/panel/migrations/0207_auto_20240618_1054.py b/panel/migrations/0207_auto_20240618_1054.py new file mode 100644 index 0000000..0ff0085 --- /dev/null +++ b/panel/migrations/0207_auto_20240618_1054.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-18 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0206_auto_20240617_1954'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='buyer_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 275707)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 166699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 166699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 166699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 166699)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 174700)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 174700)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 174700)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 10, 54, 16, 192701)), + ), + ] diff --git a/panel/migrations/0208_auto_20240618_1417.py b/panel/migrations/0208_auto_20240618_1417.py new file mode 100644 index 0000000..f52bbef --- /dev/null +++ b/panel/migrations/0208_auto_20240618_1417.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-06-18 14:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0207_auto_20240618_1054'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='buyer_city', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='buyer_fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='buyer_province', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 24, 55435)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 915434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 915434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 915434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 915434)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 924431)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 924431)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 924431)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 17, 23, 944435)), + ), + ] diff --git a/panel/migrations/0209_auto_20240618_1451.py b/panel/migrations/0209_auto_20240618_1451.py new file mode 100644 index 0000000..71bda8c --- /dev/null +++ b/panel/migrations/0209_auto_20240618_1451.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2024-06-18 14:51 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0040_auto_20240618_1451'), + ('panel', '0208_auto_20240618_1417'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='internal_transaction_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 397388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 273396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 273396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 273396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 273396)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 280392)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 280392)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 280392)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 18, 14, 51, 39, 306388)), + ), + ] diff --git a/panel/migrations/0210_auto_20240619_1119.py b/panel/migrations/0210_auto_20240619_1119.py new file mode 100644 index 0000000..f318624 --- /dev/null +++ b/panel/migrations/0210_auto_20240619_1119.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-06-19 11:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0209_auto_20240618_1451'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='company_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='company_user_city', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='company_user_fullname', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='company_user_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='company_user_province', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='chainallocation', + name='registerer', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 420635)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 355638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 355638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 355638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 355638)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 358637)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 358637)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 358637)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 11, 19, 41, 368637)), + ), + ] diff --git a/panel/migrations/0211_auto_20240619_1701.py b/panel/migrations/0211_auto_20240619_1701.py new file mode 100644 index 0000000..21de9f8 --- /dev/null +++ b/panel/migrations/0211_auto_20240619_1701.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-19 17:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0210_auto_20240619_1119'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='agent', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 811933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 745933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 745933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 745933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 745933)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 749935)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 749935)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 749935)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 19, 17, 0, 55, 759933)), + ), + ] diff --git a/panel/migrations/0212_auto_20240620_1006.py b/panel/migrations/0212_auto_20240620_1006.py new file mode 100644 index 0000000..3988da1 --- /dev/null +++ b/panel/migrations/0212_auto_20240620_1006.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-20 10:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0211_auto_20240619_1701'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='hatching_left_over', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 228875)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 41944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 41944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 41944)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 41944)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 50163)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 50163)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 50163)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 20, 10, 6, 45, 74704)), + ), + ] diff --git a/panel/migrations/0213_auto_20240622_1055.py b/panel/migrations/0213_auto_20240622_1055.py new file mode 100644 index 0000000..44787fe --- /dev/null +++ b/panel/migrations/0213_auto_20240622_1055.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-06-22 10:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0212_auto_20240620_1006'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_city', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_province', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_unit_name', + field=models.CharField(max_length=300, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 940701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 772694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 772694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 772694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 772694)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 779698)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 779698)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 779698)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 10, 54, 57, 797695)), + ), + ] diff --git a/panel/migrations/0214_auto_20240622_1153.py b/panel/migrations/0214_auto_20240622_1153.py new file mode 100644 index 0000000..ecb089f --- /dev/null +++ b/panel/migrations/0214_auto_20240622_1153.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-06-22 11:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0213_auto_20240622_1055'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='kill_house_unique_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_unique_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 795929)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 694930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 694930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 694930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 694930)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 713939)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 713939)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 713939)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 53, 13, 736932)), + ), + ] diff --git a/panel/migrations/0215_auto_20240622_1158.py b/panel/migrations/0215_auto_20240622_1158.py new file mode 100644 index 0000000..1ebcd23 --- /dev/null +++ b/panel/migrations/0215_auto_20240622_1158.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-06-22 11:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0214_auto_20240622_1153'), + ] + + operations = [ + migrations.RemoveField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_unique_id', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 282646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 69649)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 68649)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 69649)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 69649)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 78648)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 77647)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 77647)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 11, 58, 29, 99648)), + ), + ] diff --git a/panel/migrations/0216_auto_20240622_1229.py b/panel/migrations/0216_auto_20240622_1229.py new file mode 100644 index 0000000..b6fbd70 --- /dev/null +++ b/panel/migrations/0216_auto_20240622_1229.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2024-06-22 12:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0215_auto_20240622_1158'), + ] + + operations = [ + migrations.RemoveField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_city', + ), + migrations.RemoveField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_province', + ), + migrations.RemoveField( + model_name='outprovincepoultryrequestbuyer', + name='killer_kill_house_unit_name', + ), + migrations.AddField( + model_name='poultryrequest', + name='kill_house_unique_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='killer_kill_house_city', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='killer_kill_house_province', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='poultryrequest', + name='killer_kill_house_unit_name', + field=models.CharField(max_length=300, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 296176)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 96175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 96175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 96175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 96175)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 104176)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 104176)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 104176)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 12, 29, 40, 127173)), + ), + ] diff --git a/panel/migrations/0217_auto_20240622_1622.py b/panel/migrations/0217_auto_20240622_1622.py new file mode 100644 index 0000000..7e098f8 --- /dev/null +++ b/panel/migrations/0217_auto_20240622_1622.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-22 16:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0216_auto_20240622_1229'), + ] + + operations = [ + migrations.AddField( + model_name='killhousepurchaserequest', + name='total_limitation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 629905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 515909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 515909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 515909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 515909)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 523909)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 523909)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 523909)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 22, 16, 22, 18, 542910)), + ), + ] diff --git a/panel/migrations/0218_auto_20240624_1409.py b/panel/migrations/0218_auto_20240624_1409.py new file mode 100644 index 0000000..151022e --- /dev/null +++ b/panel/migrations/0218_auto_20240624_1409.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-24 14:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0217_auto_20240622_1622'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='document_status', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 772796)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 702798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 702798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 702798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 702798)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 706798)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 706798)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 706798)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 24, 14, 9, 28, 715798)), + ), + ] diff --git a/panel/migrations/0219_auto_20240629_1100.py b/panel/migrations/0219_auto_20240629_1100.py new file mode 100644 index 0000000..0ec5ad9 --- /dev/null +++ b/panel/migrations/0219_auto_20240629_1100.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-29 11:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0218_auto_20240624_1409'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='date_of_ware_house', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 534483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 468478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 468478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 468478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 468478)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 472480)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 472480)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 472480)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 0, 17, 481481)), + ), + ] diff --git a/panel/migrations/0220_auto_20240629_1118.py b/panel/migrations/0220_auto_20240629_1118.py new file mode 100644 index 0000000..428d3cb --- /dev/null +++ b/panel/migrations/0220_auto_20240629_1118.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-06-29 11:18 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0219_auto_20240629_1100'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 962134)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 868132)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 868132)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 868132)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 868132)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 874136)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 874136)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 874136)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 18, 15, 888133)), + ), + migrations.CreateModel( + name='BarDocumentStatus', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=500, null=True)), + ('sms', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bardocumentstatus_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bardocumentstatus_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0221_auto_20240629_1150.py b/panel/migrations/0221_auto_20240629_1150.py new file mode 100644 index 0000000..f0862f5 --- /dev/null +++ b/panel/migrations/0221_auto_20240629_1150.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-06-29 11:50 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0220_auto_20240629_1118'), + ] + + operations = [ + migrations.AddField( + model_name='bardocumentstatus', + name='is_error', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='bar_document_status', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_request_bar_document_status', to='panel.bardocumentstatus'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 237978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 74977)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 74977)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 74977)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 74977)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 82980)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 82980)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 82980)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 29, 11, 49, 46, 103976)), + ), + ] diff --git a/panel/migrations/0222_auto_20240630_1147.py b/panel/migrations/0222_auto_20240630_1147.py new file mode 100644 index 0000000..06ed3d4 --- /dev/null +++ b/panel/migrations/0222_auto_20240630_1147.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2024-06-30 11:47 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0221_auto_20240629_1150'), + ] + + operations = [ + migrations.CreateModel( + name='Reports', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=500, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reports_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reports_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='ReportsUsers', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=True)), + ('firstname', models.CharField(max_length=100, null=True)), + ('lastname', models.CharField(max_length=100, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('post', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportsusers_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportsusers_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 635688)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 573181)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 47, 32, 588807)), + ), + migrations.CreateModel( + name='UserReports', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userreports_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userreports_modifiedby', to=settings.AUTH_USER_MODEL)), + ('report', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='report_user_reports', to='panel.reports')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_reports_user', to='panel.reportsusers')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0223_auto_20240630_1148.py b/panel/migrations/0223_auto_20240630_1148.py new file mode 100644 index 0000000..a40b332 --- /dev/null +++ b/panel/migrations/0223_auto_20240630_1148.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-30 11:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0222_auto_20240630_1147'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 759623)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 650026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 650026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 650026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 650026)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 665644)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 665644)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 665644)), + ), + migrations.AlterField( + model_name='reportsusers', + name='post', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 11, 48, 22, 681276)), + ), + ] diff --git a/panel/migrations/0224_auto_20240630_1351.py b/panel/migrations/0224_auto_20240630_1351.py new file mode 100644 index 0000000..75bd157 --- /dev/null +++ b/panel/migrations/0224_auto_20240630_1351.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-06-30 13:51 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0223_auto_20240630_1148'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 137894)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 75384)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 13, 51, 47, 91010)), + ), + migrations.CreateModel( + name='ReportSubmissionTime', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(max_length=100, null=True)), + ('hour', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportsubmissiontime_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reportsubmissiontime_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0225_auto_20240630_1443.py b/panel/migrations/0225_auto_20240630_1443.py new file mode 100644 index 0000000..ecc59b7 --- /dev/null +++ b/panel/migrations/0225_auto_20240630_1443.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-06-30 14:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0224_auto_20240630_1351'), + ] + + operations = [ + migrations.AddField( + model_name='reports', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 530443)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 421065)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 6, 30, 14, 43, 1, 436691)), + ), + ] diff --git a/panel/migrations/0226_auto_20240701_1553.py b/panel/migrations/0226_auto_20240701_1553.py new file mode 100644 index 0000000..ec14463 --- /dev/null +++ b/panel/migrations/0226_auto_20240701_1553.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-01 15:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0225_auto_20240630_1443'), + ] + + operations = [ + migrations.AddField( + model_name='bardocumentstatus', + name='priority_id', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 184071)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 14072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 14072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 14072)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 14072)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 23070)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 23070)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 23070)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 1, 15, 53, 5, 47067)), + ), + ] diff --git a/panel/migrations/0227_auto_20240702_1406.py b/panel/migrations/0227_auto_20240702_1406.py new file mode 100644 index 0000000..744e810 --- /dev/null +++ b/panel/migrations/0227_auto_20240702_1406.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-07-02 14:06 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0226_auto_20240701_1553'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 744294)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 614783)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 614783)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 614783)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 614783)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 624909)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 624909)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 624909)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 6, 24, 645149)), + ), + migrations.CreateModel( + name='UserPosition', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('title', models.CharField(max_length=500, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userposition_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='userposition_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0228_auto_20240702_1417.py b/panel/migrations/0228_auto_20240702_1417.py new file mode 100644 index 0000000..44f3f34 --- /dev/null +++ b/panel/migrations/0228_auto_20240702_1417.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-02 14:17 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0227_auto_20240702_1406'), + ] + + operations = [ + migrations.RemoveField( + model_name='reportsusers', + name='post', + ), + migrations.AddField( + model_name='reportsusers', + name='user_position', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='reports_user_positon', to='panel.userposition'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 29, 507043)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 737269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 737269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 737269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 737269)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 745332)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 745332)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 745332)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 14, 17, 27, 899346)), + ), + ] diff --git a/panel/migrations/0229_auto_20240702_1510.py b/panel/migrations/0229_auto_20240702_1510.py new file mode 100644 index 0000000..a675d7d --- /dev/null +++ b/panel/migrations/0229_auto_20240702_1510.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-02 15:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0228_auto_20240702_1417'), + ] + + operations = [ + migrations.AddField( + model_name='reportsusers', + name='city', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 18, 152825)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 941822)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 941822)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 941822)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 941822)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 947821)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 947821)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 947821)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 2, 15, 10, 17, 965823)), + ), + ] diff --git a/panel/migrations/0230_auto_20240703_0926.py b/panel/migrations/0230_auto_20240703_0926.py new file mode 100644 index 0000000..0ee4355 --- /dev/null +++ b/panel/migrations/0230_auto_20240703_0926.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-03 09:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0229_auto_20240702_1510'), + ] + + operations = [ + migrations.AddField( + model_name='reportsusers', + name='user_token', + field=models.CharField(max_length=4, null=True, unique=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 703980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 652978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 652978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 652978)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 652978)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 655979)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 655979)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 655979)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 9, 26, 31, 662979)), + ), + ] diff --git a/panel/migrations/0231_auto_20240703_1036.py b/panel/migrations/0231_auto_20240703_1036.py new file mode 100644 index 0000000..e427d28 --- /dev/null +++ b/panel/migrations/0231_auto_20240703_1036.py @@ -0,0 +1,71 @@ +# Generated by Django 3.2.13 on 2024-07-03 10:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0230_auto_20240703_0926'), + ] + + operations = [ + migrations.RemoveField( + model_name='reportsusers', + name='user_position', + ), + migrations.AddField( + model_name='reportsusers', + name='position', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 36, 0, 64385)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 906214)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 10, 35, 59, 923757)), + ), + migrations.DeleteModel( + name='UserPosition', + ), + ] diff --git a/panel/migrations/0232_auto_20240703_1101.py b/panel/migrations/0232_auto_20240703_1101.py new file mode 100644 index 0000000..c0076e0 --- /dev/null +++ b/panel/migrations/0232_auto_20240703_1101.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-03 11:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0231_auto_20240703_1036'), + ] + + operations = [ + migrations.AddField( + model_name='reports', + name='description', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 685451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 544823)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 11, 1, 32, 576077)), + ), + ] diff --git a/panel/migrations/0233_auto_20240703_1419.py b/panel/migrations/0233_auto_20240703_1419.py new file mode 100644 index 0000000..2ea1160 --- /dev/null +++ b/panel/migrations/0233_auto_20240703_1419.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-03 14:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0232_auto_20240703_1101'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='description', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 527305)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 24303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 24303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 24303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 24303)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 78302)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 78302)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 78302)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 14, 19, 5, 98301)), + ), + ] diff --git a/panel/migrations/0234_auto_20240703_1555.py b/panel/migrations/0234_auto_20240703_1555.py new file mode 100644 index 0000000..b70be61 --- /dev/null +++ b/panel/migrations/0234_auto_20240703_1555.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-03 15:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0233_auto_20240703_1419'), + ] + + operations = [ + migrations.AddField( + model_name='reports', + name='end_point', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='reportsusers', + name='fullname', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 50, 211682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 162685)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 162685)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 162685)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 162685)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 170683)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 170683)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 170683)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 3, 15, 54, 49, 199681)), + ), + ] diff --git a/panel/migrations/0235_auto_20240706_1424.py b/panel/migrations/0235_auto_20240706_1424.py new file mode 100644 index 0000000..d050bfc --- /dev/null +++ b/panel/migrations/0235_auto_20240706_1424.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-07-06 14:24 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0234_auto_20240703_1555'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 526892)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 323890)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 323890)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 323890)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 323890)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 364892)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 363893)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 363893)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 14, 24, 21, 385896)), + ), + migrations.CreateModel( + name='MovingText', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('moving_text', models.TextField(null=True)), + ('role', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtext_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtext_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0236_auto_20240706_1520.py b/panel/migrations/0236_auto_20240706_1520.py new file mode 100644 index 0000000..b90487c --- /dev/null +++ b/panel/migrations/0236_auto_20240706_1520.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-06 15:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0235_auto_20240706_1424'), + ] + + operations = [ + migrations.AddField( + model_name='movingtext', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 872489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 734489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 734489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 734489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 734489)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 742489)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 742489)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 742489)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 15, 20, 22, 763489)), + ), + ] diff --git a/panel/migrations/0237_auto_20240706_1652.py b/panel/migrations/0237_auto_20240706_1652.py new file mode 100644 index 0000000..17ee1a2 --- /dev/null +++ b/panel/migrations/0237_auto_20240706_1652.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2024-07-06 16:52 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0236_auto_20240706_1520'), + ] + + operations = [ + migrations.CreateModel( + name='MovingTextRole', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('role', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextrole_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextrole_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.RemoveField( + model_name='movingtext', + name='role', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 514005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 368004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 368004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 368004)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 368004)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 376006)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 376006)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 376006)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 6, 16, 52, 2, 397006)), + ), + migrations.CreateModel( + name='MovingTextWithRole', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextwithrole_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextwithrole_modifiedby', to=settings.AUTH_USER_MODEL)), + ('moving_text', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='role_moving_text', to='panel.movingtext')), + ('role', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='moving_text_role', to='panel.movingtextrole')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='MovingTextDashboardStatus', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextdashboardstatus_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='movingtextdashboardstatus_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0238_auto_20240707_1153.py b/panel/migrations/0238_auto_20240707_1153.py new file mode 100644 index 0000000..a0afa73 --- /dev/null +++ b/panel/migrations/0238_auto_20240707_1153.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-07 11:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0237_auto_20240706_1652'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 483179)), + ), + migrations.AlterField( + model_name='movingtextwithrole', + name='active', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 350187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 350187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 350187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 350187)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 360187)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 359187)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 359187)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 7, 11, 53, 30, 379184)), + ), + ] diff --git a/panel/migrations/0239_auto_20240708_1341.py b/panel/migrations/0239_auto_20240708_1341.py new file mode 100644 index 0000000..1fe5a8c --- /dev/null +++ b/panel/migrations/0239_auto_20240708_1341.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-07-08 13:41 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0238_auto_20240707_1153'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 171191)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 8192)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 7194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 7194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 7194)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 16192)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 16192)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 16192)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 8, 13, 41, 32, 37191)), + ), + migrations.CreateModel( + name='NewProduct', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=300, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='newproduct_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='newproduct_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child', to='panel.newproduct')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0240_auto_20240709_1204.py b/panel/migrations/0240_auto_20240709_1204.py new file mode 100644 index 0000000..a2f17ca --- /dev/null +++ b/panel/migrations/0240_auto_20240709_1204.py @@ -0,0 +1,159 @@ +# Generated by Django 3.2.13 on 2024-07-09 12:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0239_auto_20240708_1341'), + ] + + operations = [ + migrations.AddField( + model_name='newproduct', + name='Conventional_sales_package', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='Conventional_sales_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='Conventional_sales_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='approved_price', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='approved_price_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='product_id', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_inquiry_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_inquiry_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_number_of_purchases', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_number_of_purchases_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_number_of_purchases_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_package', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_package_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_maximum_weight_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='sale_limitation_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='newproduct', + name='sale_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='newproduct', + name='sale_type_package_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='newproduct', + name='selling_more_than_inventory', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 449050)), + ), + migrations.AlterField( + model_name='newproduct', + name='name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 379045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 379045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 379045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 379045)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 383047)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 383047)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 383047)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 9, 12, 4, 7, 393048)), + ), + ] diff --git a/panel/migrations/0241_auto_20240710_1333.py b/panel/migrations/0241_auto_20240710_1333.py new file mode 100644 index 0000000..562670e --- /dev/null +++ b/panel/migrations/0241_auto_20240710_1333.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-10 13:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0240_auto_20240709_1204'), + ] + + operations = [ + migrations.AddField( + model_name='paymentgatewaypercentage', + name='other', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='totalpaymentgatewaypercentage', + name='other', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 589941)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 441526)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 441526)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 441526)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 441526)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 450526)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 449524)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 449524)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 10, 13, 33, 29, 470525)), + ), + ] diff --git a/panel/migrations/0242_auto_20240713_0951.py b/panel/migrations/0242_auto_20240713_0951.py new file mode 100644 index 0000000..bead2de --- /dev/null +++ b/panel/migrations/0242_auto_20240713_0951.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-07-13 09:51 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0041_auto_20240713_0951'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0241_auto_20240710_1333'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 133959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 81957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 81957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 81957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 81957)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 85956)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 84956)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 84956)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 9, 51, 8, 92960)), + ), + migrations.CreateModel( + name='AdminX', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_x_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adminx_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='adminx_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_x_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_x_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='admin_x_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0243_auto_20240713_1024.py b/panel/migrations/0243_auto_20240713_1024.py new file mode 100644 index 0000000..c06703c --- /dev/null +++ b/panel/migrations/0243_auto_20240713_1024.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-07-13 10:24 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0042_auto_20240713_1024'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0242_auto_20240713_0951'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 764775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 708803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 708803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 708803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 708803)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 712776)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 712776)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 712776)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 10, 24, 12, 719803)), + ), + migrations.CreateModel( + name='Supporter', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='supporter_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0244_auto_20240713_1139.py b/panel/migrations/0244_auto_20240713_1139.py new file mode 100644 index 0000000..f777a86 --- /dev/null +++ b/panel/migrations/0244_auto_20240713_1139.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-07-13 11:39 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0243_auto_20240713_1024'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 212960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 57951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 57951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 57951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 57951)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 62957)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 62957)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 62957)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 11, 39, 27, 83955)), + ), + migrations.CreateModel( + name='ZarinPalAccounts', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('account', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='zarinpalaccounts_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='zarinpalaccounts_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0245_auto_20240713_1236.py b/panel/migrations/0245_auto_20240713_1236.py new file mode 100644 index 0000000..0f49959 --- /dev/null +++ b/panel/migrations/0245_auto_20240713_1236.py @@ -0,0 +1,87 @@ +# Generated by Django 3.2.13 on 2024-07-13 12:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0244_auto_20240713_1139'), + ] + + operations = [ + migrations.RemoveField( + model_name='zarinpalaccounts', + name='account', + ), + migrations.RemoveField( + model_name='zarinpalaccounts', + name='name', + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='company_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='guild_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='other_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='union_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 138847)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 75847)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 75847)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 75847)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 75847)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 79847)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 79847)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 79847)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 36, 27, 88846)), + ), + ] diff --git a/panel/migrations/0246_auto_20240713_1250.py b/panel/migrations/0246_auto_20240713_1250.py new file mode 100644 index 0000000..73686d0 --- /dev/null +++ b/panel/migrations/0246_auto_20240713_1250.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-07-13 12:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0245_auto_20240713_1236'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='city_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='company_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='guilds_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='other_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='union_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='wallet_account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 332084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 264081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 264081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 264081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 264081)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 269084)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 269084)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 269084)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 12, 50, 36, 279081)), + ), + ] diff --git a/panel/migrations/0247_auto_20240713_1516.py b/panel/migrations/0247_auto_20240713_1516.py new file mode 100644 index 0000000..cd9729b --- /dev/null +++ b/panel/migrations/0247_auto_20240713_1516.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2024-07-13 15:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0246_auto_20240713_1250'), + ] + + operations = [ + migrations.RemoveField( + model_name='zarinpalaccounts', + name='company_account', + ), + migrations.RemoveField( + model_name='zarinpalaccounts', + name='guild_account', + ), + migrations.RemoveField( + model_name='zarinpalaccounts', + name='other_account', + ), + migrations.RemoveField( + model_name='zarinpalaccounts', + name='union_account', + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='account', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='en_name', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='zarinpalaccounts', + name='name', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 22, 339101)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 929104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 929104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 929104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 929104)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 938105)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 938105)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 938105)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 13, 15, 15, 21, 958101)), + ), + ] diff --git a/panel/migrations/0248_auto_20240717_1145.py b/panel/migrations/0248_auto_20240717_1145.py new file mode 100644 index 0000000..4c69736 --- /dev/null +++ b/panel/migrations/0248_auto_20240717_1145.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-17 11:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0247_auto_20240713_1516'), + ] + + operations = [ + migrations.AddField( + model_name='provinceallowkillhousedirectbuying', + name='export_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provinceallowkillhousedirectbuying', + name='freezing_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 130480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 11, 45, 14, 67974)), + ), + ] diff --git a/panel/migrations/0249_auto_20240717_1208.py b/panel/migrations/0249_auto_20240717_1208.py new file mode 100644 index 0000000..b362584 --- /dev/null +++ b/panel/migrations/0249_auto_20240717_1208.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2024-07-17 12:08 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0248_auto_20240717_1145'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='export_killed_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='export_killed_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='export', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 33, 106662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 984960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 984960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 984960)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 984960)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 995117)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 995117)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 32, 995117)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 12, 8, 33, 15381)), + ), + migrations.CreateModel( + name='PoultryExport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryexport_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryexport_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0250_auto_20240717_1306.py b/panel/migrations/0250_auto_20240717_1306.py new file mode 100644 index 0000000..1bcffe8 --- /dev/null +++ b/panel/migrations/0250_auto_20240717_1306.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-17 13:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0249_auto_20240717_1208'), + ] + + operations = [ + migrations.AddField( + model_name='poultryexport', + name='limitation', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryexport', + name='limitation_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 529378)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 375616)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 375616)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 375616)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 375616)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 384808)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 384808)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 384808)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 6, 33, 406114)), + ), + ] diff --git a/panel/migrations/0251_auto_20240717_1332.py b/panel/migrations/0251_auto_20240717_1332.py new file mode 100644 index 0000000..208e52f --- /dev/null +++ b/panel/migrations/0251_auto_20240717_1332.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-07-17 13:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0250_auto_20240717_1306'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 474937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 333193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 333193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 333193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 333193)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 343297)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 343297)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 343297)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 32, 40, 363570)), + ), + migrations.CreateModel( + name='PoultryOutProvinceRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('limitation_status', models.BooleanField(default=False)), + ('limitation', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryoutprovincerequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryoutprovincerequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0252_auto_20240717_1350.py b/panel/migrations/0252_auto_20240717_1350.py new file mode 100644 index 0000000..8c9e524 --- /dev/null +++ b/panel/migrations/0252_auto_20240717_1350.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-17 13:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0251_auto_20240717_1332'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='export_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 859679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 674747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 674747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 674747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 674747)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 683745)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 683745)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 683745)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 17, 13, 50, 34, 705748)), + ), + ] diff --git a/panel/migrations/0253_auto_20240718_1206.py b/panel/migrations/0253_auto_20240718_1206.py new file mode 100644 index 0000000..f7dcece --- /dev/null +++ b/panel/migrations/0253_auto_20240718_1206.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-18 12:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0252_auto_20240717_1350'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='export_country', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 490715)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 426711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 426711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 426711)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 426711)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 430711)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 430711)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 430711)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 12, 6, 7, 439711)), + ), + ] diff --git a/panel/migrations/0254_auto_20240718_1303.py b/panel/migrations/0254_auto_20240718_1303.py new file mode 100644 index 0000000..b4cadcf --- /dev/null +++ b/panel/migrations/0254_auto_20240718_1303.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-07-18 13:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0253_auto_20240718_1206'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='export_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='export_message', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='export_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AddField( + model_name='killrequest', + name='input_export_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 4, 137577)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 381579)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 381579)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 381579)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 381579)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 389578)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 388577)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 389578)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 18, 13, 3, 3, 419578)), + ), + ] diff --git a/panel/migrations/0255_auto_20240720_1218.py b/panel/migrations/0255_auto_20240720_1218.py new file mode 100644 index 0000000..ba62316 --- /dev/null +++ b/panel/migrations/0255_auto_20240720_1218.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-20 12:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0254_auto_20240718_1303'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='accept_reject_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 285281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 133281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 133281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 133281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 133281)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 142281)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 141281)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 141281)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 20, 12, 18, 15, 161276)), + ), + ] diff --git a/panel/migrations/0256_auto_20240724_1147.py b/panel/migrations/0256_auto_20240724_1147.py new file mode 100644 index 0000000..2830068 --- /dev/null +++ b/panel/migrations/0256_auto_20240724_1147.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-24 11:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0255_auto_20240720_1218'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 852930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 790437)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 24, 11, 47, 13, 806067)), + ), + ] diff --git a/panel/migrations/0257_auto_20240725_1040.py b/panel/migrations/0257_auto_20240725_1040.py new file mode 100644 index 0000000..f7d278c --- /dev/null +++ b/panel/migrations/0257_auto_20240725_1040.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-07-25 10:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0256_auto_20240724_1147'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='kill_house_vet_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='kill_house_vet_state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='kill_house_vet_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 716044)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 653538)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 10, 40, 32, 669170)), + ), + ] diff --git a/panel/migrations/0258_auto_20240725_1112.py b/panel/migrations/0258_auto_20240725_1112.py new file mode 100644 index 0000000..59e8637 --- /dev/null +++ b/panel/migrations/0258_auto_20240725_1112.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-25 11:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0257_auto_20240725_1040'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='acceptor_rejector', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='date_of_accept_reject', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 724611)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 646482)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 646482)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 646482)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 646482)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 662102)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 662102)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 662102)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 25, 11, 12, 29, 662102)), + ), + ] diff --git a/panel/migrations/0259_auto_20240727_1222.py b/panel/migrations/0259_auto_20240727_1222.py new file mode 100644 index 0000000..fff7e3b --- /dev/null +++ b/panel/migrations/0259_auto_20240727_1222.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-07-27 12:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0258_auto_20240725_1112'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='bar_clearance_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 877934)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 715876)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 715876)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 715876)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 715876)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 726021)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 726021)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 726021)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 27, 12, 21, 42, 746257)), + ), + ] diff --git a/panel/migrations/0260_auto_20240731_2252.py b/panel/migrations/0260_auto_20240731_2252.py new file mode 100644 index 0000000..7da014f --- /dev/null +++ b/panel/migrations/0260_auto_20240731_2252.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-07-31 22:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0259_auto_20240727_1222'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='Lat', + field=models.FloatField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='Long', + field=models.FloatField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 896840)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 416776)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 7, 31, 22, 51, 47, 526157)), + ), + ] diff --git a/panel/migrations/0261_auto_20240802_1111.py b/panel/migrations/0261_auto_20240802_1111.py new file mode 100644 index 0000000..b1a3d1b --- /dev/null +++ b/panel/migrations/0261_auto_20240802_1111.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-08-02 11:11 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0260_auto_20240731_2252'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='to_guilds', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_guilds', to='panel.guilds'), + ), + migrations.AddField( + model_name='stewardallocation', + name='to_steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_steward', to='panel.steward'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 413422)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 2, 11, 11, 18, 350912)), + ), + ] diff --git a/panel/migrations/0262_auto_20240803_1121.py b/panel/migrations/0262_auto_20240803_1121.py new file mode 100644 index 0000000..d343885 --- /dev/null +++ b/panel/migrations/0262_auto_20240803_1121.py @@ -0,0 +1,88 @@ +# Generated by Django 3.2.13 on 2024-08-03 11:21 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0043_auto_20240803_1121'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0261_auto_20240802_1111'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 606197)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 539193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 539193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 539193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 539193)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 543193)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 543193)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 543193)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 11, 21, 40, 552192)), + ), + migrations.CreateModel( + name='Dispenser', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('dispenser_type', models.CharField(max_length=100, null=True)), + ('car', models.CharField(max_length=100, null=True)), + ('pelak', models.CharField(max_length=100, null=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_steward', to='panel.steward')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0263_auto_20240803_1509.py b/panel/migrations/0263_auto_20240803_1509.py new file mode 100644 index 0000000..864d86e --- /dev/null +++ b/panel/migrations/0263_auto_20240803_1509.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-08-03 15:09 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0262_auto_20240803_1121'), + ] + + operations = [ + migrations.RemoveField( + model_name='dispenser', + name='steward', + ), + migrations.AddField( + model_name='dispenser', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_guild', to='panel.guilds'), + ), + migrations.AddField( + model_name='dispenser', + name='limitation_amount', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 908887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 718886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 718886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 718886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 718886)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 734888)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 734888)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 734888)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 9, 15, 763886)), + ), + ] diff --git a/panel/migrations/0264_auto_20240803_1523.py b/panel/migrations/0264_auto_20240803_1523.py new file mode 100644 index 0000000..bcdd6a7 --- /dev/null +++ b/panel/migrations/0264_auto_20240803_1523.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-03 15:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0263_auto_20240803_1509'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 370463)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 188460)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 188460)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 188460)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 188460)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 196462)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 196462)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 196462)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 23, 46, 215461)), + ), + ] diff --git a/panel/migrations/0265_auto_20240803_1527.py b/panel/migrations/0265_auto_20240803_1527.py new file mode 100644 index 0000000..a8d303d --- /dev/null +++ b/panel/migrations/0265_auto_20240803_1527.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-08-03 15:27 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0264_auto_20240803_1523'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_pos', to='panel.dispenser'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 170645)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 53646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 53646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 53646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 53646)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 61644)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 61644)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 61644)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 3, 15, 27, 22, 80646)), + ), + ] diff --git a/panel/migrations/0266_auto_20240804_1011.py b/panel/migrations/0266_auto_20240804_1011.py new file mode 100644 index 0000000..61667c4 --- /dev/null +++ b/panel/migrations/0266_auto_20240804_1011.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-04 10:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0265_auto_20240803_1527'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='has_pos', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 547291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 199108)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 10, 10, 37, 273510)), + ), + ] diff --git a/panel/migrations/0267_auto_20240804_1406.py b/panel/migrations/0267_auto_20240804_1406.py new file mode 100644 index 0000000..d173980 --- /dev/null +++ b/panel/migrations/0267_auto_20240804_1406.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-08-04 14:06 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0266_auto_20240804_1011'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='registrar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_dispenser', to='panel.dispenser'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 956548)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 889547)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 889547)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 889547)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 889547)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 893547)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 893547)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 893547)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 14, 6, 13, 902547)), + ), + ] diff --git a/panel/migrations/0268_auto_20240804_2127.py b/panel/migrations/0268_auto_20240804_2127.py new file mode 100644 index 0000000..88734cb --- /dev/null +++ b/panel/migrations/0268_auto_20240804_2127.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-08-04 21:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0267_auto_20240804_1406'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='free_guilds', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='dispenser', + name='free_sale', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='dispenser', + name='free_stewards', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 911516)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 777840)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 777840)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 777840)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 777840)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 794067)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 794067)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 794067)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 27, 26, 794821)), + ), + ] diff --git a/panel/migrations/0269_auto_20240804_2128.py b/panel/migrations/0269_auto_20240804_2128.py new file mode 100644 index 0000000..6ff8cba --- /dev/null +++ b/panel/migrations/0269_auto_20240804_2128.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-08-04 21:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0268_auto_20240804_2127'), + ] + + operations = [ + migrations.AlterField( + model_name='dispenser', + name='free_guilds', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='dispenser', + name='free_sale', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='dispenser', + name='free_stewards', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 8, 50513)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 894264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 894264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 894264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 894264)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 909884)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 909884)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 909884)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 4, 21, 28, 7, 925515)), + ), + ] diff --git a/panel/migrations/0270_auto_20240806_2324.py b/panel/migrations/0270_auto_20240806_2324.py new file mode 100644 index 0000000..fa44938 --- /dev/null +++ b/panel/migrations/0270_auto_20240806_2324.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-06 23:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0269_auto_20240804_2128'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='kill_house', + field=models.ManyToManyField(blank=True, null=True, related_name='guild_kill_houses', to='panel.KillHouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 407593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 217587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 216587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 217587)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 217587)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 226587)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 225589)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 226587)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 6, 23, 23, 46, 252588)), + ), + ] diff --git a/panel/migrations/0271_auto_20240808_1144.py b/panel/migrations/0271_auto_20240808_1144.py new file mode 100644 index 0000000..153ac09 --- /dev/null +++ b/panel/migrations/0271_auto_20240808_1144.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.13 on 2024-08-08 11:44 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0270_auto_20240806_2324'), + ] + + operations = [ + migrations.AddField( + model_name='newproduct', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_guild', to='panel.guilds'), + ), + migrations.AddField( + model_name='newproduct', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_kill_house', to='panel.movingtextrole'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 374105)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 308106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 308106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 308106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 308106)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 312110)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 312110)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 312110)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 11, 44, 29, 321106)), + ), + ] diff --git a/panel/migrations/0272_auto_20240808_1209.py b/panel/migrations/0272_auto_20240808_1209.py new file mode 100644 index 0000000..958ef1a --- /dev/null +++ b/panel/migrations/0272_auto_20240808_1209.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2024-08-08 12:09 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0271_auto_20240808_1144'), + ] + + operations = [ + migrations.RemoveField( + model_name='newproduct', + name='guild', + ), + migrations.RemoveField( + model_name='newproduct', + name='kill_house', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 606272)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 538267)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 538267)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 538267)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 538267)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 542267)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 541267)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 541267)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 12, 9, 31, 551272)), + ), + migrations.CreateModel( + name='RolesProducts', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rolesproducts_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_guild', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='rolesproducts_modifiedby', to=settings.AUTH_USER_MODEL)), + ('parent_product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_new_product', to='panel.newproduct')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='stewardallocation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_product', to='panel.rolesproducts'), + ), + ] diff --git a/panel/migrations/0273_auto_20240808_1410.py b/panel/migrations/0273_auto_20240808_1410.py new file mode 100644 index 0000000..305d82e --- /dev/null +++ b/panel/migrations/0273_auto_20240808_1410.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-08-08 14:10 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0272_auto_20240808_1209'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_kill_house_product', to='panel.rolesproducts'), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_kill_house_product', to='panel.rolesproducts'), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_steward_product', to='panel.rolesproducts'), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_steward_product', to='panel.rolesproducts'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 778885)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 651887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 651887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 651887)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 651887)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 659886)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 659886)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 659886)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 8, 14, 10, 11, 672884)), + ), + ] diff --git a/panel/migrations/0274_auto_20240809_1838.py b/panel/migrations/0274_auto_20240809_1838.py new file mode 100644 index 0000000..6586489 --- /dev/null +++ b/panel/migrations/0274_auto_20240809_1838.py @@ -0,0 +1,228 @@ +# Generated by Django 3.2.13 on 2024-08-09 18:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0273_auto_20240808_1410'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='active', + ), + migrations.AddField( + model_name='rolesproducts', + name='accepted_allocated_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='accepted_allocated_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='ave_weight_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_sale_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='freezing_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='freezing_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_accepted_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_buying_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_live_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_rejected_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_returned_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='real_allocated_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='real_allocated_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='rejected_allocated_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='rejected_allocated_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='returned_allocated_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='returned_allocated_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_number_of_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_remain_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 988648)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 598813)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 38, 30, 676942)), + ), + ] diff --git a/panel/migrations/0275_auto_20240809_1850.py b/panel/migrations/0275_auto_20240809_1850.py new file mode 100644 index 0000000..35de096 --- /dev/null +++ b/panel/migrations/0275_auto_20240809_1850.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-09 18:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0274_auto_20240809_1838'), + ] + + operations = [ + migrations.AddField( + model_name='poscompany', + name='en_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 944993)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 762281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 762281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 762281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 762281)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 770562)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 770562)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 770562)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 9, 18, 49, 46, 788872)), + ), + ] diff --git a/panel/migrations/0276_auto_20240810_0922.py b/panel/migrations/0276_auto_20240810_0922.py new file mode 100644 index 0000000..e7892ec --- /dev/null +++ b/panel/migrations/0276_auto_20240810_0922.py @@ -0,0 +1,191 @@ +# Generated by Django 3.2.13 on 2024-08-10 09:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0275_auto_20240809_1850'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='accepted_allocated_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='accepted_allocated_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='ave_weight_of_carcasses', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_sale_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_sale_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='freezing_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='freezing_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_accepted_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_buying_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_live_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_rejected_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_returned_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='real_allocated_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='real_allocated_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='rejected_allocated_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='rejected_allocated_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='returned_allocated_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='returned_allocated_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_number_of_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_remain_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_remain_weight', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 815832)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 706454)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 22, 8, 722075)), + ), + ] diff --git a/panel/migrations/0277_auto_20240810_0928.py b/panel/migrations/0277_auto_20240810_0928.py new file mode 100644 index 0000000..42da043 --- /dev/null +++ b/panel/migrations/0277_auto_20240810_0928.py @@ -0,0 +1,224 @@ +# Generated by Django 3.2.13 on 2024-08-10 09:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0276_auto_20240810_0922'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='accepted_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='accepted_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_sale_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='freezing_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='freezing_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='live_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_accepted_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_buying_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_live_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_rejected_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_returned_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='real_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='real_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='rejected_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='rejected_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='returned_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='returned_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_number_of_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_remain_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='weight_ave', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 3, 46873)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 915155)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 915155)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 915155)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 915155)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 930779)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 930779)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 930779)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 9, 28, 2, 946402)), + ), + ] diff --git a/panel/migrations/0278_auto_20240810_1357.py b/panel/migrations/0278_auto_20240810_1357.py new file mode 100644 index 0000000..3429c53 --- /dev/null +++ b/panel/migrations/0278_auto_20240810_1357.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2024-08-10 13:57 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0277_auto_20240810_0928'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='real_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='coldhouseallocations', + name='real_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_quantity_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='allocated_weight_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='to_kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_kill_house', to='panel.killhouse'), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_guild', to='panel.guilds'), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_guild', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 424449)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 348453)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 348453)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 348453)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 348453)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 351453)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 351453)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 351453)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 10, 13, 57, 29, 361453)), + ), + ] diff --git a/panel/migrations/0279_auto_20240811_1102.py b/panel/migrations/0279_auto_20240811_1102.py new file mode 100644 index 0000000..c80151d --- /dev/null +++ b/panel/migrations/0279_auto_20240811_1102.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-11 11:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0278_auto_20240810_1357'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='steward_active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='guilds', + name='steward_allocation_limit', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='guilds', + name='steward_limitation_allocation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='stewards', + field=models.ManyToManyField(blank=True, null=True, related_name='_panel_guilds_stewards_+', to='panel.Guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 504334)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 433671)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 11, 11, 2, 33, 449317)), + ), + ] diff --git a/panel/migrations/0280_auto_20240812_1015.py b/panel/migrations/0280_auto_20240812_1015.py new file mode 100644 index 0000000..16cfa3f --- /dev/null +++ b/panel/migrations/0280_auto_20240812_1015.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-08-12 10:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0279_auto_20240811_1102'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhousepurchaserequest', + name='limitation_number', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 194366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 133372)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 133372)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 133372)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 133372)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 136370)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 136370)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 136370)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 26, 145403)), + ), + ] diff --git a/panel/migrations/0281_auto_20240812_1015.py b/panel/migrations/0281_auto_20240812_1015.py new file mode 100644 index 0000000..e61e363 --- /dev/null +++ b/panel/migrations/0281_auto_20240812_1015.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-12 10:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0280_auto_20240812_1015'), + ] + + operations = [ + migrations.AddField( + model_name='killhousepurchaserequest', + name='limitation_number', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 219928)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 138931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 138931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 138931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 138931)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 143929)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 143929)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 143929)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 10, 15, 42, 157930)), + ), + ] diff --git a/panel/migrations/0282_auto_20240812_1349.py b/panel/migrations/0282_auto_20240812_1349.py new file mode 100644 index 0000000..05b1641 --- /dev/null +++ b/panel/migrations/0282_auto_20240812_1349.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-12 13:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0281_auto_20240812_1015'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='steward_kill_house', + field=models.ManyToManyField(blank=True, null=True, related_name='steward_kill_houses', to='panel.KillHouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 293722)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 137705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 136706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 137705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 137705)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 144905)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 144905)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 144905)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 12, 13, 49, 6, 164178)), + ), + ] diff --git a/panel/migrations/0283_auto_20240813_0921.py b/panel/migrations/0283_auto_20240813_0921.py new file mode 100644 index 0000000..343db87 --- /dev/null +++ b/panel/migrations/0283_auto_20240813_0921.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-13 09:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0282_auto_20240812_1349'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='company_gateway_percent', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='guilds_gateway_percent', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='other_gateway_percent', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='union_gateway_percent', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 275421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 212919)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 13, 9, 20, 55, 228547)), + ), + ] diff --git a/panel/migrations/0284_auto_20240814_1007.py b/panel/migrations/0284_auto_20240814_1007.py new file mode 100644 index 0000000..d4eeb31 --- /dev/null +++ b/panel/migrations/0284_auto_20240814_1007.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-14 10:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0283_auto_20240813_0921'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='registerar_fullname', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='guilds', + name='registerar_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 426552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 322552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 322552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 322552)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 322552)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 327552)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 327552)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 327552)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 7, 19, 339550)), + ), + ] diff --git a/panel/migrations/0285_auto_20240814_1017.py b/panel/migrations/0285_auto_20240814_1017.py new file mode 100644 index 0000000..ad310fc --- /dev/null +++ b/panel/migrations/0285_auto_20240814_1017.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-14 10:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0284_auto_20240814_1007'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='registerar_role', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 624676)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 487679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 487679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 487679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 487679)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 496677)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 496677)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 496677)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 14, 10, 17, 37, 515678)), + ), + ] diff --git a/panel/migrations/0286_auto_20240815_1337.py b/panel/migrations/0286_auto_20240815_1337.py new file mode 100644 index 0000000..41ab42a --- /dev/null +++ b/panel/migrations/0286_auto_20240815_1337.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-15 13:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0285_auto_20240814_1017'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='extra_bar_kill_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_kill_capacity', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 958087)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 884085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 884085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 884085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 884085)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 888086)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 888086)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 888086)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 15, 13, 37, 43, 897088)), + ), + ] diff --git a/panel/migrations/0287_auto_20240817_1040.py b/panel/migrations/0287_auto_20240817_1040.py new file mode 100644 index 0000000..d4bb6d1 --- /dev/null +++ b/panel/migrations/0287_auto_20240817_1040.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-17 10:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0286_auto_20240815_1337'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='aggregate_code', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='aggregate_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 10, 181057)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 901054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 901054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 901054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 901054)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 919053)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 919053)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 919053)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 40, 9, 962050)), + ), + ] diff --git a/panel/migrations/0288_auto_20240817_1052.py b/panel/migrations/0288_auto_20240817_1052.py new file mode 100644 index 0000000..e005d0b --- /dev/null +++ b/panel/migrations/0288_auto_20240817_1052.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-08-17 10:52 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0287_auto_20240817_1040'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 709868)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 383323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 383323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 383323)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 383323)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 398322)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 398322)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 398322)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 17, 10, 51, 21, 439325)), + ), + migrations.CreateModel( + name='VetFarmAggregatePermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('limitation', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarmaggregatepermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vetfarmaggregatepermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0289_auto_20240819_1141.py b/panel/migrations/0289_auto_20240819_1141.py new file mode 100644 index 0000000..56f77ce --- /dev/null +++ b/panel/migrations/0289_auto_20240819_1141.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-19 11:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0288_auto_20240817_1052'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='off', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 485214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 417207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 417207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 417207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 417207)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 421210)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 421210)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 421210)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 11, 41, 15, 430211)), + ), + ] diff --git a/panel/migrations/0290_auto_20240819_1227.py b/panel/migrations/0290_auto_20240819_1227.py new file mode 100644 index 0000000..155519a --- /dev/null +++ b/panel/migrations/0290_auto_20240819_1227.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-08-19 12:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0289_auto_20240819_1141'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhouse', + name='off', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 885627)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 820626)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 820626)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 820626)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 820626)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 824629)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 823626)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 824629)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 27, 40, 832626)), + ), + ] diff --git a/panel/migrations/0291_auto_20240819_1233.py b/panel/migrations/0291_auto_20240819_1233.py new file mode 100644 index 0000000..df7f1dc --- /dev/null +++ b/panel/migrations/0291_auto_20240819_1233.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-19 12:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0290_auto_20240819_1227'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='off', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 327494)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 259493)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 259493)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 259493)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 259493)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 263493)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 263493)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 263493)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 12, 32, 57, 273494)), + ), + ] diff --git a/panel/migrations/0292_auto_20240819_1325.py b/panel/migrations/0292_auto_20240819_1325.py new file mode 100644 index 0000000..d41fea9 --- /dev/null +++ b/panel/migrations/0292_auto_20240819_1325.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-19 13:25 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0291_auto_20240819_1233'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 127798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 56804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 56804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 56804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 56804)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 60803)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 60803)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 60803)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 19, 13, 25, 31, 69802)), + ), + migrations.CreateModel( + name='KillHouseBarLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('limitation', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousebarlimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousebarlimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0293_auto_20240820_1038.py b/panel/migrations/0293_auto_20240820_1038.py new file mode 100644 index 0000000..fec2775 --- /dev/null +++ b/panel/migrations/0293_auto_20240820_1038.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-08-20 10:38 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0044_auto_20240820_1038'), + ('panel', '0292_auto_20240819_1325'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 835912)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 679909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 679909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 679909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 679909)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 688911)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 688911)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 688911)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 20, 10, 37, 50, 709910)), + ), + migrations.CreateModel( + name='CityPoultry', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_poultry_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citypoultry_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citypoultry_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_poultry_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_poultry_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_poultry_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0294_auto_20240821_0917.py b/panel/migrations/0294_auto_20240821_0917.py new file mode 100644 index 0000000..68d8e46 --- /dev/null +++ b/panel/migrations/0294_auto_20240821_0917.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-21 09:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0293_auto_20240820_1038'), + ] + + operations = [ + migrations.AddField( + model_name='killhousebarlimitation', + name='allow', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 178671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 53671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 53671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 53671)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 53671)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 69298)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 69298)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 69298)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 17, 5, 84916)), + ), + ] diff --git a/panel/migrations/0295_auto_20240821_1000.py b/panel/migrations/0295_auto_20240821_1000.py new file mode 100644 index 0000000..95f1e0d --- /dev/null +++ b/panel/migrations/0295_auto_20240821_1000.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-21 10:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0294_auto_20240821_0917'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='max_kill_limit', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 969874)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 919916)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 919916)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 919916)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 919916)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 922909)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 922909)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 922909)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 21, 9, 59, 52, 929911)), + ), + ] diff --git a/panel/migrations/0296_auto_20240826_1223.py b/panel/migrations/0296_auto_20240826_1223.py new file mode 100644 index 0000000..fffbdbf --- /dev/null +++ b/panel/migrations/0296_auto_20240826_1223.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-08-26 12:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0295_auto_20240821_1000'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='violation_report', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='violation_report_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='violation_reporter', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 845718)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 699715)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 699715)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 699715)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 699715)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 708717)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 708717)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 708717)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 26, 12, 23, 25, 729718)), + ), + ] diff --git a/panel/migrations/0297_auto_20240828_1203.py b/panel/migrations/0297_auto_20240828_1203.py new file mode 100644 index 0000000..c9097b5 --- /dev/null +++ b/panel/migrations/0297_auto_20240828_1203.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-08-28 12:03 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0296_auto_20240826_1223'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 31, 12666)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 823113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 823113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 823113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 823113)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 838414)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 838414)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 838414)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 12, 3, 30, 873075)), + ), + migrations.CreateModel( + name='KillHouseStewardGuildRelation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allocation_number', models.IntegerField(default=0)), + ('Guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_relation', to='panel.guilds')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousestewardguildrelation_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_relation', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousestewardguildrelation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_relation', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0298_auto_20240828_1410.py b/panel/migrations/0298_auto_20240828_1410.py new file mode 100644 index 0000000..8f1660f --- /dev/null +++ b/panel/migrations/0298_auto_20240828_1410.py @@ -0,0 +1,67 @@ +# Generated by Django 3.2.13 on 2024-08-28 14:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0297_auto_20240828_1203'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhousestewardguildrelation', + name='Guild', + ), + migrations.RemoveField( + model_name='killhousestewardguildrelation', + name='steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 570252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 424253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 424253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 424253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 424253)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 433251)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 433251)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 433251)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 10, 32, 454251)), + ), + ] diff --git a/panel/migrations/0299_auto_20240828_1416.py b/panel/migrations/0299_auto_20240828_1416.py new file mode 100644 index 0000000..b67898e --- /dev/null +++ b/panel/migrations/0299_auto_20240828_1416.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-08-28 14:16 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0298_auto_20240828_1410'), + ] + + operations = [ + migrations.RenameField( + model_name='killhousestewardguildrelation', + old_name='allocation_number', + new_name='allocation_limit', + ), + migrations.AddField( + model_name='killhousestewardguildrelation', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_relation', to='panel.guilds'), + ), + migrations.AddField( + model_name='killhousestewardguildrelation', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_relation', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 699352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 554353)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 554353)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 554353)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 554353)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 562352)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 562352)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 562352)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 28, 14, 16, 24, 583351)), + ), + ] diff --git a/panel/migrations/0300_auto_20240829_0958.py b/panel/migrations/0300_auto_20240829_0958.py new file mode 100644 index 0000000..11fd445 --- /dev/null +++ b/panel/migrations/0300_auto_20240829_0958.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-08-29 09:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0299_auto_20240828_1416'), + ] + + operations = [ + migrations.AddField( + model_name='killhousestewardguildrelation', + name='allocation_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 250734)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 104568)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 103569)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 103569)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 103569)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 111774)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 111774)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 111774)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 9, 58, 12, 133197)), + ), + ] diff --git a/panel/migrations/0301_auto_20240829_1025.py b/panel/migrations/0301_auto_20240829_1025.py new file mode 100644 index 0000000..e366a6a --- /dev/null +++ b/panel/migrations/0301_auto_20240829_1025.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-29 10:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0300_auto_20240829_0958'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_report_edit_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='violation_report_editor', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 688278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 637277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 637277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 637277)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 637277)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 640277)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 640277)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 640277)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 29, 10, 25, 19, 647276)), + ), + ] diff --git a/panel/migrations/0302_auto_20240830_1023.py b/panel/migrations/0302_auto_20240830_1023.py new file mode 100644 index 0000000..abf3f7c --- /dev/null +++ b/panel/migrations/0302_auto_20240830_1023.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-08-30 10:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0301_auto_20240829_1025'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 542279)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 489280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 489280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 489280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 489280)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 493279)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 493279)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 493279)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 23, 49, 500279)), + ), + ] diff --git a/panel/migrations/0303_auto_20240830_1033.py b/panel/migrations/0303_auto_20240830_1033.py new file mode 100644 index 0000000..f27c4bd --- /dev/null +++ b/panel/migrations/0303_auto_20240830_1033.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-08-30 10:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0302_auto_20240830_1023'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 327359)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 273350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 273350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 273350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 273350)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 277349)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 277349)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 277349)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 4, 285320)), + ), + ] diff --git a/panel/migrations/0304_auto_20240830_1033.py b/panel/migrations/0304_auto_20240830_1033.py new file mode 100644 index 0000000..a7e740f --- /dev/null +++ b/panel/migrations/0304_auto_20240830_1033.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-08-30 10:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0303_auto_20240830_1033'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 254046)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 202039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 202039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 202039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 202039)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 206011)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 206011)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 206011)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 30, 10, 33, 22, 213048)), + ), + ] diff --git a/panel/migrations/0305_auto_20240831_1000.py b/panel/migrations/0305_auto_20240831_1000.py new file mode 100644 index 0000000..aabae58 --- /dev/null +++ b/panel/migrations/0305_auto_20240831_1000.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-08-31 10:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0304_auto_20240830_1033'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='payer_fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='internaltransaction', + name='payer_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 910949)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 780947)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 780947)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 780947)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 780947)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 787948)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 787948)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 787948)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 8, 31, 9, 59, 48, 807948)), + ), + ] diff --git a/panel/migrations/0306_auto_20240907_1020.py b/panel/migrations/0306_auto_20240907_1020.py new file mode 100644 index 0000000..ccb5071 --- /dev/null +++ b/panel/migrations/0306_auto_20240907_1020.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-09-07 10:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0305_auto_20240831_1000'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 576427)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 525427)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 525427)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 525427)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 525427)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 529426)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 529426)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 529426)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 7, 10, 19, 59, 536427)), + ), + ] diff --git a/panel/migrations/0307_auto_20240911_1147.py b/panel/migrations/0307_auto_20240911_1147.py new file mode 100644 index 0000000..28959db --- /dev/null +++ b/panel/migrations/0307_auto_20240911_1147.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2024-09-11 11:47 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0306_auto_20240907_1020'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 619790)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 519485)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 11, 11, 46, 32, 535107)), + ), + migrations.CreateModel( + name='OutOfProvinceSellingCarcassesPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('type', models.CharField(max_length=100, null=True)), + ('percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outofprovincesellingcarcassespermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outofprovincesellingcarcassespermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0308_auto_20240912_0926.py b/panel/migrations/0308_auto_20240912_0926.py new file mode 100644 index 0000000..2569a23 --- /dev/null +++ b/panel/migrations/0308_auto_20240912_0926.py @@ -0,0 +1,87 @@ +# Generated by Django 3.2.13 on 2024-09-12 09:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0046_auto_20240912_0926'), + ('panel', '0307_auto_20240911_1147'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 102356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 31361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 31361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 31361)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 31361)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 35361)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 35361)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 35361)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 9, 25, 53, 46356)), + ), + migrations.CreateModel( + name='OutProvinceCarcassesBuyer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('type', models.CharField(max_length=100, null=True)), + ('fullname', models.CharField(max_length=300, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('unit_name', models.CharField(max_length=300, null=True)), + ('city', models.CharField(max_length=300, null=True)), + ('province', models.CharField(max_length=300, null=True)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincecarcassesbuyer_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincecarcassesbuyer_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='out_province_carcasses_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0309_auto_20240912_1121.py b/panel/migrations/0309_auto_20240912_1121.py new file mode 100644 index 0000000..512dd5f --- /dev/null +++ b/panel/migrations/0309_auto_20240912_1121.py @@ -0,0 +1,103 @@ +# Generated by Django 3.2.13 on 2024-09-12 11:21 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0308_auto_20240912_0926'), + ] + + operations = [ + migrations.RemoveField( + model_name='outprovincecarcassesbuyer', + name='type', + ), + migrations.RemoveField( + model_name='outprovincecarcassesbuyer', + name='user', + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='buyer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_buyer', to='panel.outprovincecarcassesbuyer'), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='permission_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='registerar_fullname', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='status', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='first_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='last_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 776880)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 710883)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 710883)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 710883)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 710883)), + ), + migrations.AlterField( + model_name='outprovincecarcassesbuyer', + name='fullname', + field=models.CharField(max_length=150, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 715882)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 715882)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 715882)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 11, 21, 11, 724882)), + ), + ] diff --git a/panel/migrations/0310_auto_20240912_1211.py b/panel/migrations/0310_auto_20240912_1211.py new file mode 100644 index 0000000..800c882 --- /dev/null +++ b/panel/migrations/0310_auto_20240912_1211.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-09-12 12:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0309_auto_20240912_1121'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 251205)), + ), + migrations.AlterField( + model_name='killhousefreesalebarinformation', + name='status', + field=models.CharField(default='pending', max_length=300), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 10194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 10194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 10194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 10194)), + ), + migrations.AlterField( + model_name='outprovincecarcassesbuyer', + name='fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 20191)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 20191)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 20191)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 12, 12, 11, 0, 41185)), + ), + ] diff --git a/panel/migrations/0311_auto_20240914_1038.py b/panel/migrations/0311_auto_20240914_1038.py new file mode 100644 index 0000000..fda0177 --- /dev/null +++ b/panel/migrations/0311_auto_20240914_1038.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-09-14 10:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0310_auto_20240912_1211'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='accepted_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='accepted_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='real_number_of_carcasses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='real_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 500959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 438452)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 14, 10, 38, 45, 454082)), + ), + ] diff --git a/panel/migrations/0312_auto_20240915_1241.py b/panel/migrations/0312_auto_20240915_1241.py new file mode 100644 index 0000000..46bc36b --- /dev/null +++ b/panel/migrations/0312_auto_20240915_1241.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-09-15 12:41 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0311_auto_20240914_1038'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='Kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_buyer', to='panel.killhouse'), + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_buyer', to='panel.guilds'), + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='type_activity', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='buyer_activity', to='panel.typeactivity'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 175479)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 106474)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 106474)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 106474)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 106474)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 110477)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 110477)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 110477)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 9, 15, 12, 41, 21, 120477)), + ), + ] diff --git a/panel/migrations/0313_auto_20241005_1310.py b/panel/migrations/0313_auto_20241005_1310.py new file mode 100644 index 0000000..b37b55d --- /dev/null +++ b/panel/migrations/0313_auto_20241005_1310.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-10-05 13:10 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0312_auto_20240915_1241'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 40, 462800)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 236442)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 236442)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 236442)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 236442)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 244482)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 244482)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 244482)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 5, 13, 9, 39, 266764)), + ), + migrations.CreateModel( + name='ProductPricingType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('province', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='productpricingtype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='productpricingtype_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0314_auto_20241012_1226.py b/panel/migrations/0314_auto_20241012_1226.py new file mode 100644 index 0000000..78d8092 --- /dev/null +++ b/panel/migrations/0314_auto_20241012_1226.py @@ -0,0 +1,129 @@ +# Generated by Django 3.2.13 on 2024-10-12 12:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0313_auto_20241005_1310'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='city_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='city_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='company_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='company_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='guilds_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='guilds_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='other_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='other_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='total_wage_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='union_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='union_share_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='wage', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='wallet_share', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='wallet_share_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 185647)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 132109)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 131110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 132109)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 131110)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 136107)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 136107)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 136107)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 12, 12, 26, 22, 144125)), + ), + ] diff --git a/panel/migrations/0315_auto_20241015_1027.py b/panel/migrations/0315_auto_20241015_1027.py new file mode 100644 index 0000000..3c81dd8 --- /dev/null +++ b/panel/migrations/0315_auto_20241015_1027.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-10-15 10:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0314_auto_20241012_1226'), + ] + + operations = [ + migrations.RemoveField( + model_name='internaltransaction', + name='poultry_request', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 5, 42750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 899314)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 899314)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 899314)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 899314)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 908308)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 907309)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 907309)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 27, 4, 928297)), + ), + ] diff --git a/panel/migrations/0316_auto_20241015_1036.py b/panel/migrations/0316_auto_20241015_1036.py new file mode 100644 index 0000000..9136c2b --- /dev/null +++ b/panel/migrations/0316_auto_20241015_1036.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-15 10:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0315_auto_20241015_1027'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='poultry_request', + field=models.ManyToManyField(blank=True, null=True, related_name='poutry_request_transactions', to='panel.PoultryRequest'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 54, 550482)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 401345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 401345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 401345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 401345)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 409340)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 409340)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 409340)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 15, 10, 35, 53, 431327)), + ), + ] diff --git a/panel/migrations/0317_auto_20241017_1226.py b/panel/migrations/0317_auto_20241017_1226.py new file mode 100644 index 0000000..4f87b38 --- /dev/null +++ b/panel/migrations/0317_auto_20241017_1226.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-17 12:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0316_auto_20241015_1036'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='payment_link', + field=models.CharField(max_length=300, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 40, 274885)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 11683)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 11683)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 11683)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 11683)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 245149)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 244145)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 244145)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 17, 12, 24, 39, 277137)), + ), + ] diff --git a/panel/migrations/0318_auto_20241022_1026.py b/panel/migrations/0318_auto_20241022_1026.py new file mode 100644 index 0000000..c8a57fe --- /dev/null +++ b/panel/migrations/0318_auto_20241022_1026.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-10-22 10:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0317_auto_20241017_1226'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 804487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 750632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 750632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 750632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 750632)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 754621)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 753624)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 753624)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 26, 9, 762600)), + ), + migrations.CreateModel( + name='KillHousePricePermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepricepermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='killhousepricepermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0319_auto_20241022_1028.py b/panel/migrations/0319_auto_20241022_1028.py new file mode 100644 index 0000000..0fb8396 --- /dev/null +++ b/panel/migrations/0319_auto_20241022_1028.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-22 10:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0318_auto_20241022_1026'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='kill_house_price', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 762873)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 703033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 703033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 703033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 703033)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 707022)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 707022)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 707022)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 22, 10, 28, 1, 715001)), + ), + ] diff --git a/panel/migrations/0320_auto_20241023_1309.py b/panel/migrations/0320_auto_20241023_1309.py new file mode 100644 index 0000000..73af8f9 --- /dev/null +++ b/panel/migrations/0320_auto_20241023_1309.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2024-10-23 13:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0319_auto_20241022_1028'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='direct_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='direct_losses_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='direct_losses_editor', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='direct_losses_inputer', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='direct_losses_last_edit_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 412392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 357891)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 357891)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 357891)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 357891)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 361369)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 361369)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 361369)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 8, 55, 370062)), + ), + ] diff --git a/panel/migrations/0321_auto_20241023_1326.py b/panel/migrations/0321_auto_20241023_1326.py new file mode 100644 index 0000000..c1afca5 --- /dev/null +++ b/panel/migrations/0321_auto_20241023_1326.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-23 13:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0320_auto_20241023_1309'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='total_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 979501)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 925602)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 925602)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 925602)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 925602)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 929079)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 929079)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 929079)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 23, 13, 26, 2, 937773)), + ), + ] diff --git a/panel/migrations/0322_auto_20241024_0931.py b/panel/migrations/0322_auto_20241024_0931.py new file mode 100644 index 0000000..3c8aa57 --- /dev/null +++ b/panel/migrations/0322_auto_20241024_0931.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-24 09:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0321_auto_20241023_1326'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 529543)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 481794)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 9, 31, 4, 497574)), + ), + ] diff --git a/panel/migrations/0323_auto_20241024_2016.py b/panel/migrations/0323_auto_20241024_2016.py new file mode 100644 index 0000000..641e9bc --- /dev/null +++ b/panel/migrations/0323_auto_20241024_2016.py @@ -0,0 +1,78 @@ +# Generated by Django 3.2.13 on 2024-10-24 20:16 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0322_auto_20241024_0931'), + ] + + operations = [ + migrations.CreateModel( + name='IranProvinces', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=19)), + ('slug', models.CharField(max_length=17)), + ('tel_prefix', models.CharField(max_length=3, null=True)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 554224)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 505589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 505589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 505589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 505589)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 508588)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 508588)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 508588)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 15, 50, 515594)), + ), + migrations.CreateModel( + name='IranCities', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=17)), + ('slug', models.CharField(max_length=26)), + ('province_id', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='panel.iranprovinces')), + ], + ), + ] diff --git a/panel/migrations/0324_auto_20241024_2018.py b/panel/migrations/0324_auto_20241024_2018.py new file mode 100644 index 0000000..e98474e --- /dev/null +++ b/panel/migrations/0324_auto_20241024_2018.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-10-24 20:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0323_auto_20241024_2016'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 1, 47441)), + ), + migrations.AlterField( + model_name='irancities', + name='name', + field=models.CharField(max_length=250), + ), + migrations.AlterField( + model_name='irancities', + name='slug', + field=models.CharField(max_length=250), + ), + migrations.AlterField( + model_name='iranprovinces', + name='name', + field=models.CharField(max_length=250), + ), + migrations.AlterField( + model_name='iranprovinces', + name='slug', + field=models.CharField(max_length=250), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 990919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 990919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 990919)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 990919)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 993918)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 993918)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 0, 993918)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 1, 1920)), + ), + ] diff --git a/panel/migrations/0325_auto_20241024_2018.py b/panel/migrations/0325_auto_20241024_2018.py new file mode 100644 index 0000000..d3112c2 --- /dev/null +++ b/panel/migrations/0325_auto_20241024_2018.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-10-24 20:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0324_auto_20241024_2018'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 330457)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 274490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 274490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 274490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 274490)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 279491)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 279491)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 279491)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 24, 20, 18, 18, 286493)), + ), + ] diff --git a/panel/migrations/0326_auto_20241026_0950.py b/panel/migrations/0326_auto_20241026_0950.py new file mode 100644 index 0000000..ef79428 --- /dev/null +++ b/panel/migrations/0326_auto_20241026_0950.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-10-26 09:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0325_auto_20241024_2018'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='total_free_commitment_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_free_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 702285)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 650395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 650395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 650395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 650395)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 653520)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 653520)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 653520)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 9, 50, 41, 661195)), + ), + ] diff --git a/panel/migrations/0327_auto_20241026_1309.py b/panel/migrations/0327_auto_20241026_1309.py new file mode 100644 index 0000000..12edab3 --- /dev/null +++ b/panel/migrations/0327_auto_20241026_1309.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-10-26 13:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0326_auto_20241026_0950'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='commitment_type', + field=models.CharField(default='govermental', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 947395)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 882225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 882225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 882225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 882225)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 898342)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 898342)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 898342)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 26, 13, 9, 24, 898342)), + ), + ] diff --git a/panel/migrations/0328_auto_20241029_1116.py b/panel/migrations/0328_auto_20241029_1116.py new file mode 100644 index 0000000..c80baf3 --- /dev/null +++ b/panel/migrations/0328_auto_20241029_1116.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2024-10-29 11:16 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0050_auto_20241029_1116'), + ('panel', '0327_auto_20241026_1309'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 785111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 730745)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 730745)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 730745)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 730745)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 734223)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 734223)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 734223)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 10, 29, 11, 16, 42, 742915)), + ), + migrations.CreateModel( + name='BaseOutProvinceCarcassesBuyer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fullname', models.CharField(max_length=200, null=True)), + ('first_name', models.CharField(max_length=200, null=True)), + ('last_name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('unit_name', models.CharField(max_length=300, null=True)), + ('city', models.CharField(max_length=300, null=True)), + ('province', models.CharField(max_length=300, null=True)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='baseoutprovincecarcassesbuyer_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='baseoutprovincecarcassesbuyer_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='base_buyer_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='buyer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='base_buyer', to='panel.baseoutprovincecarcassesbuyer'), + ), + ] diff --git a/panel/migrations/0329_auto_20241103_0927.py b/panel/migrations/0329_auto_20241103_0927.py new file mode 100644 index 0000000..09e014a --- /dev/null +++ b/panel/migrations/0329_auto_20241103_0927.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-03 09:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0328_auto_20241029_1116'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_image1', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 624676)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 570320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 570320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 570320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 570320)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 573416)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 573416)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 573416)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 27, 42, 582091)), + ), + ] diff --git a/panel/migrations/0330_auto_20241103_0936.py b/panel/migrations/0330_auto_20241103_0936.py new file mode 100644 index 0000000..c093f14 --- /dev/null +++ b/panel/migrations/0330_auto_20241103_0936.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-03 09:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0329_auto_20241103_0927'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryhatching', + name='violation_image', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 826621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 773093)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 773093)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 773093)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 773093)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 776198)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 776198)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 776198)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 36, 8, 783900)), + ), + ] diff --git a/panel/migrations/0331_auto_20241103_0938.py b/panel/migrations/0331_auto_20241103_0938.py new file mode 100644 index 0000000..1918cb0 --- /dev/null +++ b/panel/migrations/0331_auto_20241103_0938.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-03 09:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0330_auto_20241103_0936'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='violation_image', + field=models.JSONField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 209006)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 157271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 157271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 157271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 157271)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 160263)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 160263)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 160263)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 38, 23, 168735)), + ), + ] diff --git a/panel/migrations/0332_auto_20241103_0939.py b/panel/migrations/0332_auto_20241103_0939.py new file mode 100644 index 0000000..211f3dd --- /dev/null +++ b/panel/migrations/0332_auto_20241103_0939.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-03 09:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0331_auto_20241103_0938'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 89194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 21375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 21375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 21375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 21375)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 25365)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 25365)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 25365)), + ), + migrations.AlterField( + model_name='poultryhatching', + name='violation_image', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 39, 7, 34340)), + ), + ] diff --git a/panel/migrations/0333_auto_20241103_0947.py b/panel/migrations/0333_auto_20241103_0947.py new file mode 100644 index 0000000..a57b20d --- /dev/null +++ b/panel/migrations/0333_auto_20241103_0947.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-03 09:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0332_auto_20241103_0939'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultryhatching', + name='violation_image1', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 252329)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 191990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 191990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 191990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 191990)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 196369)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 196369)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 196369)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 3, 9, 46, 53, 204600)), + ), + ] diff --git a/panel/migrations/0334_auto_20241104_1433.py b/panel/migrations/0334_auto_20241104_1433.py new file mode 100644 index 0000000..8859c53 --- /dev/null +++ b/panel/migrations/0334_auto_20241104_1433.py @@ -0,0 +1,324 @@ +# Generated by Django 3.2.13 on 2024-11-04 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0333_auto_20241103_0947'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='free_accepted_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_accepted_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_free_sale_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_freezing_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_freezing_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_real_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_real_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_rejected_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_rejected_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_returned_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_returned_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_accepted_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_accepted_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_free_sale_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_free_sale_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_freezing_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_freezing_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_real_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_real_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_rejected_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_rejected_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_returned_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_returned_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_accepted_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_rejected_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_free_returned_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_governmental_accepted_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_governmental_rejected_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_governmental_returned_allocations', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_province_free_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='number_of_province_governmental_bars', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_live_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_live_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_live_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_live_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_live_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_live_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_live_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_live_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_bars_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_bars_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_bars_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_bars_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_free_remain_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_governmental_remain_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_governmental_remain_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 287782)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 234799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 234799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 234799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 234799)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 237791)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 237791)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 237791)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 14, 33, 30, 245769)), + ), + ] diff --git a/panel/migrations/0335_auto_20241104_2248.py b/panel/migrations/0335_auto_20241104_2248.py new file mode 100644 index 0000000..c4210fb --- /dev/null +++ b/panel/migrations/0335_auto_20241104_2248.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-11-04 22:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0334_auto_20241104_1433'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='live_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_live_bars', + ), + migrations.AddField( + model_name='rolesproducts', + name='total_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 632356)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 486409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 486409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 486409)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 486409)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 497407)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 497407)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 497407)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 4, 22, 47, 22, 518906)), + ), + ] diff --git a/panel/migrations/0336_auto_20241105_0834.py b/panel/migrations/0336_auto_20241105_0834.py new file mode 100644 index 0000000..f9d7013 --- /dev/null +++ b/panel/migrations/0336_auto_20241105_0834.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-05 08:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0335_auto_20241104_2248'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='name', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='rolesproducts', + name='weight_average', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 733110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 8, 34, 37, 685808)), + ), + ] diff --git a/panel/migrations/0337_auto_20241105_2335.py b/panel/migrations/0337_auto_20241105_2335.py new file mode 100644 index 0000000..c4cdbd1 --- /dev/null +++ b/panel/migrations/0337_auto_20241105_2335.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2024-11-05 23:35 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0336_auto_20241105_0834'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_free_sale_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_free_sale_weight', + ), + migrations.AddField( + model_name='coldhouseallocations', + name='allocation_type', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='coldhouseallocations', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_kill_house', to='panel.killhouse'), + ), + migrations.AddField( + model_name='stewardallocation', + name='sale_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 315592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 262053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 262053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 262053)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 262053)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 265051)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 265051)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 265051)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 5, 23, 34, 57, 273046)), + ), + ] diff --git a/panel/migrations/0338_auto_20241106_1605.py b/panel/migrations/0338_auto_20241106_1605.py new file mode 100644 index 0000000..6549d37 --- /dev/null +++ b/panel/migrations/0338_auto_20241106_1605.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-06 16:05 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0337_auto_20241105_2335'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='product', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_allocations_product', to='panel.rolesproducts'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 780042)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 732512)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 732512)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 732512)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 732512)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 736062)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 736062)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 736062)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 6, 16, 5, 26, 743017)), + ), + ] diff --git a/panel/migrations/0339_auto_20241107_1047.py b/panel/migrations/0339_auto_20241107_1047.py new file mode 100644 index 0000000..b2c8cf4 --- /dev/null +++ b/panel/migrations/0339_auto_20241107_1047.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-07 10:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0338_auto_20241106_1605'), + ] + + operations = [ + migrations.RemoveField( + model_name='stewardallocation', + name='steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 442024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 396578)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 396578)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 396578)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 396578)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 400054)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 398315)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 398315)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 47, 29, 407008)), + ), + ] diff --git a/panel/migrations/0340_auto_20241107_1055.py b/panel/migrations/0340_auto_20241107_1055.py new file mode 100644 index 0000000..60d2d56 --- /dev/null +++ b/panel/migrations/0340_auto_20241107_1055.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-07 10:55 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0339_auto_20241107_1047'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_steward_allocation', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 512087)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 456180)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 10, 55, 45, 471853)), + ), + ] diff --git a/panel/migrations/0341_auto_20241107_1450.py b/panel/migrations/0341_auto_20241107_1450.py new file mode 100644 index 0000000..d3f4268 --- /dev/null +++ b/panel/migrations/0341_auto_20241107_1450.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-07 14:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0340_auto_20241107_1055'), + ] + + operations = [ + migrations.RemoveField( + model_name='stewardallocation', + name='to_steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 46, 40322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 45, 993033)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 50, 46, 8781)), + ), + ] diff --git a/panel/migrations/0342_auto_20241107_1456.py b/panel/migrations/0342_auto_20241107_1456.py new file mode 100644 index 0000000..92c2a12 --- /dev/null +++ b/panel/migrations/0342_auto_20241107_1456.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-07 14:56 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0341_auto_20241107_1450'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='to_steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_steward', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 371033)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 312755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 312755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 312755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 312755)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 323790)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 323790)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 323790)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 7, 14, 56, 46, 323790)), + ), + ] diff --git a/panel/migrations/0343_auto_20241108_1518.py b/panel/migrations/0343_auto_20241108_1518.py new file mode 100644 index 0000000..3a4451d --- /dev/null +++ b/panel/migrations/0343_auto_20241108_1518.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-08 15:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0342_auto_20241107_1456'), + ] + + operations = [ + migrations.RemoveField( + model_name='stewardfreebarinformation', + name='steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 457986)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 393024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 392024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 393024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 392024)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 397022)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 397022)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 397022)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 18, 44, 407015)), + ), + ] diff --git a/panel/migrations/0344_auto_20241108_1527.py b/panel/migrations/0344_auto_20241108_1527.py new file mode 100644 index 0000000..d4f0ee2 --- /dev/null +++ b/panel/migrations/0344_auto_20241108_1527.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-08 15:27 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0343_auto_20241108_1518'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreebarinformation', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_steward', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 21, 441695)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 954396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 954396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 954396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 954396)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 960393)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 960393)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 960393)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 27, 20, 978382)), + ), + ] diff --git a/panel/migrations/0345_auto_20241108_1547.py b/panel/migrations/0345_auto_20241108_1547.py new file mode 100644 index 0000000..418badf --- /dev/null +++ b/panel/migrations/0345_auto_20241108_1547.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-08 15:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0344_auto_20241108_1527'), + ] + + operations = [ + migrations.RemoveField( + model_name='stewardfreesalebarinformation', + name='steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 173215)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 70756)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 70756)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 70756)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 70756)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 78267)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 78267)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 78267)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 46, 40, 98255)), + ), + ] diff --git a/panel/migrations/0346_auto_20241108_1552.py b/panel/migrations/0346_auto_20241108_1552.py new file mode 100644 index 0000000..4144fe7 --- /dev/null +++ b/panel/migrations/0346_auto_20241108_1552.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-11-08 15:52 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0345_auto_20241108_1547'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_steward', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 508750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 393303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 393303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 393303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 393303)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 403296)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 403296)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 403296)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 8, 15, 52, 12, 420287)), + ), + ] diff --git a/panel/migrations/0347_auto_20241109_1406.py b/panel/migrations/0347_auto_20241109_1406.py new file mode 100644 index 0000000..d87a6d5 --- /dev/null +++ b/panel/migrations/0347_auto_20241109_1406.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2024-11-09 14:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0346_auto_20241108_1552'), + ] + + operations = [ + migrations.RemoveField( + model_name='chaincompany', + name='address', + ), + migrations.AddField( + model_name='chaincompany', + name='city', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='chaincompany', + name='province', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 926932)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 875069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 875069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 875069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 875069)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 876074)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 876074)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 876074)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 6, 1, 876074)), + ), + ] diff --git a/panel/migrations/0348_auto_20241109_1421.py b/panel/migrations/0348_auto_20241109_1421.py new file mode 100644 index 0000000..e82a4ce --- /dev/null +++ b/panel/migrations/0348_auto_20241109_1421.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-09 14:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0347_auto_20241109_1406'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompany', + name='address', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 6, 23616)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 973191)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 973191)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 973191)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 973191)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 976672)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 976672)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 976672)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 14, 21, 5, 983626)), + ), + ] diff --git a/panel/migrations/0349_auto_20241109_1506.py b/panel/migrations/0349_auto_20241109_1506.py new file mode 100644 index 0000000..a60ddb0 --- /dev/null +++ b/panel/migrations/0349_auto_20241109_1506.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2024-11-09 15:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0348_auto_20241109_1421'), + ] + + operations = [ + migrations.CreateModel( + name='AutomaticDirectBuyingPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('allow', models.BooleanField(default=False)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 83357)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 20253)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 6, 42, 43368)), + ), + ] diff --git a/panel/migrations/0350_auto_20241109_1555.py b/panel/migrations/0350_auto_20241109_1555.py new file mode 100644 index 0000000..b910b67 --- /dev/null +++ b/panel/migrations/0350_auto_20241109_1555.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-09 15:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0349_auto_20241109_1506'), + ] + + operations = [ + migrations.AddField( + model_name='chaincompany', + name='postal_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 737274)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 664271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 664271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 664271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 664271)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 680124)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 680124)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 680124)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 15, 55, 9, 680124)), + ), + ] diff --git a/panel/migrations/0351_auto_20241109_2036.py b/panel/migrations/0351_auto_20241109_2036.py new file mode 100644 index 0000000..b5feaf7 --- /dev/null +++ b/panel/migrations/0351_auto_20241109_2036.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-09 20:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0350_auto_20241109_1555'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='breeding_unique_id', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='licence_number', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 461905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 392342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 392342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 392342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 392342)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 397304)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 397304)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 397304)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 9, 20, 35, 48, 404928)), + ), + ] diff --git a/panel/migrations/0352_auto_20241110_1035.py b/panel/migrations/0352_auto_20241110_1035.py new file mode 100644 index 0000000..e229353 --- /dev/null +++ b/panel/migrations/0352_auto_20241110_1035.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-10 10:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0351_auto_20241109_2036'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='free_direct_buying', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 176021)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 134688)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 10, 35, 32, 144494)), + ), + ] diff --git a/panel/migrations/0353_auto_20241110_1345.py b/panel/migrations/0353_auto_20241110_1345.py new file mode 100644 index 0000000..ccdb5b7 --- /dev/null +++ b/panel/migrations/0353_auto_20241110_1345.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-10 13:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0352_auto_20241110_1035'), + ] + + operations = [ + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='end_hour', + field=models.CharField(max_length=5, null=True), + ), + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='start_hour', + field=models.CharField(max_length=5, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 924135)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 45, 23, 876406)), + ), + ] diff --git a/panel/migrations/0354_auto_20241110_1354.py b/panel/migrations/0354_auto_20241110_1354.py new file mode 100644 index 0000000..b311832 --- /dev/null +++ b/panel/migrations/0354_auto_20241110_1354.py @@ -0,0 +1,77 @@ +# Generated by Django 3.2.13 on 2024-11-10 13:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0353_auto_20241110_1345'), + ] + + operations = [ + migrations.RemoveField( + model_name='automaticdirectbuyingpermission', + name='end_hour', + ), + migrations.RemoveField( + model_name='automaticdirectbuyingpermission', + name='start_hour', + ), + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='end_time', + field=models.TimeField(null=True), + ), + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='start_time', + field=models.TimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 911213)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 858915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 858915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 858915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 858915)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 862008)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 862008)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 862008)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 13, 53, 51, 870258)), + ), + ] diff --git a/panel/migrations/0355_auto_20241110_2306.py b/panel/migrations/0355_auto_20241110_2306.py new file mode 100644 index 0000000..47c4e2f --- /dev/null +++ b/panel/migrations/0355_auto_20241110_2306.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-10 23:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0354_auto_20241110_1354'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 958712)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 33078)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 33078)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 33078)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 33078)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 280487)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 280487)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 280487)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 10, 23, 5, 7, 301476)), + ), + ] diff --git a/panel/migrations/0356_auto_20241112_1250.py b/panel/migrations/0356_auto_20241112_1250.py new file mode 100644 index 0000000..990f3cf --- /dev/null +++ b/panel/migrations/0356_auto_20241112_1250.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-11-12 12:50 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0355_auto_20241110_2306'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 210167)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 142359)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 142359)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 142359)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 142359)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 145837)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 145837)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 145837)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 12, 50, 15, 154530)), + ), + migrations.CreateModel( + name='AgeNotificationPoultry', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('message', models.TextField()), + ('poultry_age', models.CharField(max_length=2)), + ('hour_send', models.CharField(max_length=2)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='agenotificationpoultry_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ManyToManyField(null=True, related_name='poultry_hatching_age_notification', to='panel.PoultryHatching')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='agenotificationpoultry_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0357_auto_20241112_1332.py b/panel/migrations/0357_auto_20241112_1332.py new file mode 100644 index 0000000..313fdce --- /dev/null +++ b/panel/migrations/0357_auto_20241112_1332.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-12 13:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0356_auto_20241112_1250'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='interface_number', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 138426)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 88006)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 88006)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 88006)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 88006)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 91482)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 91482)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 91482)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 13, 32, 4, 98437)), + ), + ] diff --git a/panel/migrations/0358_auto_20241112_1459.py b/panel/migrations/0358_auto_20241112_1459.py new file mode 100644 index 0000000..8664379 --- /dev/null +++ b/panel/migrations/0358_auto_20241112_1459.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-12 14:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0357_auto_20241112_1332'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='amount', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 503664)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 456496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 456496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 456496)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 456496)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 459971)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 459971)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 459971)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 14, 59, 1, 468664)), + ), + ] diff --git a/panel/migrations/0359_auto_20241112_1511.py b/panel/migrations/0359_auto_20241112_1511.py new file mode 100644 index 0000000..22b8644 --- /dev/null +++ b/panel/migrations/0359_auto_20241112_1511.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-12 15:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0358_auto_20241112_1459'), + ] + + operations = [ + migrations.RemoveField( + model_name='agenotificationpoultry', + name='hatching', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 307194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 247335)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 247335)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 247335)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 247335)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 250343)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 250343)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 250343)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 12, 15, 11, 40, 259347)), + ), + ] diff --git a/panel/migrations/0360_auto_20241113_1050.py b/panel/migrations/0360_auto_20241113_1050.py new file mode 100644 index 0000000..3418d53 --- /dev/null +++ b/panel/migrations/0360_auto_20241113_1050.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-11-13 10:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0359_auto_20241112_1511'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 738892)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 687128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 687128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 687128)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 687128)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 690426)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 690426)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 690426)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 50, 36, 698675)), + ), + ] diff --git a/panel/migrations/0361_auto_20241113_1058.py b/panel/migrations/0361_auto_20241113_1058.py new file mode 100644 index 0000000..4451dd0 --- /dev/null +++ b/panel/migrations/0361_auto_20241113_1058.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-11-13 10:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0360_auto_20241113_1050'), + ] + + operations = [ + migrations.RemoveField( + model_name='guilds', + name='stewards', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 689819)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 635980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 635980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 635980)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 635980)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 640109)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 640109)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 640109)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 10, 57, 54, 648163)), + ), + ] diff --git a/panel/migrations/0362_auto_20241113_1102.py b/panel/migrations/0362_auto_20241113_1102.py new file mode 100644 index 0000000..356fa07 --- /dev/null +++ b/panel/migrations/0362_auto_20241113_1102.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-13 11:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0361_auto_20241113_1058'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='stewards', + field=models.ManyToManyField(blank=True, related_name='_panel_guilds_stewards_+', to='panel.Guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 982127)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 930485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 930485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 930485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 930485)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 933533)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 933533)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 933533)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 13, 11, 2, 33, 940751)), + ), + ] diff --git a/panel/migrations/0363_auto_20241114_1345.py b/panel/migrations/0363_auto_20241114_1345.py new file mode 100644 index 0000000..3ecfb76 --- /dev/null +++ b/panel/migrations/0363_auto_20241114_1345.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-14 13:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0362_auto_20241113_1102'), + ] + + operations = [ + migrations.AddField( + model_name='newproduct', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 923802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 871217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 871217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 871217)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 871217)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 874694)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 874694)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 874694)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 14, 13, 45, 8, 874694)), + ), + ] diff --git a/panel/migrations/0364_auto_20241115_1217.py b/panel/migrations/0364_auto_20241115_1217.py new file mode 100644 index 0000000..70e86df --- /dev/null +++ b/panel/migrations/0364_auto_20241115_1217.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-15 12:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0363_auto_20241114_1345'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='company_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='posmachine', + name='last_check', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 51, 332362)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 965749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 965749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 965749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 965749)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 978742)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 978742)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 49, 978742)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 15, 12, 14, 50, 336648)), + ), + ] diff --git a/panel/migrations/0365_auto_20241116_0944.py b/panel/migrations/0365_auto_20241116_0944.py new file mode 100644 index 0000000..20b080f --- /dev/null +++ b/panel/migrations/0365_auto_20241116_0944.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-16 09:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0364_auto_20241115_1217'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='approved_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_price', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 85123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 37613)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 9, 44, 17, 53766)), + ), + ] diff --git a/panel/migrations/0366_auto_20241116_1121.py b/panel/migrations/0366_auto_20241116_1121.py new file mode 100644 index 0000000..da40702 --- /dev/null +++ b/panel/migrations/0366_auto_20241116_1121.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-11-16 11:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0365_auto_20241116_0944'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='pos_free_real_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='pos_governmental_real_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='pos_real_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 208447)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 161061)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 21, 10, 176852)), + ), + ] diff --git a/panel/migrations/0367_auto_20241116_1144.py b/panel/migrations/0367_auto_20241116_1144.py new file mode 100644 index 0000000..423ba66 --- /dev/null +++ b/panel/migrations/0367_auto_20241116_1144.py @@ -0,0 +1,67 @@ +# Generated by Django 3.2.13 on 2024-11-16 11:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0366_auto_20241116_1121'), + ] + + operations = [ + migrations.RemoveField( + model_name='newproduct', + name='approved_price', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='approved_price', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 326180)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 278816)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 43, 57, 294564)), + ), + ] diff --git a/panel/migrations/0368_auto_20241116_1148.py b/panel/migrations/0368_auto_20241116_1148.py new file mode 100644 index 0000000..6f288ab --- /dev/null +++ b/panel/migrations/0368_auto_20241116_1148.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-16 11:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0367_auto_20241116_1144'), + ] + + operations = [ + migrations.AddField( + model_name='newproduct', + name='approved_price', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 938713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 897351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 897351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 897351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 897351)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 901367)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 901367)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 901367)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 16, 11, 48, 4, 909131)), + ), + ] diff --git a/panel/migrations/0369_auto_20241117_1013.py b/panel/migrations/0369_auto_20241117_1013.py new file mode 100644 index 0000000..c13d6e0 --- /dev/null +++ b/panel/migrations/0369_auto_20241117_1013.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2024-11-17 10:13 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0368_auto_20241116_1148'), + ] + + operations = [ + migrations.RemoveField( + model_name='guilds', + name='stewards', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 521581)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 468920)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 468920)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 468920)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 468920)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 472910)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 472910)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 472910)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 13, 1, 481238)), + ), + migrations.CreateModel( + name='GuildSteward', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildsteward_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='guild_to_stewards', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildsteward_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='steward_to_guilds', to='panel.guilds')), + ], + options={ + 'unique_together': {('guild', 'steward')}, + }, + ), + ] diff --git a/panel/migrations/0370_auto_20241117_1020.py b/panel/migrations/0370_auto_20241117_1020.py new file mode 100644 index 0000000..f969517 --- /dev/null +++ b/panel/migrations/0370_auto_20241117_1020.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-17 10:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0369_auto_20241117_1013'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='stewards', + field=models.ManyToManyField(blank=True, related_name='guild_stewards', through='panel.GuildSteward', to='panel.Guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 345099)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 290808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 290808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 290808)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 290808)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 295057)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 295057)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 295057)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 10, 19, 57, 302243)), + ), + ] diff --git a/panel/migrations/0371_auto_20241117_1545.py b/panel/migrations/0371_auto_20241117_1545.py new file mode 100644 index 0000000..4deabc6 --- /dev/null +++ b/panel/migrations/0371_auto_20241117_1545.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2024-11-17 15:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0370_auto_20241117_1020'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='free_allocated_quantity_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_allocated_weight_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_allocated_quantity_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='governmental_allocated_weight_from', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_governmental_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='total_governmental_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 248153)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 195680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 195680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 195680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 195680)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 198772)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 198772)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 198772)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 15, 45, 26, 206392)), + ), + ] diff --git a/panel/migrations/0372_auto_20241117_2222.py b/panel/migrations/0372_auto_20241117_2222.py new file mode 100644 index 0000000..12c4f7d --- /dev/null +++ b/panel/migrations/0372_auto_20241117_2222.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2024-11-17 22:22 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0371_auto_20241117_1545'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 491951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 431458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 431458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 431458)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 431458)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 435455)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 435455)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 435455)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 17, 22, 22, 26, 443473)), + ), + migrations.CreateModel( + name='PosMachineTransactions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('check_id', models.CharField(max_length=100, null=True)), + ('mobile', models.CharField(max_length=100, null=True)), + ('natcode', models.CharField(max_length=100, null=True)), + ('fullname', models.CharField(max_length=100, null=True)), + ('date', models.DateTimeField(null=True)), + ('price', models.BigIntegerField(default=0)), + ('paid', models.BooleanField(default=False)), + ('checkout', models.BooleanField(default=False)), + ('hasTry', models.BooleanField(default=False)), + ('state', models.IntegerField(default=0)), + ('posProvider', models.CharField(max_length=100, null=True)), + ('result', models.CharField(max_length=100, null=True)), + ('refnum', models.CharField(max_length=100, null=True)), + ('terminal', models.CharField(max_length=100, null=True)), + ('cart', models.CharField(max_length=100, null=True)), + ('weight', models.IntegerField(default=0)), + ('lng', models.FloatField(default=0)), + ('lot', models.FloatField(default=0)), + ('additional', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posmachinetransactions_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posmachinetransactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ('pos', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_pos_transactions', to='panel.posmachine')), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_pos_transactions', to='panel.rolesproducts')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0373_auto_20241118_0811.py b/panel/migrations/0373_auto_20241118_0811.py new file mode 100644 index 0000000..e6aba59 --- /dev/null +++ b/panel/migrations/0373_auto_20241118_0811.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-18 08:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0372_auto_20241117_2222'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='steward_temp_key', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 576544)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 528588)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 527080)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 528588)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 527080)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 528588)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 528588)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 528588)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 8, 10, 49, 539929)), + ), + ] diff --git a/panel/migrations/0374_auto_20241118_0946.py b/panel/migrations/0374_auto_20241118_0946.py new file mode 100644 index 0000000..785d7bd --- /dev/null +++ b/panel/migrations/0374_auto_20241118_0946.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-11-18 09:46 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0373_auto_20241118_0811'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 727351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 667811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 667811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 667811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 667811)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 679401)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 679401)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 679401)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 9, 46, 4, 679401)), + ), + migrations.CreateModel( + name='BroadcastPrice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('kill_house_price', models.FloatField(default=0)), + ('steward_price', models.FloatField(default=0)), + ('guild_price', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='broadcastprice_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='broadcastprice_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0375_auto_20241118_1054.py b/panel/migrations/0375_auto_20241118_1054.py new file mode 100644 index 0000000..02877f9 --- /dev/null +++ b/panel/migrations/0375_auto_20241118_1054.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-18 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0374_auto_20241118_0946'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='approved_price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='approved_price_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 979780)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 914531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 914531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 914531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 914531)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 930215)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 930215)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 930215)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 10, 54, 34, 930215)), + ), + ] diff --git a/panel/migrations/0376_auto_20241118_2152.py b/panel/migrations/0376_auto_20241118_2152.py new file mode 100644 index 0000000..878ee2d --- /dev/null +++ b/panel/migrations/0376_auto_20241118_2152.py @@ -0,0 +1,379 @@ +# Generated by Django 3.2.13 on 2024-11-18 21:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0375_auto_20241118_1054'), + ] + + operations = [ + migrations.RemoveField( + model_name='rolesproducts', + name='accepted_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='accepted_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_quantity_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='allocated_weight_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_accepted_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_accepted_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_allocated_quantity_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_allocated_weight_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_buying_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_free_sale_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_free_sale_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_freezing_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_freezing_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_real_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_real_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_rejected_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_rejected_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_returned_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_returned_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_sale_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='free_sale_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_accepted_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_accepted_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_allocated_quantity_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_allocated_weight_from', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_freezing_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_freezing_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_real_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_real_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_rejected_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_rejected_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_returned_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='governmental_returned_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_accepted_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_accepted_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_buying_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_rejected_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_free_returned_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_governmental_accepted_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_governmental_rejected_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_governmental_returned_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_province_free_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_province_governmental_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_rejected_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='number_of_returned_allocations', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='pos_free_real_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='pos_governmental_real_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='pos_real_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_free_live_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_free_live_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_free_live_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_free_live_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_governmental_live_bars_carcasses_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_governmental_live_bars_carcasses_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_governmental_live_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='province_governmental_live_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='rejected_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='rejected_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='returned_allocated_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='returned_allocated_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_free_bars_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_free_bars_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_free_remain_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_free_remain_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_governmental_remain_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_governmental_remain_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_number_of_bars', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_quantity', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='total_weight', + ), + migrations.RemoveField( + model_name='rolesproducts', + name='weight_ave', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 671767)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 521766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 521766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 521766)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 521766)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 530765)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 530765)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 530765)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 51, 44, 553765)), + ), + ] diff --git a/panel/migrations/0377_auto_20241118_2157.py b/panel/migrations/0377_auto_20241118_2157.py new file mode 100644 index 0000000..1aa1872 --- /dev/null +++ b/panel/migrations/0377_auto_20241118_2157.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-18 21:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0376_auto_20241118_2152'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='loss_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='pos_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 37, 114071)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 971074)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 971074)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 971074)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 971074)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 979075)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 979075)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 36, 979075)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 21, 57, 37, 74)), + ), + ] diff --git a/panel/migrations/0378_auto_20241118_2317.py b/panel/migrations/0378_auto_20241118_2317.py new file mode 100644 index 0000000..94583e9 --- /dev/null +++ b/panel/migrations/0378_auto_20241118_2317.py @@ -0,0 +1,134 @@ +# Generated by Django 3.2.13 on 2024-11-18 23:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0377_auto_20241118_2157'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='free_buying_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='free_buying_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='out_province_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='out_province_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_allocated_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_free_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='receive_free_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='receive_free_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='receive_governmental_carcasses_quantity', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='receive_governmental_carcasses_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='approved_price_status', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 597718)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 490724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 490724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 490724)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 490724)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 499716)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 499716)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 499716)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 18, 23, 17, 9, 512715)), + ), + ] diff --git a/panel/migrations/0379_auto_20241120_0810.py b/panel/migrations/0379_auto_20241120_0810.py new file mode 100644 index 0000000..bc317a2 --- /dev/null +++ b/panel/migrations/0379_auto_20241120_0810.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-20 08:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0378_auto_20241118_2317'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='archive_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 521863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 480355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 480355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 480355)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 480355)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 482867)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 482867)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 482867)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 20, 8, 10, 5, 490399)), + ), + ] diff --git a/panel/migrations/0380_auto_20241126_1028.py b/panel/migrations/0380_auto_20241126_1028.py new file mode 100644 index 0000000..47f7fb1 --- /dev/null +++ b/panel/migrations/0380_auto_20241126_1028.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2024-11-26 10:28 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0379_auto_20241120_0810'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 755333)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 706047)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 706047)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 706047)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 706047)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 709792)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 709792)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 709792)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 28, 37, 717802)), + ), + migrations.CreateModel( + name='OutProvinceSaleLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('kill_house', models.FloatField(default=0)), + ('steward', models.FloatField(default=0)), + ('guild', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincesalelimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='outprovincesalelimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0381_auto_20241126_1047.py b/panel/migrations/0381_auto_20241126_1047.py new file mode 100644 index 0000000..81566df --- /dev/null +++ b/panel/migrations/0381_auto_20241126_1047.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-26 10:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0380_auto_20241126_1028'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='weight_loss', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 521335)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 474133)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 10, 47, 21, 489797)), + ), + ] diff --git a/panel/migrations/0382_auto_20241126_1606.py b/panel/migrations/0382_auto_20241126_1606.py new file mode 100644 index 0000000..76f9e92 --- /dev/null +++ b/panel/migrations/0382_auto_20241126_1606.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-26 16:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0381_auto_20241126_1047'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='automatic_accept', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 932393)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 873939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 873939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 873939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 873939)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 876931)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 876931)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 876931)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 26, 16, 5, 53, 886775)), + ), + ] diff --git a/panel/migrations/0383_auto_20241127_0958.py b/panel/migrations/0383_auto_20241127_0958.py new file mode 100644 index 0000000..cecaf90 --- /dev/null +++ b/panel/migrations/0383_auto_20241127_0958.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-11-27 09:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0382_auto_20241126_1606'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='calculate_status', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='calculate_status', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='calculate_status', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='calculate_status', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 447438)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 384249)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 384249)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 384249)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 384249)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 400031)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 400031)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 400031)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 27, 9, 58, 44, 400031)), + ), + ] diff --git a/panel/migrations/0384_auto_20241130_1018.py b/panel/migrations/0384_auto_20241130_1018.py new file mode 100644 index 0000000..5c870a3 --- /dev/null +++ b/panel/migrations/0384_auto_20241130_1018.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2024-11-30 10:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0383_auto_20241127_0958'), + ] + + operations = [ + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='coldhouseallocations', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardallocation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 494738)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 431374)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 18, 29, 449051)), + ), + ] diff --git a/panel/migrations/0385_auto_20241130_1048.py b/panel/migrations/0385_auto_20241130_1048.py new file mode 100644 index 0000000..2b239b9 --- /dev/null +++ b/panel/migrations/0385_auto_20241130_1048.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2024-11-30 10:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0384_auto_20241130_1018'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouseallocations', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouseassignmentinformation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardallocation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 826754)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 769116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 769116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 769116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 769116)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 770859)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 770859)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 770859)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 10, 48, 18, 780724)), + ), + ] diff --git a/panel/migrations/0386_auto_20241130_1830.py b/panel/migrations/0386_auto_20241130_1830.py new file mode 100644 index 0000000..e2c4540 --- /dev/null +++ b/panel/migrations/0386_auto_20241130_1830.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-30 18:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0385_auto_20241130_1048'), + ] + + operations = [ + migrations.AddField( + model_name='internaltransaction', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='internaltransaction', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 744002)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 694002)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 694002)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 694002)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 694002)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 697000)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 697000)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 697000)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 30, 13, 704003)), + ), + ] diff --git a/panel/migrations/0387_auto_20241130_1836.py b/panel/migrations/0387_auto_20241130_1836.py new file mode 100644 index 0000000..1838c03 --- /dev/null +++ b/panel/migrations/0387_auto_20241130_1836.py @@ -0,0 +1,59 @@ +# Generated by Django 3.2.13 on 2024-11-30 18:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0386_auto_20241130_1830'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 30, 7309)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 954682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 954682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 954682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 954682)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 958682)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 958682)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 958682)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 18, 36, 29, 966682)), + ), + ] diff --git a/panel/migrations/0388_auto_20241130_1902.py b/panel/migrations/0388_auto_20241130_1902.py new file mode 100644 index 0000000..3847ab9 --- /dev/null +++ b/panel/migrations/0388_auto_20241130_1902.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-11-30 19:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0387_auto_20241130_1836'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryhatching', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 216917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 164917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 163917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 164917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 164917)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 167918)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 167918)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 167918)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 19, 2, 7, 175917)), + ), + ] diff --git a/panel/migrations/0389_auto_20241130_2009.py b/panel/migrations/0389_auto_20241130_2009.py new file mode 100644 index 0000000..5461264 --- /dev/null +++ b/panel/migrations/0389_auto_20241130_2009.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-11-30 20:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0388_auto_20241130_1902'), + ] + + operations = [ + migrations.AddField( + model_name='cityoperatorcheckrequest', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 973531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 907506)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 907506)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 907506)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 907506)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 912506)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 912506)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 912506)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 11, 30, 20, 9, 25, 921506)), + ), + ] diff --git a/panel/migrations/0390_auto_20241203_0901.py b/panel/migrations/0390_auto_20241203_0901.py new file mode 100644 index 0000000..78e851b --- /dev/null +++ b/panel/migrations/0390_auto_20241203_0901.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-03 09:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0389_auto_20241130_2009'), + ] + + operations = [ + migrations.AddField( + model_name='killhousepercentage', + name='change_data', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 78407)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 15250)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 15250)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 15250)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 15250)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 24371)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 24371)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 24371)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 0, 57, 37124)), + ), + ] diff --git a/panel/migrations/0391_auto_20241203_0935.py b/panel/migrations/0391_auto_20241203_0935.py new file mode 100644 index 0000000..83ab194 --- /dev/null +++ b/panel/migrations/0391_auto_20241203_0935.py @@ -0,0 +1,63 @@ +# Generated by Django 3.2.13 on 2024-12-03 09:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0390_auto_20241203_0901'), + ] + + operations = [ + migrations.RemoveField( + model_name='agenotificationpoultry', + name='hour_send', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 990898)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 937628)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 937628)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 937628)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 937628)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 941633)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 941633)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 941633)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 35, 14, 949641)), + ), + ] diff --git a/panel/migrations/0392_auto_20241203_0946.py b/panel/migrations/0392_auto_20241203_0946.py new file mode 100644 index 0000000..18911b2 --- /dev/null +++ b/panel/migrations/0392_auto_20241203_0946.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-03 09:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0391_auto_20241203_0935'), + ] + + operations = [ + migrations.AddField( + model_name='agenotificationpoultry', + name='losses_percent', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 335840)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 278517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 278517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 278517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 278517)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 290295)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 288291)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 288291)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 3, 9, 46, 33, 298305)), + ), + ] diff --git a/panel/migrations/0393_auto_20241204_1334.py b/panel/migrations/0393_auto_20241204_1334.py new file mode 100644 index 0000000..23ea649 --- /dev/null +++ b/panel/migrations/0393_auto_20241204_1334.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2024-12-04 13:34 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0392_auto_20241203_0946'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 639596)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 580193)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 34, 18, 597812)), + ), + migrations.CreateModel( + name='PosAllocationTransactions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('check_id', models.CharField(max_length=100, null=True)), + ('date', models.DateTimeField(null=True)), + ('price', models.BigIntegerField(default=0)), + ('paid', models.BooleanField(default=False)), + ('state', models.IntegerField(default=0)), + ('posProvider', models.CharField(max_length=100, null=True)), + ('result', models.TextField(null=True)), + ('refnum', models.CharField(max_length=100, null=True)), + ('terminal', models.CharField(max_length=100, null=True)), + ('cart', models.CharField(max_length=100, null=True)), + ('lng', models.FloatField(default=0)), + ('lot', models.FloatField(default=0)), + ('additional', models.CharField(max_length=200, null=True)), + ('allocation', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_allocation_transactions', to='panel.stewardallocation')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posallocationtransactions_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posallocationtransactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ('pos', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_allocation_pos_transactions', to='panel.posmachine')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0394_auto_20241204_1357.py b/panel/migrations/0394_auto_20241204_1357.py new file mode 100644 index 0000000..aebb0d2 --- /dev/null +++ b/panel/migrations/0394_auto_20241204_1357.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-12-04 13:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0393_auto_20241204_1334'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='total_amount_paid', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='total_amount_remain', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 76197)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 36867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 36867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 36867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 36867)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 38869)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 38869)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 38869)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 4, 13, 57, 38, 42613)), + ), + ] diff --git a/panel/migrations/0395_auto_20241207_1034.py b/panel/migrations/0395_auto_20241207_1034.py new file mode 100644 index 0000000..0cfb09a --- /dev/null +++ b/panel/migrations/0395_auto_20241207_1034.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-12-07 10:34 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0394_auto_20241204_1357'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 23, 57412)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 916411)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 916411)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 916411)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 916411)), + ), + migrations.AlterField( + model_name='posallocationtransactions', + name='additional', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='posallocationtransactions', + name='cart', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posallocationtransactions', + name='refnum', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posallocationtransactions', + name='terminal', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 925408)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 925408)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 925408)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 7, 10, 34, 22, 946411)), + ), + ] diff --git a/panel/migrations/0396_auto_20241208_1147.py b/panel/migrations/0396_auto_20241208_1147.py new file mode 100644 index 0000000..282f4e4 --- /dev/null +++ b/panel/migrations/0396_auto_20241208_1147.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2024-12-08 11:47 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0052_auto_20241208_1147'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0395_auto_20241207_1034'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 620353)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 576799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 576799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 576799)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 576799)), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='additional', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='cart', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='refnum', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='terminal', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 578802)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 578802)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 578802)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 8, 11, 47, 31, 586812)), + ), + migrations.CreateModel( + name='ParentCompany', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_company_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parentcompany_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parentcompany_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_company_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_company_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='parent_company_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0397_auto_20241209_1422.py b/panel/migrations/0397_auto_20241209_1422.py new file mode 100644 index 0000000..015b17a --- /dev/null +++ b/panel/migrations/0397_auto_20241209_1422.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-12-09 14:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0396_auto_20241208_1147'), + ] + + operations = [ + migrations.AddField( + model_name='chainallocation', + name='temporary_deleted', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='chainallocation', + name='temporary_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 718310)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 672543)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 9, 14, 22, 21, 686607)), + ), + ] diff --git a/panel/migrations/0398_auto_20241211_0956.py b/panel/migrations/0398_auto_20241211_0956.py new file mode 100644 index 0000000..b221993 --- /dev/null +++ b/panel/migrations/0398_auto_20241211_0956.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2024-12-11 09:56 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0397_auto_20241209_1422'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='total_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='coldhouse', + name='total_input_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='coldhouse', + name='total_remain_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='to_cold_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_cold_house', to='panel.coldhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 341632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 278540)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 278540)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 278540)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 278540)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 294187)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 294187)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 294187)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 9, 55, 58, 297890)), + ), + ] diff --git a/panel/migrations/0399_auto_20241211_1115.py b/panel/migrations/0399_auto_20241211_1115.py new file mode 100644 index 0000000..7525131 --- /dev/null +++ b/panel/migrations/0399_auto_20241211_1115.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-11 11:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0398_auto_20241211_0956'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='cold_house_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 21, 15940)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 964280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 964280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 964280)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 964280)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 968028)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 968028)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 968028)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 11, 11, 15, 20, 978054)), + ), + ] diff --git a/panel/migrations/0400_auto_20241214_1358.py b/panel/migrations/0400_auto_20241214_1358.py new file mode 100644 index 0000000..7a8d814 --- /dev/null +++ b/panel/migrations/0400_auto_20241214_1358.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-12-14 13:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0399_auto_20241211_1115'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='end_period_losses_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='end_period_losses_editor', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='end_period_losses_inputer', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='end_period_losses_last_edit_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 146992)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 109296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 109296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 109296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 109296)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 111304)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 111304)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 111304)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 14, 13, 58, 20, 121076)), + ), + ] diff --git a/panel/migrations/0401_auto_20241215_1031.py b/panel/migrations/0401_auto_20241215_1031.py new file mode 100644 index 0000000..be03f51 --- /dev/null +++ b/panel/migrations/0401_auto_20241215_1031.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2024-12-15 10:31 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0053_auto_20241215_1031'), + ('panel', '0400_auto_20241214_1358'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 547975)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 494571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 494571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 494571)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 494571)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 498586)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 498586)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 498586)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 10, 31, 13, 508356)), + ), + migrations.CreateModel( + name='ColdHouseSteward', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('identity_documents', models.JSONField(null=True)), + ('active', models.BooleanField(default=True)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_steward_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhousesteward_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='coldhousesteward_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_steward_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_steward_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_steward_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='coldhouse', + name='cold_house_steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cold_house_steward_cold_house', to='panel.coldhousesteward'), + ), + ] diff --git a/panel/migrations/0402_auto_20241215_1139.py b/panel/migrations/0402_auto_20241215_1139.py new file mode 100644 index 0000000..1c72690 --- /dev/null +++ b/panel/migrations/0402_auto_20241215_1139.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-15 11:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0401_auto_20241215_1031'), + ] + + operations = [ + migrations.AddField( + model_name='coldhousesteward', + name='name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 998861)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 947484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 947484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 947484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 947484)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 951236)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 949493)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 949493)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 11, 39, 45, 959272)), + ), + ] diff --git a/panel/migrations/0403_auto_20241215_1458.py b/panel/migrations/0403_auto_20241215_1458.py new file mode 100644 index 0000000..a3c7e65 --- /dev/null +++ b/panel/migrations/0403_auto_20241215_1458.py @@ -0,0 +1,66 @@ +# Generated by Django 3.2.13 on 2024-12-15 14:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0402_auto_20241215_1139'), + ] + + operations = [ + migrations.RemoveField( + model_name='coldhouse', + name='cold_house_steward', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 388133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 328905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 328905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 328905)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 328905)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 332923)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 332923)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 332923)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 15, 14, 58, 29, 342707)), + ), + migrations.DeleteModel( + name='ColdHouseSteward', + ), + ] diff --git a/panel/migrations/0404_auto_20241216_1214.py b/panel/migrations/0404_auto_20241216_1214.py new file mode 100644 index 0000000..d3c2910 --- /dev/null +++ b/panel/migrations/0404_auto_20241216_1214.py @@ -0,0 +1,65 @@ +# Generated by Django 3.2.13 on 2024-12-16 12:14 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0403_auto_20241215_1458'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_cold_house', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 860134)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 12, 13, 59, 811116)), + ), + ] diff --git a/panel/migrations/0405_auto_20241216_1524.py b/panel/migrations/0405_auto_20241216_1524.py new file mode 100644 index 0000000..8a9ec47 --- /dev/null +++ b/panel/migrations/0405_auto_20241216_1524.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2024-12-16 15:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0404_auto_20241216_1214'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='city', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='coldhouse', + name='province', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 566639)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 501236)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 501236)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 501236)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 501236)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 517378)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 517378)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 517378)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 23, 40, 517378)), + ), + ] diff --git a/panel/migrations/0406_auto_20241216_1532.py b/panel/migrations/0406_auto_20241216_1532.py new file mode 100644 index 0000000..8850ef6 --- /dev/null +++ b/panel/migrations/0406_auto_20241216_1532.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-16 15:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0405_auto_20241216_1524'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='address', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 642789)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 15, 32, 6, 587202)), + ), + ] diff --git a/panel/migrations/0407_auto_20241216_1625.py b/panel/migrations/0407_auto_20241216_1625.py new file mode 100644 index 0000000..ce04307 --- /dev/null +++ b/panel/migrations/0407_auto_20241216_1625.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-12-16 16:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0406_auto_20241216_1532'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='coldhouse', + name='broadcast', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='coldhouse', + name='relocate', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 772998)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 725421)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 16, 16, 25, 25, 741157)), + ), + ] diff --git a/panel/migrations/0408_auto_20241218_1435.py b/panel/migrations/0408_auto_20241218_1435.py new file mode 100644 index 0000000..8329f8f --- /dev/null +++ b/panel/migrations/0408_auto_20241218_1435.py @@ -0,0 +1,64 @@ +# Generated by Django 3.2.13 on 2024-12-18 14:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0407_auto_20241216_1625'), + ] + + operations = [ + migrations.AddField( + model_name='coldhouse', + name='capacity', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 783568)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 728394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 728394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 728394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 728394)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 732146)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 732146)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 732146)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 18, 14, 35, 2, 740180)), + ), + ] diff --git a/panel/migrations/0409_auto_20241221_1150.py b/panel/migrations/0409_auto_20241221_1150.py new file mode 100644 index 0000000..e21207e --- /dev/null +++ b/panel/migrations/0409_auto_20241221_1150.py @@ -0,0 +1,116 @@ +# Generated by Django 3.2.13 on 2024-12-21 11:50 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0408_auto_20241218_1435'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 357582)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 304662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 304662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 304662)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 304662)), + ), + migrations.AlterField( + model_name='poscompany', + name='en_name', + field=models.CharField(default='', max_length=100, unique=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 308678)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 308678)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 308678)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 314435)), + ), + migrations.CreateModel( + name='POSDeviceSession', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('version', models.IntegerField()), + ('mac', models.CharField(max_length=50)), + ('name', models.TextField(default='')), + ('sdk', models.TextField(default='')), + ('serial', models.TextField(default='')), + ('ip', models.CharField(default='0.0.0.0', max_length=15)), + ('password', models.CharField(max_length=10)), + ('session_create_date', models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 422783))), + ('session_last_seen_date', models.DateTimeField(default=datetime.datetime(2024, 12, 21, 11, 50, 49, 422783))), + ('lng', models.FloatField(default=0)), + ('lot', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdevicesession_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdevicesession_modifiedby', to=settings.AUTH_USER_MODEL)), + ('pos', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pos_device_session', to='panel.posmachine')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PosDeviceVersion', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('code', models.IntegerField()), + ('description', models.TextField()), + ('enable', models.BooleanField(default=True)), + ('remove', models.BooleanField(default=False)), + ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='pos_version_company', to='panel.poscompany')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdeviceversion_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdeviceversion_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'unique_together': {('company', 'code')}, + }, + ), + ] diff --git a/panel/migrations/0410_auto_20241221_1258.py b/panel/migrations/0410_auto_20241221_1258.py new file mode 100644 index 0000000..5f95188 --- /dev/null +++ b/panel/migrations/0410_auto_20241221_1258.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-12-21 12:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0409_auto_20241221_1150'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='multi_device', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 621034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 684608)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 684608)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 557976)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 12, 58, 16, 573665)), + ), + ] diff --git a/panel/migrations/0411_auto_20241221_1357.py b/panel/migrations/0411_auto_20241221_1357.py new file mode 100644 index 0000000..17a2d18 --- /dev/null +++ b/panel/migrations/0411_auto_20241221_1357.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2024-12-21 13:57 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0410_auto_20241221_1258'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 527747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='pos', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pos_device_session', to='panel.posmachine'), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 598977)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 598977)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 464764)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 13, 57, 2, 480519)), + ), + ] diff --git a/panel/migrations/0412_auto_20241221_1535.py b/panel/migrations/0412_auto_20241221_1535.py new file mode 100644 index 0000000..841a78d --- /dev/null +++ b/panel/migrations/0412_auto_20241221_1535.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-12-21 15:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0411_auto_20241221_1357'), + ] + + operations = [ + migrations.AddField( + model_name='poscompany', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 670983)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 635641)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 635641)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 635641)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 635641)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 749659)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 749659)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 637649)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 637649)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 637649)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 21, 15, 35, 0, 645414)), + ), + ] diff --git a/panel/migrations/0413_auto_20241222_1203.py b/panel/migrations/0413_auto_20241222_1203.py new file mode 100644 index 0000000..dcf8578 --- /dev/null +++ b/panel/migrations/0413_auto_20241222_1203.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2024-12-22 12:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0412_auto_20241221_1535'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 306557)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 255159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 255159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 255159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 255159)), + ), + migrations.AlterField( + model_name='poscompany', + name='en_name', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 359503)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 359503)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 257166)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 257166)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 257166)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 22, 12, 3, 16, 264930)), + ), + ] diff --git a/panel/migrations/0414_auto_20241223_1441.py b/panel/migrations/0414_auto_20241223_1441.py new file mode 100644 index 0000000..2886777 --- /dev/null +++ b/panel/migrations/0414_auto_20241223_1441.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2024-12-23 14:41 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0413_auto_20241222_1203'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 221956)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 160774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 160774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 160774)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 160774)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 296932)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 296932)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 164791)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 164791)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 164791)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 14, 40, 50, 176573)), + ), + migrations.CreateModel( + name='SubSectorTransactions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('from_account', models.CharField(max_length=200, null=True)), + ('to_account', models.CharField(max_length=200, null=True)), + ('type', models.CharField(max_length=50, null=True)), + ('amount', models.BigIntegerField(default=0)), + ('image', models.CharField(max_length=500, null=True)), + ('city_operator', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_operator_transactions', to='panel.cityoperator')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subsectortransactions_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subsectortransactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0415_auto_20241223_1547.py b/panel/migrations/0415_auto_20241223_1547.py new file mode 100644 index 0000000..ec4f522 --- /dev/null +++ b/panel/migrations/0415_auto_20241223_1547.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2024-12-23 15:47 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0414_auto_20241223_1441'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 351303)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 414433)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 414433)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 303866)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 23, 15, 47, 16, 319538)), + ), + migrations.CreateModel( + name='SubSectorPercentageOfWageType', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('city', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subsectorpercentageofwagetype_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subsectorpercentageofwagetype_modifiedby', to=settings.AUTH_USER_MODEL)), + ('percentage_of_wage_type', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sub_sector_wage_type', to='panel.percentageofwagetype')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0416_auto_20241225_1417.py b/panel/migrations/0416_auto_20241225_1417.py new file mode 100644 index 0000000..da47004 --- /dev/null +++ b/panel/migrations/0416_auto_20241225_1417.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-12-25 14:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0415_auto_20241223_1547'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='entered_message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='entered_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 830692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 893755)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 893755)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 25, 14, 17, 38, 783333)), + ), + ] diff --git a/panel/migrations/0417_auto_20241231_1523.py b/panel/migrations/0417_auto_20241231_1523.py new file mode 100644 index 0000000..b0efdaa --- /dev/null +++ b/panel/migrations/0417_auto_20241231_1523.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2024-12-31 15:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0416_auto_20241225_1417'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='segmentation_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 827142)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 773720)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 773720)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 773720)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 773720)), + ), + migrations.AlterField( + model_name='poscompany', + name='en_name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 896526)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 896526)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 777736)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 777736)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 777736)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 15, 23, 48, 785767)), + ), + ] diff --git a/panel/migrations/0418_auto_20241231_2121.py b/panel/migrations/0418_auto_20241231_2121.py new file mode 100644 index 0000000..dd503f7 --- /dev/null +++ b/panel/migrations/0418_auto_20241231_2121.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2024-12-31 21:21 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0417_auto_20241231_1523'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 900798)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 47, 214724)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 47, 214724)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 431295)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2024, 12, 31, 21, 20, 46, 509421)), + ), + migrations.CreateModel( + name='PosSegmentation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('weight', models.BigIntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='possegmentation_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_segmentation', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='possegmentation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='product_segmentation', to='panel.rolesproducts')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0419_auto_20250106_1612.py b/panel/migrations/0419_auto_20250106_1612.py new file mode 100644 index 0000000..8475d35 --- /dev/null +++ b/panel/migrations/0419_auto_20250106_1612.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-01-06 16:12 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0418_auto_20241231_2121'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='vet_farm', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_poultry_request', to='panel.vet'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 923259)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 678264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 678264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 678264)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 678264)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 36, 322261)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 36, 322261)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 689264)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 689264)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 689264)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 6, 16, 12, 35, 725259)), + ), + ] diff --git a/panel/migrations/0420_auto_20250107_1233.py b/panel/migrations/0420_auto_20250107_1233.py new file mode 100644 index 0000000..22e9796 --- /dev/null +++ b/panel/migrations/0420_auto_20250107_1233.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-01-07 12:33 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0419_auto_20250106_1612'), + ] + + operations = [ + migrations.AddField( + model_name='subsectortransactions', + name='vet', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='vet_transactions', to='panel.vet'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 210911)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 140904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 140904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 140904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 140904)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 288907)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 288907)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 144913)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 144913)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 144913)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 12, 33, 10, 155904)), + ), + ] diff --git a/panel/migrations/0421_auto_20250107_1807.py b/panel/migrations/0421_auto_20250107_1807.py new file mode 100644 index 0000000..cc9b9b7 --- /dev/null +++ b/panel/migrations/0421_auto_20250107_1807.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-01-07 18:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0420_auto_20250107_1233'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='current_price', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 59, 79680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 301593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 301593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 301593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 301593)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 7, 0, 610830)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 7, 0, 610830)), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='check_id', + field=models.CharField(max_length=100, null=True, unique=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 314003)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 314003)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 314003)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 7, 18, 6, 58, 368243)), + ), + ] diff --git a/panel/migrations/0422_auto_20250112_1004.py b/panel/migrations/0422_auto_20250112_1004.py new file mode 100644 index 0000000..b557d1e --- /dev/null +++ b/panel/migrations/0422_auto_20250112_1004.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-01-12 10:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0421_auto_20250107_1807'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='first_date_input_archive', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='input_archiver', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='output_archive_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='output_archiver', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='second_date_input_archive', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 198471)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 147451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 147451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 147451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 147451)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 259729)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 259729)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 150452)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 150452)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 150452)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 10, 4, 2, 159452)), + ), + ] diff --git a/panel/migrations/0423_auto_20250112_1550.py b/panel/migrations/0423_auto_20250112_1550.py new file mode 100644 index 0000000..e37da68 --- /dev/null +++ b/panel/migrations/0423_auto_20250112_1550.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-01-12 15:50 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0055_auto_20250112_1550'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0422_auto_20250112_1004'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 406622)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 345434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 345434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 345434)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 345434)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 485627)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 485627)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 349451)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 349451)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 349451)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 12, 15, 50, 33, 359224)), + ), + migrations.CreateModel( + name='CityGuild', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('wallet_amount', models.BigIntegerField(default=0)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_guild_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityguild_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cityguild_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_guild_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_guild_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_guild_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0424_auto_20250113_1532.py b/panel/migrations/0424_auto_20250113_1532.py new file mode 100644 index 0000000..79e4068 --- /dev/null +++ b/panel/migrations/0424_auto_20250113_1532.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-01-13 15:32 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0423_auto_20250112_1550'), + ] + + operations = [ + migrations.AddField( + model_name='subsectortransactions', + name='city_guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='city_guild_transactions', to='panel.cityguild'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 223579)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 175634)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 175634)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 175634)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 175634)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 287469)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 287469)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 177642)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 177642)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 177642)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 13, 15, 32, 48, 177642)), + ), + ] diff --git a/panel/migrations/0425_auto_20250119_1410.py b/panel/migrations/0425_auto_20250119_1410.py new file mode 100644 index 0000000..87db522 --- /dev/null +++ b/panel/migrations/0425_auto_20250119_1410.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-01-19 14:10 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0424_auto_20250113_1532'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='bar_code', + field=models.BigIntegerField(null=True), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='exclusive_killer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_exclusive_killer', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 749225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 678351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 678351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 678351)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 678351)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 833728)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 833728)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 682099)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 682099)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 682099)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 19, 14, 10, 37, 692122)), + ), + ] diff --git a/panel/migrations/0426_auto_20250120_0929.py b/panel/migrations/0426_auto_20250120_0929.py new file mode 100644 index 0000000..09fd5c1 --- /dev/null +++ b/panel/migrations/0426_auto_20250120_0929.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2025-01-20 09:29 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0425_auto_20250119_1410'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhousefreebarinformation', + name='bar_code', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 728285)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 676731)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 676731)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 676731)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 676731)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 783379)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 783379)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 680738)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 680738)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 680738)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 29, 32, 688756)), + ), + ] diff --git a/panel/migrations/0427_auto_20250120_0941.py b/panel/migrations/0427_auto_20250120_0941.py new file mode 100644 index 0000000..decf49e --- /dev/null +++ b/panel/migrations/0427_auto_20250120_0941.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-01-20 09:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0426_auto_20250120_0929'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='bar_code', + field=models.BigIntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 484543)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 557797)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 557797)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 437207)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 9, 40, 52, 453030)), + ), + ] diff --git a/panel/migrations/0428_auto_20250120_1638.py b/panel/migrations/0428_auto_20250120_1638.py new file mode 100644 index 0000000..1067515 --- /dev/null +++ b/panel/migrations/0428_auto_20250120_1638.py @@ -0,0 +1,149 @@ +# Generated by Django 3.2.13 on 2025-01-20 16:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0427_auto_20250120_0941'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='unit_address', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_city', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_economical_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_national_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_postal_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_province', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouse', + name='unit_registration_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_address', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_city', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_economical_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_name', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_national_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_postal_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_province', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='provinceoperator', + name='unit_registration_number', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 304283)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 369060)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 369060)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 242955)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 20, 16, 38, 46, 260748)), + ), + ] diff --git a/panel/migrations/0429_auto_20250121_0857.py b/panel/migrations/0429_auto_20250121_0857.py new file mode 100644 index 0000000..a354e87 --- /dev/null +++ b/panel/migrations/0429_auto_20250121_0857.py @@ -0,0 +1,133 @@ +# Generated by Django 3.2.13 on 2025-01-21 08:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0428_auto_20250120_1638'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhouse', + name='unit_address', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_city', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_economical_number', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_name', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_national_id', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_postal_code', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_province', + ), + migrations.RemoveField( + model_name='killhouse', + name='unit_registration_number', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_address', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_city', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_economical_number', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_name', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_national_id', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_postal_code', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_province', + ), + migrations.RemoveField( + model_name='provinceoperator', + name='unit_registration_number', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 42, 18768)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 42, 101751)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 42, 101751)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 971136)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 21, 8, 57, 41, 991011)), + ), + ] diff --git a/panel/migrations/0430_auto_20250125_1225.py b/panel/migrations/0430_auto_20250125_1225.py new file mode 100644 index 0000000..342489a --- /dev/null +++ b/panel/migrations/0430_auto_20250125_1225.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2025-01-25 12:25 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0429_auto_20250121_0857'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 931853)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 882524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 882524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 882524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 882524)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 994586)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 994586)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 886273)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 886273)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 886273)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 25, 12, 24, 48, 894300)), + ), + migrations.CreateModel( + name='DistributionUserLevel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fa_title', models.CharField(max_length=200, null=True)), + ('en_title', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='distributionuserlevel_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='distributionuserlevel_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='guilds', + name='user_level', + field=models.ManyToManyField(blank=True, null=True, related_name='guild_user_level', to='panel.DistributionUserLevel'), + ), + ] diff --git a/panel/migrations/0431_auto_20250127_1622.py b/panel/migrations/0431_auto_20250127_1622.py new file mode 100644 index 0000000..984ed6d --- /dev/null +++ b/panel/migrations/0431_auto_20250127_1622.py @@ -0,0 +1,111 @@ +# Generated by Django 3.2.13 on 2025-01-27 16:22 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0430_auto_20250125_1225'), + ] + + operations = [ + migrations.CreateModel( + name='OtherProducts', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=300, null=True)), + ('unit', models.CharField(max_length=100, null=True)), + ('image', models.CharField(max_length=500, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='otherproducts_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='other_products_guild', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='other_products_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='otherproducts_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 737693)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 801506)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 801506)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 689741)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 1, 27, 16, 22, 25, 705865)), + ), + migrations.CreateModel( + name='ProductsTransactions', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='productstransactions_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='productstransactions_modifiedby', to=settings.AUTH_USER_MODEL)), + ('other_product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products_transactions_other_product', to='panel.otherproducts')), + ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products_transactions_product', to='panel.rolesproducts')), + ('transaction', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_products_transactions', to='panel.posmachinetransactions')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0432_auto_20250201_1449.py b/panel/migrations/0432_auto_20250201_1449.py new file mode 100644 index 0000000..781c68d --- /dev/null +++ b/panel/migrations/0432_auto_20250201_1449.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-01 14:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0431_auto_20250127_1622'), + ] + + operations = [ + migrations.AddField( + model_name='cityguild', + name='unit_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 477473)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 424957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 424957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 424957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 424957)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 542472)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 542472)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 427958)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 427958)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 427958)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 1, 14, 49, 12, 436962)), + ), + ] diff --git a/panel/migrations/0433_auto_20250205_1303.py b/panel/migrations/0433_auto_20250205_1303.py new file mode 100644 index 0000000..cae202d --- /dev/null +++ b/panel/migrations/0433_auto_20250205_1303.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-02-05 13:03 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0432_auto_20250201_1449'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='poultry_hatching', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_hatching_kill_req', to='panel.poultryhatching'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 139756)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 87546)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 87546)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 87546)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 87546)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 203901)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 203901)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 90547)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 90547)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 90547)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 5, 13, 3, 20, 99546)), + ), + ] diff --git a/panel/migrations/0434_auto_20250209_0918.py b/panel/migrations/0434_auto_20250209_0918.py new file mode 100644 index 0000000..c98c37e --- /dev/null +++ b/panel/migrations/0434_auto_20250209_0918.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-09 09:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0433_auto_20250205_1303'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='killing_age', + field=models.IntegerField(default=1), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 750045)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 805068)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 805068)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 9, 18, 20, 694838)), + ), + ] diff --git a/panel/migrations/0435_auto_20250209_1024.py b/panel/migrations/0435_auto_20250209_1024.py new file mode 100644 index 0000000..5636830 --- /dev/null +++ b/panel/migrations/0435_auto_20250209_1024.py @@ -0,0 +1,95 @@ +# Generated by Django 3.2.13 on 2025-02-09 10:24 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0434_auto_20250209_0918'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 178145)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 114993)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 114993)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 114993)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 114993)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 241425)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 241425)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 130904)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 130904)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 130904)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 9, 10, 24, 42, 130904)), + ), + migrations.CreateModel( + name='PoultryPrediction', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('killing_ave_age', models.IntegerField(default=1)), + ('active_left_over', models.IntegerField(default=0)), + ('killing_ave_count', models.IntegerField(default=0)), + ('killing_ave_weight', models.IntegerField(default=0)), + ('killing_loss_weight_percent', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryprediction_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryprediction_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='prediction_poultry', to='panel.poultry')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0436_auto_20250210_1938.py b/panel/migrations/0436_auto_20250210_1938.py new file mode 100644 index 0000000..0f1eb15 --- /dev/null +++ b/panel/migrations/0436_auto_20250210_1938.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-02-10 19:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0435_auto_20250209_1024'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='active_left_over', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultry', + name='killing_ave_age', + field=models.IntegerField(default=1), + ), + migrations.AddField( + model_name='poultry', + name='killing_ave_count', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='killing_ave_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='killing_carcasses_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='killing_live_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='killing_loss_weight_percent', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 806956)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 661957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 661957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 661957)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 661957)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 42, 2958)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 42, 2958)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 669956)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 669956)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 669956)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 10, 19, 37, 41, 694957)), + ), + ] diff --git a/panel/migrations/0437_auto_20250211_1410.py b/panel/migrations/0437_auto_20250211_1410.py new file mode 100644 index 0000000..fca998a --- /dev/null +++ b/panel/migrations/0437_auto_20250211_1410.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-11 14:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0436_auto_20250210_1938'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='predicate_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 108857)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 57572)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 57572)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 57572)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 57572)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 167892)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 167892)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 61578)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 59575)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 59575)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 11, 14, 10, 6, 69588)), + ), + ] diff --git a/panel/migrations/0438_auto_20250212_0900.py b/panel/migrations/0438_auto_20250212_0900.py new file mode 100644 index 0000000..e50f588 --- /dev/null +++ b/panel/migrations/0438_auto_20250212_0900.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-02-12 09:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0437_auto_20250211_1410'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='real_killing_ave_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_carcasses_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_live_weight', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_loss_weight_percent', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 968136)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 53, 31412)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 53, 31412)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 8, 59, 52, 920917)), + ), + ] diff --git a/panel/migrations/0439_auto_20250212_0957.py b/panel/migrations/0439_auto_20250212_0957.py new file mode 100644 index 0000000..aa88436 --- /dev/null +++ b/panel/migrations/0439_auto_20250212_0957.py @@ -0,0 +1,85 @@ +# Generated by Django 3.2.13 on 2025-02-12 09:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0438_auto_20250212_0900'), + ] + + operations = [ + migrations.RemoveField( + model_name='poultry', + name='real_killing_ave_weight', + ), + migrations.RemoveField( + model_name='poultry', + name='real_killing_carcasses_weight', + ), + migrations.RemoveField( + model_name='poultry', + name='real_killing_live_weight', + ), + migrations.RemoveField( + model_name='poultry', + name='real_killing_loss_weight_percent', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 999092)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 957362)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 957362)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 957362)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 957362)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 35, 62384)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 35, 62384)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 959365)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 959365)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 959365)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 9, 57, 34, 967113)), + ), + ] diff --git a/panel/migrations/0440_auto_20250212_1003.py b/panel/migrations/0440_auto_20250212_1003.py new file mode 100644 index 0000000..4afde45 --- /dev/null +++ b/panel/migrations/0440_auto_20250212_1003.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-02-12 10:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0439_auto_20250212_0957'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='real_killing_ave_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_carcasses_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_live_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultry', + name='real_killing_loss_weight_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 93891)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 30788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 30788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 30788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 30788)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 157646)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 157646)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 46600)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 46600)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 46600)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 10, 3, 46, 46600)), + ), + ] diff --git a/panel/migrations/0441_auto_20250212_1455.py b/panel/migrations/0441_auto_20250212_1455.py new file mode 100644 index 0000000..80e12e4 --- /dev/null +++ b/panel/migrations/0441_auto_20250212_1455.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2025-02-12 14:55 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0440_auto_20250212_1003'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='bar_difference_request_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='bar_difference_request_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 988034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 934837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 934837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 934837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 934837)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 59, 51297)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 59, 51297)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 936579)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 936579)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 936579)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 12, 14, 54, 58, 936579)), + ), + migrations.CreateModel( + name='BarDifferenceRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('state', models.CharField(default='pending', max_length=20)), + ('register_fullname', models.CharField(max_length=200, null=True)), + ('register_mobile', models.CharField(max_length=200, null=True)), + ('quantity', models.IntegerField(default=0)), + ('real_quantity', models.IntegerField(default=0)), + ('weight', models.IntegerField(default=0)), + ('real_weight', models.IntegerField(default=0)), + ('violation_image', models.JSONField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bardifferencerequest_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='difference_hatching', to='panel.poultryhatching')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='difference_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='bardifferencerequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0442_auto_20250216_1014.py b/panel/migrations/0442_auto_20250216_1014.py new file mode 100644 index 0000000..c17f094 --- /dev/null +++ b/panel/migrations/0442_auto_20250216_1014.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-02-16 10:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0441_auto_20250212_1455'), + ] + + operations = [ + migrations.AddField( + model_name='otherproducts', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='otherproducts', + name='price', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='posmachine', + name='password', + field=models.CharField(max_length=10, null=True), + ), + migrations.AddField( + model_name='posmachine', + name='serial', + field=models.TextField(default=''), + ), + migrations.AddField( + model_name='productstransactions', + name='cur_price', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='productstransactions', + name='cur_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='productstransactions', + name='total_price', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 101937)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 164950)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 164950)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 16, 10, 14, 32, 54854)), + ), + ] diff --git a/panel/migrations/0443_auto_20250217_1419.py b/panel/migrations/0443_auto_20250217_1419.py new file mode 100644 index 0000000..dac32ba --- /dev/null +++ b/panel/migrations/0443_auto_20250217_1419.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-02-17 14:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0442_auto_20250216_1014'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='price_paid', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='posmachinetransactions', + name='price_type', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='posmachinetransactions', + name='products', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 115270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 72010)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 72010)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 72010)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 72010)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 178564)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 178564)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 74018)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 74018)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 74018)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 14, 19, 35, 83558)), + ), + ] diff --git a/panel/migrations/0444_auto_20250217_1557.py b/panel/migrations/0444_auto_20250217_1557.py new file mode 100644 index 0000000..cdcb74f --- /dev/null +++ b/panel/migrations/0444_auto_20250217_1557.py @@ -0,0 +1,98 @@ +# Generated by Django 3.2.13 on 2025-02-17 15:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0443_auto_20250217_1419'), + ] + + operations = [ + migrations.RemoveField( + model_name='posmachinetransactions', + name='products', + ), + migrations.AddField( + model_name='productstransactions', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='productstransactions', + name='name', + field=models.CharField(max_length=300, null=True), + ), + migrations.AddField( + model_name='productstransactions', + name='price_approved', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='productstransactions', + name='targetunit', + field=models.CharField(max_length=10, null=True), + ), + migrations.AddField( + model_name='productstransactions', + name='unit', + field=models.CharField(max_length=10, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 72792)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 19431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 19431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 19431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 19431)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 140357)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 140357)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 23447)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 23447)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 23447)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 15, 57, 16, 25188)), + ), + ] diff --git a/panel/migrations/0445_auto_20250217_1707.py b/panel/migrations/0445_auto_20250217_1707.py new file mode 100644 index 0000000..a8896ce --- /dev/null +++ b/panel/migrations/0445_auto_20250217_1707.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-17 17:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0444_auto_20250217_1557'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='pos_date', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 288068)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 224487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 224487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 224487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 224487)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 351467)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 351467)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 240152)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 240152)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 240152)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 17, 17, 7, 8, 240152)), + ), + ] diff --git a/panel/migrations/0446_auto_20250218_0853.py b/panel/migrations/0446_auto_20250218_0853.py new file mode 100644 index 0000000..3a97d67 --- /dev/null +++ b/panel/migrations/0446_auto_20250218_0853.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-02-18 08:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0445_auto_20250217_1707'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 373562)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 312553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 312553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 312553)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 312553)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 447066)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 447066)), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='fullname', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='mobile', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='natcode', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 326259)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 326259)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 326259)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 8, 53, 40, 326259)), + ), + ] diff --git a/panel/migrations/0447_auto_20250218_1015.py b/panel/migrations/0447_auto_20250218_1015.py new file mode 100644 index 0000000..fd18b3a --- /dev/null +++ b/panel/migrations/0447_auto_20250218_1015.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-18 10:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0446_auto_20250218_0853'), + ] + + operations = [ + migrations.AddField( + model_name='productstransactions', + name='price', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 223131)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 285946)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 285946)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 159967)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 18, 10, 15, 31, 175993)), + ), + ] diff --git a/panel/migrations/0448_auto_20250222_1023.py b/panel/migrations/0448_auto_20250222_1023.py new file mode 100644 index 0000000..78779fc --- /dev/null +++ b/panel/migrations/0448_auto_20250222_1023.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-02-22 10:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0447_auto_20250218_1015'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='inquiry_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='inquiry_destination', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='inquiry_driver', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='inquiry_origin', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='inquiry_pelak', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 481689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 424692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 424692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 424692)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 424692)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 557216)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 557216)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 428690)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 428690)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 428690)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 10, 23, 30, 437727)), + ), + ] diff --git a/panel/migrations/0449_auto_20250222_1112.py b/panel/migrations/0449_auto_20250222_1112.py new file mode 100644 index 0000000..95b9b94 --- /dev/null +++ b/panel/migrations/0449_auto_20250222_1112.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-22 11:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0448_auto_20250222_1023'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 15, 66783)), + ), + migrations.AlterField( + model_name='killhouserequest', + name='inquiry_date', + field=models.DateField(null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 960733)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 960733)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 960733)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 960733)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 15, 148784)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 15, 148784)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 967733)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 967733)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 967733)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 11, 12, 14, 983731)), + ), + ] diff --git a/panel/migrations/0450_auto_20250222_1636.py b/panel/migrations/0450_auto_20250222_1636.py new file mode 100644 index 0000000..5d14240 --- /dev/null +++ b/panel/migrations/0450_auto_20250222_1636.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-22 16:36 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0449_auto_20250222_1112'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='unique_identifier', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 881342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 828077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 828077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 828077)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 828077)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 944772)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 944772)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 832093)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 832093)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 832093)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 22, 16, 36, 19, 841866)), + ), + ] diff --git a/panel/migrations/0451_auto_20250223_0958.py b/panel/migrations/0451_auto_20250223_0958.py new file mode 100644 index 0000000..ad19bef --- /dev/null +++ b/panel/migrations/0451_auto_20250223_0958.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-02-23 09:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0450_auto_20250222_1636'), + ] + + operations = [ + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_fullname', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_mobile', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 602089)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 546124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 546124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 546124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 546124)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 669116)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 669116)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 549123)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 549123)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 549123)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 9, 58, 8, 559125)), + ), + ] diff --git a/panel/migrations/0452_auto_20250223_1001.py b/panel/migrations/0452_auto_20250223_1001.py new file mode 100644 index 0000000..7a50799 --- /dev/null +++ b/panel/migrations/0452_auto_20250223_1001.py @@ -0,0 +1,77 @@ +# Generated by Django 3.2.13 on 2025-02-23 10:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0451_auto_20250223_0958'), + ] + + operations = [ + migrations.CreateModel( + name='CookieSamasat', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('asp_net_session_id', models.CharField(default='-', max_length=250, null=True)), + ('aspxauth', models.TextField(default='-', null=True)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 721902)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 618904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 618904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 618904)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 618904)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 949442)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 949442)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 627904)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 627904)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 627904)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 1, 15, 641898)), + ), + ] diff --git a/panel/migrations/0453_auto_20250223_1005.py b/panel/migrations/0453_auto_20250223_1005.py new file mode 100644 index 0000000..7a6fd06 --- /dev/null +++ b/panel/migrations/0453_auto_20250223_1005.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-23 10:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0452_auto_20250223_1001'), + ] + + operations = [ + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 329451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 274451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 274451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 274451)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 274451)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 400485)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 400485)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 277445)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 277445)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 277445)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 5, 18, 286447)), + ), + ] diff --git a/panel/migrations/0454_auto_20250223_1006.py b/panel/migrations/0454_auto_20250223_1006.py new file mode 100644 index 0000000..74ce9c5 --- /dev/null +++ b/panel/migrations/0454_auto_20250223_1006.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-02-23 10:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0453_auto_20250223_1005'), + ] + + operations = [ + migrations.AlterField( + model_name='cookiesamasat', + name='asp_net_session_id', + field=models.CharField(max_length=250, null=True), + ), + migrations.AlterField( + model_name='cookiesamasat', + name='aspxauth', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 176319)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 20159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 20159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 20159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 20159)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 330324)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 330324)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 27158)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 27158)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 27158)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 10, 6, 40, 42172)), + ), + ] diff --git a/panel/migrations/0455_auto_20250223_1128.py b/panel/migrations/0455_auto_20250223_1128.py new file mode 100644 index 0000000..92e31f4 --- /dev/null +++ b/panel/migrations/0455_auto_20250223_1128.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-23 11:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0454_auto_20250223_1006'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='share_debt_counting_wage', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 145444)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 208267)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 208267)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 23, 11, 28, 29, 97930)), + ), + ] diff --git a/panel/migrations/0456_auto_20250224_1320.py b/panel/migrations/0456_auto_20250224_1320.py new file mode 100644 index 0000000..0c8aeb4 --- /dev/null +++ b/panel/migrations/0456_auto_20250224_1320.py @@ -0,0 +1,72 @@ +# Generated by Django 3.2.13 on 2025-02-24 13:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0455_auto_20250223_1128'), + ] + + operations = [ + migrations.DeleteModel( + name='CookieSamasat', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 179710)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 124485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 124485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 124485)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 124485)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 244710)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 244710)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 127484)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 127484)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 127484)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 20, 15, 137075)), + ), + ] diff --git a/panel/migrations/0457_auto_20250224_1322.py b/panel/migrations/0457_auto_20250224_1322.py new file mode 100644 index 0000000..daae981 --- /dev/null +++ b/panel/migrations/0457_auto_20250224_1322.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.13 on 2025-02-24 13:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0456_auto_20250224_1320'), + ] + + operations = [ + migrations.CreateModel( + name='CookieSamasat', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('cookie', models.TextField(null=True)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 607350)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 85927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 85927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 85927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 85927)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 911630)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 912632)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 215978)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 215978)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 215978)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 24, 13, 22, 35, 233979)), + ), + ] diff --git a/panel/migrations/0458_auto_20250225_1118.py b/panel/migrations/0458_auto_20250225_1118.py new file mode 100644 index 0000000..f4dcf62 --- /dev/null +++ b/panel/migrations/0458_auto_20250225_1118.py @@ -0,0 +1,98 @@ +# Generated by Django 3.2.13 on 2025-02-25 11:18 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0457_auto_20250224_1322'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 44, 37893)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 570069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 570069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 570069)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 570069)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 44, 582534)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 44, 582534)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 583595)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 583595)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 583595)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 17, 43, 644135)), + ), + migrations.CreateModel( + name='LiveChickenTransportDetails', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quarantine_code', models.CharField(max_length=100, null=True)), + ('rejester_date', models.DateTimeField(null=True)), + ('quantity', models.IntegerField(null=True)), + ('state', models.CharField(max_length=100, null=True)), + ('product_name', models.CharField(max_length=200, null=True)), + ('kill_house_unique_identifier', models.CharField(max_length=100, null=True)), + ('kill_house_name', models.CharField(max_length=100, null=True)), + ('status_registration_date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livechickentransportdetails_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='panel.poultryhatching')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='livechickentransportdetails_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0459_auto_20250225_1144.py b/panel/migrations/0459_auto_20250225_1144.py new file mode 100644 index 0000000..1c4a493 --- /dev/null +++ b/panel/migrations/0459_auto_20250225_1144.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-25 11:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0458_auto_20250225_1118'), + ] + + operations = [ + migrations.AddField( + model_name='cookiesamasat', + name='table_name', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 802252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 741614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 741614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 741614)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 741614)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 877300)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 877300)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 744616)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 744616)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 744616)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 25, 11, 44, 20, 755662)), + ), + ] diff --git a/panel/migrations/0460_auto_20250226_0937.py b/panel/migrations/0460_auto_20250226_0937.py new file mode 100644 index 0000000..72352ee --- /dev/null +++ b/panel/migrations/0460_auto_20250226_0937.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-02-26 09:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0459_auto_20250225_1144'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='health_certificate', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 68278)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 13642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 13642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 13642)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 13642)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 132278)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 132278)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 17642)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 17642)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 17642)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 2, 26, 9, 36, 48, 28643)), + ), + ] diff --git a/panel/migrations/0461_auto_20250302_1203.py b/panel/migrations/0461_auto_20250302_1203.py new file mode 100644 index 0000000..d1c5ddc --- /dev/null +++ b/panel/migrations/0461_auto_20250302_1203.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-02 12:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0460_auto_20250226_0937'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 269923)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 349474)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 349474)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 222211)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 12, 2, 54, 238331)), + ), + ] diff --git a/panel/migrations/0462_auto_20250302_1351.py b/panel/migrations/0462_auto_20250302_1351.py new file mode 100644 index 0000000..b9e73de --- /dev/null +++ b/panel/migrations/0462_auto_20250302_1351.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-02 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0461_auto_20250302_1203'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 218645)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 171251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 171251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 171251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 171251)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 297544)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 297544)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 173260)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 173260)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 173260)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 13, 51, 24, 183299)), + ), + ] diff --git a/panel/migrations/0463_auto_20250302_1458.py b/panel/migrations/0463_auto_20250302_1458.py new file mode 100644 index 0000000..bbfcb22 --- /dev/null +++ b/panel/migrations/0463_auto_20250302_1458.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-02 14:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0462_auto_20250302_1351'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 502833)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 566111)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 566111)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 14, 58, 25, 455023)), + ), + ] diff --git a/panel/migrations/0464_auto_20250302_1628.py b/panel/migrations/0464_auto_20250302_1628.py new file mode 100644 index 0000000..9b7e777 --- /dev/null +++ b/panel/migrations/0464_auto_20250302_1628.py @@ -0,0 +1,81 @@ +# Generated by Django 3.2.13 on 2025-03-02 16:28 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0006_auto_20250302_1627'), + ('panel', '0463_auto_20250302_1458'), + ] + + operations = [ + migrations.AddField( + model_name='posmachine', + name='cooperative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_pos', to='LiveStock.cooperative'), + ), + migrations.AddField( + model_name='postransactions', + name='cooperative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='cooperative_pos_transaction', to='LiveStock.cooperative'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 286157)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 220689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 220689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 220689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 220689)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 347567)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 347567)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 236438)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 236438)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 236438)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 2, 16, 28, 37, 236438)), + ), + ] diff --git a/panel/migrations/0465_auto_20250303_1205.py b/panel/migrations/0465_auto_20250303_1205.py new file mode 100644 index 0000000..3acdfec --- /dev/null +++ b/panel/migrations/0465_auto_20250303_1205.py @@ -0,0 +1,76 @@ +# Generated by Django 3.2.13 on 2025-03-03 12:05 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('LiveStock', '0011_remove_livestockallocations_rancher'), + ('panel', '0464_auto_20250302_1628'), + ] + + operations = [ + migrations.AddField( + model_name='productstransactions', + name='live_stack_products', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='products_transactions_live_stack_products', to='LiveStock.livestockrolseproduct'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 267991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 206651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 206651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 206651)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 206651)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 338154)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 338154)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 209728)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 209728)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 209728)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 12, 5, 3, 220046)), + ), + ] diff --git a/panel/migrations/0466_auto_20250303_1315.py b/panel/migrations/0466_auto_20250303_1315.py new file mode 100644 index 0000000..70015b9 --- /dev/null +++ b/panel/migrations/0466_auto_20250303_1315.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-03-03 13:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0465_auto_20250303_1205'), + ] + + operations = [ + migrations.AddField( + model_name='otherproducts', + name='targetunit', + field=models.CharField(default='g', max_length=100), + ), + migrations.AddField( + model_name='posmachinetransactions', + name='live_stock', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 92332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 34263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 34263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 34263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 34263)), + ), + migrations.AlterField( + model_name='otherproducts', + name='unit', + field=models.CharField(default='kg', max_length=100), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 160318)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 160318)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 37255)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 37255)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 37255)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 13, 15, 44, 48485)), + ), + ] diff --git a/panel/migrations/0467_auto_20250303_1500.py b/panel/migrations/0467_auto_20250303_1500.py new file mode 100644 index 0000000..a3cddb6 --- /dev/null +++ b/panel/migrations/0467_auto_20250303_1500.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-03 15:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0466_auto_20250303_1315'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 105824)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 52406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 52406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 52406)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 52406)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 163071)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 163071)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 56422)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 56422)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 56422)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 3, 14, 59, 55, 64454)), + ), + ] diff --git a/panel/migrations/0468_auto_20250304_1730.py b/panel/migrations/0468_auto_20250304_1730.py new file mode 100644 index 0000000..eff3082 --- /dev/null +++ b/panel/migrations/0468_auto_20250304_1730.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-03-04 17:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0467_auto_20250303_1500'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='interest_license_id', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 191973)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 138607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 138607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 138607)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 138607)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 258942)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 258942)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 142606)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 142606)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 142606)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 4, 17, 29, 54, 151649)), + ), + ] diff --git a/panel/migrations/0469_auto_20250305_1330.py b/panel/migrations/0469_auto_20250305_1330.py new file mode 100644 index 0000000..11c0d76 --- /dev/null +++ b/panel/migrations/0469_auto_20250305_1330.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-03-05 13:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0468_auto_20250304_1730'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 293058)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 238817)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 238817)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 238817)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 238817)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 358060)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 358060)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 241814)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 241814)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 241814)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 5, 13, 30, 35, 250815)), + ), + ] diff --git a/panel/migrations/0470_auto_20250307_1650.py b/panel/migrations/0470_auto_20250307_1650.py new file mode 100644 index 0000000..1ca6af4 --- /dev/null +++ b/panel/migrations/0470_auto_20250307_1650.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-03-07 16:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0469_auto_20250305_1330'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 688507)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 630991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 630991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 630991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 630991)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 755806)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 755806)), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='additional', + field=models.TextField(blank=True, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 634769)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 634769)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 634769)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 7, 16, 50, 14, 634769)), + ), + ] diff --git a/panel/migrations/0471_auto_20250316_2255.py b/panel/migrations/0471_auto_20250316_2255.py new file mode 100644 index 0000000..b46d156 --- /dev/null +++ b/panel/migrations/0471_auto_20250316_2255.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-03-16 22:55 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0470_auto_20250307_1650'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 3, 124044)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 890050)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 890050)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 890050)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 890050)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 3, 394045)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 3, 394045)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 954044)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 954044)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 954044)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 3, 16, 22, 55, 2, 976050)), + ), + migrations.CreateModel( + name='RequestLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('limitation', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='requestlimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='requestlimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0472_auto_20250413_1442.py b/panel/migrations/0472_auto_20250413_1442.py new file mode 100644 index 0000000..b2e8477 --- /dev/null +++ b/panel/migrations/0472_auto_20250413_1442.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-04-13 14:42 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0471_auto_20250316_2255'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 970156)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 15, 35215)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 15, 35215)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 907205)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 14, 42, 14, 922874)), + ), + migrations.CreateModel( + name='PriceConfirmation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_status', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='priceconfirmation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='priceconfirmation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0473_auto_20250413_1557.py b/panel/migrations/0473_auto_20250413_1557.py new file mode 100644 index 0000000..109defd --- /dev/null +++ b/panel/migrations/0473_auto_20250413_1557.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-04-13 15:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0472_auto_20250413_1442'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='price_confirmation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='poultryrequest', + name='price_confirmation_code', + field=models.CharField(max_length=10, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 97621)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 44868)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 42860)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 44868)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 44868)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 168622)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 168622)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 46876)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 46876)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 46876)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 13, 15, 57, 31, 56653)), + ), + ] diff --git a/panel/migrations/0474_auto_20250414_1231.py b/panel/migrations/0474_auto_20250414_1231.py new file mode 100644 index 0000000..a3bb752 --- /dev/null +++ b/panel/migrations/0474_auto_20250414_1231.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-14 12:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0473_auto_20250413_1557'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='input_price_confirmation_code', + field=models.CharField(max_length=10, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 311620)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 390458)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 390458)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 264468)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 12, 31, 9, 280178)), + ), + ] diff --git a/panel/migrations/0475_auto_20250414_1710.py b/panel/migrations/0475_auto_20250414_1710.py new file mode 100644 index 0000000..63cf8a8 --- /dev/null +++ b/panel/migrations/0475_auto_20250414_1710.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-14 17:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0474_auto_20250414_1231'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='price_confirmation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 829546)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 773829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 773829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 773829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 773829)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 899300)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 899300)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 776841)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 776841)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 776841)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 14, 17, 10, 7, 787208)), + ), + ] diff --git a/panel/migrations/0476_auto_20250420_1106.py b/panel/migrations/0476_auto_20250420_1106.py new file mode 100644 index 0000000..ed2a242 --- /dev/null +++ b/panel/migrations/0476_auto_20250420_1106.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-20 11:06 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0475_auto_20250414_1710'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='register_type', + field=models.CharField(max_length=250, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 613325)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 561032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 561032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 561032)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 561032)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 678957)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 678957)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 564290)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 564290)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 564290)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 6, 13, 573290)), + ), + ] diff --git a/panel/migrations/0477_auto_20250420_1108.py b/panel/migrations/0477_auto_20250420_1108.py new file mode 100644 index 0000000..785ee53 --- /dev/null +++ b/panel/migrations/0477_auto_20250420_1108.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-20 11:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0476_auto_20250420_1106'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 25, 35345)), + ), + migrations.AlterField( + model_name='killhousefreebarinformation', + name='register_type', + field=models.CharField(default='manual', max_length=250), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 932803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 932803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 932803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 932803)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 25, 141342)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 25, 141342)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 938811)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 938811)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 938811)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 20, 11, 8, 24, 963819)), + ), + ] diff --git a/panel/migrations/0478_auto_20250428_1358.py b/panel/migrations/0478_auto_20250428_1358.py new file mode 100644 index 0000000..7a6c9f1 --- /dev/null +++ b/panel/migrations/0478_auto_20250428_1358.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-04-28 13:58 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0477_auto_20250420_1108'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='final_accept', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 13, 149184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 921184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 921184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 921184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 921184)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 13, 443185)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 13, 443185)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 936185)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 936185)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 936185)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 4, 28, 13, 58, 12, 988186)), + ), + ] diff --git a/panel/migrations/0479_auto_20250503_1400.py b/panel/migrations/0479_auto_20250503_1400.py new file mode 100644 index 0000000..d050105 --- /dev/null +++ b/panel/migrations/0479_auto_20250503_1400.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2025-05-03 14:00 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0478_auto_20250428_1358'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 311657)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 256484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 256484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 256484)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 256484)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 382834)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 382834)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 260234)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 260234)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 260234)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 3, 13, 59, 59, 270277)), + ), + migrations.CreateModel( + name='ArchiveWageInfo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('start_year', models.DateTimeField(null=True)), + ('end_year', models.DateTimeField(null=True)), + ('total_wage', models.BigIntegerField(default=0)), + ('total_paid_wage', models.BigIntegerField(default=0)), + ('total_company_paid_wage', models.BigIntegerField(default=0)), + ('total_union_paid_wage', models.BigIntegerField(default=0)), + ('total_guild_paid_wage', models.BigIntegerField(default=0)), + ('total_vet_paid_wage', models.BigIntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='archivewageinfo_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='archivewageinfo_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0480_auto_20250504_1149.py b/panel/migrations/0480_auto_20250504_1149.py new file mode 100644 index 0000000..0a20279 --- /dev/null +++ b/panel/migrations/0480_auto_20250504_1149.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2025-05-04 11:49 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0479_auto_20250503_1400'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 23, 664637)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 406293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 406293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 406293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 406293)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 23, 735896)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 23, 735896)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 408301)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 408301)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 22, 408301)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 11, 48, 23, 196458)), + ), + migrations.CreateModel( + name='CompanyBeneficiaryAccount', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=200, null=True)), + ('percent', models.BigIntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='companybeneficiaryaccount_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='companybeneficiaryaccount_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0481_auto_20250504_1207.py b/panel/migrations/0481_auto_20250504_1207.py new file mode 100644 index 0000000..2fe0799 --- /dev/null +++ b/panel/migrations/0481_auto_20250504_1207.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-04 12:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0480_auto_20250504_1149'), + ] + + operations = [ + migrations.AddField( + model_name='companybeneficiaryaccount', + name='shaba', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 347412)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 284262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 284262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 284262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 284262)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 411233)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 411233)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 300078)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 300078)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 300078)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 4, 12, 7, 29, 300078)), + ), + ] diff --git a/panel/migrations/0482_auto_20250505_1431.py b/panel/migrations/0482_auto_20250505_1431.py new file mode 100644 index 0000000..9615136 --- /dev/null +++ b/panel/migrations/0482_auto_20250505_1431.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-05-05 14:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0481_auto_20250504_1207'), + ] + + operations = [ + migrations.AddField( + model_name='companybeneficiaryaccount', + name='in_province', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='companybeneficiaryaccount', + name='out_province', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 725490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 789006)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 789006)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 677832)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 5, 14, 30, 52, 693897)), + ), + ] diff --git a/panel/migrations/0483_auto_20250506_1054.py b/panel/migrations/0483_auto_20250506_1054.py new file mode 100644 index 0000000..45efc9c --- /dev/null +++ b/panel/migrations/0483_auto_20250506_1054.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-06 10:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0482_auto_20250505_1431'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='samasat_discharge_percentage', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 816669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 740124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 740124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 740124)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 740124)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 922646)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 922646)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 745652)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 745652)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 745652)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 6, 10, 54, 4, 758786)), + ), + ] diff --git a/panel/migrations/0484_auto_20250510_1211.py b/panel/migrations/0484_auto_20250510_1211.py new file mode 100644 index 0000000..5c5614f --- /dev/null +++ b/panel/migrations/0484_auto_20250510_1211.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-10 12:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0483_auto_20250506_1054'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='InteractTypeName', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='PersonTypeName', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='UnionTypeName', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 599550)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 545483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 545483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 545483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 545483)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 666618)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 666618)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 548589)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 548589)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 548589)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 10, 12, 11, 0, 558202)), + ), + ] diff --git a/panel/migrations/0485_auto_20250511_1456.py b/panel/migrations/0485_auto_20250511_1456.py new file mode 100644 index 0000000..baf73eb --- /dev/null +++ b/panel/migrations/0485_auto_20250511_1456.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-11 14:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0484_auto_20250510_1211'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 204123)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 149931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 149931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 149931)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 149931)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 269685)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 269685)), + ), + migrations.AlterField( + model_name='posmachinetransactions', + name='result', + field=models.CharField(max_length=1000, null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 153027)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 153027)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 153027)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 11, 14, 56, 11, 162494)), + ), + ] diff --git a/panel/migrations/0486_auto_20250517_0910.py b/panel/migrations/0486_auto_20250517_0910.py new file mode 100644 index 0000000..88662ee --- /dev/null +++ b/panel/migrations/0486_auto_20250517_0910.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-17 09:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0485_auto_20250511_1456'), + ] + + operations = [ + migrations.AddField( + model_name='companybeneficiaryaccount', + name='unique_code', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 87896)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 36262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 36262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 36262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 36262)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 153895)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 153895)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 39262)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 39262)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 39262)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 9, 10, 18, 48262)), + ), + ] diff --git a/panel/migrations/0487_auto_20250517_1602.py b/panel/migrations/0487_auto_20250517_1602.py new file mode 100644 index 0000000..69fbe71 --- /dev/null +++ b/panel/migrations/0487_auto_20250517_1602.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-05-17 16:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0486_auto_20250517_0910'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='out_province_selling_limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='out_province_selling_limitation_percent', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 154748)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 217794)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 217794)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 107117)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 16, 2, 6, 123214)), + ), + ] diff --git a/panel/migrations/0488_auto_20250517_1701.py b/panel/migrations/0488_auto_20250517_1701.py new file mode 100644 index 0000000..6a2361e --- /dev/null +++ b/panel/migrations/0488_auto_20250517_1701.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-05-17 17:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0487_auto_20250517_1602'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='in_province_selling_limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='in_province_selling_limitation_percent', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 908665)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 852452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 852452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 852452)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 852452)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 976471)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 976471)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 855988)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 855988)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 855988)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 17, 17, 1, 31, 866866)), + ), + ] diff --git a/panel/migrations/0489_auto_20250518_1144.py b/panel/migrations/0489_auto_20250518_1144.py new file mode 100644 index 0000000..1a649ab --- /dev/null +++ b/panel/migrations/0489_auto_20250518_1144.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-18 11:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0488_auto_20250517_1701'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='quarantine_weight_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 913969)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 859288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 859288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 859288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 859288)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 980965)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 980965)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 862280)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 862280)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 862280)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 18, 11, 44, 15, 872136)), + ), + ] diff --git a/panel/migrations/0490_auto_20250520_1132.py b/panel/migrations/0490_auto_20250520_1132.py new file mode 100644 index 0000000..c6df344 --- /dev/null +++ b/panel/migrations/0490_auto_20250520_1132.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-20 11:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0489_auto_20250518_1144'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='CertId', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 491945)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 437946)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 437946)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 437946)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 437946)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 555944)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 555944)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 441908)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 441908)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 441908)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 20, 11, 31, 54, 451948)), + ), + ] diff --git a/panel/migrations/0491_auto_20250525_1503.py b/panel/migrations/0491_auto_20250525_1503.py new file mode 100644 index 0000000..41a2a2d --- /dev/null +++ b/panel/migrations/0491_auto_20250525_1503.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0490_auto_20250520_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 253633)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 197749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 197749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 197749)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 197749)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 321918)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 321918)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 201900)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 201900)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 201900)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 2, 53, 211179)), + ), + ] diff --git a/panel/migrations/0492_auto_20250525_1504.py b/panel/migrations/0492_auto_20250525_1504.py new file mode 100644 index 0000000..bd90a48 --- /dev/null +++ b/panel/migrations/0492_auto_20250525_1504.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0491_auto_20250525_1503'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 135589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 77519)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 76488)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 76488)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 76488)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 208362)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 208362)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 80788)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 80788)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 80788)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 4, 13, 90869)), + ), + ] diff --git a/panel/migrations/0493_auto_20250525_1505.py b/panel/migrations/0493_auto_20250525_1505.py new file mode 100644 index 0000000..21f482d --- /dev/null +++ b/panel/migrations/0493_auto_20250525_1505.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-05-25 15:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0492_auto_20250525_1504'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 294893)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 238863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 238863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 238863)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 238863)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 362839)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 362839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 241987)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 241987)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 241987)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 25, 15, 5, 28, 251492)), + ), + ] diff --git a/panel/migrations/0494_auto_20250526_0939.py b/panel/migrations/0494_auto_20250526_0939.py new file mode 100644 index 0000000..e0e60ab --- /dev/null +++ b/panel/migrations/0494_auto_20250526_0939.py @@ -0,0 +1,103 @@ +# Generated by Django 3.2.13 on 2025-05-26 09:39 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0493_auto_20250525_1505'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='increase_quantity', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 40, 41495)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 969999)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 969999)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 969999)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 969999)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 40, 138437)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 40, 138437)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 973993)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 973993)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 973993)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 9, 39, 39, 985609)), + ), + migrations.CreateModel( + name='HatchingIncreaseRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('hatching_quantity', models.IntegerField(null=True)), + ('quantity', models.IntegerField(null=True)), + ('hatching_kill_quantity', models.IntegerField(null=True)), + ('hatching_left_over', models.IntegerField(null=True)), + ('message', models.TextField(null=True)), + ('registerer_name', models.CharField(max_length=250, null=True)), + ('registerer_role', models.CharField(max_length=50, null=True)), + ('registerer_mobile', models.CharField(max_length=20, null=True)), + ('date', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchingincreaserequest_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='increase_hatching', to='panel.poultryhatching')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchingincreaserequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0495_auto_20250526_1214.py b/panel/migrations/0495_auto_20250526_1214.py new file mode 100644 index 0000000..a22b091 --- /dev/null +++ b/panel/migrations/0495_auto_20250526_1214.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-26 12:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0494_auto_20250526_0939'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='license', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='license_file', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='guilds', + name='license_form', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 759005)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 711431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 711431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 711431)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 711431)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 846169)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 846169)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 719289)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 719289)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 719289)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 12, 14, 25, 731373)), + ), + ] diff --git a/panel/migrations/0496_auto_20250526_1440.py b/panel/migrations/0496_auto_20250526_1440.py new file mode 100644 index 0000000..b33b1b4 --- /dev/null +++ b/panel/migrations/0496_auto_20250526_1440.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-05-26 14:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0495_auto_20250526_1214'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='checker_message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='guilds', + name='final_accept', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='reviewer_fullname', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='guilds', + name='reviewer_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='guilds', + name='reviewer_role', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 940928)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 886263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 886263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 886263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 886263)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 41, 7838)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 41, 7838)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 890278)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 890278)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 890278)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 26, 14, 40, 40, 901319)), + ), + ] diff --git a/panel/migrations/0497_auto_20250527_0854.py b/panel/migrations/0497_auto_20250527_0854.py new file mode 100644 index 0000000..f309f49 --- /dev/null +++ b/panel/migrations/0497_auto_20250527_0854.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-27 08:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0496_auto_20250526_1440'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='temporary_registration', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 29, 58207)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 993976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 993976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 993976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 993976)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 29, 129217)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 29, 129217)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 999593)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 999593)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 28, 999593)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 8, 54, 29, 11739)), + ), + ] diff --git a/panel/migrations/0498_auto_20250527_1032.py b/panel/migrations/0498_auto_20250527_1032.py new file mode 100644 index 0000000..d1cf263 --- /dev/null +++ b/panel/migrations/0498_auto_20250527_1032.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-27 10:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0497_auto_20250527_0854'), + ] + + operations = [ + migrations.AddField( + model_name='hatchingincreaserequest', + name='hatching_losses', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 385260)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 328648)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 328648)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 328648)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 328648)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 463753)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 463753)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 331742)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 331742)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 331742)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 27, 10, 32, 36, 341530)), + ), + ] diff --git a/panel/migrations/0499_auto_20250528_1132.py b/panel/migrations/0499_auto_20250528_1132.py new file mode 100644 index 0000000..c3fbf69 --- /dev/null +++ b/panel/migrations/0499_auto_20250528_1132.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-05-28 11:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0498_auto_20250527_1032'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 632526)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 576823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 576823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 576823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 576823)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 702213)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 702213)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 579920)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 579920)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 579920)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 32, 7, 590973)), + ), + migrations.CreateModel( + name='ChickenCommissionPrices', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_price', models.IntegerField(default=0)), + ('wholesaler_price', models.IntegerField(default=0)), + ('retailer_price', models.IntegerField(default=0)), + ('chicken_average_price', models.IntegerField(default=0)), + ('date', models.DateTimeField(auto_now_add=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chickencommissionprices_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='chickencommissionprices_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0500_auto_20250528_1140.py b/panel/migrations/0500_auto_20250528_1140.py new file mode 100644 index 0000000..f6d6f03 --- /dev/null +++ b/panel/migrations/0500_auto_20250528_1140.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-28 11:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0499_auto_20250528_1132'), + ] + + operations = [ + migrations.AlterField( + model_name='chickencommissionprices', + name='kill_house_price', + field=models.IntegerField(default=1500), + ), + migrations.AlterField( + model_name='chickencommissionprices', + name='retailer_price', + field=models.IntegerField(default=4000), + ), + migrations.AlterField( + model_name='chickencommissionprices', + name='wholesaler_price', + field=models.IntegerField(default=2000), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 250349)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 194646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 194646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 194646)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 194646)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 318847)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 318847)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 197550)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 197550)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 197550)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 11, 40, 2, 207882)), + ), + ] diff --git a/panel/migrations/0501_auto_20250528_1554.py b/panel/migrations/0501_auto_20250528_1554.py new file mode 100644 index 0000000..470cbb1 --- /dev/null +++ b/panel/migrations/0501_auto_20250528_1554.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-28 15:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0500_auto_20250528_1140'), + ] + + operations = [ + migrations.AddField( + model_name='chickencommissionprices', + name='kill_request_amount', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='chickencommissionprices', + name='poultry_request_amount', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='chickencommissionprices', + name='province_kill_request_amount', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 896874)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 828889)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 828889)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 828889)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 828889)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 988848)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 988848)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 833707)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 833707)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 833707)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 28, 15, 54, 1, 844910)), + ), + ] diff --git a/panel/migrations/0502_auto_20250531_1005.py b/panel/migrations/0502_auto_20250531_1005.py new file mode 100644 index 0000000..daa1a8a --- /dev/null +++ b/panel/migrations/0502_auto_20250531_1005.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 10:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0501_auto_20250528_1554'), + ] + + operations = [ + migrations.AlterField( + model_name='chickencommissionprices', + name='date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 857054)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 650126)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 650126)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 650126)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 650126)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 976787)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 976787)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 661494)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 661494)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 661494)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 10, 5, 24, 678243)), + ), + ] diff --git a/panel/migrations/0503_auto_20250531_1207.py b/panel/migrations/0503_auto_20250531_1207.py new file mode 100644 index 0000000..772b4ac --- /dev/null +++ b/panel/migrations/0503_auto_20250531_1207.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-05-31 12:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0502_auto_20250531_1005'), + ] + + operations = [ + migrations.AlterField( + model_name='chickencommissionprices', + name='kill_house_price', + field=models.IntegerField(default=15000), + ), + migrations.AlterField( + model_name='chickencommissionprices', + name='retailer_price', + field=models.IntegerField(default=40000), + ), + migrations.AlterField( + model_name='chickencommissionprices', + name='wholesaler_price', + field=models.IntegerField(default=20000), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 950795)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 854630)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 854630)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 854630)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 854630)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 48, 146217)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 48, 146217)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 859617)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 858620)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 858620)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 6, 47, 871584)), + ), + ] diff --git a/panel/migrations/0504_auto_20250531_1249.py b/panel/migrations/0504_auto_20250531_1249.py new file mode 100644 index 0000000..deb4b67 --- /dev/null +++ b/panel/migrations/0504_auto_20250531_1249.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 12:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0503_auto_20250531_1207'), + ] + + operations = [ + migrations.AddField( + model_name='chickencommissionprices', + name='shipping_price', + field=models.IntegerField(default=25000), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 103178)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 48589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 48589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 48589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 48589)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 173466)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 173466)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 51580)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 51580)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 51580)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 12, 49, 18, 62046)), + ), + ] diff --git a/panel/migrations/0505_auto_20250531_1332.py b/panel/migrations/0505_auto_20250531_1332.py new file mode 100644 index 0000000..943036b --- /dev/null +++ b/panel/migrations/0505_auto_20250531_1332.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 13:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0504_auto_20250531_1249'), + ] + + operations = [ + migrations.AlterField( + model_name='chickencommissionprices', + name='shipping_price', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 864669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 806794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 806794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 806794)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 806794)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 938401)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 938401)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 809942)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 809942)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 809942)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 32, 30, 820585)), + ), + ] diff --git a/panel/migrations/0506_auto_20250531_1344.py b/panel/migrations/0506_auto_20250531_1344.py new file mode 100644 index 0000000..25abe08 --- /dev/null +++ b/panel/migrations/0506_auto_20250531_1344.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2025-05-31 13:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0505_auto_20250531_1332'), + ] + + operations = [ + migrations.RemoveField( + model_name='chickencommissionprices', + name='shipping_price', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 178880)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 112165)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 112165)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 112165)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 112165)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 286547)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 286547)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 116182)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 116182)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 116182)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 13, 44, 38, 127964)), + ), + ] diff --git a/panel/migrations/0507_auto_20250531_1433.py b/panel/migrations/0507_auto_20250531_1433.py new file mode 100644 index 0000000..c4df035 --- /dev/null +++ b/panel/migrations/0507_auto_20250531_1433.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-05-31 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0506_auto_20250531_1344'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='quarantine_quantity', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 300822)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 234288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 234288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 234288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 234288)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 406500)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 406500)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 238278)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 238278)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 238278)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 5, 31, 14, 32, 56, 249842)), + ), + ] diff --git a/panel/migrations/0508_auto_20250601_1023.py b/panel/migrations/0508_auto_20250601_1023.py new file mode 100644 index 0000000..60269b2 --- /dev/null +++ b/panel/migrations/0508_auto_20250601_1023.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-06-01 10:23 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0071_auto_20250601_1023'), + ('panel', '0507_auto_20250531_1433'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 831670)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 756490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 756490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 756490)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 756490)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 909045)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 909045)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 774258)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 774258)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 774258)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 1, 10, 23, 19, 784295)), + ), + migrations.CreateModel( + name='ProteinGuild', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('address', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='protein_guild_address', to='authentication.systemaddress')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='proteinguild_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='proteinguild_modifiedby', to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='protein_guild_user', to='authentication.systemuserprofile')), + ('user_bank_info', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='protein_guild_bank_info', to='authentication.bankcard')), + ('wallet', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='protein_guild_wallet', to='panel.wallet')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0509_auto_20250602_1504.py b/panel/migrations/0509_auto_20250602_1504.py new file mode 100644 index 0000000..72ff1e4 --- /dev/null +++ b/panel/migrations/0509_auto_20250602_1504.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-02 15:04 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0508_auto_20250601_1023'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='weight_loss_of_carcasses', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 30, 51554)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 994154)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 994154)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 994154)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 994154)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 30, 120716)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 30, 120716)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 998168)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 998168)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 29, 998168)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 2, 15, 4, 30, 8194)), + ), + ] diff --git a/panel/migrations/0510_auto_20250603_1443.py b/panel/migrations/0510_auto_20250603_1443.py new file mode 100644 index 0000000..fdb14b3 --- /dev/null +++ b/panel/migrations/0510_auto_20250603_1443.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-06-03 14:43 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0509_auto_20250602_1504'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 102987)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 36709)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 36709)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 36709)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 36709)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 194004)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 194004)), + ), + migrations.AlterField( + model_name='posdeviceversion', + name='company', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pos_version_company', to='panel.poscompany'), + ), + migrations.AlterField( + model_name='posdeviceversion', + name='description', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 40698)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 40698)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 40698)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 3, 14, 43, 35, 52943)), + ), + ] diff --git a/panel/migrations/0511_auto_20250607_0938.py b/panel/migrations/0511_auto_20250607_0938.py new file mode 100644 index 0000000..607a034 --- /dev/null +++ b/panel/migrations/0511_auto_20250607_0938.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-06-07 09:38 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0510_auto_20250603_1443'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 285936)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 220682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 220682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 220682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 220682)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 372735)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 372735)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 224699)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 224699)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 224699)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 9, 38, 12, 236510)), + ), + migrations.CreateModel( + name='CommonlyUsed', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('exclusive', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonlyused_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonly_used_guild', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonly_used_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonlyused_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0512_auto_20250607_1053.py b/panel/migrations/0512_auto_20250607_1053.py new file mode 100644 index 0000000..580dec5 --- /dev/null +++ b/panel/migrations/0512_auto_20250607_1053.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.13 on 2025-06-07 10:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0511_auto_20250607_0938'), + ] + + operations = [ + migrations.RemoveField( + model_name='commonlyused', + name='exclusive', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 167705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 106803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 106803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 106803)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 106803)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 238327)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 238327)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 109802)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 109802)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 109802)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 10, 52, 57, 121564)), + ), + ] diff --git a/panel/migrations/0513_auto_20250607_1502.py b/panel/migrations/0513_auto_20250607_1502.py new file mode 100644 index 0000000..25251c7 --- /dev/null +++ b/panel/migrations/0513_auto_20250607_1502.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-06-07 15:02 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0512_auto_20250607_1053'), + ] + + operations = [ + migrations.AddField( + model_name='commonlyused', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='commonly_used_steward', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 94820)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 5886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 5886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 5886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 5886)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 584922)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 584922)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 9902)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 9902)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 9902)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 15, 1, 43, 25742)), + ), + ] diff --git a/panel/migrations/0514_auto_20250607_1612.py b/panel/migrations/0514_auto_20250607_1612.py new file mode 100644 index 0000000..e0b2eb8 --- /dev/null +++ b/panel/migrations/0514_auto_20250607_1612.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-07 16:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0513_auto_20250607_1502'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='register_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 613592)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 528530)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 528530)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 528530)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 528530)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 696621)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 696621)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 532547)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 532547)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 532547)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 12, 1, 546352)), + ), + ] diff --git a/panel/migrations/0515_auto_20250607_1624.py b/panel/migrations/0515_auto_20250607_1624.py new file mode 100644 index 0000000..73c677e --- /dev/null +++ b/panel/migrations/0515_auto_20250607_1624.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-07 16:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0514_auto_20250607_1612'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='overhead', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 765249)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 707463)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 707463)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 707463)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 707463)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 833617)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 833617)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 717434)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 717434)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 717434)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 7, 16, 24, 45, 717434)), + ), + ] diff --git a/panel/migrations/0516_auto_20250609_1157.py b/panel/migrations/0516_auto_20250609_1157.py new file mode 100644 index 0000000..4fdfad4 --- /dev/null +++ b/panel/migrations/0516_auto_20250609_1157.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-09 11:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0515_auto_20250607_1624'), + ] + + operations = [ + migrations.AddField( + model_name='commonlyused', + name='priority', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 309019)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 371832)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 371832)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 246332)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 11, 57, 39, 261985)), + ), + ] diff --git a/panel/migrations/0517_auto_20250609_1435.py b/panel/migrations/0517_auto_20250609_1435.py new file mode 100644 index 0000000..55b3310 --- /dev/null +++ b/panel/migrations/0517_auto_20250609_1435.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-06-09 14:35 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0516_auto_20250609_1157'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='buyer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_free_sale_bar_info_buyer', to='panel.outprovincecarcassesbuyer'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 214604)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 153824)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 153824)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 153824)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 153824)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 290569)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 290569)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 156824)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 156824)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 156824)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 9, 14, 35, 9, 169487)), + ), + ] diff --git a/panel/migrations/0518_auto_20250610_1345.py b/panel/migrations/0518_auto_20250610_1345.py new file mode 100644 index 0000000..37c3202 --- /dev/null +++ b/panel/migrations/0518_auto_20250610_1345.py @@ -0,0 +1,119 @@ +# Generated by Django 3.2.13 on 2025-06-10 13:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0517_auto_20250609_1435'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='description', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_editor', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_editor_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_editor_role', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_register_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_registerar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='price_registerar_role', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='settlement_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 305343)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 368442)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 368442)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 15, 257989)), + ), + ] diff --git a/panel/migrations/0519_auto_20250610_1345.py b/panel/migrations/0519_auto_20250610_1345.py new file mode 100644 index 0000000..7b1476d --- /dev/null +++ b/panel/migrations/0519_auto_20250610_1345.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-06-10 13:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0518_auto_20250610_1345'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 248364)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 321059)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 321059)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 186723)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 10, 13, 45, 46, 202729)), + ), + ] diff --git a/panel/migrations/0520_auto_20250628_1428.py b/panel/migrations/0520_auto_20250628_1428.py new file mode 100644 index 0000000..989ddf5 --- /dev/null +++ b/panel/migrations/0520_auto_20250628_1428.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-28 14:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0519_auto_20250610_1345'), + ] + + operations = [ + migrations.AddField( + model_name='bardocumentstatus', + name='description', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 84182)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 147535)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 147535)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 20982)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 14, 27, 54, 40677)), + ), + ] diff --git a/panel/migrations/0521_auto_20250628_1502.py b/panel/migrations/0521_auto_20250628_1502.py new file mode 100644 index 0000000..4b0ef7c --- /dev/null +++ b/panel/migrations/0521_auto_20250628_1502.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-06-28 15:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0520_auto_20250628_1428'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='bar_document_description', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 658308)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 585023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 585023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 585023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 585023)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 766966)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 766966)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 589039)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 587031)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 587031)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 6, 28, 15, 1, 51, 600828)), + ), + ] diff --git a/panel/migrations/0522_auto_20250707_0926.py b/panel/migrations/0522_auto_20250707_0926.py new file mode 100644 index 0000000..63a148c --- /dev/null +++ b/panel/migrations/0522_auto_20250707_0926.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-07-07 09:26 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0521_auto_20250628_1502'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 399532)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 336424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 336424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 336424)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 336424)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 462689)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 462689)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 344142)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 344142)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 344142)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 25, 45, 356175)), + ), + migrations.CreateModel( + name='PoultryRequestQuarantineCode', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quarantine_code', models.CharField(max_length=200, null=True)), + ('quarantine_quantity', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestquarantinecode_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryrequestquarantinecode_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_code', to='panel.poultryrequest')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0523_auto_20250707_0959.py b/panel/migrations/0523_auto_20250707_0959.py new file mode 100644 index 0000000..a37ee93 --- /dev/null +++ b/panel/migrations/0523_auto_20250707_0959.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-07 09:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0522_auto_20250707_0926'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequestquarantinecode', + name='system_quarantine_quantity', + field=models.IntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 48, 16337)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 952935)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 952935)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 952935)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 952935)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 48, 95465)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 48, 95465)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 968894)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 968894)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 968894)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 7, 9, 58, 47, 968894)), + ), + ] diff --git a/panel/migrations/0524_auto_20250708_0838.py b/panel/migrations/0524_auto_20250708_0838.py new file mode 100644 index 0000000..ad5fc2d --- /dev/null +++ b/panel/migrations/0524_auto_20250708_0838.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-07-08 08:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0523_auto_20250707_0959'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequestquarantinecode', + name='register_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='poultryrequestquarantinecode', + name='registrar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 598369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 661543)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 661543)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 535610)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 8, 38, 24, 553538)), + ), + ] diff --git a/panel/migrations/0525_auto_20250708_1018.py b/panel/migrations/0525_auto_20250708_1018.py new file mode 100644 index 0000000..5a1a154 --- /dev/null +++ b/panel/migrations/0525_auto_20250708_1018.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-08 10:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0524_auto_20250708_0838'), + ] + + operations = [ + migrations.AddField( + model_name='poultry', + name='order_limit', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 215751)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 132638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 132638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 132638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 132638)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 393590)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 393590)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 134646)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 134646)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 134646)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 10, 18, 23, 148456)), + ), + ] diff --git a/panel/migrations/0526_auto_20250708_1421.py b/panel/migrations/0526_auto_20250708_1421.py new file mode 100644 index 0000000..d9e67a0 --- /dev/null +++ b/panel/migrations/0526_auto_20250708_1421.py @@ -0,0 +1,109 @@ +# Generated by Django 3.2.13 on 2025-07-08 14:21 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0525_auto_20250708_1018'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 16, 33025)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 14, 939813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 14, 939813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 14, 939813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 14, 939813)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 18, 220599)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 18, 220599)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 15, 228558)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 15, 228558)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 15, 228558)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 8, 14, 21, 15, 525000)), + ), + migrations.CreateModel( + name='UploadImageLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_allocation', models.BooleanField(default=False)), + ('kill_house_free_sale', models.BooleanField(default=False)), + ('steward_allocation', models.BooleanField(default=False)), + ('steward_free_sale', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='uploadimagelimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='uploadimagelimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='PercentageDropLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('kill_house_limit_percent_down', models.IntegerField(default=0)), + ('kill_house_limit_percent_up', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentagedroplimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='percentagedroplimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0527_auto_20250709_1112.py b/panel/migrations/0527_auto_20250709_1112.py new file mode 100644 index 0000000..3d2335a --- /dev/null +++ b/panel/migrations/0527_auto_20250709_1112.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-09 11:12 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0526_auto_20250708_1421'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='image', + field=models.CharField(max_length=500, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 85731)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 165616)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 165616)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 21962)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 9, 11, 12, 13, 37660)), + ), + ] diff --git a/panel/migrations/0528_auto_20250713_1028.py b/panel/migrations/0528_auto_20250713_1028.py new file mode 100644 index 0000000..e45c320 --- /dev/null +++ b/panel/migrations/0528_auto_20250713_1028.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-13 10:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0527_auto_20250709_1112'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='role_activation', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 804539)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 742089)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 742089)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 742089)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 742089)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 880340)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 880340)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 747344)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 747344)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 747344)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 13, 10, 28, 14, 759699)), + ), + ] diff --git a/panel/migrations/0529_auto_20250714_1045.py b/panel/migrations/0529_auto_20250714_1045.py new file mode 100644 index 0000000..2cd2e5c --- /dev/null +++ b/panel/migrations/0529_auto_20250714_1045.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-07-14 10:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0528_auto_20250713_1028'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='tenant_city', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='tenant_fullname', + field=models.CharField(blank=True, max_length=300, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='tenant_mobile', + field=models.CharField(blank=True, max_length=20, null=True), + ), + migrations.AddField( + model_name='poultryhatching', + name='tenant_national_code', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 646000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 596927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 596927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 596927)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 596927)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 721321)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 721321)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 600677)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 600677)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 600677)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 45, 17, 610698)), + ), + ] diff --git a/panel/migrations/0530_auto_20250714_1100.py b/panel/migrations/0530_auto_20250714_1100.py new file mode 100644 index 0000000..b545935 --- /dev/null +++ b/panel/migrations/0530_auto_20250714_1100.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-14 11:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0529_auto_20250714_1045'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='has_tenant', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 106447)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 46837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 46837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 46837)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 46837)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 181246)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 181246)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 51170)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 49918)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 49918)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 14, 10, 59, 52, 62139)), + ), + ] diff --git a/panel/migrations/0531_auto_20250719_0857.py b/panel/migrations/0531_auto_20250719_0857.py new file mode 100644 index 0000000..4893208 --- /dev/null +++ b/panel/migrations/0531_auto_20250719_0857.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-19 08:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0530_auto_20250714_1100'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='non_receipt', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 48, 137)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 48, 83600)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 48, 83600)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 950202)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 8, 56, 47, 966887)), + ), + ] diff --git a/panel/migrations/0532_auto_20250719_0938.py b/panel/migrations/0532_auto_20250719_0938.py new file mode 100644 index 0000000..3654dae --- /dev/null +++ b/panel/migrations/0532_auto_20250719_0938.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-19 09:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0531_auto_20250719_0857'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 315001)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 109879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 109879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 109879)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 109879)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 665325)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 665325)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 182942)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 181938)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 182942)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 19, 9, 38, 37, 196218)), + ), + ] diff --git a/panel/migrations/0533_auto_20250720_1445.py b/panel/migrations/0533_auto_20250720_1445.py new file mode 100644 index 0000000..7298dfc --- /dev/null +++ b/panel/migrations/0533_auto_20250720_1445.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2025-07-20 14:45 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0532_auto_20250719_0938'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 870699)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 937670)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 937670)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 811222)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 14, 44, 59, 827110)), + ), + migrations.CreateModel( + name='ApkInfo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('info', models.JSONField(null=True)), + ('download_link', models.CharField(blank=True, max_length=700, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='apkinfo_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='apkinfo_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0534_auto_20250720_1510.py b/panel/migrations/0534_auto_20250720_1510.py new file mode 100644 index 0000000..1f3e1c3 --- /dev/null +++ b/panel/migrations/0534_auto_20250720_1510.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-07-20 15:10 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0533_auto_20250720_1445'), + ] + + operations = [ + migrations.AddField( + model_name='possegmentation', + name='to_guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='to_guild_segmentation', to='panel.guilds'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 123294)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 65908)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 65908)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 65908)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 65908)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 196236)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 196236)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 69918)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 69918)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 69918)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 20, 15, 10, 7, 79685)), + ), + ] diff --git a/panel/migrations/0535_auto_20250722_1133.py b/panel/migrations/0535_auto_20250722_1133.py new file mode 100644 index 0000000..f23df46 --- /dev/null +++ b/panel/migrations/0535_auto_20250722_1133.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-07-22 11:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0534_auto_20250720_1510'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='receipt', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 422441)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 282039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 282039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 282039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 282039)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 829213)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 829213)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 285802)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 285802)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 285802)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 11, 33, 38, 337268)), + ), + ] diff --git a/panel/migrations/0536_auto_20250722_1248.py b/panel/migrations/0536_auto_20250722_1248.py new file mode 100644 index 0000000..d1d7c03 --- /dev/null +++ b/panel/migrations/0536_auto_20250722_1248.py @@ -0,0 +1,108 @@ +# Generated by Django 3.2.13 on 2025-07-22 12:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0535_auto_20250722_1133'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhouserequest', + name='receipt', + ), + migrations.AddField( + model_name='killhouserequest', + name='main_non_receipt', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_check_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_checker', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_checker_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_return_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_returner', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_returner_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 348209)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 298104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 298104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 298104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 298104)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 431602)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 431602)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 302279)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 302279)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 302279)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 22, 12, 48, 25, 313760)), + ), + ] diff --git a/panel/migrations/0537_auto_20250723_0917.py b/panel/migrations/0537_auto_20250723_0917.py new file mode 100644 index 0000000..a4fc4d8 --- /dev/null +++ b/panel/migrations/0537_auto_20250723_0917.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-07-23 09:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0536_auto_20250722_1248'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_checker_message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 297196)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 237591)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 237591)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 237591)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 237591)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 368970)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 368970)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 240591)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 240591)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 240591)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 9, 16, 57, 252142)), + ), + ] diff --git a/panel/migrations/0538_auto_20250723_1013.py b/panel/migrations/0538_auto_20250723_1013.py new file mode 100644 index 0000000..5cf2a71 --- /dev/null +++ b/panel/migrations/0538_auto_20250723_1013.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-07-23 10:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0537_auto_20250723_0917'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_return', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='non_receipt_return_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 46, 71841)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 992864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 992864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 992864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 992864)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 46, 150749)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 46, 150749)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 998628)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 998628)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 45, 998628)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 23, 10, 12, 46, 10672)), + ), + ] diff --git a/panel/migrations/0539_auto_20250727_0734.py b/panel/migrations/0539_auto_20250727_0734.py new file mode 100644 index 0000000..5f99885 --- /dev/null +++ b/panel/migrations/0539_auto_20250727_0734.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-07-27 07:34 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0538_auto_20250723_1013'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='poultry_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_request_kill_req', to='panel.poultryrequest'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 665446)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 606524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 606524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 606524)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 606524)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 745055)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 745055)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 618150)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 618150)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 618150)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 7, 34, 12, 633949)), + ), + ] diff --git a/panel/migrations/0540_auto_20250727_1238.py b/panel/migrations/0540_auto_20250727_1238.py new file mode 100644 index 0000000..f200a2a --- /dev/null +++ b/panel/migrations/0540_auto_20250727_1238.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-07-27 12:38 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0539_auto_20250727_0734'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 141096)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 66862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 66862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 66862)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 66862)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 211380)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 211380)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 84756)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 83863)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 83863)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 12, 38, 17, 94792)), + ), + migrations.CreateModel( + name='DirectBuyingVerification', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('poultry_code_mandatory', models.BooleanField(default=False)), + ('payment_deadline', models.BooleanField(default=False)), + ('payment_deadline_days', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='directbuyingverification_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='directbuyingverification_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0541_auto_20250727_1453.py b/panel/migrations/0541_auto_20250727_1453.py new file mode 100644 index 0000000..f4180be --- /dev/null +++ b/panel/migrations/0541_auto_20250727_1453.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2025-07-27 14:53 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0540_auto_20250727_1238'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='extension_payment_deadline_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='extension_payment_deadline_days', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='payment_deadline_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killrequest', + name='payment_deadline_days', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='killrequest', + name='poultry_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 751631)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 678843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 678843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 678843)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 678843)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 808891)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 808891)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 682594)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 682594)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 682594)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 7, 27, 14, 52, 48, 694628)), + ), + migrations.CreateModel( + name='DirectBuyingPayment', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('amount', models.BigIntegerField(default=0)), + ('image', models.CharField(max_length=700, null=True)), + ('date', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='directbuyingpayment_createdby', to=settings.AUTH_USER_MODEL)), + ('kill_request', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='direct_buying_kill_request', to='panel.killrequest')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='directbuyingpayment_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0542_auto_20250803_0821.py b/panel/migrations/0542_auto_20250803_0821.py new file mode 100644 index 0000000..0eea485 --- /dev/null +++ b/panel/migrations/0542_auto_20250803_0821.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-08-03 08:21 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0541_auto_20250727_1453'), + ] + + operations = [ + migrations.RemoveField( + model_name='directbuyingpayment', + name='kill_request', + ), + migrations.AddField( + model_name='directbuyingpayment', + name='province_kill_request', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='direct_buying_province_kill_request', to='panel.provincekillrequest'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 70588)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 134072)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 134072)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 7445)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 8, 21, 20, 29074)), + ), + ] diff --git a/panel/migrations/0543_auto_20250803_1532.py b/panel/migrations/0543_auto_20250803_1532.py new file mode 100644 index 0000000..5561553 --- /dev/null +++ b/panel/migrations/0543_auto_20250803_1532.py @@ -0,0 +1,139 @@ +# Generated by Django 3.2.13 on 2025-08-03 15:32 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0542_auto_20250803_0821'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='payment_deadline', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='extension_payment_deadline_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='extension_payment_deadline_days', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='final_accept', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_archive', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_archive_message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_check_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_checker_fullname', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_checker_mobile', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_days', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 214232)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 162704)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 162704)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 162704)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 162704)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 277655)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 277655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 166453)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 166453)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 166453)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 3, 15, 32, 44, 178481)), + ), + ] diff --git a/panel/migrations/0544_auto_20250805_0852.py b/panel/migrations/0544_auto_20250805_0852.py new file mode 100644 index 0000000..2bdc273 --- /dev/null +++ b/panel/migrations/0544_auto_20250805_0852.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-08-05 08:52 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0543_auto_20250803_1532'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='other_cold_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_to_other_cold_house', to='panel.coldhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 476670)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 417208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 417208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 417208)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 417208)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 550536)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 550536)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 421208)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 420209)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 420209)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 5, 8, 51, 47, 432691)), + ), + ] diff --git a/panel/migrations/0545_auto_20250806_1515.py b/panel/migrations/0545_auto_20250806_1515.py new file mode 100644 index 0000000..e3639ec --- /dev/null +++ b/panel/migrations/0545_auto_20250806_1515.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-08-06 15:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0544_auto_20250805_0852'), + ] + + operations = [ + migrations.AddField( + model_name='directbuyingpayment', + name='payment_registrar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='directbuyingpayment', + name='payment_registrar_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='final_accept_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='final_accept_registrar', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='final_accept_registrar_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 300885)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 108915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 108915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 108915)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 108915)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 636379)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 636379)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 112935)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 112935)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 112935)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 15, 24, 211849)), + ), + ] diff --git a/panel/migrations/0546_auto_20250806_1553.py b/panel/migrations/0546_auto_20250806_1553.py new file mode 100644 index 0000000..d167701 --- /dev/null +++ b/panel/migrations/0546_auto_20250806_1553.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-08-06 15:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0545_auto_20250806_1515'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 20, 343909)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 975984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 975984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 975984)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 975984)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 20, 532469)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 20, 532469)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 978985)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 978985)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 19, 978985)), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='payment_deadline_checker_fullname', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='provincekillrequest', + name='payment_deadline_checker_mobile', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 6, 15, 53, 20, 34940)), + ), + ] diff --git a/panel/migrations/0547_auto_20250809_0949.py b/panel/migrations/0547_auto_20250809_0949.py new file mode 100644 index 0000000..fd74fb9 --- /dev/null +++ b/panel/migrations/0547_auto_20250809_0949.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-08-09 09:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0546_auto_20250806_1553'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='company_document', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouserequest', + name='document_number', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='fine', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='fine', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 210801)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 157367)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 157367)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 157367)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 157367)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 274069)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 274069)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 159373)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 159373)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 159373)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 9, 49, 11, 171148)), + ), + ] diff --git a/panel/migrations/0548_auto_20250809_1021.py b/panel/migrations/0548_auto_20250809_1021.py new file mode 100644 index 0000000..e540135 --- /dev/null +++ b/panel/migrations/0548_auto_20250809_1021.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 10:21 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0547_auto_20250809_0949'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='direct_buying', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 540483)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 456991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 456991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 456991)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 456991)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 621762)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 621762)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 460996)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 460996)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 460996)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 10, 20, 55, 474727)), + ), + ] diff --git a/panel/migrations/0549_auto_20250809_1237.py b/panel/migrations/0549_auto_20250809_1237.py new file mode 100644 index 0000000..042fb6b --- /dev/null +++ b/panel/migrations/0549_auto_20250809_1237.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 12:37 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0548_auto_20250809_1021'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='fine', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 140637)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 78000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 78000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 78000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 78000)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 208071)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 208071)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 80006)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 80006)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 80006)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 12, 37, 4, 82012)), + ), + ] diff --git a/panel/migrations/0550_auto_20250809_1351.py b/panel/migrations/0550_auto_20250809_1351.py new file mode 100644 index 0000000..a567642 --- /dev/null +++ b/panel/migrations/0550_auto_20250809_1351.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-09 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0549_auto_20250809_1237'), + ] + + operations = [ + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='fine_active', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='fine_end_time', + field=models.TimeField(null=True), + ), + migrations.AddField( + model_name='automaticdirectbuyingpermission', + name='fine_start_time', + field=models.TimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 441160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 379243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 379243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 379243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 379243)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 515663)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 515663)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 382977)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 382977)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 382977)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 13, 51, 19, 394010)), + ), + ] diff --git a/panel/migrations/0551_auto_20250809_1409.py b/panel/migrations/0551_auto_20250809_1409.py new file mode 100644 index 0000000..d799e57 --- /dev/null +++ b/panel/migrations/0551_auto_20250809_1409.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 14:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0550_auto_20250809_1351'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='archive_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 442289)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 373380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 373380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 373380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 373380)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 522380)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 522380)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 376569)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 376569)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 376569)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 14, 9, 27, 389995)), + ), + ] diff --git a/panel/migrations/0552_auto_20250809_1522.py b/panel/migrations/0552_auto_20250809_1522.py new file mode 100644 index 0000000..4fa9439 --- /dev/null +++ b/panel/migrations/0552_auto_20250809_1522.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 15:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0551_auto_20250809_1409'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='payment_deadline_supporter_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 874577)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 945684)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 945684)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 805184)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 15, 21, 43, 820987)), + ), + ] diff --git a/panel/migrations/0553_auto_20250809_1613.py b/panel/migrations/0553_auto_20250809_1613.py new file mode 100644 index 0000000..df10671 --- /dev/null +++ b/panel/migrations/0553_auto_20250809_1613.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-09 16:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0552_auto_20250809_1522'), + ] + + operations = [ + migrations.AddField( + model_name='directbuyingpayment', + name='payment_deadline_supporter_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 21, 14046)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 21, 91455)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 21, 91455)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 948459)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 9, 16, 13, 20, 964488)), + ), + ] diff --git a/panel/migrations/0554_auto_20250810_1256.py b/panel/migrations/0554_auto_20250810_1256.py new file mode 100644 index 0000000..92b5678 --- /dev/null +++ b/panel/migrations/0554_auto_20250810_1256.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-08-10 12:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0553_auto_20250809_1613'), + ] + + operations = [ + migrations.CreateModel( + name='FinePermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('out_poultry_request', models.BooleanField(default=False)), + ('out_poultry_request_start_time', models.TimeField(null=True)), + ('out_poultry_request_end_time', models.TimeField(null=True)), + ('out_poultry_request_fine_coefficient', models.FloatField(default=0)), + ('direct_buying', models.BooleanField(default=False)), + ('direct_buying_start_time', models.TimeField(null=True)), + ('direct_buying_end_time', models.TimeField(null=True)), + ('direct_buying_fine_coefficient', models.FloatField(default=0)), + ('in_province_allocations', models.BooleanField(default=False)), + ('in_province_allocations_fine_coefficient', models.FloatField(default=0)), + ('in_province_bars', models.BooleanField(default=False)), + ('in_province_bars_fine_coefficient', models.FloatField(default=0)), + ], + ), + migrations.RemoveField( + model_name='automaticdirectbuyingpermission', + name='fine_active', + ), + migrations.RemoveField( + model_name='automaticdirectbuyingpermission', + name='fine_end_time', + ), + migrations.RemoveField( + model_name='automaticdirectbuyingpermission', + name='fine_start_time', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 20, 675480)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 562340)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 562340)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 562340)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 562340)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 20, 938713)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 20, 938713)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 566097)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 566097)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 566097)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 12, 56, 19, 775568)), + ), + ] diff --git a/panel/migrations/0555_auto_20250810_1354.py b/panel/migrations/0555_auto_20250810_1354.py new file mode 100644 index 0000000..4603676 --- /dev/null +++ b/panel/migrations/0555_auto_20250810_1354.py @@ -0,0 +1,105 @@ +# Generated by Django 3.2.13 on 2025-08-10 13:54 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0554_auto_20250810_1256'), + ] + + operations = [ + migrations.AddField( + model_name='finepermission', + name='create_date', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='finepermission', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finepermission_createdby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='finepermission', + name='key', + field=models.UUIDField(default=uuid.uuid4, editable=False, unique=True), + ), + migrations.AddField( + model_name='finepermission', + name='modified_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='finepermission_modifiedby', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='finepermission', + name='modify_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AddField( + model_name='finepermission', + name='trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 636802)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 539755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 539755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 539755)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 539755)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 719611)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 719611)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 543203)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 543203)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 543203)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 13, 53, 48, 555434)), + ), + ] diff --git a/panel/migrations/0556_auto_20250810_1414.py b/panel/migrations/0556_auto_20250810_1414.py new file mode 100644 index 0000000..4ae2492 --- /dev/null +++ b/panel/migrations/0556_auto_20250810_1414.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2025-08-10 14:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0555_auto_20250810_1354'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='fine_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='fine_coefficient', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='fine_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryrequest', + name='fine_coefficient', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='direct_buying_fine', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='direct_buying_fine_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='direct_buying_fine_coefficient', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='fine_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='provincekillrequest', + name='fine_coefficient', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 733783)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 817347)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 817347)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 666990)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 10, 14, 14, 1, 685079)), + ), + ] diff --git a/panel/migrations/0557_auto_20250811_0909.py b/panel/migrations/0557_auto_20250811_0909.py new file mode 100644 index 0000000..7439194 --- /dev/null +++ b/panel/migrations/0557_auto_20250811_0909.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-08-11 09:09 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0556_auto_20250810_1414'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 120372)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 200536)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 200536)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 54962)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 11, 9, 9, 8, 71655)), + ), + migrations.CreateModel( + name='ManagementSendSms', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('username', models.CharField(max_length=100, null=True)), + ('password', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='managementsendsms_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='managementsendsms_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0558_auto_20250817_0851.py b/panel/migrations/0558_auto_20250817_0851.py new file mode 100644 index 0000000..880d02a --- /dev/null +++ b/panel/migrations/0558_auto_20250817_0851.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 08:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0557_auto_20250811_0909'), + ] + + operations = [ + migrations.AddField( + model_name='provincekillrequest', + name='market', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 642022)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 705036)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 705036)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 579029)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 8, 50, 55, 594728)), + ), + ] diff --git a/panel/migrations/0559_auto_20250817_1014.py b/panel/migrations/0559_auto_20250817_1014.py new file mode 100644 index 0000000..872038e --- /dev/null +++ b/panel/migrations/0559_auto_20250817_1014.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 10:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0558_auto_20250817_0851'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='market', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 126162)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 67026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 67026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 67026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 67026)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 197498)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 197498)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 70057)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 70057)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 70057)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 14, 39, 81644)), + ), + ] diff --git a/panel/migrations/0560_auto_20250817_1040.py b/panel/migrations/0560_auto_20250817_1040.py new file mode 100644 index 0000000..0644670 --- /dev/null +++ b/panel/migrations/0560_auto_20250817_1040.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 10:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0559_auto_20250817_1014'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='market_state', + field=models.CharField(default='pending', max_length=20), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 382081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 321052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 321052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 321052)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 321052)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 454544)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 454544)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 324018)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 324018)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 324018)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 40, 6, 335958)), + ), + ] diff --git a/panel/migrations/0561_auto_20250817_1048.py b/panel/migrations/0561_auto_20250817_1048.py new file mode 100644 index 0000000..d17b22c --- /dev/null +++ b/panel/migrations/0561_auto_20250817_1048.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-08-17 10:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0560_auto_20250817_1040'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='market_capacity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='market_capacity_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 990425)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 849026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 849026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 849026)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 849026)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 46, 181534)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 46, 181534)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 853026)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 853026)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 853026)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 10, 47, 45, 901280)), + ), + ] diff --git a/panel/migrations/0562_auto_20250817_1351.py b/panel/migrations/0562_auto_20250817_1351.py new file mode 100644 index 0000000..276f977 --- /dev/null +++ b/panel/migrations/0562_auto_20250817_1351.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-17 13:51 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0561_auto_20250817_1048'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='market_final_accept', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 379531)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 235394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 235394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 235394)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 235394)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 488984)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 488984)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 239963)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 239963)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 239963)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 17, 13, 51, 9, 253026)), + ), + ] diff --git a/panel/migrations/0563_auto_20250818_0941.py b/panel/migrations/0563_auto_20250818_0941.py new file mode 100644 index 0000000..c517dcd --- /dev/null +++ b/panel/migrations/0563_auto_20250818_0941.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2025-08-18 09:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0562_auto_20250817_1351'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhouse', + name='market_capacity', + ), + migrations.AddField( + model_name='killhouse', + name='market_light_capacity', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='market_light_capacity_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 239632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 166381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 166381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 166381)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 166381)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 336581)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 336581)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 168130)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 168130)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 168130)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 18, 9, 40, 47, 183833)), + ), + ] diff --git a/panel/migrations/0564_auto_20250820_1145.py b/panel/migrations/0564_auto_20250820_1145.py new file mode 100644 index 0000000..3b94319 --- /dev/null +++ b/panel/migrations/0564_auto_20250820_1145.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-20 11:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0563_auto_20250818_0941'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='market_buying', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 264698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 328086)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 328086)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 201500)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 11, 45, 29, 217194)), + ), + ] diff --git a/panel/migrations/0565_auto_20250820_1530.py b/panel/migrations/0565_auto_20250820_1530.py new file mode 100644 index 0000000..b85a146 --- /dev/null +++ b/panel/migrations/0565_auto_20250820_1530.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-20 15:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0564_auto_20250820_1145'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='market_state_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 570780)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 510845)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 510845)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 510845)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 510845)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 650397)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 650397)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 513845)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 513845)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 513845)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 20, 15, 30, 35, 525448)), + ), + ] diff --git a/panel/migrations/0566_auto_20250825_1122.py b/panel/migrations/0566_auto_20250825_1122.py new file mode 100644 index 0000000..bff6fdc --- /dev/null +++ b/panel/migrations/0566_auto_20250825_1122.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-08-25 11:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0565_auto_20250820_1530'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='market_buying_limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killrequest', + name='market_expire_date_time', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 999969)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 938242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 938242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 938242)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 938242)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 37, 73788)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 37, 73788)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 942162)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 942162)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 942162)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 11, 22, 36, 954160)), + ), + ] diff --git a/panel/migrations/0567_auto_20250825_1535.py b/panel/migrations/0567_auto_20250825_1535.py new file mode 100644 index 0000000..8f6b37d --- /dev/null +++ b/panel/migrations/0567_auto_20250825_1535.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-25 15:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0566_auto_20250825_1122'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='market_buying_capacity_percent_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 849885)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 787312)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 787312)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 787312)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 787312)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 925219)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 925219)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 791175)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 791175)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 791175)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 15, 35, 17, 802175)), + ), + ] diff --git a/panel/migrations/0568_auto_20250825_1605.py b/panel/migrations/0568_auto_20250825_1605.py new file mode 100644 index 0000000..b892b8c --- /dev/null +++ b/panel/migrations/0568_auto_20250825_1605.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-25 16:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0567_auto_20250825_1535'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequest', + name='market', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 949376)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 41, 30350)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 41, 30350)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 885933)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 25, 16, 5, 40, 902063)), + ), + ] diff --git a/panel/migrations/0569_auto_20250826_0913.py b/panel/migrations/0569_auto_20250826_0913.py new file mode 100644 index 0000000..ef14b32 --- /dev/null +++ b/panel/migrations/0569_auto_20250826_0913.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-08-26 09:13 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0568_auto_20250825_1605'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 479237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 261691)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 261691)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 261691)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 261691)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 759890)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 759890)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 265693)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 265693)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 265693)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 12, 38, 294154)), + ), + migrations.CreateModel( + name='ShowMarketRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('start_time', models.TimeField(null=True)), + ('end_time', models.TimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='showmarketrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='showmarketrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0570_auto_20250826_0943.py b/panel/migrations/0570_auto_20250826_0943.py new file mode 100644 index 0000000..dd00f20 --- /dev/null +++ b/panel/migrations/0570_auto_20250826_0943.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-26 09:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0569_auto_20250826_0913'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='direct_buying_intermediary_mobile', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 179886)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 116466)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 116466)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 116466)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 116466)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 243083)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 243083)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 132242)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 132242)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 132242)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 26, 9, 43, 44, 132242)), + ), + ] diff --git a/panel/migrations/0571_auto_20250827_1013.py b/panel/migrations/0571_auto_20250827_1013.py new file mode 100644 index 0000000..0734c7c --- /dev/null +++ b/panel/migrations/0571_auto_20250827_1013.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-27 10:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0570_auto_20250826_0943'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='poultry_payment_limitation', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 280577)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 218560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 218560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 218560)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 218560)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 356242)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 356242)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 222614)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 221606)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 221606)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 10, 13, 15, 233640)), + ), + ] diff --git a/panel/migrations/0572_auto_20250827_1509.py b/panel/migrations/0572_auto_20250827_1509.py new file mode 100644 index 0000000..bbe473c --- /dev/null +++ b/panel/migrations/0572_auto_20250827_1509.py @@ -0,0 +1,92 @@ +# Generated by Django 3.2.13 on 2025-08-27 15:09 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0571_auto_20250827_1013'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 299175)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 220332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 220332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 220332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 220332)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 377318)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 377318)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 230305)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 230305)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 230305)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 27, 15, 8, 38, 245265)), + ), + migrations.CreateModel( + name='ManagementHatchingAgeRange', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('from_age', models.SmallIntegerField(default=0, max_length=3)), + ('to_age', models.SmallIntegerField(default=0, max_length=3)), + ('from_weight', models.FloatField(default=0)), + ('to_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='managementhatchingagerange_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='managementhatchingagerange_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0573_auto_20250829_0135.py b/panel/migrations/0573_auto_20250829_0135.py new file mode 100644 index 0000000..0aa9c4f --- /dev/null +++ b/panel/migrations/0573_auto_20250829_0135.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-29 01:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0572_auto_20250827_1509'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='input_market_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='market_code', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='killrequest', + name='market_code_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 908416)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 547043)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 542530)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 547043)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 542530)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 26, 436192)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 26, 436192)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 593424)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 593424)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 593424)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 29, 1, 34, 25, 667629)), + ), + ] diff --git a/panel/migrations/0574_auto_20250830_0839.py b/panel/migrations/0574_auto_20250830_0839.py new file mode 100644 index 0000000..135b17d --- /dev/null +++ b/panel/migrations/0574_auto_20250830_0839.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-08-30 08:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0573_auto_20250829_0135'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_kill_capacity_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 659969)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 497743)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 497743)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 497743)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 497743)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 757962)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 757962)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 501762)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 501762)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 501762)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 30, 8, 39, 18, 524234)), + ), + ] diff --git a/panel/migrations/0575_auto_20250831_0913.py b/panel/migrations/0575_auto_20250831_0913.py new file mode 100644 index 0000000..70ffaa6 --- /dev/null +++ b/panel/migrations/0575_auto_20250831_0913.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-08-31 09:13 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0574_auto_20250830_0839'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='free_quota', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='governmental_quota', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='quota', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 125108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 77789)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 77789)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 77789)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 77789)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 204546)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 204546)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 81801)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 81801)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 81801)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 8, 31, 9, 13, 1, 91826)), + ), + ] diff --git a/panel/migrations/0576_auto_20250901_0847.py b/panel/migrations/0576_auto_20250901_0847.py new file mode 100644 index 0000000..da8398d --- /dev/null +++ b/panel/migrations/0576_auto_20250901_0847.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-09-01 08:47 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0575_auto_20250831_0913'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 758000)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 219705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 219705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 219705)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 219705)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 856804)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 856804)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 223704)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 223704)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 223704)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 8, 47, 26, 236775)), + ), + migrations.CreateModel( + name='IndexWeightCategory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('min_value', models.FloatField(default=0)), + ('max_value', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='indexweightcategory_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='indexweightcategory_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0577_auto_20250901_1207.py b/panel/migrations/0577_auto_20250901_1207.py new file mode 100644 index 0000000..9520205 --- /dev/null +++ b/panel/migrations/0577_auto_20250901_1207.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-09-01 12:07 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0072_auto_20250901_1207'), + ('panel', '0576_auto_20250901_0847'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 733492)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 673537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 673537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 673537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 673537)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 807700)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 807700)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 676773)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 676773)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 676773)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 1, 12, 6, 58, 687744)), + ), + migrations.CreateModel( + name='PoultryScience', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryscience_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultryscience_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry', models.ManyToManyField(related_name='poultry_entries', to='panel.Poultry')), + ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_science_user', to='authentication.systemuserprofile')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0578_auto_20250902_1208.py b/panel/migrations/0578_auto_20250902_1208.py new file mode 100644 index 0000000..2176fc3 --- /dev/null +++ b/panel/migrations/0578_auto_20250902_1208.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-09-02 12:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0577_auto_20250901_1207'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='quota_custom', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='quota_custom_quantity', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='quota_max_kill_limit', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='quota_request', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 804899)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 874103)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 874103)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 741775)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 12, 8, 0, 757556)), + ), + ] diff --git a/panel/migrations/0579_auto_20250902_1540.py b/panel/migrations/0579_auto_20250902_1540.py new file mode 100644 index 0000000..de1ce13 --- /dev/null +++ b/panel/migrations/0579_auto_20250902_1540.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-02 15:40 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0578_auto_20250902_1208'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 825214)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 755793)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 755793)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 755793)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 755793)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 895647)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 895647)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 771740)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 771740)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 771740)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 2, 15, 40, 21, 771740)), + ), + migrations.CreateModel( + name='PoultryScienceReport', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('image', models.JSONField(null=True)), + ('lat', models.CharField(max_length=250, null=True)), + ('log', models.CharField(max_length=250, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultrysciencereport_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_science_hatching', to='panel.poultryhatching')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultrysciencereport_modifiedby', to=settings.AUTH_USER_MODEL)), + ('poultry_science', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_science_reporter', to='panel.poultryscience')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0580_auto_20250903_0907.py b/panel/migrations/0580_auto_20250903_0907.py new file mode 100644 index 0000000..a347564 --- /dev/null +++ b/panel/migrations/0580_auto_20250903_0907.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-09-03 09:07 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0579_auto_20250902_1540'), + ] + + operations = [ + migrations.AddField( + model_name='poultrysciencereport', + name='reporter_fullname', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='reporter_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 620948)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 519459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 519459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 519459)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 519459)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 745579)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 747592)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 524490)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 524490)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 524490)), + ), + migrations.AlterField( + model_name='poultrysciencereport', + name='lat', + field=models.FloatField(null=True), + ), + migrations.AlterField( + model_name='poultrysciencereport', + name='log', + field=models.FloatField(null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 3, 9, 6, 43, 540326)), + ), + ] diff --git a/panel/migrations/0581_auto_20250914_1103.py b/panel/migrations/0581_auto_20250914_1103.py new file mode 100644 index 0000000..ffd980a --- /dev/null +++ b/panel/migrations/0581_auto_20250914_1103.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-14 11:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0580_auto_20250903_0907'), + ] + + operations = [ + migrations.AddField( + model_name='finepermission', + name='end_time', + field=models.TimeField(null=True), + ), + migrations.AddField( + model_name='finepermission', + name='fine', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='finepermission', + name='fine_coefficient', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='finepermission', + name='name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='finepermission', + name='start_time', + field=models.TimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 863307)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 928495)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 928495)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 799680)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 11, 3, 25, 815759)), + ), + ] diff --git a/panel/migrations/0582_auto_20250914_1449.py b/panel/migrations/0582_auto_20250914_1449.py new file mode 100644 index 0000000..91a5241 --- /dev/null +++ b/panel/migrations/0582_auto_20250914_1449.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-14 14:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0581_auto_20250914_1103'), + ] + + operations = [ + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_message', + field=models.TextField(null=True), + ), + migrations.AddField( + model_name='bardifferencerequest', + name='register_message', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 868412)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 808380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 808380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 808380)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 808380)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 937416)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 937416)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 811380)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 811380)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 811380)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 14, 49, 21, 822411)), + ), + ] diff --git a/panel/migrations/0583_auto_20250914_1621.py b/panel/migrations/0583_auto_20250914_1621.py new file mode 100644 index 0000000..aa09e77 --- /dev/null +++ b/panel/migrations/0583_auto_20250914_1621.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-09-14 16:21 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0582_auto_20250914_1449'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 216537)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 148392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 148392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 148392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 148392)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 295416)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 295416)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 152655)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 152655)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 152655)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 21, 13, 164656)), + ), + migrations.CreateModel( + name='MarketPoultryRequestPermission', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('min_age_value', models.IntegerField(default=0)), + ('max_age_value', models.IntegerField(default=0)), + ('governmental_percent', models.FloatField(default=0)), + ('free_percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketpoultryrequestpermission_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketpoultryrequestpermission_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0584_auto_20250914_1630.py b/panel/migrations/0584_auto_20250914_1630.py new file mode 100644 index 0000000..5f1a0ac --- /dev/null +++ b/panel/migrations/0584_auto_20250914_1630.py @@ -0,0 +1,72 @@ +# Generated by Django 3.2.13 on 2025-09-14 16:30 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0583_auto_20250914_1621'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 242342)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 166581)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 166581)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 166581)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 166581)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 356112)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 356112)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 170582)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 170582)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 170582)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 14, 16, 30, 24, 183234)), + ), + migrations.DeleteModel( + name='MarketPoultryRequestPermission', + ), + ] diff --git a/panel/migrations/0585_auto_20250915_0902.py b/panel/migrations/0585_auto_20250915_0902.py new file mode 100644 index 0000000..d51847c --- /dev/null +++ b/panel/migrations/0585_auto_20250915_0902.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-15 09:02 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0584_auto_20250914_1630'), + ] + + operations = [ + migrations.AddField( + model_name='bardifferencerequest', + name='acceptor_image', + field=models.JSONField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 439706)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 378063)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 378063)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 378063)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 378063)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 510519)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 510519)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 382062)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 382062)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 382062)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 9, 2, 2, 394815)), + ), + ] diff --git a/panel/migrations/0586_auto_20250915_1411.py b/panel/migrations/0586_auto_20250915_1411.py new file mode 100644 index 0000000..35329dc --- /dev/null +++ b/panel/migrations/0586_auto_20250915_1411.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-15 14:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0585_auto_20250915_0902'), + ] + + operations = [ + migrations.CreateModel( + name='TokenEitaaForEachVet', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('token', models.CharField(max_length=250)), + ('vet_fullname', models.CharField(max_length=50)), + ('vet_mobile', models.CharField(max_length=11)), + ('grop_name', models.CharField(max_length=250)), + ], + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 201456)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 142194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 142194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 142194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 142194)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 274016)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 274016)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 145291)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 145291)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 145291)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 10, 40, 157269)), + ), + ] diff --git a/panel/migrations/0587_auto_20250915_1433.py b/panel/migrations/0587_auto_20250915_1433.py new file mode 100644 index 0000000..50d6bfa --- /dev/null +++ b/panel/migrations/0587_auto_20250915_1433.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-15 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0586_auto_20250915_1411'), + ] + + operations = [ + migrations.RenameField( + model_name='tokeneitaaforeachvet', + old_name='grop_name', + new_name='group_name', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 940225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 884804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 884804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 884804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 884804)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 13, 1686)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 13, 1686)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 886813)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 886813)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 886813)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 14, 33, 12, 898860)), + ), + ] diff --git a/panel/migrations/0588_auto_20250915_1603.py b/panel/migrations/0588_auto_20250915_1603.py new file mode 100644 index 0000000..5a5e1bf --- /dev/null +++ b/panel/migrations/0588_auto_20250915_1603.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-09-15 16:03 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0587_auto_20250915_1433'), + ] + + operations = [ + migrations.AddField( + model_name='possegmentation', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_segmentation', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 159972)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 100122)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 100122)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 100122)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 100122)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 230663)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 230663)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 103768)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 103768)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 103768)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 15, 16, 3, 37, 114846)), + ), + ] diff --git a/panel/migrations/0589_auto_20250916_0935.py b/panel/migrations/0589_auto_20250916_0935.py new file mode 100644 index 0000000..872a69d --- /dev/null +++ b/panel/migrations/0589_auto_20250916_0935.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-16 09:35 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0588_auto_20250915_1603'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='out_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='out_province_free_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='out_province_governmental_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='out_province_governmental_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='out_province_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 938573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 881160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 881160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 881160)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 881160)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 35, 7431)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 35, 7431)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 885173)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 885173)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 885173)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 9, 35, 34, 895205)), + ), + ] diff --git a/panel/migrations/0590_auto_20250916_1031.py b/panel/migrations/0590_auto_20250916_1031.py new file mode 100644 index 0000000..e41fbb9 --- /dev/null +++ b/panel/migrations/0590_auto_20250916_1031.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-16 10:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0589_auto_20250916_0935'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='sale_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 361220)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 308110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 308110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 308110)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 308110)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 436315)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 436315)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 310118)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 310118)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 310118)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 10, 31, 24, 322153)), + ), + ] diff --git a/panel/migrations/0591_auto_20250916_1427.py b/panel/migrations/0591_auto_20250916_1427.py new file mode 100644 index 0000000..3e4646b --- /dev/null +++ b/panel/migrations/0591_auto_20250916_1427.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-09-16 14:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0590_auto_20250916_1031'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='in_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='in_province_free_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='in_province_governmental_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='in_province_governmental_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='in_province_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 874690)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 812039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 812039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 812039)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 812039)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 949437)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 949437)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 816052)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 816052)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 816052)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 16, 14, 27, 1, 827074)), + ), + ] diff --git a/panel/migrations/0592_auto_20250920_0849.py b/panel/migrations/0592_auto_20250920_0849.py new file mode 100644 index 0000000..8ac53cc --- /dev/null +++ b/panel/migrations/0592_auto_20250920_0849.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-20 08:49 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0591_auto_20250916_1427'), + ] + + operations = [ + migrations.AddField( + model_name='poultrysciencereport', + name='state', + field=models.CharField(default='pending', max_length=50), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 859106)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 795659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 795659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 795659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 795659)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 922664)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 922664)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 811694)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 811694)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 811694)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 8, 49, 2, 811694)), + ), + ] diff --git a/panel/migrations/0592_auto_20250920_0938.py b/panel/migrations/0592_auto_20250920_0938.py new file mode 100644 index 0000000..67eba66 --- /dev/null +++ b/panel/migrations/0592_auto_20250920_0938.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-20 09:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0591_auto_20250916_1427'), + ] + + operations = [ + migrations.AddField( + model_name='rolesproducts', + name='province_free_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='province_governmental_allocated_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 290014)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 229293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 229293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 229293)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 229293)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 362812)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 362812)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 233528)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 233528)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 233528)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 9, 38, 12, 244155)), + ), + ] diff --git a/panel/migrations/0593_merge_0592_auto_20250920_0849_0592_auto_20250920_0938.py b/panel/migrations/0593_merge_0592_auto_20250920_0849_0592_auto_20250920_0938.py new file mode 100644 index 0000000..c683b9c --- /dev/null +++ b/panel/migrations/0593_merge_0592_auto_20250920_0849_0592_auto_20250920_0938.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.13 on 2025-09-20 12:57 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0592_auto_20250920_0849'), + ('panel', '0592_auto_20250920_0938'), + ] + + operations = [ + ] diff --git a/panel/migrations/0594_auto_20250920_1257.py b/panel/migrations/0594_auto_20250920_1257.py new file mode 100644 index 0000000..cad82dc --- /dev/null +++ b/panel/migrations/0594_auto_20250920_1257.py @@ -0,0 +1,82 @@ +# Generated by Django 3.2.13 on 2025-09-20 12:57 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0073_auto_20250920_1257'), + ('panel', '0593_merge_0592_auto_20250920_0849_0592_auto_20250920_0938'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 643388)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 556023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 556023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 556023)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 556023)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 819793)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 819793)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 560012)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 560012)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 560012)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 12, 57, 40, 571981)), + ), + migrations.CreateModel( + name='UserLoginLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('headers', models.JSONField(blank=True, null=True)), + ('ip_address', models.CharField(blank=True, max_length=500, null=True)), + ('user_agent', models.CharField(blank=True, max_length=500, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='login_logs_user', to='authentication.systemuserprofile')), + ], + ), + ] diff --git a/panel/migrations/0595_auto_20250920_1554.py b/panel/migrations/0595_auto_20250920_1554.py new file mode 100644 index 0000000..f69c75c --- /dev/null +++ b/panel/migrations/0595_auto_20250920_1554.py @@ -0,0 +1,113 @@ +# Generated by Django 3.2.13 on 2025-09-20 15:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0594_auto_20250920_1257'), + ] + + operations = [ + migrations.RemoveField( + model_name='killhouse', + name='in_province_free_selling_permission', + ), + migrations.RemoveField( + model_name='killhouse', + name='in_province_governmental_selling_permission', + ), + migrations.RemoveField( + model_name='killhouse', + name='in_province_selling_permission', + ), + migrations.RemoveField( + model_name='killhouse', + name='out_province_free_selling_permission', + ), + migrations.RemoveField( + model_name='killhouse', + name='out_province_governmental_selling_permission', + ), + migrations.RemoveField( + model_name='killhouse', + name='out_province_selling_permission', + ), + migrations.AddField( + model_name='killhouse', + name='free_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='governmental_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='segmentation_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='segmentation_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 27, 15262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 961971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 961971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 961971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 961971)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 27, 78519)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 27, 78519)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 963977)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 963977)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 963977)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 15, 53, 26, 967731)), + ), + ] diff --git a/panel/migrations/0595_auto_20250920_1648.py b/panel/migrations/0595_auto_20250920_1648.py new file mode 100644 index 0000000..ad1328d --- /dev/null +++ b/panel/migrations/0595_auto_20250920_1648.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-09-20 16:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0594_auto_20250920_1257'), + ] + + operations = [ + migrations.AddField( + model_name='poultrysciencereport', + name='message', + field=models.CharField(max_length=250, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='message_ai', + field=models.CharField(max_length=250, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='message_registerer_fullname', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='message_registerer_mobile', + field=models.CharField(max_length=11, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='real_quantity', + field=models.SmallIntegerField(null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='real_quantity_ai', + field=models.SmallIntegerField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 570823)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 521433)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 521433)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 521433)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 521433)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 644254)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 644254)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 523441)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 523441)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 523441)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 48, 30, 535487)), + ), + ] diff --git a/panel/migrations/0596_merge_0595_auto_20250920_1554_0595_auto_20250920_1648.py b/panel/migrations/0596_merge_0595_auto_20250920_1554_0595_auto_20250920_1648.py new file mode 100644 index 0000000..5b14a3a --- /dev/null +++ b/panel/migrations/0596_merge_0595_auto_20250920_1554_0595_auto_20250920_1648.py @@ -0,0 +1,14 @@ +# Generated by Django 3.2.13 on 2025-09-20 16:52 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0595_auto_20250920_1554'), + ('panel', '0595_auto_20250920_1648'), + ] + + operations = [ + ] diff --git a/panel/migrations/0597_auto_20250920_1652.py b/panel/migrations/0597_auto_20250920_1652.py new file mode 100644 index 0000000..5d73e75 --- /dev/null +++ b/panel/migrations/0597_auto_20250920_1652.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-20 16:52 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0596_merge_0595_auto_20250920_1554_0595_auto_20250920_1648'), + ] + + operations = [ + migrations.AddField( + model_name='poultrysciencereport', + name='message_registerer_role', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 773659)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 708253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 708253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 708253)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 708253)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 850774)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 850774)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 724280)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 724280)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 724280)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 20, 16, 52, 19, 724280)), + ), + ] diff --git a/panel/migrations/0598_auto_20250921_0848.py b/panel/migrations/0598_auto_20250921_0848.py new file mode 100644 index 0000000..e3ec7f2 --- /dev/null +++ b/panel/migrations/0598_auto_20250921_0848.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-21 08:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0597_auto_20250920_1652'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 4, 1804)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 954489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 954489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 954489)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 954489)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 4, 76929)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 4, 76929)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 958508)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 958508)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 958508)), + ), + migrations.AlterField( + model_name='poultrysciencereport', + name='real_quantity', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='poultrysciencereport', + name='real_quantity_ai', + field=models.IntegerField(null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 21, 8, 48, 3, 968547)), + ), + ] diff --git a/panel/migrations/0599_auto_20250922_0840.py b/panel/migrations/0599_auto_20250922_0840.py new file mode 100644 index 0000000..7dfa2c7 --- /dev/null +++ b/panel/migrations/0599_auto_20250922_0840.py @@ -0,0 +1,134 @@ +# Generated by Django 3.2.13 on 2025-09-22 08:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0598_auto_20250921_0848'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_input_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_input_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_input_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_remain_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_remain_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 102974)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 42392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 42392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 42392)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 42392)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 177691)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 177691)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 46219)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 46219)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 46219)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 8, 39, 51, 57955)), + ), + ] diff --git a/panel/migrations/0600_auto_20250922_1048.py b/panel/migrations/0600_auto_20250922_1048.py new file mode 100644 index 0000000..79df757 --- /dev/null +++ b/panel/migrations/0600_auto_20250922_1048.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-22 10:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0599_auto_20250922_0840'), + ] + + operations = [ + migrations.AddField( + model_name='possegmentation', + name='sale_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 131709)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 72605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 72605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 72605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 72605)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 203123)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 203123)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 75605)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 75605)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 75605)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 10, 48, 9, 87290)), + ), + ] diff --git a/panel/migrations/0601_auto_20250922_1333.py b/panel/migrations/0601_auto_20250922_1333.py new file mode 100644 index 0000000..94c0010 --- /dev/null +++ b/panel/migrations/0601_auto_20250922_1333.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2025-09-22 13:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0600_auto_20250922_1048'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_cold_house_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_in_province_free_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_in_province_governmental_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_out_province_buying_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_remain_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_segmentation_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_selling_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 696007)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 616809)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 616809)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 616809)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 616809)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 912395)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 912395)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 620826)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 620826)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 620826)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 32, 43, 633451)), + ), + ] diff --git a/panel/migrations/0602_auto_20250922_1339.py b/panel/migrations/0602_auto_20250922_1339.py new file mode 100644 index 0000000..301fb2f --- /dev/null +++ b/panel/migrations/0602_auto_20250922_1339.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-22 13:39 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0601_auto_20250922_1333'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_commitment_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 580722)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 643571)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 643571)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 518058)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 22, 13, 38, 49, 533696)), + ), + ] diff --git a/panel/migrations/0603_auto_20250924_1347.py b/panel/migrations/0603_auto_20250924_1347.py new file mode 100644 index 0000000..9d5b6a1 --- /dev/null +++ b/panel/migrations/0603_auto_20250924_1347.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-09-24 13:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0602_auto_20250922_1339'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='quota', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='possegmentation', + name='quota', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='quota', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 19, 596291)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 350108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 350108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 350108)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 350108)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 20, 557163)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 20, 557163)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 354127)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 354127)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 354127)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 13, 46, 18, 367951)), + ), + ] diff --git a/panel/migrations/0604_auto_20250924_1427.py b/panel/migrations/0604_auto_20250924_1427.py new file mode 100644 index 0000000..a812f39 --- /dev/null +++ b/panel/migrations/0604_auto_20250924_1427.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-09-24 14:27 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0603_auto_20250924_1347'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='killhouserequest', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='possegmentation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='provincekillrequest', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 825104)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 904733)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 904733)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 777273)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 24, 14, 26, 59, 793392)), + ), + ] diff --git a/panel/migrations/0605_auto_20250925_1046.py b/panel/migrations/0605_auto_20250925_1046.py new file mode 100644 index 0000000..b2f7c9f --- /dev/null +++ b/panel/migrations/0605_auto_20250925_1046.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-25 10:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0604_auto_20250924_1427'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='free_sale_form_governmental_quota', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 55, 28362)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 865276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 865276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 865276)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 865276)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 55, 215861)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 55, 215861)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 880901)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 880901)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 880901)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 10, 45, 54, 912145)), + ), + ] diff --git a/panel/migrations/0606_auto_20250925_1108.py b/panel/migrations/0606_auto_20250925_1108.py new file mode 100644 index 0000000..bf61ce3 --- /dev/null +++ b/panel/migrations/0606_auto_20250925_1108.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-25 11:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0605_auto_20250925_1046'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='cold_house_free_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='cold_house_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 987332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 831083)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 831083)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 831083)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 831083)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 38, 181051)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 38, 181051)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 846708)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 846708)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 846708)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 11, 7, 37, 877958)), + ), + ] diff --git a/panel/migrations/0607_auto_20250925_1345.py b/panel/migrations/0607_auto_20250925_1345.py new file mode 100644 index 0000000..407811b --- /dev/null +++ b/panel/migrations/0607_auto_20250925_1345.py @@ -0,0 +1,129 @@ +# Generated by Django 3.2.13 on 2025-09-25 13:45 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0606_auto_20250925_1108'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='out_province_free_buying_commitment_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='warehouse_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouserequest', + name='warehouse_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 479946)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 573696)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 573696)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 401813)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 13, 44, 52, 417436)), + ), + ] diff --git a/panel/migrations/0608_auto_20250925_1422.py b/panel/migrations/0608_auto_20250925_1422.py new file mode 100644 index 0000000..aed41a5 --- /dev/null +++ b/panel/migrations/0608_auto_20250925_1422.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-09-25 14:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0607_auto_20250925_1345'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_in_province_free_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_in_province_governmental_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_out_province_buying_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 535811)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 870337)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 870337)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 200034)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 14, 21, 46, 262535)), + ), + ] diff --git a/panel/migrations/0609_auto_20250925_1501.py b/panel/migrations/0609_auto_20250925_1501.py new file mode 100644 index 0000000..fbd70d7 --- /dev/null +++ b/panel/migrations/0609_auto_20250925_1501.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-25 15:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0608_auto_20250925_1422'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_in_province_free_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='total_commitment_selling_in_province_governmental_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 351378)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 242003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 242003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 242003)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 242003)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 481337)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 481337)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 257627)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 257627)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 257627)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 25, 15, 0, 34, 273252)), + ), + ] diff --git a/panel/migrations/0610_auto_20250927_2016.py b/panel/migrations/0610_auto_20250927_2016.py new file mode 100644 index 0000000..33bf94f --- /dev/null +++ b/panel/migrations/0610_auto_20250927_2016.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0609_auto_20250925_1501'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='payment_deadline_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 919090)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 856377)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 856377)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 856377)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 856377)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 986702)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 986702)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 863611)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 863611)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 863611)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 16, 1, 863611)), + ), + ] diff --git a/panel/migrations/0611_auto_20250927_2020.py b/panel/migrations/0611_auto_20250927_2020.py new file mode 100644 index 0000000..21f06ab --- /dev/null +++ b/panel/migrations/0611_auto_20250927_2020.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:20 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0610_auto_20250927_2016'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 769159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 711971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 711971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 711971)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 711971)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 834274)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 834274)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 713978)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 713978)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 713978)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 19, 52, 725523)), + ), + migrations.CreateModel( + name='AllowRegisterCodeForStewardAllocation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforstewardallocation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforstewardallocation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0612_auto_20250927_2024.py b/panel/migrations/0612_auto_20250927_2024.py new file mode 100644 index 0000000..944ce7f --- /dev/null +++ b/panel/migrations/0612_auto_20250927_2024.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0611_auto_20250927_2020'), + ] + + operations = [ + migrations.RenameField( + model_name='stewardallocation', + old_name='payment_deadline_date', + new_name='expire_date_time_registration_code', + ), + migrations.AddField( + model_name='allowregistercodeforstewardallocation', + name='time', + field=models.CharField(max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 201652)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 456453)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 456453)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 134266)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 24, 3, 154243)), + ), + ] diff --git a/panel/migrations/0613_auto_20250927_2026.py b/panel/migrations/0613_auto_20250927_2026.py new file mode 100644 index 0000000..21bf6a5 --- /dev/null +++ b/panel/migrations/0613_auto_20250927_2026.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:26 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0612_auto_20250927_2024'), + ] + + operations = [ + migrations.RenameField( + model_name='allowregistercodeforstewardallocation', + old_name='allow', + new_name='active', + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 52, 76001)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 935740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 935740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 935740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 935740)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 52, 255944)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 52, 255944)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 939758)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 939758)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 939758)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 25, 51, 953563)), + ), + ] diff --git a/panel/migrations/0614_auto_20250927_2028.py b/panel/migrations/0614_auto_20250927_2028.py new file mode 100644 index 0000000..3ea969d --- /dev/null +++ b/panel/migrations/0614_auto_20250927_2028.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:28 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0613_auto_20250927_2026'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='active_expire_date_time', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 400725)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 321689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 321689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 321689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 321689)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 493839)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 493839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 331733)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 331733)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 331733)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 28, 2, 345538)), + ), + ] diff --git a/panel/migrations/0615_auto_20250927_2041.py b/panel/migrations/0615_auto_20250927_2041.py new file mode 100644 index 0000000..a8ca4dd --- /dev/null +++ b/panel/migrations/0615_auto_20250927_2041.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-27 20:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0614_auto_20250927_2028'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='interface_number', + field=models.CharField(max_length=11, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 352777)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 472020)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 472020)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 289245)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 27, 20, 41, 27, 315417)), + ), + ] diff --git a/panel/migrations/0616_auto_20250929_1505.py b/panel/migrations/0616_auto_20250929_1505.py new file mode 100644 index 0000000..9390028 --- /dev/null +++ b/panel/migrations/0616_auto_20250929_1505.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-29 15:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0615_auto_20250927_2041'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='free_sale_from_free_quota_in_province', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 686330)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 267332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 267332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 267332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 267332)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 26, 206328)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 26, 206328)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 279331)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 279331)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 279331)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 15, 4, 25, 312330)), + ), + ] diff --git a/panel/migrations/0617_auto_20250929_1856.py b/panel/migrations/0617_auto_20250929_1856.py new file mode 100644 index 0000000..847b122 --- /dev/null +++ b/panel/migrations/0617_auto_20250929_1856.py @@ -0,0 +1,106 @@ +# Generated by Django 3.2.13 on 2025-09-29 18:56 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0616_auto_20250929_1505'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='active_register_code', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='logged_register_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='guilds', + name='register_code', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 506219)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 405222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 405222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 405222)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 405222)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 689605)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 689605)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 410215)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 410215)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 410215)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 18, 55, 36, 429222)), + ), + migrations.CreateModel( + name='AllowRegisterCodeForGuilds', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('time', models.CharField(max_length=50, null=True)), + ('has_time', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforguilds_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforguilds_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0618_auto_20250929_1900.py b/panel/migrations/0618_auto_20250929_1900.py new file mode 100644 index 0000000..75a5c9e --- /dev/null +++ b/panel/migrations/0618_auto_20250929_1900.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-29 19:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0617_auto_20250929_1856'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='expire_time_register_code', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 371159)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 235268)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 235268)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 235268)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 235268)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 471449)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 471449)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 238753)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 238753)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 238753)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 29, 19, 0, 36, 253273)), + ), + ] diff --git a/panel/migrations/0619_auto_20250930_1003.py b/panel/migrations/0619_auto_20250930_1003.py new file mode 100644 index 0000000..b2ec636 --- /dev/null +++ b/panel/migrations/0619_auto_20250930_1003.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-30 10:03 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0618_auto_20250929_1900'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='register_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 358573)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 293048)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 293048)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 293048)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 293048)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 437002)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 437002)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 297054)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 297054)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 297054)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 10, 3, 21, 311042)), + ), + ] diff --git a/panel/migrations/0620_auto_20250930_1118.py b/panel/migrations/0620_auto_20250930_1118.py new file mode 100644 index 0000000..7b7b9aa --- /dev/null +++ b/panel/migrations/0620_auto_20250930_1118.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-09-30 11:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0619_auto_20250930_1003'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='register_date_register_code', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 498959)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 424521)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 422309)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 422309)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 422309)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 588423)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 588423)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 426524)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 426524)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 426524)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 9, 30, 11, 17, 43, 442520)), + ), + ] diff --git a/panel/migrations/0621_auto_20251001_1123.py b/panel/migrations/0621_auto_20251001_1123.py new file mode 100644 index 0000000..e920e4a --- /dev/null +++ b/panel/migrations/0621_auto_20251001_1123.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-01 11:23 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0620_auto_20250930_1118'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='is_registered', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 782700)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 728701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 728701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 728701)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 728701)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 844700)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 844700)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 731701)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 731701)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 731701)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 1, 11, 23, 29, 741700)), + ), + ] diff --git a/panel/migrations/0622_auto_20251004_1105.py b/panel/migrations/0622_auto_20251004_1105.py new file mode 100644 index 0000000..0e63cba --- /dev/null +++ b/panel/migrations/0622_auto_20251004_1105.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-10-04 11:05 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0621_auto_20251001_1123'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='input_warehouse', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_input_warehouse', to='panel.killhouse'), + ), + migrations.AddField( + model_name='killhouserequest', + name='input_warehouse', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_input_warehouse', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 701514)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 775134)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 775134)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 646111)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 4, 11, 5, 3, 661603)), + ), + ] diff --git a/panel/migrations/0623_auto_20251005_1416.py b/panel/migrations/0623_auto_20251005_1416.py new file mode 100644 index 0000000..bec7dd0 --- /dev/null +++ b/panel/migrations/0623_auto_20251005_1416.py @@ -0,0 +1,390 @@ +# Generated by Django 3.2.13 on 2025-10-05 14:16 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0622_auto_20251004_1105'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='cold_house_free_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='cold_house_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='free_sale_form_governmental_quota', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='free_sale_from_free_quota_in_province', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='free_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='governmental_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='in_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='in_province_governmental_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='out_province_free_buying_commitment_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='out_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='out_province_governmental_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='segmentation_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='segmentation_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_cold_house_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_in_province_free_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_in_province_governmental_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_commitment_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_in_province_free_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_in_province_free_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_in_province_governmental_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_in_province_governmental_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_input_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_input_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_input_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_out_province_buying_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_out_province_buying_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_remain_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_remain_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_remain_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_segmentation_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='total_selling_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 613503)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 692181)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 692181)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 546562)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 5, 14, 16, 1, 571467)), + ), + migrations.CreateModel( + name='GuildsGeneralConfigs', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('activator', models.CharField(max_length=200, null=True)), + ('out_province_governmental_selling_percent', models.FloatField(default=0)), + ('out_province_free_selling_percent', models.FloatField(default=0)), + ('out_province_free_buying_commitment_percent', models.FloatField(default=0)), + ('in_province_governmental_selling_percent', models.FloatField(default=0)), + ('in_province_free_selling_percent', models.FloatField(default=0)), + ('segmentation_governmental_percent', models.FloatField(default=0)), + ('segmentation_free_selling_percent', models.FloatField(default=0)), + ('cold_house_governmental_percent', models.FloatField(default=0)), + ('cold_house_free_percent', models.FloatField(default=0)), + ('governmental_selling_permission', models.BooleanField(default=False)), + ('free_selling_permission', models.BooleanField(default=False)), + ('free_sale_form_governmental_quota', models.BooleanField(default=False)), + ('free_sale_from_free_quota_in_province', models.BooleanField(default=False)), + ('total_input_warehouse_weight', models.FloatField(default=0)), + ('total_input_warehouse_governmental_weight', models.FloatField(default=0)), + ('total_input_warehouse_free_weight', models.FloatField(default=0)), + ('total_selling_warehouse_governmental_weight', models.FloatField(default=0)), + ('total_selling_warehouse_free_weight', models.FloatField(default=0)), + ('total_remain_warehouse_governmental_weight', models.FloatField(default=0)), + ('total_remain_warehouse_free_weight', models.FloatField(default=0)), + ('total_remain_warehouse_weight', models.FloatField(default=0)), + ('total_selling_in_province_governmental_weight', models.FloatField(default=0)), + ('total_selling_in_province_free_weight', models.FloatField(default=0)), + ('total_selling_out_province_governmental_weight', models.FloatField(default=0)), + ('total_selling_out_province_free_weight', models.FloatField(default=0)), + ('total_segmentation_governmental_weight', models.FloatField(default=0)), + ('total_segmentation_free_weight', models.FloatField(default=0)), + ('total_in_province_governmental_bars_weight', models.FloatField(default=0)), + ('total_in_province_free_bars_weight', models.FloatField(default=0)), + ('total_out_province_buying_bars_weight', models.FloatField(default=0)), + ('total_selling_warehouse_weight', models.FloatField(default=0)), + ('total_segmentation_weight', models.FloatField(default=0)), + ('total_cold_house_weight', models.FloatField(default=0)), + ('total_cold_house_governmental_weight', models.FloatField(default=0)), + ('total_cold_house_free_weight', models.FloatField(default=0)), + ('total_commitment_governmental_weight', models.FloatField(default=0)), + ('total_commitment_free_weight', models.FloatField(default=0)), + ('total_in_province_governmental_bars_commitment_weight', models.FloatField(default=0)), + ('total_in_province_free_bars_commitment_weight', models.FloatField(default=0)), + ('total_out_province_buying_bars_commitment_weight', models.FloatField(default=0)), + ('total_commitment_selling_in_province_governmental_weight', models.FloatField(default=0)), + ('total_commitment_selling_in_province_free_weight', models.FloatField(default=0)), + ('total_commitment_selling_in_province_governmental_remain_weight', models.FloatField(default=0)), + ('total_commitment_selling_in_province_free_remain_weight', models.FloatField(default=0)), + ('total_commitment_selling_out_province_governmental_weight', models.FloatField(default=0)), + ('total_commitment_selling_out_province_free_weight', models.FloatField(default=0)), + ('total_commitment_cold_house_governmental_weight', models.FloatField(default=0)), + ('total_commitment_cold_house_free_weight', models.FloatField(default=0)), + ('total_commitment_segmentation_governmental_weight', models.FloatField(default=0)), + ('total_commitment_segmentation_free_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildsgeneralconfigs_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildsgeneralconfigs_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0624_auto_20251006_0847.py b/panel/migrations/0624_auto_20251006_0847.py new file mode 100644 index 0000000..accf0aa --- /dev/null +++ b/panel/migrations/0624_auto_20251006_0847.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-06 08:47 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0623_auto_20251005_1416'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreebarinformation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 420961)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 362561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 362561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 362561)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 362561)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 490832)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 490832)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 365552)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 365552)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 365552)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 8, 47, 27, 376105)), + ), + ] diff --git a/panel/migrations/0625_auto_20251006_0905.py b/panel/migrations/0625_auto_20251006_0905.py new file mode 100644 index 0000000..59dd57e --- /dev/null +++ b/panel/migrations/0625_auto_20251006_0905.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-06 09:05 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0624_auto_20251006_0847'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreebarinformation', + name='quota', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='quota', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 43, 16386)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 957682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 957682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 957682)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 957682)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 43, 88542)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 43, 88542)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 960783)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 960783)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 960783)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 9, 5, 42, 971751)), + ), + ] diff --git a/panel/migrations/0626_auto_20251006_1457.py b/panel/migrations/0626_auto_20251006_1457.py new file mode 100644 index 0000000..60afef9 --- /dev/null +++ b/panel/migrations/0626_auto_20251006_1457.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-06 14:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0625_auto_20251006_0905'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='return_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 516113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 447500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 447500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 447500)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 447500)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 673245)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 673245)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 449504)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 449504)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 449504)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 14, 56, 39, 464089)), + ), + ] diff --git a/panel/migrations/0627_auto_20251006_1554.py b/panel/migrations/0627_auto_20251006_1554.py new file mode 100644 index 0000000..88e8444 --- /dev/null +++ b/panel/migrations/0627_auto_20251006_1554.py @@ -0,0 +1,101 @@ +# Generated by Django 3.2.13 on 2025-10-06 15:54 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0626_auto_20251006_1457'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='return_trash_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='returner_trash', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 607296)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 703294)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 703294)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 544352)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 6, 15, 54, 18, 559983)), + ), + migrations.CreateModel( + name='StewardAppLogin', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('device_name', models.CharField(max_length=200, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardapplogin_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardapplogin_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_login', to='panel.guilds')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0628_auto_20251007_1220.py b/panel/migrations/0628_auto_20251007_1220.py new file mode 100644 index 0000000..980124f --- /dev/null +++ b/panel/migrations/0628_auto_20251007_1220.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-07 12:20 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0627_auto_20251006_1554'), + ] + + operations = [ + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='sale_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 110869)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 51788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 51788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 51788)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 51788)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 180340)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 180340)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 57084)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 57084)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 57084)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 12, 20, 28, 67662)), + ), + ] diff --git a/panel/migrations/0629_auto_20251007_1443.py b/panel/migrations/0629_auto_20251007_1443.py new file mode 100644 index 0000000..e199467 --- /dev/null +++ b/panel/migrations/0629_auto_20251007_1443.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-07 14:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0628_auto_20251007_1220'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='steward_warehouse', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 403817)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 116366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 116366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 116366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 116366)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 690994)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 690994)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 120355)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 120355)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 120355)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 14, 43, 33, 148709)), + ), + ] diff --git a/panel/migrations/0630_auto_20251007_1546.py b/panel/migrations/0630_auto_20251007_1546.py new file mode 100644 index 0000000..f61594b --- /dev/null +++ b/panel/migrations/0630_auto_20251007_1546.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-07 15:46 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0629_auto_20251007_1443'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='expire_time_ten_minute', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 64713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 3976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 3976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 3976)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 3976)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 138216)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 138216)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 7033)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 7033)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 7033)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 7, 15, 46, 9, 18391)), + ), + ] diff --git a/panel/migrations/0631_auto_20251008_1014.py b/panel/migrations/0631_auto_20251008_1014.py new file mode 100644 index 0000000..f7e7e28 --- /dev/null +++ b/panel/migrations/0631_auto_20251008_1014.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-08 10:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0630_auto_20251007_1546'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='return_trash', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='provincekillrequest', + name='return_trash', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 789867)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 730570)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 730570)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 730570)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 730570)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 864871)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 864871)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 733669)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 733669)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 733669)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 8, 10, 13, 57, 744483)), + ), + ] diff --git a/panel/migrations/0632_auto_20251012_1433.py b/panel/migrations/0632_auto_20251012_1433.py new file mode 100644 index 0000000..28f4cea --- /dev/null +++ b/panel/migrations/0632_auto_20251012_1433.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-12 14:33 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0631_auto_20251008_1014'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='maximum_load_volume_increase', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='maximum_load_volume_reduction', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 867819)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 705366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 704271)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 705366)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 704271)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 5, 72514)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 5, 72514)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 708358)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 708358)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 708358)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 12, 14, 33, 4, 771072)), + ), + ] diff --git a/panel/migrations/0633_auto_20251018_2111.py b/panel/migrations/0633_auto_20251018_2111.py new file mode 100644 index 0000000..df3882e --- /dev/null +++ b/panel/migrations/0633_auto_20251018_2111.py @@ -0,0 +1,96 @@ +# Generated by Django 3.2.13 on 2025-10-18 21:11 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0632_auto_20251012_1433'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 746369)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 684373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 684373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 684373)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 684373)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 825405)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 825405)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 688365)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 688365)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 688365)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 18, 21, 11, 28, 700365)), + ), + migrations.CreateModel( + name='StewardRequest', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('quantity', models.IntegerField(default=0)), + ('weight', models.IntegerField(default=0)), + ('state', models.CharField(default='pending', max_length=50)), + ('registerer', models.CharField(max_length=250, null=True)), + ('registerer_mobile', models.CharField(max_length=250, null=True)), + ('registerer_role', models.CharField(max_length=250, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardrequest_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='stewardrequest_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_request', to='panel.guilds')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0634_auto_20251021_1331.py b/panel/migrations/0634_auto_20251021_1331.py new file mode 100644 index 0000000..140fb0f --- /dev/null +++ b/panel/migrations/0634_auto_20251021_1331.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2025-10-21 13:31 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0633_auto_20251018_2111'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 167071)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 246938)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 246938)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 119669)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 13, 30, 54, 135359)), + ), + migrations.CreateModel( + name='RestrictionCarcassDistribution', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('allow', models.BooleanField(default=False)), + ('time', models.TimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='restrictioncarcassdistribution_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='restrictioncarcassdistribution_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0635_auto_20251021_1408.py b/panel/migrations/0635_auto_20251021_1408.py new file mode 100644 index 0000000..c4018f0 --- /dev/null +++ b/panel/migrations/0635_auto_20251021_1408.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-21 14:08 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0634_auto_20251021_1331'), + ] + + operations = [ + migrations.AddField( + model_name='restrictioncarcassdistribution', + name='distribution_type', + field=models.CharField(default='KillHouse', max_length=50), + ), + migrations.AddField( + model_name='restrictioncarcassdistribution', + name='out', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 212632)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 153437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 153437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 153437)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 153437)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 289655)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 289655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 156272)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 156272)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 156272)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 8, 5, 167631)), + ), + ] diff --git a/panel/migrations/0636_auto_20251021_1424.py b/panel/migrations/0636_auto_20251021_1424.py new file mode 100644 index 0000000..16ecdf9 --- /dev/null +++ b/panel/migrations/0636_auto_20251021_1424.py @@ -0,0 +1,89 @@ +# Generated by Django 3.2.13 on 2025-10-21 14:24 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0635_auto_20251021_1408'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='ware_house_remaining_percent_limitation', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_remaining_percent_limitation_status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_remaining_weight_limitation', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_remaining_weight_limitation_status', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 50, 959569)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 842514)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 842514)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 842514)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 842514)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 51, 629552)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 51, 629552)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 846532)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 846532)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 49, 846532)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 14, 23, 50, 71797)), + ), + ] diff --git a/panel/migrations/0637_auto_20251021_1531.py b/panel/migrations/0637_auto_20251021_1531.py new file mode 100644 index 0000000..163fc50 --- /dev/null +++ b/panel/migrations/0637_auto_20251021_1531.py @@ -0,0 +1,129 @@ +# Generated by Django 3.2.13 on 2025-10-21 15:31 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0636_auto_20251021_1424'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='active_expire_date_time', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='expire_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='logged_registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='register_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='system_registration_code', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='active_expire_date_time', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='expire_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='logged_registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='register_date_time_registration_code', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='registration_code', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='system_registration_code', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 275693)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 217091)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 217091)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 217091)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 217091)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 347575)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 347575)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 220083)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 220083)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 220083)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 31, 35, 231426)), + ), + ] diff --git a/panel/migrations/0638_auto_20251021_1541.py b/panel/migrations/0638_auto_20251021_1541.py new file mode 100644 index 0000000..49e424a --- /dev/null +++ b/panel/migrations/0638_auto_20251021_1541.py @@ -0,0 +1,107 @@ +# Generated by Django 3.2.13 on 2025-10-21 15:41 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0637_auto_20251021_1531'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 478605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 353081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 352084)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 353081)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 352084)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 563809)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 563809)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 356074)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 356074)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 356074)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 21, 15, 40, 57, 369039)), + ), + migrations.CreateModel( + name='AllowRegisterCodeForStewardFreeSaleBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('time', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforstewardfreesalebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforstewardfreesalebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='AllowRegisterCodeForKillHouseFreeSaleBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('time', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforkillhousefreesalebarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allowregistercodeforkillhousefreesalebarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0639_auto_20251022_1518.py b/panel/migrations/0639_auto_20251022_1518.py new file mode 100644 index 0000000..914607e --- /dev/null +++ b/panel/migrations/0639_auto_20251022_1518.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-22 15:18 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0638_auto_20251021_1541'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='expire_time_ten_minute', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='expire_time_ten_minute', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 585673)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 524375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 524375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 524375)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 524375)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 669375)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 669375)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 527472)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 527472)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 527472)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 22, 15, 17, 54, 539125)), + ), + ] diff --git a/panel/migrations/0640_auto_20251025_1110.py b/panel/migrations/0640_auto_20251025_1110.py new file mode 100644 index 0000000..fe14d72 --- /dev/null +++ b/panel/migrations/0640_auto_20251025_1110.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-10-25 11:10 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0639_auto_20251022_1518'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='production_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='possegmentation', + name='production_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='distribution_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='stewardallocation', + name='production_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='production_date', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 340193)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 421445)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 421445)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 292663)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 10, 22, 308447)), + ), + ] diff --git a/panel/migrations/0641_auto_20251025_1116.py b/panel/migrations/0641_auto_20251025_1116.py new file mode 100644 index 0000000..3e97418 --- /dev/null +++ b/panel/migrations/0641_auto_20251025_1116.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-10-25 11:16 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0640_auto_20251025_1110'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='distribution_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='possegmentation', + name='distribution_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='distribution_type', + field=models.CharField(max_length=20, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 813258)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 754133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 754133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 754133)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 754133)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 884428)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 884428)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 756139)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 756139)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 756139)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 25, 11, 15, 55, 767913)), + ), + ] diff --git a/panel/migrations/0642_auto_20251026_1719.py b/panel/migrations/0642_auto_20251026_1719.py new file mode 100644 index 0000000..a1041aa --- /dev/null +++ b/panel/migrations/0642_auto_20251026_1719.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-26 17:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0641_auto_20251025_1116'), + ] + + operations = [ + migrations.AddField( + model_name='stewardallocation', + name='Settlement_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 18, 56237)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 948829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 948829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 948829)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 948829)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 18, 195330)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 18, 195330)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 954359)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 954359)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 954359)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 17, 19, 17, 973417)), + ), + ] diff --git a/panel/migrations/0643_auto_20251026_2043.py b/panel/migrations/0643_auto_20251026_2043.py new file mode 100644 index 0000000..248e0a3 --- /dev/null +++ b/panel/migrations/0643_auto_20251026_2043.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-26 20:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0642_auto_20251026_1719'), + ] + + operations = [ + migrations.AddField( + model_name='killrequest', + name='expire_time_ten_minute', + field=models.DateTimeField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 48, 27713)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 973679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 973679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 973679)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 973679)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 48, 91712)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 48, 91712)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 976703)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 976703)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 976703)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 42, 47, 986713)), + ), + ] diff --git a/panel/migrations/0644_auto_20251026_2048.py b/panel/migrations/0644_auto_20251026_2048.py new file mode 100644 index 0000000..5169c3f --- /dev/null +++ b/panel/migrations/0644_auto_20251026_2048.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-10-26 20:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0643_auto_20251026_2043'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 537781)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 481603)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 481603)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 481603)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 481603)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 605814)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 605814)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 484813)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 484813)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 484813)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 26, 20, 48, 12, 494813)), + ), + ] diff --git a/panel/migrations/0645_auto_20251027_0917.py b/panel/migrations/0645_auto_20251027_0917.py new file mode 100644 index 0000000..66fae4c --- /dev/null +++ b/panel/migrations/0645_auto_20251027_0917.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-10-27 09:17 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0644_auto_20251026_2048'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='pos_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='pos_free_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='pos_governmental_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='pos_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='pos_free_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='pos_governmental_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 928698)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 48, 3628)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 48, 3628)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 867263)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 9, 16, 47, 877126)), + ), + ] diff --git a/panel/migrations/0646_auto_20251027_1215.py b/panel/migrations/0646_auto_20251027_1215.py new file mode 100644 index 0000000..7ca90b8 --- /dev/null +++ b/panel/migrations/0646_auto_20251027_1215.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-27 12:15 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0645_auto_20251027_0917'), + ] + + operations = [ + migrations.AddField( + model_name='productstransactions', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 715300)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 650085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 650085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 650085)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 650085)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 791209)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 791209)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 653086)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 653086)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 653086)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 27, 12, 14, 48, 664749)), + ), + ] diff --git a/panel/migrations/0647_auto_20251028_0856.py b/panel/migrations/0647_auto_20251028_0856.py new file mode 100644 index 0000000..25f0afb --- /dev/null +++ b/panel/migrations/0647_auto_20251028_0856.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-28 08:56 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0646_auto_20251027_1215'), + ] + + operations = [ + migrations.AddField( + model_name='poultryrequestquarantinecode', + name='trafic_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 727806)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 665805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 665805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 665805)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 665805)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 799279)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 799279)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 667805)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 667805)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 667805)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 55, 52, 679808)), + ), + ] diff --git a/panel/migrations/0648_auto_20251028_0857.py b/panel/migrations/0648_auto_20251028_0857.py new file mode 100644 index 0000000..d3100dc --- /dev/null +++ b/panel/migrations/0648_auto_20251028_0857.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-10-28 08:57 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0647_auto_20251028_0856'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 16, 20073)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 16, 98221)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 16, 98221)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 955399)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 8, 57, 15, 975873)), + ), + ] diff --git a/panel/migrations/0649_auto_20251028_0940.py b/panel/migrations/0649_auto_20251028_0940.py new file mode 100644 index 0000000..d7c1ce7 --- /dev/null +++ b/panel/migrations/0649_auto_20251028_0940.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-10-28 09:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0648_auto_20251028_0857'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 753855)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 691354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 691354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 691354)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 691354)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 823825)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 823825)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 706981)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 706981)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 706981)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 9, 40, 1, 706981)), + ), + ] diff --git a/panel/migrations/0650_rename_trafic_to_traffic_code.py b/panel/migrations/0650_rename_trafic_to_traffic_code.py new file mode 100644 index 0000000..e670b28 --- /dev/null +++ b/panel/migrations/0650_rename_trafic_to_traffic_code.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2025-10-28 09:55 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0649_auto_20251028_0940'), + ] + + operations = [ + migrations.RenameField( + model_name='poultryrequestquarantinecode', + old_name='trafic_code', + new_name='traffic_code', + ), + ] diff --git a/panel/migrations/0651_auto_20251028_1219.py b/panel/migrations/0651_auto_20251028_1219.py new file mode 100644 index 0000000..9a2b189 --- /dev/null +++ b/panel/migrations/0651_auto_20251028_1219.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-10-28 12:19 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0650_rename_trafic_to_traffic_code'), + ] + + operations = [ + migrations.AddField( + model_name='killhouserequest', + name='amount', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 983589)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 874509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 874509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 874509)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 874509)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 58, 73551)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 58, 73551)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 880015)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 880015)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 880015)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 28, 12, 18, 57, 891657)), + ), + ] diff --git a/panel/migrations/0652_auto_20251029_0933.py b/panel/migrations/0652_auto_20251029_0933.py new file mode 100644 index 0000000..3ba1ccf --- /dev/null +++ b/panel/migrations/0652_auto_20251029_0933.py @@ -0,0 +1,90 @@ +# Generated by Django 3.2.13 on 2025-10-29 09:33 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0651_auto_20251028_1219'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 172197)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 234696)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 234696)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 125319)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 32, 55, 140947)), + ), + migrations.CreateModel( + name='LimitationForDirectPurchaseAndBarInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('time', models.CharField(max_length=50, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='limitationfordirectpurchaseandbarinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='limitationfordirectpurchaseandbarinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0653_auto_20251029_0954.py b/panel/migrations/0653_auto_20251029_0954.py new file mode 100644 index 0000000..feec52e --- /dev/null +++ b/panel/migrations/0653_auto_20251029_0954.py @@ -0,0 +1,83 @@ +# Generated by Django 3.2.13 on 2025-10-29 09:54 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0652_auto_20251029_0933'), + ] + + operations = [ + migrations.RemoveField( + model_name='limitationfordirectpurchaseandbarinformation', + name='time', + ), + migrations.AddField( + model_name='limitationfordirectpurchaseandbarinformation', + name='end_time', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='limitationfordirectpurchaseandbarinformation', + name='start_time', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 718954)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 626320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 626320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 626320)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 626320)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 860332)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 860332)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 630318)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 630318)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 630318)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 53, 56, 647317)), + ), + ] diff --git a/panel/migrations/0654_auto_20251029_0955.py b/panel/migrations/0654_auto_20251029_0955.py new file mode 100644 index 0000000..798ac89 --- /dev/null +++ b/panel/migrations/0654_auto_20251029_0955.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-29 09:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0653_auto_20251029_0954'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 989506)), + ), + migrations.AlterField( + model_name='limitationfordirectpurchaseandbarinformation', + name='end_time', + field=models.TimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name='limitationfordirectpurchaseandbarinformation', + name='start_time', + field=models.TimeField(blank=True, null=True), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 918739)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 918739)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 918739)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 918739)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 1, 77944)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 1, 77944)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 922734)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 922734)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 922734)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 9, 55, 0, 932733)), + ), + ] diff --git a/panel/migrations/0655_auto_20251029_1055.py b/panel/migrations/0655_auto_20251029_1055.py new file mode 100644 index 0000000..0bd711c --- /dev/null +++ b/panel/migrations/0655_auto_20251029_1055.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-29 10:55 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0654_auto_20251029_0955'), + ] + + operations = [ + migrations.AddField( + model_name='possegmentation', + name='amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='possegmentation', + name='total_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 643043)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 582502)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 582502)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 582502)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 582502)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 705461)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 705461)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 586508)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 586508)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 586508)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 10, 54, 57, 601513)), + ), + ] diff --git a/panel/migrations/0656_auto_20251029_1609.py b/panel/migrations/0656_auto_20251029_1609.py new file mode 100644 index 0000000..d3881aa --- /dev/null +++ b/panel/migrations/0656_auto_20251029_1609.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-10-29 16:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0655_auto_20251029_1055'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='amount', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='total_amount', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 408487)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 338605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 338605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 338605)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 338605)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 493757)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 493757)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 343617)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 343617)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 343617)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 10, 29, 16, 9, 33, 356329)), + ), + ] diff --git a/panel/migrations/0657_auto_20251102_1322.py b/panel/migrations/0657_auto_20251102_1322.py new file mode 100644 index 0000000..503da1f --- /dev/null +++ b/panel/migrations/0657_auto_20251102_1322.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-02 13:22 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0656_auto_20251029_1609'), + ] + + operations = [ + migrations.AddField( + model_name='posdeviceversion', + name='link', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 223923)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 158243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 158243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 158243)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 158243)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 300194)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 300194)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 161785)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 161785)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 161785)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 13, 22, 18, 174907)), + ), + ] diff --git a/panel/migrations/0658_auto_20251102_1437.py b/panel/migrations/0658_auto_20251102_1437.py new file mode 100644 index 0000000..468a2c3 --- /dev/null +++ b/panel/migrations/0658_auto_20251102_1437.py @@ -0,0 +1,99 @@ +# Generated by Django 3.2.13 on 2025-11-02 14:37 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0657_auto_20251102_1322'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 598288)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 536939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 536939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 536939)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 536939)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 672615)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 672615)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 540512)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 540512)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 540512)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 14, 37, 30, 551672)), + ), + migrations.CreateModel( + name='WarehouseArchive', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('date', models.DateTimeField(null=True)), + ('weight', models.FloatField(default=0)), + ('image', models.CharField(max_length=500, null=True)), + ('quota', models.CharField(max_length=20, null=True)), + ('description', models.TextField(null=True)), + ('registerer', models.CharField(max_length=250, null=True)), + ('registerer_mobile', models.CharField(max_length=250, null=True)), + ('registerer_role', models.CharField(max_length=250, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='warehousearchive_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guild_archive', to='panel.guilds')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_archive', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='warehousearchive_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_archive', to='panel.guilds')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0659_auto_20251102_1614.py b/panel/migrations/0659_auto_20251102_1614.py new file mode 100644 index 0000000..7e2b3e7 --- /dev/null +++ b/panel/migrations/0659_auto_20251102_1614.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-02 16:14 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0658_auto_20251102_1437'), + ] + + operations = [ + migrations.AddField( + model_name='posdeviceversion', + name='checksum', + field=models.TextField(null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 7, 27311)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 959689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 959689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 959689)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 959689)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 7, 113497)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 7, 113497)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 962687)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 962687)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 962687)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 16, 14, 6, 976208)), + ), + ] diff --git a/panel/migrations/0660_auto_20251102_2037.py b/panel/migrations/0660_auto_20251102_2037.py new file mode 100644 index 0000000..1840b63 --- /dev/null +++ b/panel/migrations/0660_auto_20251102_2037.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-11-02 20:37 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0659_auto_20251102_1614'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 608750)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 477082)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 477082)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 477082)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 477082)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 717026)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 717026)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 485084)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 485084)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 485084)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 36, 34, 520850)), + ), + migrations.CreateModel( + name='SmsRecipient', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('phone_number', models.CharField(max_length=11, unique=True)), + ('name', models.CharField(max_length=100)), + ('is_active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='smsrecipient_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='smsrecipient_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0661_auto_20251102_2044.py b/panel/migrations/0661_auto_20251102_2044.py new file mode 100644 index 0000000..43ac310 --- /dev/null +++ b/panel/migrations/0661_auto_20251102_2044.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-02 20:44 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0660_auto_20251102_2037'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 944418)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 735638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 735638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 735638)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 735638)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 43, 178738)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 43, 178738)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 745639)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 745639)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 745639)), + ), + migrations.AlterField( + model_name='smsrecipient', + name='name', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 2, 20, 43, 42, 785380)), + ), + ] diff --git a/panel/migrations/0662_auto_20251103_1453.py b/panel/migrations/0662_auto_20251103_1453.py new file mode 100644 index 0000000..9cbf8b5 --- /dev/null +++ b/panel/migrations/0662_auto_20251103_1453.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-11-03 14:53 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0661_auto_20251102_2044'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 774809)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 838938)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 838938)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 14, 53, 39, 714062)), + ), + migrations.CreateModel( + name='PosDeviceSetting', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('pos_machin', models.CharField(max_length=100, null=True)), + ('owner', models.TextField(null=True)), + ('serial', models.TextField(null=True)), + ('key_id', models.TextField(null=True)), + ('key_value', models.TextField(null=True)), + ('last_modify', models.DateTimeField(null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdevicesetting_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posdevicesetting_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0663_auto_20251103_1525.py b/panel/migrations/0663_auto_20251103_1525.py new file mode 100644 index 0000000..ad33039 --- /dev/null +++ b/panel/migrations/0663_auto_20251103_1525.py @@ -0,0 +1,104 @@ +# Generated by Django 3.2.13 on 2025-11-03 15:25 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0662_auto_20251103_1453'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='ware_house_archive_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='ware_house_archive_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='guilds', + name='ware_house_archive_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_archive_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_archive_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='killhouse', + name='ware_house_archive_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='rolesproducts', + name='ware_house_archive_weight', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 333127)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 273336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 273336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 273336)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 273336)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 407615)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 407615)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 276335)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 276335)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 276335)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 3, 15, 24, 55, 287882)), + ), + ] diff --git a/panel/migrations/0664_auto_20251104_1353.py b/panel/migrations/0664_auto_20251104_1353.py new file mode 100644 index 0000000..6c5c241 --- /dev/null +++ b/panel/migrations/0664_auto_20251104_1353.py @@ -0,0 +1,114 @@ +# Generated by Django 3.2.13 on 2025-11-04 13:53 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0663_auto_20251103_1525'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='company_identifier', + field=models.CharField(max_length=100, null=True), + ), + migrations.AddField( + model_name='guilds', + name='company_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='guilds', + name='has_inquiry', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='has_partner', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='is_foreign_national', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='guilds', + name='license_expire_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='guilds', + name='license_issue_date', + field=models.DateTimeField(null=True), + ), + migrations.AddField( + model_name='guilds', + name='license_status', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='guilds', + name='license_type', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 521248)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 460251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 460251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 460251)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 460251)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 593502)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 593502)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 463245)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 463245)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 463245)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 4, 13, 52, 39, 474996)), + ), + ] diff --git a/panel/migrations/0665_auto_20251105_1111.py b/panel/migrations/0665_auto_20251105_1111.py new file mode 100644 index 0000000..c10e5a5 --- /dev/null +++ b/panel/migrations/0665_auto_20251105_1111.py @@ -0,0 +1,84 @@ +# Generated by Django 3.2.13 on 2025-11-05 11:11 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0664_auto_20251104_1353'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='national_code', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='guilds', + name='phone_number', + field=models.CharField(max_length=200, null=True), + ), + migrations.AddField( + model_name='guilds', + name='union_name', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 191787)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 131593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 131593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 131593)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 131593)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 265270)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 265270)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 135340)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 135010)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 135010)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 5, 11, 11, 17, 146507)), + ), + ] diff --git a/panel/migrations/0666_auto_20251109_1151.py b/panel/migrations/0666_auto_20251109_1151.py new file mode 100644 index 0000000..8001ce7 --- /dev/null +++ b/panel/migrations/0666_auto_20251109_1151.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-11-09 11:51 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0665_auto_20251105_1111'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='guild', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_guild', to='panel.guilds'), + ), + migrations.AddField( + model_name='posmachinetransactions', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='transaction_kill_house', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 20, 284182)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 31194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 31194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 31194)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 31194)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 20, 434432)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 20, 434432)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 36194)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 36194)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 36194)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 11, 51, 18, 56502)), + ), + ] diff --git a/panel/migrations/0667_auto_20251109_1443.py b/panel/migrations/0667_auto_20251109_1443.py new file mode 100644 index 0000000..ae47692 --- /dev/null +++ b/panel/migrations/0667_auto_20251109_1443.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-09 14:43 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0666_auto_20251109_1151'), + ] + + operations = [ + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='national_id', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 450884)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 366396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 366396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 366396)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 366396)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 563405)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 563405)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 379397)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 379397)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 379397)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 42, 34, 398820)), + ), + ] diff --git a/panel/migrations/0668_auto_20251109_1448.py b/panel/migrations/0668_auto_20251109_1448.py new file mode 100644 index 0000000..98394ec --- /dev/null +++ b/panel/migrations/0668_auto_20251109_1448.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-09 14:48 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0667_auto_20251109_1443'), + ] + + operations = [ + migrations.AddField( + model_name='outprovincecarcassesbuyer', + name='national_id', + field=models.CharField(max_length=200, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 677143)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 492322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 492322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 492322)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 492322)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 848577)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 848577)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 544321)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 544321)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 544321)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 9, 14, 48, 9, 562320)), + ), + ] diff --git a/panel/migrations/0669_auto_20251110_1001.py b/panel/migrations/0669_auto_20251110_1001.py new file mode 100644 index 0000000..d48ba11 --- /dev/null +++ b/panel/migrations/0669_auto_20251110_1001.py @@ -0,0 +1,123 @@ +# Generated by Django 3.2.13 on 2025-11-10 10:01 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0668_auto_20251109_1448'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 173864)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 120951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 120951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 120951)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 120951)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 256896)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 256896)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 124042)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 124042)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 124042)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 10, 0, 47, 126234)), + ), + migrations.CreateModel( + name='EvacuationHatchingDetail', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('PartIdCode', models.CharField(blank=True, max_length=200, null=True)), + ('RequestId', models.CharField(blank=True, max_length=200, null=True)), + ('MoReportId', models.CharField(blank=True, max_length=200, null=True)), + ('ReportType', models.IntegerField(blank=True, null=True)), + ('ReportTypeString', models.CharField(blank=True, max_length=255, null=True)), + ('ReportDate', models.CharField(blank=True, max_length=200, null=True)), + ('ReportDateShamsi', models.CharField(blank=True, max_length=200, null=True)), + ('MoReason', models.TextField(blank=True, null=True)), + ('MoDate', models.CharField(blank=True, max_length=200, null=True)), + ('MoDateShamsi', models.CharField(blank=True, max_length=200, null=True)), + ('MoStartDay', models.IntegerField(blank=True, null=True)), + ('MoEndDay', models.IntegerField(blank=True, null=True)), + ('MoReportSubId', models.CharField(blank=True, max_length=200, null=True)), + ('ReportStatus', models.IntegerField(blank=True, null=True)), + ('GoodCount', models.IntegerField(blank=True, null=True)), + ('Message', models.TextField(blank=True, null=True)), + ('ErrorCode', models.IntegerField(blank=True, null=True)), + ('IsDeleted', models.BooleanField(default=False)), + ('RegDate', models.CharField(blank=True, max_length=200, null=True)), + ('RegDateShamsi', models.CharField(blank=True, max_length=200, null=True)), + ('RegDateShamsiWithTime', models.CharField(blank=True, max_length=200, null=True)), + ('RegDateShamsiOnlyTime', models.CharField(blank=True, max_length=200, null=True)), + ('ExternalId', models.CharField(blank=True, max_length=200, null=True)), + ('StringId', models.CharField(blank=True, max_length=200, null=True)), + ('IsPersisted', models.BooleanField(default=False)), + ('AllowInsert', models.BooleanField(default=False)), + ('AllowUpdate', models.BooleanField(default=False)), + ('ModalCss', models.CharField(blank=True, max_length=255, null=True)), + ('GridContainerParametersModel', models.CharField(blank=True, max_length=255, null=True)), + ('MenuUserAccess', models.CharField(blank=True, max_length=255, null=True)), + ('MenuUserAccessId', models.IntegerField(blank=True, null=True)), + ('LogTableName', models.CharField(blank=True, max_length=255, null=True)), + ('LogTableAlias', models.CharField(blank=True, max_length=255, null=True)), + ('PageTitle', models.CharField(blank=True, max_length=255, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evacuationhatchingdetail_createdby', to=settings.AUTH_USER_MODEL)), + ('hatching', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evacuation_details', to='panel.poultryhatching')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='evacuationhatchingdetail_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0670_auto_20251110_1100.py b/panel/migrations/0670_auto_20251110_1100.py new file mode 100644 index 0000000..cca996c --- /dev/null +++ b/panel/migrations/0670_auto_20251110_1100.py @@ -0,0 +1,94 @@ +# Generated by Django 3.2.13 on 2025-11-10 11:00 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0669_auto_20251110_1001'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='total_disease_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_fire_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_flock_destruction', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_force_majeure_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AddField( + model_name='poultryhatching', + name='total_normal_flock_losses', + field=models.BigIntegerField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 22, 39187)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 946660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 946660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 946660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 946660)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 22, 142655)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 22, 142655)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 952987)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 952987)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 952987)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 0, 21, 970666)), + ), + ] diff --git a/panel/migrations/0671_auto_20251110_1101.py b/panel/migrations/0671_auto_20251110_1101.py new file mode 100644 index 0000000..0360739 --- /dev/null +++ b/panel/migrations/0671_auto_20251110_1101.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-11-10 11:01 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0670_auto_20251110_1100'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 837270)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 778235)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 773225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 773225)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 773225)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 917597)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 917597)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 780244)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 780244)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 780244)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 11, 1, 19, 793296)), + ), + ] diff --git a/panel/migrations/0672_auto_20251110_2116.py b/panel/migrations/0672_auto_20251110_2116.py new file mode 100644 index 0000000..7401e9c --- /dev/null +++ b/panel/migrations/0672_auto_20251110_2116.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-11-10 21:16 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0671_auto_20251110_1101'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 668019)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 609024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 609024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 609024)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 609024)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 761013)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 761013)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 612019)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 612019)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 612019)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 10, 21, 16, 5, 625027)), + ), + migrations.CreateModel( + name='HatchingLossManagement', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('include_total_disease_losses', models.BooleanField(default=False)), + ('include_total_flock_destruction', models.BooleanField(default=False)), + ('include_total_normal_flock_losses', models.BooleanField(default=False)), + ('include_total_force_majeure_losses', models.BooleanField(default=False)), + ('include_total_fire_losses', models.BooleanField(default=False)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchinglossmanagement_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchinglossmanagement_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0673_auto_20251111_1150.py b/panel/migrations/0673_auto_20251111_1150.py new file mode 100644 index 0000000..ccff71c --- /dev/null +++ b/panel/migrations/0673_auto_20251111_1150.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-11 11:50 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0672_auto_20251110_2116'), + ] + + operations = [ + migrations.AddField( + model_name='poultryhatching', + name='unknown', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 135047)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 204767)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 204767)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 67747)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 11, 11, 50, 9, 91702)), + ), + ] diff --git a/panel/migrations/0674_auto_20251115_1354.py b/panel/migrations/0674_auto_20251115_1354.py new file mode 100644 index 0000000..5c48baa --- /dev/null +++ b/panel/migrations/0674_auto_20251115_1354.py @@ -0,0 +1,137 @@ +# Generated by Django 3.2.13 on 2025-11-15 13:54 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0673_auto_20251111_1150'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 637332)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 579858)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 579858)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 579858)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 579858)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 705343)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 705343)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 581869)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 581869)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 581869)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 13, 54, 36, 589635)), + ), + migrations.CreateModel( + name='GuildLegalPersonDetail', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('status', models.BooleanField(default=False)), + ('status_code', models.IntegerField(default=0)), + ('api_log_id', models.CharField(blank=True, max_length=100, null=True)), + ('legal_person_info_dto_id', models.CharField(blank=True, max_length=100, null=True)), + ('parent_legal_person_id', models.CharField(blank=True, max_length=100, null=True)), + ('successful', models.BooleanField(default=False)), + ('message', models.TextField(blank=True, null=True)), + ('name', models.CharField(blank=True, max_length=300, null=True)), + ('national_code', models.CharField(blank=True, max_length=20, null=True)), + ('post_code', models.CharField(blank=True, max_length=20, null=True)), + ('address', models.TextField(blank=True, null=True)), + ('legal_person_type', models.CharField(blank=True, max_length=100, null=True)), + ('register_number', models.CharField(blank=True, max_length=100, null=True)), + ('register_unit', models.CharField(blank=True, max_length=100, null=True)), + ('register_date', models.CharField(blank=True, max_length=100, null=True)), + ('register_date_unix', models.BigIntegerField(default=0)), + ('residency', models.CharField(blank=True, max_length=100, null=True)), + ('state', models.CharField(blank=True, max_length=100, null=True)), + ('is_settle', models.BooleanField(default=False)), + ('settle_date', models.CharField(blank=True, max_length=100, null=True)), + ('is_break_up', models.BooleanField(default=False)), + ('break_up_date', models.CharField(blank=True, max_length=100, null=True)), + ('is_branch', models.BooleanField(default=False)), + ('branch_list', models.JSONField(blank=True, null=True)), + ('parent_legal_person_raw', models.JSONField(blank=True, null=True)), + ('establishment_date', models.CharField(blank=True, max_length=100, null=True)), + ('is_db_result', models.BooleanField(default=False)), + ('service_type', models.IntegerField(default=0)), + ('parent_name', models.CharField(blank=True, max_length=300, null=True)), + ('parent_national_code', models.CharField(blank=True, max_length=20, null=True)), + ('parent_post_code', models.CharField(blank=True, max_length=20, null=True)), + ('parent_address', models.TextField(blank=True, null=True)), + ('parent_legal_person_type', models.CharField(blank=True, max_length=100, null=True)), + ('parent_register_number', models.CharField(blank=True, max_length=100, null=True)), + ('parent_register_unit', models.CharField(blank=True, max_length=100, null=True)), + ('parent_register_date', models.CharField(blank=True, max_length=100, null=True)), + ('parent_register_date_unix', models.BigIntegerField(default=0)), + ('parent_residency', models.CharField(blank=True, max_length=100, null=True)), + ('parent_state', models.CharField(blank=True, max_length=100, null=True)), + ('parent_is_settle', models.BooleanField(default=False)), + ('parent_settle_date', models.CharField(blank=True, max_length=100, null=True)), + ('parent_is_break_up', models.BooleanField(default=False)), + ('parent_break_up_date', models.CharField(blank=True, max_length=100, null=True)), + ('parent_is_branch', models.BooleanField(default=False)), + ('parent_branch_list', models.JSONField(blank=True, null=True)), + ('parent_establishment_date', models.CharField(blank=True, max_length=100, null=True)), + ('parent_is_db_result', models.BooleanField(default=False)), + ('parent_service_type', models.IntegerField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildlegalpersondetail_createdby', to=settings.AUTH_USER_MODEL)), + ('guild', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='legal_person_details', to='panel.guilds')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='guildlegalpersondetail_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0675_auto_20251115_1509.py b/panel/migrations/0675_auto_20251115_1509.py new file mode 100644 index 0000000..ffae98d --- /dev/null +++ b/panel/migrations/0675_auto_20251115_1509.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-15 15:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0674_auto_20251115_1354'), + ] + + operations = [ + migrations.AddField( + model_name='poultryscience', + name='engineering_code', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 489778)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 382413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 382413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 382413)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 382413)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 621129)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 621129)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 385917)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 385917)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 385917)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 15, 8, 25, 413289)), + ), + ] diff --git a/panel/migrations/0676_auto_20251115_1709.py b/panel/migrations/0676_auto_20251115_1709.py new file mode 100644 index 0000000..4e722ae --- /dev/null +++ b/panel/migrations/0676_auto_20251115_1709.py @@ -0,0 +1,329 @@ +# Generated by Django 3.2.13 on 2025-11-15 17:09 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0675_auto_20251115_1509'), + ] + + operations = [ + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='address', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='apiLogId', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='branchList', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='breakUpdate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='establishmentDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='isBranch', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='isBreakUp', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='isDbResult', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='isRealPerson', + field=models.BooleanField(default=True, verbose_name='حقیقی=True / حقوقی=False'), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='isSettle', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='legalPersonInfoDtoId', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='legalPersonType', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='message', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='name', + field=models.CharField(blank=True, max_length=300, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='nationalCode', + field=models.CharField(blank=True, max_length=20, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonAddress', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonBranchList', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonBreakUpdate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonEstablishmentDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonId', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonInfoDtoId', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonIsBranch', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonIsBreakUp', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonIsDbResult', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonIsSettle', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonMessage', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonName', + field=models.CharField(blank=True, max_length=300, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonNationalCode', + field=models.CharField(blank=True, max_length=20, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonParentId', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonPostCode', + field=models.CharField(blank=True, max_length=20, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonRegisterDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonRegisterDateUnix', + field=models.BigIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonRegisterNumber', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonRegisterUnit', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonResidency', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonServiceType', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonSettleDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonState', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonSuccessful', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='parentLegalPersonType', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='postCode', + field=models.CharField(blank=True, max_length=20, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='registerDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='registerDateUnix', + field=models.BigIntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='registerNumber', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='registerUnit', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='residency', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='serviceType', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='settleDate', + field=models.CharField(blank=True, max_length=50, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='state', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='status', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='statusCode', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AddField( + model_name='baseoutprovincecarcassesbuyer', + name='successful', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 382269)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 323418)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 323418)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 323418)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 323418)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 445426)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 445426)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 325426)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 325426)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 325426)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 15, 17, 9, 18, 338650)), + ), + ] diff --git a/panel/migrations/0677_auto_20251116_1459.py b/panel/migrations/0677_auto_20251116_1459.py new file mode 100644 index 0000000..0673bcc --- /dev/null +++ b/panel/migrations/0677_auto_20251116_1459.py @@ -0,0 +1,69 @@ +# Generated by Django 3.2.13 on 2025-11-16 14:59 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0676_auto_20251115_1709'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 201648)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 53181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 53181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 53181)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 53181)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 469784)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 469784)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 57202)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 57202)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 57202)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 16, 14, 58, 51, 75393)), + ), + ] diff --git a/panel/migrations/0678_auto_20251125_0840.py b/panel/migrations/0678_auto_20251125_0840.py new file mode 100644 index 0000000..ced30bc --- /dev/null +++ b/panel/migrations/0678_auto_20251125_0840.py @@ -0,0 +1,79 @@ +# Generated by Django 3.2.13 on 2025-11-25 08:40 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0677_auto_20251116_1459'), + ] + + operations = [ + migrations.AddField( + model_name='posmachinetransactions', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='warehousearchive', + name='warehouse', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 507660)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 420681)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 420681)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 420681)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 420681)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 590737)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 590737)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 424682)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 423681)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 423681)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 39, 53, 437780)), + ), + ] diff --git a/panel/migrations/0679_auto_20251125_0843.py b/panel/migrations/0679_auto_20251125_0843.py new file mode 100644 index 0000000..642bd7d --- /dev/null +++ b/panel/migrations/0679_auto_20251125_0843.py @@ -0,0 +1,75 @@ +# Generated by Django 3.2.13 on 2025-11-25 08:43 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0678_auto_20251125_0840'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='public_killer', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_public_killer', to='panel.killhouse'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 372263)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 304262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 304262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 304262)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 304262)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 468290)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 468290)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 307261)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 307261)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 307261)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 25, 8, 43, 19, 322260)), + ), + ] diff --git a/panel/migrations/0680_auto_20251130_1538.py b/panel/migrations/0680_auto_20251130_1538.py new file mode 100644 index 0000000..95ade32 --- /dev/null +++ b/panel/migrations/0680_auto_20251130_1538.py @@ -0,0 +1,74 @@ +# Generated by Django 3.2.13 on 2025-11-30 15:38 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('panel', '0679_auto_20251125_0843'), + ] + + operations = [ + migrations.AddField( + model_name='killhouse', + name='ware_house_remaining_weight_archive_percent', + field=models.FloatField(default=0), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 271694)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 175517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 175517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 175517)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 175517)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 383358)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 383358)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 179572)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 179572)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 179572)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 11, 30, 15, 37, 59, 201763)), + ), + ] diff --git a/panel/migrations/0681_auto_20251202_1539.py b/panel/migrations/0681_auto_20251202_1539.py new file mode 100644 index 0000000..1f07f5d --- /dev/null +++ b/panel/migrations/0681_auto_20251202_1539.py @@ -0,0 +1,93 @@ +# Generated by Django 3.2.13 on 2025-12-02 15:39 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0680_auto_20251130_1538'), + ] + + operations = [ + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 940389)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 9, 8437)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 9, 8437)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 866113)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 2, 15, 39, 8, 882581)), + ), + migrations.CreateModel( + name='MarketDailyLimitation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('quantity', models.IntegerField(default=0)), + ('active', models.BooleanField(default=False)), + ('register_role', models.CharField(max_length=50, null=True)), + ('register_fullname', models.CharField(max_length=100, null=True)), + ('register_mobile', models.CharField(max_length=100, null=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketdailylimitation_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='marketdailylimitation_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0682_auto_20251203_1617.py b/panel/migrations/0682_auto_20251203_1617.py new file mode 100644 index 0000000..ad6ad21 --- /dev/null +++ b/panel/migrations/0682_auto_20251203_1617.py @@ -0,0 +1,100 @@ +# Generated by Django 3.2.13 on 2025-12-03 16:17 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0681_auto_20251202_1539'), + ] + + operations = [ + migrations.AddField( + model_name='killhouseaddcar', + name='archive', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='killhousedriver', + name='archive', + field=models.BooleanField(default=False), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 978726)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 912008)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 912008)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 912008)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 912008)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 43, 57016)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 43, 57016)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 916475)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 916475)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 916475)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 3, 16, 16, 42, 931200)), + ), + migrations.CreateModel( + name='HatchingArchivePercent', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('active', models.BooleanField(default=False)), + ('percent', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchingarchivepercent_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='hatchingarchivepercent_modifiedby', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0683_auto_20251208_1617.py b/panel/migrations/0683_auto_20251208_1617.py new file mode 100644 index 0000000..cdd1a2f --- /dev/null +++ b/panel/migrations/0683_auto_20251208_1617.py @@ -0,0 +1,91 @@ +# Generated by Django 3.2.13 on 2025-12-08 16:17 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0078_auto_20251208_1617'), + ('panel', '0682_auto_20251203_1617'), + ] + + operations = [ + migrations.AddField( + model_name='guilds', + name='is_real_person', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='report_information', + field=models.JSONField(null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='reporter_role', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='poultry_science_report_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 47, 521281)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 382345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 382345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 382345)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 382345)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 47, 600275)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 47, 600275)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 433770)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 433770)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 433770)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 8, 16, 14, 46, 463107)), + ), + ] diff --git a/panel/migrations/0684_auto_20251213_1632.py b/panel/migrations/0684_auto_20251213_1632.py new file mode 100644 index 0000000..0d58ede --- /dev/null +++ b/panel/migrations/0684_auto_20251213_1632.py @@ -0,0 +1,197 @@ +# Generated by Django 3.2.13 on 2025-12-13 16:32 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentication', '0079_auto_20251213_1632'), + ('panel', '0683_auto_20251208_1617'), + ] + + operations = [ + migrations.AddField( + model_name='posdevicesession', + name='pos_unique_id', + field=models.CharField(max_length=6, null=True, unique=True), + ), + migrations.AddField( + model_name='posmachine', + name='current_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_pos', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='posmachine', + name='ip', + field=models.CharField(default='0.0.0.0', max_length=15), + ), + migrations.AddField( + model_name='posmachine', + name='mac', + field=models.CharField(max_length=50, null=True), + ), + migrations.AddField( + model_name='posmachine', + name='name', + field=models.TextField(default=''), + ), + migrations.AddField( + model_name='posmachine', + name='owner', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='owned_pos', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='posmachine', + name='pos_unique_id', + field=models.CharField(max_length=6, null=True, unique=True), + ), + migrations.AddField( + model_name='posmachine', + name='sdk', + field=models.TextField(default=''), + ), + migrations.AddField( + model_name='posmachine', + name='version', + field=models.IntegerField(default=0), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='chicken_age', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='poultrysciencereport', + name='report_id', + field=models.IntegerField(null=True), + ), + migrations.AddField( + model_name='steward', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_user', to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 869998)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 809478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 809478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 809478)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 809478)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 944867)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 944867)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 812470)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 812470)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 812470)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 13, 16, 31, 59, 825057)), + ), + migrations.CreateModel( + name='Representative', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('first_name', models.CharField(max_length=200, null=True)), + ('last_name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=15, null=True)), + ('city', models.CharField(max_length=100, null=True)), + ('Kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_representative', to='panel.killhouse')), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='representative_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='representative_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_representative', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='POSAuditLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('action', models.CharField(choices=[('CHANGE_OWNER', 'تغییر مالک'), ('CHANGE_CURRENT_USER', 'تغییر توزیع کننده'), ('CHANGE_CURRENT_REPRESENTATIVE', 'تغییر نماینده'), ('ACCESSLEVEL_UPDATE', 'بروزرسانی سطح دسترسی')], max_length=50)), + ('old_value', models.JSONField(blank=True, null=True)), + ('new_value', models.JSONField(blank=True, null=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('description', models.TextField(blank=True, null=True)), + ('performed_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ('pos', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='audit_logs', to='panel.posmachine')), + ], + ), + migrations.CreateModel( + name='POSAccessLevel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('name', models.CharField(max_length=100, null=True)), + ('in_province_sale', models.BooleanField(default=True)), + ('out_province_sale', models.BooleanField(default=True)), + ('cutting', models.BooleanField(default=True)), + ('freezing', models.BooleanField(default=True)), + ('warehouse', models.BooleanField(default=True)), + ('retail', models.BooleanField(default=True)), + ('active', models.BooleanField(default=True)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posaccesslevel_createdby', to=settings.AUTH_USER_MODEL)), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='posaccesslevel_modifiedby', to=settings.AUTH_USER_MODEL)), + ('pos', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='access_levels', to='panel.posmachine')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='posmachine', + name='current_representative', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='representative_pos', to='panel.representative'), + ), + ] diff --git a/panel/migrations/0685_auto_20251214_1635.py b/panel/migrations/0685_auto_20251214_1635.py new file mode 100644 index 0000000..49b33e1 --- /dev/null +++ b/panel/migrations/0685_auto_20251214_1635.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.13 on 2025-12-14 16:35 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0080_auto_20251214_1635'), + ('panel', '0684_auto_20251213_1632'), + ] + + operations = [ + migrations.RemoveField( + model_name='posauditlog', + name='performed_by', + ), + migrations.AddField( + model_name='posauditlog', + name='performed', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='authentication.systemuserprofile'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 831099)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 765958)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 765958)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 765958)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 765958)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 912737)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 912737)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 769316)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 769316)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 769316)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 14, 16, 35, 24, 782910)), + ), + ] diff --git a/panel/migrations/0686_auto_20251215_1654.py b/panel/migrations/0686_auto_20251215_1654.py new file mode 100644 index 0000000..a142325 --- /dev/null +++ b/panel/migrations/0686_auto_20251215_1654.py @@ -0,0 +1,117 @@ +# Generated by Django 3.2.13 on 2025-12-15 16:54 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0685_auto_20251214_1635'), + ] + + operations = [ + migrations.AddField( + model_name='dispenser', + name='in_use', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='dispenser', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_steward', to='panel.steward'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 644176)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 579426)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 579426)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 579426)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 579426)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 726839)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 726839)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 583940)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 582932)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 582932)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 15, 16, 54, 28, 596473)), + ), + migrations.CreateModel( + name='DispenserInformation', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('key', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)), + ('create_date', models.DateTimeField(auto_now_add=True)), + ('modify_date', models.DateTimeField(auto_now=True)), + ('trash', models.BooleanField(default=False)), + ('fullname', models.CharField(max_length=200, null=True)), + ('national_id', models.CharField(max_length=200, null=True)), + ('first_name', models.CharField(max_length=200, null=True)), + ('last_name', models.CharField(max_length=200, null=True)), + ('mobile', models.CharField(max_length=11, null=True)), + ('city', models.CharField(max_length=300, null=True)), + ('province', models.CharField(max_length=300, null=True)), + ('active', models.BooleanField(default=True)), + ('limitation', models.BooleanField(default=False)), + ('free_limitation', models.BooleanField(default=False)), + ('governmental_limitation', models.BooleanField(default=False)), + ('governmental_limitation_weight', models.FloatField(default=0)), + ('free_limitation_weight', models.FloatField(default=0)), + ('total_selling_warehouse_governmental_weight', models.FloatField(default=0)), + ('total_selling_warehouse_free_weight', models.FloatField(default=0)), + ('total_selling_warehouse_weight', models.FloatField(default=0)), + ('created_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenserinformation_createdby', to=settings.AUTH_USER_MODEL)), + ('dispenser', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_info_user', to='panel.dispenser')), + ('kill_house', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_info_kill_house', to='panel.killhouse')), + ('modified_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenserinformation_modifiedby', to=settings.AUTH_USER_MODEL)), + ('steward', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='dispenser_info_steward', to='panel.steward')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/panel/migrations/0687_auto_20251216_1653.py b/panel/migrations/0687_auto_20251216_1653.py new file mode 100644 index 0000000..e2e15d1 --- /dev/null +++ b/panel/migrations/0687_auto_20251216_1653.py @@ -0,0 +1,147 @@ +# Generated by Django 3.2.13 on 2025-12-16 16:53 + +import datetime +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('panel', '0686_auto_20251215_1654'), + ] + + operations = [ + migrations.RemoveField( + model_name='representative', + name='Kill_house', + ), + migrations.AddField( + model_name='representative', + name='active', + field=models.BooleanField(default=True), + ), + migrations.AddField( + model_name='representative', + name='free_limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='representative', + name='free_limitation_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='representative', + name='governmental_limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='representative', + name='governmental_limitation_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='representative', + name='kill_house', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='kill_house_representative', to='panel.killhouse'), + ), + migrations.AddField( + model_name='representative', + name='limitation', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='representative', + name='total_selling_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='representative', + name='total_selling_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='representative', + name='total_selling_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='city', + field=models.CharField(max_length=100, null=True), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 840150)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 779153)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 779153)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 779153)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 779153)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 920246)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 920246)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 782902)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 782902)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 782902)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 16, 16, 52, 47, 794666)), + ), + migrations.CreateModel( + name='RequestLog', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('method', models.CharField(max_length=10)), + ('path', models.TextField()), + ('query_params', models.JSONField(blank=True, null=True)), + ('body', models.JSONField(blank=True, null=True)), + ('headers', models.JSONField(blank=True, null=True)), + ('status_code', models.PositiveIntegerField(null=True)), + ('ip_address', models.GenericIPAddressField(blank=True, null=True)), + ('duration', models.FloatField(help_text='Request duration in seconds')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/panel/migrations/0688_auto_20251217_1648.py b/panel/migrations/0688_auto_20251217_1648.py new file mode 100644 index 0000000..5f55dbe --- /dev/null +++ b/panel/migrations/0688_auto_20251217_1648.py @@ -0,0 +1,436 @@ +# Generated by Django 3.2.13 on 2025-12-17 16:48 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('authentication', '0081_auto_20251217_1648'), + ('panel', '0687_auto_20251216_1653'), + ] + + operations = [ + migrations.AddField( + model_name='killhousefreebarinformation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_dispenser', to='panel.dispenser'), + ), + migrations.AddField( + model_name='killhousefreebarinformation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_dispenser', to='panel.dispenser'), + ), + migrations.AddField( + model_name='killhousefreesalebarinformation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='otherproducts', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='other_products_steward', to='panel.steward'), + ), + migrations.AddField( + model_name='posmachine', + name='current_dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='current_dispenser_pos', to='authentication.systemuserprofile'), + ), + migrations.AddField( + model_name='possegmentation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='segmentation_dispenser', to='panel.dispenser'), + ), + migrations.AddField( + model_name='possegmentation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='segmentation_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='possegmentation', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_segmentation', to='panel.steward'), + ), + migrations.AddField( + model_name='possegmentation', + name='to_steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='to_steward_segmentation', to='panel.steward'), + ), + migrations.AddField( + model_name='rolesproducts', + name='steward', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles_products_steward', to='panel.steward'), + ), + migrations.AddField( + model_name='steward', + name='cold_house_free_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='cold_house_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='free_sale_form_governmental_quota', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='free_sale_from_free_quota_in_province', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='free_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='governmental_selling_permission', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='steward', + name='in_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='in_province_governmental_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='out_province_free_buying_commitment_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='out_province_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='pos_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='pos_free_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='pos_governmental_allocated_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='segmentation_free_selling_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='segmentation_governmental_percent', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_cold_house_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_cold_house_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_cold_house_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_in_province_free_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_in_province_governmental_remain_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_commitment_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_in_province_free_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_in_province_free_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_in_province_governmental_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_in_province_governmental_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_input_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_input_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_input_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_out_province_buying_bars_commitment_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_out_province_buying_bars_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_remain_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_remain_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_remain_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_segmentation_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_segmentation_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_segmentation_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_in_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_in_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_out_province_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_out_province_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_warehouse_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_warehouse_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='total_selling_warehouse_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='ware_house_archive_free_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='ware_house_archive_governmental_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='steward', + name='ware_house_archive_weight', + field=models.FloatField(default=0), + ), + migrations.AddField( + model_name='stewardallocation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='allocation_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_steward_dispenser', to='panel.dispenser'), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_steward_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='stewardfreebarinformation', + name='stewards', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_bar_info_stewards', to='panel.steward'), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='dispenser', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_free_sale_bar_info_dispenser', to='panel.dispenser'), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='representative', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='steward_free_sale_bar_info_representative', to='panel.representative'), + ), + migrations.AddField( + model_name='stewardfreesalebarinformation', + name='stewards', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='free_sale_bar_info_stewards', to='panel.steward'), + ), + migrations.AlterField( + model_name='functionexecutor', + name='compare_time', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 528740)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='assignment_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 466244)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='city_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 465252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='kill_house_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 465252)), + ), + migrations.AlterField( + model_name='operatorlasttimeenter', + name='province_operator_last_time_check', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 465252)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_create_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 612049)), + ), + migrations.AlterField( + model_name='posdevicesession', + name='session_last_seen_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 612049)), + ), + migrations.AlterField( + model_name='poultry', + name='date_of_register', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 469757)), + ), + migrations.AlterField( + model_name='poultry', + name='hatching_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 469757)), + ), + migrations.AlterField( + model_name='poultry', + name='last_party_date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 469757)), + ), + migrations.AlterField( + model_name='totalpoultryrequestquantity', + name='date', + field=models.DateTimeField(default=datetime.datetime(2025, 12, 17, 16, 47, 34, 481801)), + ), + ] diff --git a/panel/migrations/__init__.py b/panel/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/models.py b/panel/models.py new file mode 100644 index 0000000..c298e61 --- /dev/null +++ b/panel/models.py @@ -0,0 +1,7444 @@ +import random +import string +from datetime import datetime, timedelta + +from django.conf import settings +from django.contrib.auth.models import User, Group +from django.db import models +from django.utils import timezone +from jdatetime import time + +from LiveStock.models import Cooperative, LiveStockRolseProduct +from authentication.models import ( + BaseModel, + Address, + UserProfile, + SystemAddress, + SystemUserProfile, + BankCard, + Province, ExternalTransaction +) +from authentication.models import UserMessage +from general_urls import base_user_gate_way_id +from notification.models import Notification +# from .KillHouse.views import KillHouseComplaintViewSet +from .ReportingPanel.models import SearchFields + + +class CheckState(BaseModel): + poultry_request = models.ForeignKey( + 'PoultryRequest', + on_delete=models.CASCADE, + null=True, + related_name="poultry_request" + ) + notification = models.ForeignKey( + Notification, + on_delete=models.CASCADE, + null=True, + related_name="check_notification" + ) + user_message = models.ForeignKey( + UserMessage, + on_delete=models.CASCADE, + null=True, + related_name="message_check" + ) + city_operator_check = models.ForeignKey( + 'CityOperatorCheckRequest', + on_delete=models.CASCADE, + null=True, + related_name="city_operator_check_state" + ) + province_operator_check = models.ForeignKey( + 'ProvinceCheckOperatorRequest', + on_delete=models.CASCADE, + null=True, + related_name='province_operator_check_state' + ) + state = models.BooleanField(default=False) + city_state = models.BooleanField(default=False) + city_state_notification = models.BooleanField(default=False) + city_state_modal = models.BooleanField(default=False) + city_state_sms = models.BooleanField(default=False) + province_state = models.BooleanField(default=False) + province_state_notification = models.BooleanField(default=False) + province_state_modal = models.BooleanField(default=False) + province_state_sms = models.BooleanField(default=False) + kill_house_state_notification = models.BooleanField(default=False) + kill_house_state_modal = models.BooleanField(default=False) + kill_house_state_sms = models.BooleanField(default=False) + assignment_state_notification = models.BooleanField(default=False) + assignment_state_modal = models.BooleanField(default=False) + assignment_state_sms = models.BooleanField(default=False) + main_check = models.CharField(max_length=50, null=True) + + +class Wallet(BaseModel): + inventory = models.FloatField(default=0) + state = models.CharField(max_length=120, default='active') + province_name = models.CharField(max_length=50, null=True) + id_number = models.IntegerField(default=1) + + def save(self, *args, **kwargs): + super(Wallet, self).save(*args, **kwargs) + + +class OperatorLastTimeEnter(BaseModel): + city_operator_last_time_check = models.DateTimeField(default=datetime.now()) + province_operator_last_time_check = models.DateTimeField(default=datetime.now()) + kill_house_last_time_check = models.DateTimeField(default=datetime.now()) + assignment_last_time_check = models.DateTimeField(default=datetime.now()) + operator = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + null=True, + related_name="operator_last_time_check" + ) + + +# مدل مربوط به قیمت گذاری +class Pricing(BaseModel): + # price = models.FloatField(null=True) + operator = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="pricing_operator" + ) + date = models.DateTimeField(null=True) + live_chicken_price = models.FloatField(null=True) + dead_chicken_price = models.FloatField(null=True) + major_seller_price = models.FloatField(null=True) + retail_seller_price = models.FloatField(null=True) + floor_price = models.FloatField(null=True) + ceiling_price = models.FloatField(null=True) + role = models.CharField(max_length=20, null=True) + lock = models.BooleanField(default=False) + pricing_id_key = models.IntegerField(null=True) + operator_id_foreign_key = models.IntegerField(null=True) + + # partial_seller_price = models.FloatField(null=True) + + def save(self, *args, **kwargs): + super(Pricing, self).save(*args, **kwargs) + + +class ChainCompany(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="chain_company_user", + null=True + ) + + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="chain_company_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="chain_company_wallet", + null=True + ) + name = models.CharField(max_length=200, null=True) + city = models.CharField(max_length=200, null=True) + province = models.CharField(max_length=200, null=True) + postal_code = models.CharField(max_length=200, null=True) + address = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(ChainCompany, self).save(*args, **kwargs) + + +class ChainCompanyTransaction(BaseModel): + chain_company = models.ForeignKey( + ChainCompany, + on_delete=models.CASCADE, + related_name="transaction_chain_company", + null=True + ) + amount = models.BigIntegerField(default=0) + amount_with_tax = models.BigIntegerField(default=0) + transaction = models.IntegerField(null=True) + state = models.CharField(max_length=20, default='pending') + union_share = models.BigIntegerField(default=0) + company_share = models.BigIntegerField(default=0) + guilds_share = models.BigIntegerField(default=0) + city_share = models.BigIntegerField(default=0) + wallet_share = models.BigIntegerField(default=0) + other_share = models.BigIntegerField(default=0) + pay_type = models.CharField(max_length=200, null=True) + saleReferenceId = models.CharField(max_length=100, null=True) + refId = models.CharField(max_length=100, null=True) + orderId = models.CharField(max_length=100, null=True) + cardHolderPan = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ChainCompanyTransaction, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت مرغدار +class Poultry(BaseModel): + owner = models.ForeignKey( + 'self', + null=True, + blank=True, + related_name='poultry_owner', + on_delete=models.CASCADE + ) + owner_id_foreign_key = models.IntegerField(null=True) + + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="poultry_user", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="poultry_system_address", + null=True + ) + + address_id_foreign_key = models.IntegerField(null=True) + + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="poultry_bank_info", + null=True + ) + + has_chain_company = models.BooleanField(default=False) + + user_bank_id_foreign_key = models.IntegerField(null=True) + city_operator = models.CharField(max_length=150, null=True) + unit_name = models.CharField(max_length=100, null=True) + password = models.CharField(max_length=100, null=True) + gis_code = models.CharField(max_length=30, null=True) + operating_licence_capacity = models.BigIntegerField(default=0) + number_of_halls = models.IntegerField(default=0) + tenant = models.BooleanField(default=False, null=True) + has_tenant = models.BooleanField(default=False, null=True) + person_type = models.CharField(max_length=10, null=True) + economic_code = models.CharField(max_length=30, null=True) + system_code = models.CharField(max_length=20, null=True) + epidemiological_code = models.CharField(max_length=20, null=True) + breeding_unique_id = models.CharField(max_length=20, null=True) + total_capacity = models.BigIntegerField(default=0) + licence_number = models.CharField(max_length=20, null=True) + health_certificate_number = models.CharField(max_length=20, null=True) + number_of_requests = models.BigIntegerField(default=0) + hatching_date = models.DateTimeField(default=timezone.now()) + last_party_date = models.DateTimeField(default=timezone.now()) + number_of_incubators = models.BigIntegerField(default=0) + herd_age_by_day = models.IntegerField(default=0) + herd_age_by_week = models.IntegerField(default=0) + number_of_party = models.IntegerField(default=0) + communication_type = models.CharField(max_length=30, null=True) + cooperative = models.CharField(max_length=50, null=True) + date_of_register = models.DateTimeField(default=timezone.now()) + unit_status = models.CharField(max_length=20, null=True) + active = models.BooleanField(default=True) + identity_documents = models.JSONField(null=True) + samasat_user_code = models.CharField(max_length=20, null=True) + base_order = models.BigIntegerField(null=True) + incubation_date = models.DateTimeField(null=True) + wallet_amount = models.BigIntegerField(default=0) + city = models.IntegerField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="poultry_wallet", + null=True + ) + wallet_id_foreign_key = models.IntegerField(default=1) + + poultry_id_key = models.IntegerField(default=1) + Lat = models.FloatField(null=True) + Long = models.FloatField(null=True) + date = models.DateTimeField(null=True) + killing_ave_age = models.IntegerField(default=1) + active_left_over = models.IntegerField(default=0) + killing_ave_count = models.IntegerField(default=0) + killing_ave_weight = models.IntegerField(default=0) + killing_live_weight = models.IntegerField(default=0) + killing_carcasses_weight = models.IntegerField(default=0) + killing_loss_weight_percent = models.IntegerField(default=0) + real_killing_ave_weight = models.FloatField(default=0) + real_killing_live_weight = models.FloatField(default=0) + real_killing_carcasses_weight = models.FloatField(default=0) + real_killing_loss_weight_percent = models.FloatField(default=0) + interest_license_id = models.CharField(max_length=100, null=True) + order_limit = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(Poultry, self).save(*args, **kwargs) + + +# مدل مربوط به مستاجر مرغدار +class PoultryTenant(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="poultry_tenant", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="poultry_tenant_bank_info", + null=True + ) + fullname = models.CharField(max_length=150, null=True) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + natinal_id = models.CharField(max_length=10, null=True) + mobile = models.CharField(max_length=11, null=True, default="") + + def save(self, *args, **kwargs): + super(PoultryTenant, self).save(*args, **kwargs) + + +class PoultryAllowCityProvince(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="poultry_allow", + null=True + ) + poultry_id_foreign_key = models.IntegerField(null=True) + poultry_allow_city_province_id_key = models.IntegerField(null=True) + city = models.BooleanField(default=False) + province = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(PoultryAllowCityProvince, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت جوجه ریزی مرغدار +class PoultryHatching(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="poultry_hatching_user", + null=True + ) + chain_company = models.ForeignKey( + ChainCompany, + on_delete=models.CASCADE, + related_name="poultry_hatching_chain_company", + null=True + ) + has_chain_company = models.BooleanField(default=False) + poultry_id_foreign_key = models.IntegerField(null=True) + poultry_hatching_id_key = models.IntegerField(null=True) + quantity = models.BigIntegerField(default=0) + losses = models.BigIntegerField(default=0) + left_over = models.BigIntegerField(null=True) + killed_quantity = models.BigIntegerField(default=0) + extra_killed_quantity = models.BigIntegerField(default=0) + governmental_killed_quantity = models.FloatField(default=0) + governmental_quantity = models.FloatField(default=0) + free_killed_quantity = models.FloatField(default=0) + free_quantity = models.FloatField(default=0) + chain_killed_quantity = models.FloatField(default=0) + chain_killed_weight = models.FloatField(default=0) + out_province_killed_weight = models.FloatField(default=0) + out_province_killed_quantity = models.FloatField(default=0) + export_killed_weight = models.FloatField(default=0) + export_killed_quantity = models.FloatField(default=0) + total_commitment = models.FloatField(default=0) + commitment_type = models.CharField(max_length=20, default='govermental') + total_commitment_quantity = models.FloatField(default=0) + total_free_commitment_quantity = models.FloatField(default=0) + total_free_commitment_weight = models.FloatField(default=0) + total_killed_weight = models.FloatField(default=0) + total_average_killed_weight = models.FloatField(default=0) + request_left_over = models.BigIntegerField(default=0) + hall = models.IntegerField(default=0) + date = models.DateTimeField(null=True) + predicate_date = models.DateTimeField(null=True) + chicken_breed = models.CharField(max_length=200, null=True) + period = models.BigIntegerField(default=0, null=True) + allow_hatching = models.CharField(max_length=20, default='pending') + state = models.CharField(max_length=50, default="pending") + archive = models.BooleanField(default=False) + violation = models.BooleanField(default=False) + message = models.CharField(max_length=500, null=True) + registrar = models.JSONField(null=True) + breed = models.JSONField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + last_change = models.JSONField(null=True) + chicken_age = models.IntegerField(default=1) + now_age = models.IntegerField(default=1) + latest_hatching_change = models.JSONField(null=True) + violation_report = models.TextField(null=True) + violation_message = models.TextField(null=True) + violation_image = models.JSONField(null=True) + violation_reporter = models.CharField(max_length=200, null=True) + violation_report_date = models.DateTimeField(null=True) + violation_report_editor = models.CharField(max_length=200, null=True) + violation_report_edit_date = models.DateTimeField(null=True) + total_losses = models.BigIntegerField(default=0) + direct_losses = models.BigIntegerField(default=0) + direct_losses_inputer = models.CharField(max_length=200, null=True) + direct_losses_date = models.DateTimeField(null=True) + direct_losses_editor = models.CharField(max_length=200, null=True) + direct_losses_last_edit_date = models.DateTimeField(null=True) + end_period_losses_inputer = models.CharField(max_length=200, null=True) + end_period_losses_date = models.DateTimeField(null=True) + end_period_losses_editor = models.CharField(max_length=200, null=True) + end_period_losses_last_edit_date = models.DateTimeField(null=True) + breeding_unique_id = models.CharField(max_length=20, null=True) + licence_number = models.CharField(max_length=20, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + first_date_input_archive = models.DateTimeField(null=True) + second_date_input_archive = models.DateTimeField(null=True) + input_archiver = models.CharField(max_length=20, null=True) + output_archive_date = models.DateTimeField(null=True) + output_archiver = models.CharField(max_length=20, null=True) + bar_difference_request_weight = models.FloatField(default=0) + bar_difference_request_quantity = models.FloatField(default=0) + total_disease_losses = models.BigIntegerField(default=0) # مجموع تلفات ناشی از بیماری + total_flock_destruction = models.BigIntegerField(default=0) # مجموع معدوم‌سازی گله + total_normal_flock_losses = models.BigIntegerField(default=0) # مجموع تلفات عادی گله + total_force_majeure_losses = models.BigIntegerField(default=0) # مجموع تلفات ناشی از عوامل قهری و طبیعی + total_fire_losses = models.BigIntegerField(default=0) # مجموع تلفات ناشی از آتش‌سوزی + health_certificate = models.CharField(max_length=100, null=True) + samasat_discharge_percentage = models.IntegerField(default=0) + PersonTypeName = models.CharField(max_length=200, null=True, blank=True) + InteractTypeName = models.CharField(max_length=200, null=True, blank=True) + UnionTypeName = models.CharField(max_length=200, null=True, blank=True) + CertId = models.CharField(max_length=200, null=True, blank=True) + increase_quantity = models.IntegerField(default=0) + tenant_fullname = models.CharField(max_length=300, null=True, blank=True) + tenant_national_code = models.CharField(max_length=50, null=True, blank=True) + tenant_mobile = models.CharField(max_length=20, null=True, blank=True) + tenant_city = models.CharField(max_length=200, null=True, blank=True) + has_tenant = models.BooleanField(default=False) + archive_date = models.DateTimeField(null=True) + unknown = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + self.total_killed_weight = ( + (self.governmental_killed_quantity or 0) + + (self.free_killed_quantity or 0) + + (self.out_province_killed_weight or 0) + + (self.chain_killed_weight or 0) + + (self.export_killed_weight or 0) + + (self.bar_difference_request_weight or 0) + ) + + managed_losses_total = 0 + management_model = globals().get('HatchingLossManagement') + if management_model: + management = management_model.get_active() + else: + management = None + if management: + for management_field, loss_field in management_model.LOSS_FIELD_MAPPING.items(): + if getattr(management, management_field, False): + managed_losses_total += getattr(self, loss_field, 0) or 0 + + effective_losses = managed_losses_total if managed_losses_total else (self.losses or 0) + self.total_losses = effective_losses + (self.direct_losses or 0) + + self.killed_quantity = ( + (self.governmental_quantity or 0) + + (self.free_quantity or 0) + + (self.out_province_killed_quantity or 0) + + (self.chain_killed_quantity or 0) + + (self.export_killed_quantity or 0) + + (self.bar_difference_request_quantity or 0) + ) + self.total_average_killed_weight = round(self.total_killed_weight / self.killed_quantity, + 2) if self.killed_quantity > 0 else 0 + calculated_left_over = ( + (self.quantity or 0) + + (self.increase_quantity or 0) + - (self.killed_quantity or 0) + - (self.total_losses or 0) + ) + self.left_over = calculated_left_over if calculated_left_over > 0 else 0 + super(PoultryHatching, self).save(*args, **kwargs) + + +class EvacuationHatchingDetail(BaseModel): + # گزارشات تلفات جوجه ریزی + hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="evacuation_details", + null=True, + blank=True + ) + PartIdCode = models.CharField(max_length=200, null=True, blank=True) + RequestId = models.CharField(max_length=200, null=True, blank=True) + MoReportId = models.CharField(max_length=200, null=True, blank=True) + ReportType = models.IntegerField(null=True, blank=True) + ReportTypeString = models.CharField(max_length=255, null=True, blank=True) + ReportDate = models.CharField(max_length=200, null=True, blank=True) + ReportDateShamsi = models.CharField(max_length=200, null=True, blank=True) + MoReason = models.TextField(null=True, blank=True) + MoDate = models.CharField(max_length=200, null=True, blank=True) + MoDateShamsi = models.CharField(max_length=200, null=True, blank=True) + MoStartDay = models.IntegerField(null=True, blank=True) + MoEndDay = models.IntegerField(null=True, blank=True) + MoReportSubId = models.CharField(max_length=200, null=True, blank=True) + ReportStatus = models.IntegerField(null=True, blank=True) + GoodCount = models.IntegerField(null=True, blank=True) + Message = models.TextField(null=True, blank=True) + ErrorCode = models.IntegerField(null=True, blank=True) + IsDeleted = models.BooleanField(default=False) + RegDate = models.CharField(max_length=200, null=True, blank=True) + RegDateShamsi = models.CharField(max_length=200, null=True, blank=True) + RegDateShamsiWithTime = models.CharField(max_length=200, null=True, blank=True) + RegDateShamsiOnlyTime = models.CharField(max_length=200, null=True, blank=True) + ExternalId = models.CharField(max_length=200, null=True, blank=True) + StringId = models.CharField(max_length=200, null=True, blank=True) + IsPersisted = models.BooleanField(default=False) + AllowInsert = models.BooleanField(default=False) + AllowUpdate = models.BooleanField(default=False) + ModalCss = models.CharField(max_length=255, null=True, blank=True) + GridContainerParametersModel = models.CharField(max_length=255, null=True, blank=True) + MenuUserAccess = models.CharField(max_length=255, null=True, blank=True) + MenuUserAccessId = models.IntegerField(null=True, blank=True) + LogTableName = models.CharField(max_length=255, null=True, blank=True) + LogTableAlias = models.CharField(max_length=255, null=True, blank=True) + PageTitle = models.CharField(max_length=255, null=True, blank=True) + + def save(self, *args, **kwargs): + super(EvacuationHatchingDetail, self).save(*args, **kwargs) + + +class HatchingLossManagement(BaseModel): + include_total_disease_losses = models.BooleanField(default=False) + include_total_flock_destruction = models.BooleanField(default=False) + include_total_normal_flock_losses = models.BooleanField(default=False) + include_total_force_majeure_losses = models.BooleanField(default=False) + include_total_fire_losses = models.BooleanField(default=False) + + LOSS_FIELD_MAPPING = { + 'include_total_disease_losses': 'total_disease_losses', + 'include_total_flock_destruction': 'total_flock_destruction', + 'include_total_normal_flock_losses': 'total_normal_flock_losses', + 'include_total_force_majeure_losses': 'total_force_majeure_losses', + 'include_total_fire_losses': 'total_fire_losses', + } + + @classmethod + def get_active(cls): + return cls.objects.filter(trash=False).order_by('-modify_date').first() + + def as_dict(self): + return { + field: getattr(self, field, False) + for field in self.LOSS_FIELD_MAPPING.keys() + } + + +# مدل ثبت اپراتور شهرستان +class CityOperator(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_operator_user", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + city_operator_id_key = models.IntegerField(null=True) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_system_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="city_operator_bank_info", + null=True + ) + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + phone = models.CharField(max_length=20, null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_wallet", + null=True + ) + unit_name = models.CharField(max_length=50, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(CityOperator, self).save(*args, **kwargs) + + +class OutProvincePoultryRequestBuyer(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="out_province_poultry_user", + null=True + ) + + type = models.CharField(max_length=100, null=True) + fullname = models.CharField(max_length=300, null=True) + mobile = models.CharField(max_length=11, null=True) + unit_name = models.CharField(max_length=300, null=True) + city = models.CharField(max_length=300, null=True) + province = models.CharField(max_length=300, null=True) + kill_house_unique_id = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(OutProvincePoultryRequestBuyer, self).save(*args, **kwargs) + + +class Vet(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="user_profile_vet" + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="vet_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="vet_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="vet_wallet", + null=True + ) + + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + vet_id_key = models.IntegerField(null=True) + + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Vet, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست مرغدار +class PoultryRequest(BaseModel): + user = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + related_name="poultry_request", + null=True + ) + city_operator = models.ForeignKey( + CityOperator, + on_delete=models.CASCADE, + related_name="poultry_request_city_operator", + null=True + ) + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="poultry_request_poultry", + null=True + ) + hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="poultry_request_hatching", + null=True + ) + out_province_poultry_request_buyer = models.ForeignKey( + OutProvincePoultryRequestBuyer, + on_delete=models.CASCADE, + related_name="poultry_request_hatching", + null=True + ) + vet_farm = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_poultry_request", + null=True + ) + city_operator_id_foreign_key = models.IntegerField(null=True) + poultry_id_foreign_key = models.IntegerField(null=True) + poultry_hatching_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_key = models.IntegerField(null=True) + quantity = models.BigIntegerField(default=0) + previous_quantity = models.BigIntegerField(default=0) + remain_quantity = models.BigIntegerField(default=0) + first_quantity = models.BigIntegerField(default=0) + losses = models.BigIntegerField(default=0) + send_date = models.DateTimeField(null=True) + chicken_breed = models.CharField(max_length=200, null=True) + financial_operation = models.CharField(max_length=100, null=True) + Index_weight = models.FloatField(null=True) + amount = models.FloatField(default=0) + state = models.JSONField(default=dict, null=True) + state_process = models.CharField(max_length=50, default="pending") + province_state = models.CharField(max_length=50, default="pending") + order_code = models.BigIntegerField(null=True) + general_order_code = models.BigIntegerField(null=True) + message = models.CharField(max_length=500, null=True) + inspector = models.CharField(max_length=30, null=True) + union = models.BooleanField(default=False) + awaiting_payment = models.BooleanField(default=False) + assignment = models.BooleanField(default=False) + auction = models.BooleanField(default=False) + fee = models.FloatField(default=0) + final_state = models.CharField(max_length=50, default="pending") + cell_type = models.JSONField(default=dict, null=True) + kill_house_list = models.JSONField(null=True) + registrar = models.JSONField(null=True) + buyer = models.JSONField(null=True) + out = models.BooleanField(default=False) + export = models.BooleanField(default=False) + free_sale_in_province = models.BooleanField(default=False) + vet = models.BooleanField(default=False) + archive = models.BooleanField(default=False) + direct_buying = models.BooleanField(default=False) + direct_buying_kill_place = models.CharField(max_length=100, null=True) + direct_buying_buyer_info = models.JSONField(null=True) + selling_without_city = models.BooleanField(default=False) + # clearance_code = models.BigIntegerField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + quarantine_code = models.CharField(max_length=200, null=True) + quarantine_quantity = models.IntegerField(default=0) + quarantine_code_registrar = models.JSONField(null=True) + + out_province_driver_info = models.JSONField(null=True) + out_province_request_canceller = models.JSONField(null=True) + out_province_request_cancel = models.BooleanField(default=False) + freezing = models.BooleanField(default=False) + approved_price = models.BooleanField(default=False) + wage = models.FloatField(default=0) + total_wage_amount = models.BigIntegerField(default=0) + union_share = models.BigIntegerField(default=0) + union_share_percent = models.FloatField(default=0) + company_share = models.BigIntegerField(default=0) + company_share_percent = models.FloatField(default=0) + guilds_share = models.BigIntegerField(default=0) + guilds_share_percent = models.FloatField(default=0) + city_share = models.BigIntegerField(default=0) + city_share_percent = models.FloatField(default=0) + wallet_share = models.BigIntegerField(default=0) + wallet_share_percent = models.FloatField(default=0) + other_share = models.BigIntegerField(default=0) + other_share_percent = models.FloatField(default=0) + archive_wage = models.BooleanField(default=False) + wage_pay = models.BooleanField(default=False) + has_wage = models.BooleanField(default=False) + sms = models.BooleanField(default=False) + payer_type = models.CharField(max_length=20, null=True) + buyer_mobile = models.CharField(max_length=11, null=True) + buyer_fullname = models.CharField(max_length=200, null=True) + buyer_city = models.CharField(max_length=200, null=True) + buyer_province = models.CharField(max_length=200, null=True) + payer_fullname = models.CharField(max_length=200, null=True) + agent = models.JSONField(null=True) + hatching_left_over = models.IntegerField(default=0) + killing_age = models.IntegerField(default=1) + killer_kill_house_unit_name = models.CharField(max_length=300, null=True) + killer_kill_house_city = models.CharField(max_length=300, null=True) + killer_kill_house_province = models.CharField(max_length=300, null=True) + kill_house_unique_id = models.CharField(max_length=100, null=True) + payment_link = models.CharField(max_length=300, null=True) + interface_number = models.CharField(max_length=11, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + price_confirmation = models.BooleanField(default=False) + price_confirmation_code = models.CharField(max_length=10, null=True) + input_price_confirmation_code = models.CharField(max_length=10, null=True) + fine = models.BooleanField(default=False) + fine_amount = models.BigIntegerField(default=0) + fine_coefficient = models.FloatField(default=0) + market = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(PoultryRequest, self).save(*args, **kwargs) + + +class PoultryRequestQuarantineCode(BaseModel): + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_request_code", + null=True + ) + quarantine_code = models.CharField(max_length=200, null=True) + traffic_code = models.CharField(max_length=200, null=True) + registrar = models.CharField(max_length=200, null=True) + register_date = models.DateTimeField(null=True) + quarantine_quantity = models.IntegerField(default=0) + system_quarantine_quantity = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(PoultryRequestQuarantineCode, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست مرغدار +class TotalPoultryRequestQuantity(BaseModel): + quantity = models.BigIntegerField(default=0) + accepted_quantity = models.BigIntegerField(default=0) + returned_quantity = models.BigIntegerField(default=0) + first_quantity = models.BigIntegerField(default=0) + city_accepted_quantity = models.BigIntegerField(default=0) + allocated_quantity = models.BigIntegerField(default=0) + direct_buying_quantity = models.BigIntegerField(default=0) + number_of_poultry = models.BigIntegerField(default=0) + rejected_quantity = models.BigIntegerField(default=0) + waiting_quantity = models.BigIntegerField(default=0) + number_of_kill_house = models.BigIntegerField(default=0) + input_quantity = models.BigIntegerField(default=0) + assignableQuantity = models.BigIntegerField(default=0) + kill_requests_quantity = models.BigIntegerField(default=0) + date = models.DateTimeField(default=datetime.now()) + age_up_45 = models.BigIntegerField(default=0, null=True) + total_poultry_request_quantity_id_key = models.IntegerField(null=True) + + def save(self, *args, **kwargs): + super(TotalPoultryRequestQuantity, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست مزایده مرغدار +class PoultryRequestAuction(BaseModel): + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_request_auction", + null=True) + pricing = models.ForeignKey( + Pricing, + on_delete=models.CASCADE, + related_name="poultry_request_auction_pricing", + null=True + ) + fee = models.FloatField(default=0, null=True) + hour = models.CharField(max_length=10, null=True) + auction_date = models.DateTimeField(null=True) + state = models.CharField(max_length=10, default='inactive') + + def save(self, *args, **kwargs): + super(PoultryRequestAuction, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست بورسی مرغدار +class PoultryRequestExchange(BaseModel): + user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name="poultry_request_exchange", null=True) + quantity = models.BigIntegerField(default=0, null=True) + send_date = models.DateTimeField(null=True) + hatching_date = models.DateTimeField(null=True) + chicken_breed = models.CharField(max_length=20, null=True) + Index_weight = models.FloatField(null=True) + fee = models.FloatField(null=True) + order_code = models.IntegerField(null=True) + longitude = models.FloatField(default=0) + latitude = models.FloatField(default=0) + address = models.TextField() + age = models.IntegerField(default=0, null=True) + inspector = models.CharField(max_length=30, null=True) + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + super(PoultryRequestExchange, self).save(*args, **kwargs) + + +# مدل ثبت اپراتور کشتارگاه +class KillHouseOperator(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="kill_house_operator_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="kill_house_system_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="kill_house_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="kill_house_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + kill_house_operator_id_key = models.IntegerField(null=True) + wallet_amount = models.BigIntegerField(default=0) + killer = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseOperator, self).save(*args, **kwargs) + + +class Car(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="user_car", + null=True + ) + driver_name = models.CharField(max_length=500, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + type_car = models.CharField(max_length=50, null=True) + type = models.CharField(max_length=50, null=True) + transport_type = models.CharField(max_length=50, null=True) + pelak = models.CharField(max_length=200, null=True) + capocity = models.CharField(max_length=50, null=True) + weight_without_load = models.CharField(max_length=50, null=True) + health_code = models.CharField(max_length=100, null=True) + status = models.CharField(max_length=50, default="inactive") + active = models.BooleanField(default=True) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="car_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="car_wallet", + null=True + ) + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + phone = models.CharField(max_length=20, null=True) + registrar = models.JSONField(null=True) + active_state = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(Car, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت کشتارگاه +class KillHouse(BaseModel): + user = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + related_name="user_killhouse", + null=True) + userprofile = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="system_user_kill_house" + ) + address = models.ForeignKey( + Address, + on_delete=models.CASCADE, + related_name="killhouse_address", + null=True) + system_address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="killhouse_system_address", + null=True) + kill_house_operator = models.ForeignKey( + KillHouseOperator, + on_delete=models.CASCADE, + related_name="system_kill_house_operator", + null=True) + + cars = models.ManyToManyField( + Car, + related_name='kill_house_car', + null=True, blank=True) + + system_address_id_foreign_key = models.IntegerField(null=True) + kill_house_operator_id_foreign_key = models.IntegerField(null=True) + kill_house_id_key = models.IntegerField(null=True) + shift_work_from = models.CharField(max_length=50, null=True) + shift_work_to = models.CharField(max_length=50, null=True) + name = models.CharField(max_length=50, null=True) + car = models.JSONField(default=dict, null=True) + capacity = models.FloatField(default=0) + killing_race = models.CharField(max_length=20, null=True) + phone = models.CharField(max_length=20, null=True) + alternate_number = models.CharField(max_length=20, null=True) + killer = models.BooleanField(default=False) + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + type = models.CharField(max_length=100, default='public') + out_province = models.BooleanField(default=False) + has_pos = models.BooleanField(default=False) + show_exclusive = models.BooleanField(default=True) + company_gateway_percent = models.IntegerField(default=0) + union_gateway_percent = models.IntegerField(default=0) + guilds_gateway_percent = models.IntegerField(default=0) + other_gateway_percent = models.IntegerField(default=0) + total_kill_capacity = models.FloatField(default=0) + total_kill_capacity_percent = models.FloatField(default=0) + extra_bar_kill_percent = models.FloatField(default=0) + max_kill_limit = models.BooleanField(default=False) + off = models.BigIntegerField(default=0) + unique_identifier = models.CharField(max_length=20, null=True) + share_debt_counting_wage = models.BooleanField(default=False) + out_province_selling_limitation = models.BooleanField(default=False) + out_province_selling_limitation_percent = models.IntegerField(default=0) + in_province_selling_limitation = models.BooleanField(default=False) + in_province_selling_limitation_percent = models.IntegerField(default=0) + market_buying = models.BooleanField(default=False) + market_buying_limitation = models.BooleanField(default=False) + market_buying_capacity_percent_status = models.BooleanField(default=False) + market_capacity_percent = models.FloatField(default=0) + market_light_capacity = models.BooleanField(default=False) + market_light_capacity_percent = models.FloatField(default=0) + poultry_payment_limitation = models.BooleanField(default=False) + quota = models.BooleanField(default=False) + quota_max_kill_limit = models.BooleanField(default=False) + quota_request = models.BooleanField(default=False) + quota_custom = models.BooleanField(default=False) + free_quota = models.FloatField(default=0) + governmental_quota = models.FloatField(default=0) + quota_custom_quantity = models.FloatField(default=0) + out_province_governmental_selling_percent = models.FloatField(default=0) + out_province_free_selling_percent = models.FloatField(default=0) + out_province_free_buying_commitment_percent = models.FloatField(default=0) + in_province_governmental_selling_percent = models.FloatField(default=0) + in_province_free_selling_percent = models.FloatField(default=0) + segmentation_governmental_percent = models.FloatField(default=0) + segmentation_free_selling_percent = models.FloatField(default=0) + cold_house_governmental_percent = models.FloatField(default=0) + cold_house_free_percent = models.FloatField(default=0) + governmental_selling_permission = models.BooleanField(default=False) + free_selling_permission = models.BooleanField(default=False) + free_sale_form_governmental_quota = models.BooleanField(default=False) + free_sale_from_free_quota_in_province = models.BooleanField(default=False) + total_input_warehouse_weight = models.FloatField(default=0) + total_input_warehouse_governmental_weight = models.FloatField(default=0) + total_input_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_governmental_weight = models.FloatField(default=0) + total_remain_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_weight = models.FloatField(default=0) + total_selling_in_province_governmental_weight = models.FloatField(default=0) + total_selling_in_province_free_weight = models.FloatField(default=0) + total_selling_out_province_governmental_weight = models.FloatField(default=0) + total_selling_out_province_free_weight = models.FloatField(default=0) + total_segmentation_governmental_weight = models.FloatField(default=0) + total_segmentation_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_weight = models.FloatField(default=0) + total_in_province_free_bars_weight = models.FloatField(default=0) + total_out_province_buying_bars_weight = models.FloatField(default=0) + pos_allocated_weight = models.FloatField(default=0) + pos_governmental_allocated_weight = models.FloatField(default=0) + pos_free_allocated_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + total_segmentation_weight = models.FloatField(default=0) + total_cold_house_weight = models.FloatField(default=0) + total_cold_house_governmental_weight = models.FloatField(default=0) + total_cold_house_free_weight = models.FloatField(default=0) + ware_house_archive_weight = models.FloatField(default=0) + ware_house_archive_governmental_weight = models.FloatField(default=0) + ware_house_archive_free_weight = models.FloatField(default=0) + total_commitment_governmental_weight = models.FloatField(default=0) + total_commitment_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_commitment_weight = models.FloatField(default=0) + total_in_province_free_bars_commitment_weight = models.FloatField(default=0) + total_out_province_buying_bars_commitment_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_remain_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_remain_weight = models.FloatField(default=0) + total_commitment_selling_out_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_out_province_free_weight = models.FloatField(default=0) + total_commitment_cold_house_governmental_weight = models.FloatField(default=0) + total_commitment_cold_house_free_weight = models.FloatField(default=0) + total_commitment_segmentation_governmental_weight = models.FloatField(default=0) + total_commitment_segmentation_free_weight = models.FloatField(default=0) + maximum_load_volume_increase = models.FloatField(default=0) + maximum_load_volume_reduction = models.FloatField(default=0) + ware_house_remaining_percent_limitation = models.FloatField(default=0) + ware_house_remaining_percent_limitation_status = models.BooleanField(default=False) + ware_house_remaining_weight_limitation = models.FloatField(default=0) + ware_house_remaining_weight_limitation_status = models.BooleanField(default=False) + ware_house_remaining_weight_archive_percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + self.total_segmentation_weight = self.total_segmentation_governmental_weight + self.total_segmentation_free_weight + self.total_cold_house_weight = self.total_cold_house_governmental_weight + self.total_cold_house_free_weight + self.total_input_warehouse_governmental_weight = self.total_in_province_governmental_bars_weight + self.total_input_warehouse_free_weight = self.total_in_province_free_bars_weight + self.total_out_province_buying_bars_weight + self.total_input_warehouse_weight = self.total_input_warehouse_governmental_weight + self.total_input_warehouse_free_weight + self.total_selling_warehouse_governmental_weight = self.total_selling_in_province_governmental_weight + self.total_selling_out_province_governmental_weight + self.total_segmentation_governmental_weight + self.total_cold_house_governmental_weight + self.pos_governmental_allocated_weight + self.total_selling_warehouse_free_weight = self.total_selling_in_province_free_weight + self.total_selling_out_province_free_weight + self.total_segmentation_free_weight + self.total_cold_house_free_weight + self.pos_free_allocated_weight + self.total_selling_warehouse_weight = self.total_selling_warehouse_governmental_weight + self.total_selling_warehouse_free_weight + self.total_remain_warehouse_governmental_weight = ( + self.total_input_warehouse_governmental_weight - self.total_selling_warehouse_governmental_weight) - self.ware_house_archive_governmental_weight + self.total_remain_warehouse_free_weight = ( + self.total_input_warehouse_free_weight - self.total_selling_warehouse_free_weight) - self.ware_house_archive_free_weight + self.total_remain_warehouse_weight = self.total_input_warehouse_weight - self.total_selling_warehouse_weight + # self.total_commitment_governmental_weight = int((self.in_province_governmental_selling_percent/100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_selling_in_province_governmental_weight = self.total_in_province_governmental_bars_commitment_weight + self.total_commitment_selling_out_province_governmental_weight = int(( + self.out_province_governmental_selling_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_cold_house_governmental_weight = int(( + self.cold_house_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_segmentation_governmental_weight = int(( + self.segmentation_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + # self.total_commitment_free_weight = int((self.in_province_governmental_selling_percent/100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + + self.total_commitment_selling_in_province_free_weight = self.total_in_province_free_bars_commitment_weight + self.total_out_province_buying_bars_commitment_weight + self.total_commitment_selling_out_province_free_weight = int(( + self.out_province_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_cold_house_free_weight = int(( + self.cold_house_free_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_segmentation_free_weight = int(( + self.segmentation_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_selling_in_province_governmental_remain_weight = self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight if ( + self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight) > 0 else 0 + self.total_commitment_selling_in_province_free_remain_weight = self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight if ( + self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight) > 0 else 0 + + super(KillHouse, self).save(*args, **kwargs) + + +class ChainAllocation(BaseModel): + poultry_hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="poultry_hatching_chain_allocation", + null=True + ) + chain_company = models.ForeignKey( + ChainCompany, + on_delete=models.CASCADE, + related_name="chain_company_allocation", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="chain_company_allocation_kill_house", + null=True + ) + date = models.DateTimeField(null=True) + state = models.CharField(max_length=50, default="pending") + vet_farm_state = models.CharField(max_length=50, default="pending") + quantity = models.BigIntegerField(default=0) + weight = models.FloatField(default=0) + index_weight = models.FloatField(default=0) + quarantine_code = models.CharField(max_length=200, null=True) + message = models.TextField(null=True) + remover = models.JSONField(null=True) + seconder = models.JSONField(null=True) + registerer = models.JSONField(null=True) + quarantine_code_registrar = models.JSONField(null=True) + wage = models.FloatField(default=0) + total_wage_amount = models.BigIntegerField(default=0) + union_share = models.BigIntegerField(default=0) + union_share_percent = models.FloatField(default=0) + company_share = models.BigIntegerField(default=0) + company_share_percent = models.FloatField(default=0) + guilds_share = models.BigIntegerField(default=0) + guilds_share_percent = models.FloatField(default=0) + city_share = models.BigIntegerField(default=0) + city_share_percent = models.FloatField(default=0) + wallet_share = models.BigIntegerField(default=0) + wallet_share_percent = models.FloatField(default=0) + other_share = models.BigIntegerField(default=0) + other_share_percent = models.FloatField(default=0) + driver_name = models.CharField(max_length=100, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + type_car = models.CharField(max_length=100, null=True) + pelak = models.CharField(max_length=100, null=True) + health_code = models.CharField(max_length=100, null=True) + buyer_name = models.CharField(max_length=100, null=True) + buyer_mobile = models.CharField(max_length=11, null=True) + province = models.CharField(max_length=50, null=True) + city = models.CharField(max_length=50, null=True) + company_name = models.CharField(max_length=100, null=True) + company_user_fullname = models.CharField(max_length=100, null=True) + company_user_mobile = models.CharField(max_length=11, null=True) + company_user_province = models.CharField(max_length=50, null=True) + company_user_city = models.CharField(max_length=50, null=True) + out_province = models.BooleanField(default=False) + archive_wage = models.BooleanField(default=False) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ChainAllocation, self).save(*args, **kwargs) + + +class KillHouseWareHouse(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="ware_house_kill_house", + null=True) + bar_quantity = models.BigIntegerField(default=0) + allocated_quantity = models.BigIntegerField(default=0) + bar_live_weight = models.FloatField(default=0) + number_of_carcasses = models.BigIntegerField(default=0) + updated_number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + updated_weight_of_carcasses = models.FloatField(default=0) + ave_weight_of_carcasses = models.FloatField(default=0) + update_ave_weight_of_carcasses = models.FloatField(default=0) + free_bar_quantity = models.BigIntegerField(default=0) + number_of_free_carcasses = models.BigIntegerField(default=0) + free_weight_of_carcasses = models.FloatField(default=0) + total_bar_quantity = models.BigIntegerField(default=0) + total_number_of_carcasses = models.BigIntegerField(default=0) + update_total_number_of_carcasses = models.BigIntegerField(default=0) + final_total_number_of_carcasses = models.BigIntegerField(default=0) + total_weight_of_carcasses = models.FloatField(default=0) + update_total_weight_of_carcasses = models.FloatField(default=0) + final_total_weight_of_carcasses = models.FloatField(default=0) + allocated_total_number_of_carcasses = models.BigIntegerField(default=0) + allocated_total_weight_of_carcasses = models.FloatField(default=0) + remain_total_number_of_carcasses = models.BigIntegerField(default=0) + remain_total_weight_of_carcasses = models.FloatField(default=0) + pre_cold_number_of_carcasses_self_ware_house = models.BigIntegerField(default=0) + pre_cold_weight_of_carcasses_self_ware_house = models.FloatField(default=0) + pre_cold_number_of_carcasses_to_ware_house = models.BigIntegerField(default=0) + pre_cold_weight_of_carcasses_to_ware_house = models.FloatField(default=0) + freezing_quantity = models.BigIntegerField(default=0) + freezing_weight = models.FloatField(default=0) + free_sale_quantity = models.BigIntegerField(default=0) + free_sale_weight = models.FloatField(default=0) + final_registration = models.BooleanField(default=False) + + date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(KillHouseWareHouse, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت کشتارگاه +class KillHouseAllowVet(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_allow", + null=True) + kill_house_id_foreign_key = models.IntegerField(null=True) + kill_house_allow_vet_id_key = models.IntegerField(null=True) + + allow = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseAllowVet, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت کشتارگاه +class KillHousePercentage(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="percent_killhouse", + null=True) + kill_house_for_killer = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="killer_kill_house", + null=True) + + kill_house_for_killer_id_foreign_key = models.IntegerField(null=True) + kill_house_id_foreign_key = models.IntegerField(null=True) + kill_house_percentage_id_key = models.IntegerField(null=True) + percent = models.FloatField(default=0) + last_guilds_update_date = models.CharField(max_length=100, null=True) + guilds_quantity = models.IntegerField(default=0) + guilds_weight = models.FloatField(default=0) + quantity = models.BigIntegerField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + change_data = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(KillHousePercentage, self).save(*args, **kwargs) + + +# مدل مربوط به اضافه کردن راننده به کشتاگاه +class KillHouseDriver(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="user_driver", + null=True + ) + driver_name = models.CharField(max_length=500, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + type_car = models.CharField(max_length=50, null=True) + type = models.CharField(max_length=50, null=True) + pelak = models.CharField(max_length=200, null=True) + capocity = models.CharField(max_length=50, null=True) + weight_without_load = models.CharField(max_length=50, null=True) + health_code = models.CharField(max_length=100, null=True) + status = models.CharField(max_length=50, default="inactive") + active = models.BooleanField(default=True) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="driver_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="driver_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + kill_house_driver_id_key = models.IntegerField(null=True) + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + phone = models.CharField(max_length=20, null=True) + registrar = models.JSONField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + active_state = models.BooleanField(default=True) + archive = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(KillHouseDriver, self).save(*args, **kwargs) + + +# مدل مربوط به اضافه کردن ماشین به کشتاگاه +class KillHouseADDCAR(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_add_car", + null=True + ) + driver = models.ForeignKey( + KillHouseDriver, + on_delete=models.CASCADE, + related_name="kill_house_add_car_driver", + null=True + ) + kill_house_id_foreign_key = models.IntegerField(null=True) + driver_id_foreign_key = models.IntegerField(null=True) + kill_house_add_car_id_key = models.IntegerField(null=True) + status = models.CharField(max_length=50, default="inactive") + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + active_state = models.BooleanField(default=True) + archive = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(KillHouseADDCAR, self).save(*args, **kwargs) + + +# مدل بررسی درخواست های شهرستان که شامل تایید یا رد درخواست مرغدار +class CityOperatorCheckRequest(BaseModel): + city_operator = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + related_name="user_city_operator", + null=True + ) + city_operator_system = models.ForeignKey( + CityOperator, + on_delete=models.CASCADE, + related_name="system_city_operator", + null=True + ) + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_check", + null=True + ) + city_operator_system_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_foreign_key = models.IntegerField(null=True) + city_operator_check_request_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, null=True) + message = models.CharField(max_length=500, null=True) + allow_hatching = models.BooleanField(null=True) + show_province = models.BooleanField(default=True) + province_accept = models.BooleanField(default=False) + province_state = models.CharField(max_length=20, default='pending') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(CityOperatorCheckRequest, self).save(*args, **kwargs) + + +# مدل ثبت اپراتور استان +class ProvinceOperator(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="province_operator_user", + null=True + ) + + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="province_system_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="province_operator_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="province_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + province_operator_id_key = models.IntegerField(null=True) + wallet_amount = models.BigIntegerField(default=0) + identity_documents = models.JSONField(null=True) + phone = models.CharField(max_length=20, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceOperator, self).save(*args, **kwargs) + + +class ProvinceCheckOperatorOutRequest(BaseModel): + province_operator_system = models.ForeignKey( + ProvinceOperator, + on_delete=models.CASCADE, + related_name="system_province_operator_out", + null=True + ) + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="province_poultry_out_request", + null=True + ) + + province_operator_system_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_foreign_key = models.IntegerField(null=True) + province_operator_check_out_request_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=50, null=True) + + message = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceCheckOperatorOutRequest, self).save(*args, **kwargs) + + +# مدل مربوط به بررسی درخواست های استان که شامل تایید یا رد درخواست های شهرستان +class ProvinceCheckOperatorRequest(BaseModel): + province_operator = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + related_name="user_province_operator", + null=True + ) + + province_operator_system = models.ForeignKey( + ProvinceOperator, + on_delete=models.CASCADE, + related_name="system_province_operator", + null=True + ) + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="province_poultry_request", + null=True + ) + city_request_Poultry = models.ForeignKey( + CityOperatorCheckRequest, + on_delete=models.CASCADE, + related_name="Poultry_city_request_to_province", null=True + ) + province_operator_system_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_foreign_key = models.IntegerField(null=True) + city_request_poultry_id_foreign_key = models.IntegerField(null=True) + province_operator_check_request_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=50, null=True) + quantity = models.BigIntegerField(default=0, null=True) + fee = models.FloatField(null=True) + total_weight_at_end = models.FloatField(default=0, null=True) + total_cost_at_end = models.FloatField(null=True) + paid_state = models.CharField(max_length=20, default="pending") + province_show_kill_house = models.CharField(max_length=20, default="pending") + factor_state = models.CharField(max_length=20, default="pending") + message = models.CharField(max_length=200, null=True) + financial_archive = models.CharField(max_length=20, default="pending") + deposit_allocation_archive = models.CharField(max_length=20, default="pending") + end_state = models.CharField(max_length=20, default='active') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceCheckOperatorRequest, self).save(*args, **kwargs) + + +# مدل مربوط به بررسی درخواست های استان که شامل تایید یا رد درخواست های شهرستان +class ProvinceRequestAction(BaseModel): + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="province_request_auction_poultry", + null=True + ) + province_operator_system = models.ForeignKey( + ProvinceOperator, + on_delete=models.CASCADE, + related_name="system_province_operator_auction", + null=True + ) + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + super(ProvinceRequestAction, self).save(*args, **kwargs) + + +class ProvincePercentLeftOver(BaseModel): + percent = models.FloatField(default=0, null=True) + + def save(self, *args, **kwargs): + super(ProvincePercentLeftOver, self).save(*args, **kwargs) + + +class ShareOfAllocation(BaseModel): + province = models.ForeignKey( + Province, + on_delete=models.CASCADE, + related_name="share_province", + null=True) + province_id_foreign_key = models.IntegerField(null=True) + share_of_allocation_id_key = models.IntegerField(null=True) + central_union = models.FloatField(default=0, null=True) + province_union = models.FloatField(default=0, null=True) + city_union = models.FloatField(default=0, null=True) + fanava = models.FloatField(default=0, null=True) + central_control_system = models.FloatField(default=0, null=True) + company = models.FloatField(default=0, null=True) + vet = models.FloatField(default=0, null=True) + total = models.FloatField(default=0, null=True) + state = models.CharField(max_length=20, null=True) + date = models.DateTimeField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + self.total = self.central_union + self.province_union + self.city_union + self.fanava + self.company + super(ShareOfAllocation, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست بورسی کشتارگاه +class KillHouseRequestExchange(BaseModel): + user = models.ForeignKey(UserProfile, on_delete=models.CASCADE, related_name="kill_house_request_exchange", + null=True) + kill_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, + related_name="kill_house_exchange_kill_house", + null=True) + quantity = models.BigIntegerField(default=0, null=True) + send_date1 = models.DateTimeField(null=True) + send_date2 = models.DateTimeField(null=True) + chicken_breed = models.JSONField(default=[], null=True) + Index_weight = models.FloatField(default=0, null=True) + fee = models.FloatField(default=0, null=True) + longitude = models.FloatField(default=0) + latitude = models.FloatField(default=0) + address = models.TextField() + age1 = models.IntegerField(default=0, null=True) + age2 = models.IntegerField(default=0, null=True) + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + super(KillHouseRequestExchange, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست بورسی رزرو کشتارگاه +class KillHouseRequestExchangeReserve(BaseModel): + kill_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, + related_name="kill_house_request_exchange_kill_house", + null=True) + # poultry_exchange = models.ForeignKey(PoultryRequestExchange, on_delete=models.CASCADE, + # related_name="kill_house_request_exchange_poultry", + # null=True) + # quantity = models.BigIntegerField(default=0, null=True) + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + super(KillHouseRequestExchangeReserve, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست بورسی رزرو کشتارگاه +class KillHouseRequestAction(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_request_auction_kill_house", + null=True) + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="kill_house_request_auction_poultry", + null=True) + fee = models.FloatField(default=0, null=True) + date = models.DateTimeField(null=True) + + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + super(KillHouseRequestAction, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست بورسی رزرو کشتارگاه +class KillHouseRequestActionWinner(BaseModel): + kill_house_request_auction = models.ForeignKey( + KillHouseRequestAction, + on_delete=models.CASCADE, + related_name="kill_house_request_auction_kill_house", + null=True) + fee = models.FloatField(default=0, null=True) + quantity = models.BigIntegerField(default=0, null=True) + + def save(self, *args, **kwargs): + super(KillHouseRequestActionWinner, self).save(*args, **kwargs) + + +# مدل مربوط به تایید یا رد درخواست مرغدار که رزرو شده توسط کشتارگاه +class PoultryRequestExchangeAccept(BaseModel): + poultry_request_exchange = models.ForeignKey(PoultryRequestExchange, on_delete=models.CASCADE, + related_name="poultry_request_exchange_accept", null=True) + kill_house_request_exchange_reserve = models.ForeignKey(KillHouseRequestExchangeReserve, on_delete=models.CASCADE, + related_name="poultry_request_exchange_kill_house_accept", + null=True) + state = models.CharField(max_length=15, default='pending') + message = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(PoultryRequestExchangeAccept, self).save(*args, **kwargs) + + +# مدل مربوط اضافه کردن ماشین به درخواست بورسی کشتارگاه +class KillHouseRequestExchangeAddCar(BaseModel): + kill_house_reserve = models.ForeignKey(KillHouseRequestExchangeReserve, on_delete=models.CASCADE, + related_name="kill_house_request_accept_reserve", + null=True) + cars = models.JSONField(default=dict, null=True) + + def save(self, *args, **kwargs): + super(KillHouseRequestExchangeAddCar, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت درخواست کشتار از سمت کشتارگاه +class KillRequest(BaseModel): + kill_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, related_name="kill", null=True) + slaughter_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, related_name="slaughter_kill_req", + null=True) + kill_house_id_foreign_key = models.IntegerField(null=True) + slaughter_house_id_foreign_key = models.IntegerField(null=True) + kill_request_id_key = models.IntegerField(null=True) + kill_capacity = models.IntegerField(null=True) + previous_kill_capacity = models.IntegerField(default=0, null=True) + remain_quantity_for_poultry = models.IntegerField(default=0) + remain_quantity = models.IntegerField(null=True) + recive_time = models.CharField(max_length=50, null=True) + recive_date = models.DateTimeField(null=True) + state = models.CharField(max_length=20, default='pending') + province_state = models.CharField(max_length=20, default='pending') + province_quantity = models.IntegerField(null=True) + cars = models.JSONField(null=True, default=dict) + buy_type = models.JSONField(default=dict, null=True) + weight = models.CharField(max_length=200, null=True) + weight_type = models.JSONField(default=dict, null=True) + chicken_breed = models.CharField(max_length=200, null=True) + old_chicken_breed = models.CharField(max_length=200, null=True) + message = models.CharField(max_length=200, null=True) + Index_weight = models.FloatField(null=True) + first_average_weight = models.FloatField(default=0) + second_average_weight = models.FloatField(default=0) + factor_amount = models.FloatField(default=0) + allocated_number = models.FloatField(default=0) + factor_deposit = models.FloatField(default=0) + debt = models.BooleanField(default=False) + priority = models.BooleanField(default=False) + debt_amount = models.FloatField(default=0) + sms_payment = models.BooleanField(default=False) + automatic = models.BooleanField(default=False) + automatic_debt = models.BooleanField(default=False) + payment_info = models.JSONField(null=True) + registrar = models.JSONField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + poultry = models.ForeignKey(Poultry, on_delete=models.CASCADE, related_name="poultry_kill_req", null=True) + poultry_hatching = models.ForeignKey(PoultryHatching, on_delete=models.CASCADE, + related_name="poultry_hatching_kill_req", null=True) + poultry_request = models.ForeignKey(PoultryRequest, on_delete=models.CASCADE, + related_name="poultry_request_kill_req", null=True) + free_direct_buying = models.BooleanField(default=False) + direct_buying_state = models.CharField(max_length=20, default='pending') + direct_buying_message = models.CharField(max_length=500, null=True) + direct_buying_code = models.CharField(max_length=20, null=True) + input_direct_buying_code = models.CharField(max_length=20, null=True) + export_status = models.BooleanField(default=False) + export_state = models.CharField(max_length=20, default='pending') + export_message = models.CharField(max_length=500, null=True) + export_code = models.CharField(max_length=20, null=True) + input_export_code = models.CharField(max_length=20, null=True) + export_country = models.CharField(max_length=100, null=True) + accept_reject_date = models.DateTimeField(null=True) + amount = models.FloatField(default=0) + automatic_accept = models.BooleanField(default=False) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + price_confirmation = models.BooleanField(default=False) + final_accept = models.BooleanField(default=False) + poultry_mobile = models.CharField(max_length=20, null=True) + payment_deadline_days = models.IntegerField(default=0) + payment_deadline_date = models.DateTimeField(null=True) + payment_deadline = models.BooleanField(default=False) + extension_payment_deadline_days = models.IntegerField(default=0) + extension_payment_deadline_date = models.DateTimeField(null=True) + market = models.BooleanField(default=False) + market_final_accept = models.BooleanField(default=False) + market_state = models.CharField(max_length=20, default='pending') + market_state_message = models.TextField(null=True) + market_expire_date_time = models.DateTimeField(null=True) + direct_buying_intermediary_mobile = models.CharField(max_length=20, null=True) + market_code_status = models.BooleanField(default=False) + market_code = models.CharField(max_length=20, null=True) + input_market_code = models.CharField(max_length=20, null=True) + expire_time_ten_minute = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(KillRequest, self).save(*args, **kwargs) + + +class AutomaticKillRequest(BaseModel): + active = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(AutomaticKillRequest, self).save(*args, **kwargs) + + +class KillRequestFactor(BaseModel): + kill_request = models.ForeignKey(KillRequest, on_delete=models.CASCADE, related_name="factor_kill_req", null=True) + kill_request_id_foreign_key = models.IntegerField(null=True) + kill_request_factor_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, default='pending') + amount = models.FloatField(default=0) + minimum_amount = models.FloatField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillRequestFactor, self).save(*args, **kwargs) + + +class KillRequestFactorPayment(BaseModel): + kill_request_factor = models.ForeignKey(KillRequestFactor, on_delete=models.CASCADE, related_name="kill_req_factor", + null=True) + kill_request_factor_id_foreign_key = models.IntegerField(null=True) + kill_request_factor_payment_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, default='pending') + image = models.CharField(max_length=200, null=True) + payment_code = models.BigIntegerField(default=0) + amount = models.FloatField(default=0) + remain_amount = models.FloatField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillRequestFactorPayment, self).save(*args, **kwargs) + + +# مدل مربوط به تخصیص استان به کشتارگاه +class ProvinceKillRequest(BaseModel): + killhouse_user = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_user", + null=True + ) + kill_request = models.ForeignKey( + KillRequest, + on_delete=models.CASCADE, + related_name="kill_request", + null=True + ) + province_request = models.ForeignKey( + ProvinceCheckOperatorRequest, + on_delete=models.CASCADE, + related_name="kill_house_province", + null=True + ) + + killhouse_user_id_foreign_key = models.IntegerField(null=True) + kill_request_id_foreign_key = models.IntegerField(null=True) + province_request_id_foreign_key = models.IntegerField(null=True) + province_kill_request_id_key = models.IntegerField(null=True) + quantity = models.BigIntegerField(default=0) + main_quantity = models.BigIntegerField(default=0) + total_killed_quantity = models.BigIntegerField(default=0) + first_car_allocated_quantity = models.BigIntegerField(default=0) + extra_killed_quantity = models.BigIntegerField(default=0) + total_killed_weight = models.FloatField(default=0) + extra_killed_weight = models.FloatField(default=0) + fee = models.FloatField(default=0, null=True) + wage = models.FloatField(default=0, null=True) + total_amount = models.FloatField(default=0, null=True) + total_wage_amount = models.FloatField(default=0, null=True) + prev_total_amount = models.FloatField(null=True) + state = models.CharField(max_length=20, default='pending') + vet_state = models.CharField(max_length=20, default='pending') + payment_type = models.CharField(max_length=20, null=True) + payment_dead_line = models.DateTimeField(null=True) + message = models.CharField(max_length=200, null=True) + clearance_code = models.BigIntegerField(null=True) + automatic = models.BooleanField(default=False) + dont_show_kill_house = models.BooleanField(default=False) + reviewer = models.JSONField(null=True) + total_amount_editor = models.JSONField(null=True) + delete_message = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + wage_pay = models.BooleanField(default=False) + depositor = models.JSONField(null=True) + archive_by_province = models.BooleanField(default=False) + archive_wage = models.BooleanField(default=False) + return_to_province = models.BooleanField(default=False) + archive_message = models.CharField(max_length=500, null=True) + archiver = models.JSONField(null=True) + return_archive_message = models.CharField(max_length=500, null=True) + returner = models.JSONField(null=True) + wallet_pay = models.BooleanField(default=False) + union_share = models.BigIntegerField(default=0) + union_share_percent = models.FloatField(default=0) + company_share = models.BigIntegerField(default=0) + company_share_percent = models.FloatField(default=0) + guilds_share = models.BigIntegerField(default=0) + guilds_share_percent = models.FloatField(default=0) + city_share = models.BigIntegerField(default=0) + city_share_percent = models.FloatField(default=0) + wallet_share = models.BigIntegerField(default=0) + wallet_share_percent = models.FloatField(default=0) + other_share = models.BigIntegerField(default=0) + other_share_percent = models.FloatField(default=0) + kill_house_price = models.BigIntegerField(default=0) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + payment_deadline_days = models.IntegerField(default=0) + payment_deadline_date = models.DateTimeField(null=True) + payment_deadline = models.BooleanField(default=False) + payment_deadline_archive = models.BooleanField(default=False) + payment_deadline_state = models.CharField(max_length=50, default='pending') + payment_deadline_checker_fullname = models.CharField(max_length=50, null=True) + payment_deadline_checker_mobile = models.CharField(max_length=50, null=True) + payment_deadline_check_date = models.DateTimeField(null=True) + payment_deadline_archive_message = models.TextField(null=True) + payment_deadline_supporter_message = models.TextField(null=True) + final_accept = models.BooleanField(default=False) + final_accept_registrar = models.CharField(max_length=200, null=True) + final_accept_registrar_mobile = models.CharField(max_length=20, null=True) + final_accept_date = models.DateTimeField(null=True) + payment_deadline_amount = models.BigIntegerField(default=0) + extension_payment_deadline_days = models.IntegerField(default=0) + extension_payment_deadline_date = models.DateTimeField(null=True) + fine = models.BooleanField(default=False) + fine_amount = models.BigIntegerField(default=0) + fine_coefficient = models.FloatField(default=0) + direct_buying_fine = models.BooleanField(default=False) + direct_buying_fine_amount = models.BigIntegerField(default=0) + direct_buying_fine_coefficient = models.FloatField(default=0) + direct_buying = models.BooleanField(default=False) + market = models.BooleanField(default=False) + warehouse = models.BooleanField(default=True) + return_trash = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + self.extra_killed_quantity = self.total_killed_quantity - self.main_quantity if self.total_killed_quantity - self.main_quantity > 0 else 0 + + self.quantity = self.main_quantity - self.first_car_allocated_quantity if self.main_quantity - self.first_car_allocated_quantity > 0 else 0 + super(ProvinceKillRequest, self).save(*args, **kwargs) + + +class BarDocumentStatus(BaseModel): + title = models.CharField(max_length=500, null=True) + description = models.TextField(null=True) + sms = models.BooleanField(default=False) + is_error = models.BooleanField(default=False) + priority_id = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + if self.priority_id == 0: + bar_documents_status = BarDocumentStatus.objects.filter(trash=False).order_by('priority_id').last() + self.priority_id = bar_documents_status.priority_id + 1 if bar_documents_status else 1 + super(BarDocumentStatus, self).save(*args, **kwargs) + + +# مدل ایحاد درخواست کشتار از سمت کشتارگاه با توجه به میزان تخصیص از سمت استان +class KillHouseRequest(BaseModel): + killhouse_user = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_request_user", + null=True + ) + killer = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_request_killer", + null=True + ) + kill_request = models.ForeignKey( + KillRequest, + on_delete=models.CASCADE, + related_name="kill_request_kill_house", + null=True + ) + province_request = models.ForeignKey( + ProvinceCheckOperatorRequest, + on_delete=models.CASCADE, + related_name="kill_house_province_request", + null=True + ) + province_kill_request = models.ForeignKey( + ProvinceKillRequest, + on_delete=models.CASCADE, + related_name="province_kill_house_request", + null=True + ) + kill_house_request_auction_winner = models.ForeignKey( + KillHouseRequestActionWinner, + on_delete=models.CASCADE, + related_name="kill_house_request_winner", + null=True + ) + # driver = models.ForeignKey( + # KillHouseDriver, + # on_delete=models.CASCADE, + # related_name="kill_house_request_driver", + # null=True + # ) + add_car = models.ForeignKey( + KillHouseADDCAR, + on_delete=models.CASCADE, + related_name="kill_house_request_add_car", + null=True + ) + real_add_car = models.ForeignKey( + KillHouseADDCAR, + on_delete=models.CASCADE, + related_name="kill_house_request_real_add_car", + null=True + ) + bar_document_status = models.ForeignKey( + BarDocumentStatus, + on_delete=models.CASCADE, + related_name="kill_house_request_bar_document_status", + null=True + ) + input_warehouse = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_input_warehouse", + null=True + ) + killhouse_user_id_foreign_key = models.IntegerField(null=True) + kill_request_id_foreign_key = models.IntegerField(null=True) + province_request_id_foreign_key = models.IntegerField(null=True) + province_kill_request_id_foreign_key = models.IntegerField(null=True) + add_car_id_foreign_key = models.IntegerField(null=True) + kill_house_request_id_key = models.IntegerField(null=True) + capacity = models.BigIntegerField(default=0) + quantity = models.BigIntegerField(default=0) + bar_code = models.BigIntegerField(null=True) + quarantine_quantity = models.BigIntegerField(null=True) + quarantine_code_state = models.CharField(max_length=500, null=True) + fee = models.FloatField(default=0, null=True) + time = models.CharField(max_length=20, null=True) + state = models.CharField(max_length=20, null=True) + vet_state = models.CharField(max_length=20, default='pending') + active_state = models.CharField(max_length=20, default='active') + assignment_state_archive = models.CharField(max_length=20, default='pending') + show_kill_house = models.CharField(max_length=20, default='pending') + car = models.JSONField(default=dict, null=True) + kill_house_message = models.TextField(max_length=1000, null=True) + allocation_state = models.CharField(max_length=20, null=True) + auction = models.BooleanField(default=False) + role = models.JSONField(null=True) + clearance_code = models.CharField(max_length=200, null=True) + traffic_code = models.CharField(max_length=200, null=True) + registrar_clearance_code = models.JSONField(null=True) + editor_traffic_code = models.JSONField(null=True) + bar_remover = models.JSONField(null=True) + extra_killed_quantity = models.BigIntegerField(default=0) + accepted_real_quantity = models.BigIntegerField(default=0) + accepted_real_weight = models.FloatField(default=0) + extra_killed_weight = models.FloatField(default=0) + vet_accepted_real_quantity = models.BigIntegerField(default=0) + vet_accepted_real_weight = models.FloatField(default=0) + accepted_assignment_real_quantity = models.BigIntegerField(default=0) + accepted_assignment_real_weight = models.FloatField(default=0) + message = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + ware_house_confirmation = models.BooleanField(default=False) + ware_house_accepted_real_quantity = models.BigIntegerField(default=0) + ware_house_accepted_real_weight = models.FloatField(default=0) + date_of_ware_house = models.CharField(max_length=200, null=True) + freezing = models.BooleanField(default=False) + archive_wage = models.BooleanField(default=False) + weight_loss = models.FloatField(default=0) + ware_house_input_type = models.CharField(max_length=100, null=True) + document_status = models.CharField(max_length=500, null=True) + aggregate_code = models.BigIntegerField(null=True) + aggregate_status = models.BooleanField(default=False) + calculate_status = models.BooleanField(default=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + entered_message = models.TextField(null=True) + # فیلد های استعلام از قرنطینه + inquiry_date = models.DateField(null=True) + inquiry_origin = models.CharField(max_length=100, null=True) + inquiry_destination = models.CharField(max_length=100, null=True) + inquiry_driver = models.CharField(max_length=100, null=True) + inquiry_pelak = models.CharField(max_length=100, null=True) + settlement_type = models.CharField(max_length=100, null=True) + price = models.IntegerField(default=0) + description = models.TextField(null=True) + bar_document_description = models.TextField(null=True) + image = models.CharField(max_length=500, null=True) + price_registerar = models.CharField(max_length=200, null=True) + price_registerar_role = models.CharField(max_length=100, null=True) + price_register_date = models.DateTimeField(null=True) + price_editor = models.CharField(max_length=200, null=True) + price_editor_role = models.CharField(max_length=100, null=True) + price_editor_date = models.DateTimeField(null=True) + non_receipt = models.BooleanField(default=False) + non_receipt_return = models.BooleanField(default=False) + non_receipt_return_message = models.TextField(null=True) + non_receipt_message = models.TextField(null=True) + main_non_receipt = models.BooleanField(default=False) + non_receipt_state = models.CharField(max_length=20, default='pending') + non_receipt_checker = models.CharField(max_length=200, null=True) + non_receipt_checker_message = models.TextField(null=True) + non_receipt_checker_mobile = models.CharField(max_length=20, null=True) + non_receipt_check_date = models.DateTimeField(null=True) + non_receipt_returner = models.CharField(max_length=200, null=True) + non_receipt_returner_mobile = models.CharField(max_length=20, null=True) + non_receipt_return_date = models.DateTimeField(null=True) + fine = models.BooleanField(default=False) + fine_amount = models.BigIntegerField(default=0) + fine_coefficient = models.FloatField(default=0) + document_number = models.CharField(max_length=50, null=True) + company_document = models.BooleanField(default=False) + warehouse = models.BooleanField(default=True) + warehouse_commitment_weight = models.FloatField(default=0) + return_trash = models.BooleanField(default=False) + amount = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(KillHouseRequest, self).save(*args, **kwargs) + + +# مدل مربوط به تایید یا رد درخواست کشتار تخصیص داده شده به کشتارگاه توسط کشتارگاه +class KillHouseCheckRequest(BaseModel): + province_kill_request = models.ForeignKey( + ProvinceKillRequest, + on_delete=models.CASCADE, + related_name="province_kill_house_check", + null=True + ) + province_kill_request_id_foreign_key = models.IntegerField(null=True) + kill_house_check_request_id_key = models.IntegerField(null=True) + role = models.JSONField(null=True) + state = models.CharField(max_length=20, null=True) + message = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseCheckRequest, self).save(*args, **kwargs) + + +class MostSearch(BaseModel): + searched_items = models.CharField(max_length=200, null=True) + count = models.IntegerField(default=0) + + +# مدل مربوط به ورود اطلاعات بار توسط کشتارگاه +class KillHouseAssignmentInformation(BaseModel): + kill_house_check = models.ForeignKey( + KillHouseCheckRequest, + on_delete=models.CASCADE, + related_name="kill_house_check_req", + null=True + ) + kill_house_request = models.ForeignKey( + KillHouseRequest, + on_delete=models.CASCADE, + related_name="kill_house_request_assignment", + null=True + ) + + kill_house_check_id_foreign_key = models.IntegerField(null=True) + kill_house_request_id_foreign_key = models.IntegerField(null=True) + kill_house_kill_house_assingment_information_id_key = models.IntegerField(null=True) + car_weight_without_load = models.FloatField(default=0) + car_weight_without_load_image = models.CharField(max_length=500, null=True) + car_weight_with_load = models.FloatField(default=0) + car_weight_with_load_image = models.CharField(max_length=500, null=True) + message = models.CharField(max_length=200, null=True) + net_weight = models.FloatField(default=0) + exploited_carcass = models.FloatField(default=0) + state = models.CharField(max_length=15, default='pending') + poultry = models.BooleanField(default=False) + city = models.BooleanField(default=False) + province = models.BooleanField(default=False) + unusual_casualties = models.BooleanField(default=False) + real_quantity = models.IntegerField(default=0) + importer = models.JSONField(default=dict, null=True) + protest_time = models.DateTimeField(null=True) + weight_withs_losses = models.FloatField(default=0, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + # self.net_weight = float(self.car_weight_with_load) - float(self.car_weight_without_load) + super(KillHouseAssignmentInformation, self).save(*args, **kwargs) + + +# مدل مربوط به ورود اطلاعات بار توسط کشتارگاه +class KillHouseAssignmentImages(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_images", + null=True + ) + health_certificate_image = models.CharField(max_length=500, null=True) + national_card_image = models.CharField(max_length=500, null=True) + birth_certificate_image = models.CharField(max_length=500, null=True) + police_clearance_image = models.CharField(max_length=500, null=True) + no_addiction_image = models.CharField(max_length=500, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseAssignmentImages, self).save(*args, **kwargs) + + +# مدل مربوط به ورود اطلاعات بار توسط مرغدار +class PoultryAssignmentInformation(BaseModel): + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_assignment", + null=True + ) + car_weight_without_load = models.FloatField(default=0) + car_weight_without_load_image = models.CharField(max_length=500, null=True) + car_weight_with_load = models.FloatField(default=0) + car_weight_with_load_image = models.CharField(max_length=500, null=True) + net_weight = models.FloatField(default=0) + state = models.CharField(max_length=15, default='pending') + + def save(self, *args, **kwargs): + self.net_weight = float(self.car_weight_with_load) - float(self.car_weight_without_load) + super(PoultryAssignmentInformation, self).save(*args, **kwargs) + + +# مدل مربوط به بررسی اطلاعات بار وارد شده +class ProvinceCheckInformation(BaseModel): + kill_house_assignment = models.ForeignKey( + KillHouseAssignmentInformation, + on_delete=models.CASCADE, + related_name="kill_house_assign", + null=True + ) + poultry_assignment = models.ForeignKey( + PoultryAssignmentInformation, + on_delete=models.CASCADE, + related_name="poultry_assign", + null=True + ) + province_operator = models.ForeignKey( + ProvinceOperator, + on_delete=models.CASCADE, + related_name="provinc_operator_check_info", + null=True + ) + kill_house_assignment_id_foreign_key = models.IntegerField(null=True) + province_operator_id_foreign_key = models.IntegerField(null=True) + province_check_information_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, null=True) + message = models.CharField(max_length=200, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceCheckInformation, self).save(*args, **kwargs) + + +# مدل ایجاد فاکتور توسط استان برای کشتارگاه +class ProvinceFactorToKillHouseForPoultry(BaseModel): + province_check_info = models.ForeignKey( + ProvinceCheckInformation, + on_delete=models.CASCADE, + related_name="province_info_poultry", + null=True + ) + province_check_req = models.ForeignKey( + ProvinceCheckOperatorRequest, + on_delete=models.CASCADE, + related_name="province_check_poultry", + null=True + ) + + total_weight = models.FloatField(default=0) + weight = models.FloatField(default=0) + factor_fee = models.FloatField(default=0) + factor_bar_code = models.BigIntegerField(null=True) + factor_date = models.DateTimeField(null=True) + total_price = models.FloatField(default=0) + today_price = models.FloatField(default=0) + real_weight = models.FloatField(default=0) + shares = models.JSONField(default=dict, null=True) + paid_state = models.CharField(max_length=20, default='pending') + pay_for = models.CharField(max_length=20, null=True) + kill_house_factor_info = models.CharField(max_length=20, default='pending') + bank = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="bank_card_poultry", + null=True + ) + sum_state = models.CharField(max_length=20, default='pending') + out = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + # self.total_price = self.total_weight * self.factor_fee + super(ProvinceFactorToKillHouseForPoultry, self).save(*args, **kwargs) + + +# مدل ایجاد فاکتور توسط استان برای کشتارگاه +class ProvinceFactorToKillHouse(BaseModel): + province_check_info = models.ForeignKey( + ProvinceCheckInformation, + on_delete=models.CASCADE, + related_name="province_info", + null=True + ) + poultry_factor = models.ForeignKey( + ProvinceFactorToKillHouseForPoultry, + on_delete=models.CASCADE, + related_name="province_factor_poultry", + null=True + ) + province_check_req = models.ForeignKey( + ProvinceCheckOperatorRequest, + on_delete=models.CASCADE, + related_name="province_check_province", + null=True + ) + + total_weight = models.FloatField(default=0) + weight = models.FloatField(default=0) + factor_fee = models.FloatField(default=0) + factor_bar_code = models.BigIntegerField(null=True) + factor_date = models.DateTimeField(null=True) + total_price = models.FloatField(default=0) + province_input_amount = models.FloatField(default=0) + province_input_amount_type = models.CharField(max_length=20, null=True) + province_wage = models.FloatField(default=0) + previous_amount = models.FloatField(default=0) + decreasing_amount = models.FloatField(default=0) + today_price = models.FloatField(default=0) + kill_house_factor_payment_remain = models.FloatField(default=0) + real_weight = models.FloatField(default=0) + shares = models.JSONField(default=dict, null=True) + paid_state = models.CharField(max_length=20, default='pending') + pay_for = models.CharField(max_length=20, null=True) + kill_house_factor_info = models.CharField(max_length=20, default='pending') + reason = models.TextField(null=True) + sum_state = models.CharField(max_length=20, default='pending') + factor_person_type = models.CharField(max_length=20, default='pending') + # bank = models.JSONField(default={'bank_info': 'بانک کشاورزی به نام اتحادیه تعاونی کشاورزی محمد رضا کمالوندی', + # 'bank_card': '6037654323417678', 'bank_shaba': '56678876554433223445566'}) + bank = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="bank_card_province", + null=True + ) + province_check_info_id_foreign_key = models.IntegerField(null=True) + province_check_req_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + province_factor_to_kill_house_id_key = models.IntegerField(null=True) + out = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + # self.total_price = self.total_weight * self.factor_fee + super(ProvinceFactorToKillHouse, self).save(*args, **kwargs) + + +class KillHouseFactorToPoultry(BaseModel): + province_factor = models.ForeignKey( + ProvinceFactorToKillHouseForPoultry, + on_delete=models.CASCADE, + related_name="province_factor_info_poultry", + null=True + ) + + payment_code = models.CharField(max_length=100, null=True) + state = models.CharField(max_length=20, default='pending') + payment_state = models.CharField(max_length=50, null=True) + payment_method = models.CharField(max_length=50, null=True) + factor_image = models.CharField(max_length=500, null=True) + message = models.CharField(max_length=500, null=True) + importer = models.CharField(max_length=100, null=True) + archive_state = models.CharField(max_length=50, default='pending') + + def save(self, *args, **kwargs): + super(KillHouseFactorToPoultry, self).save(*args, **kwargs) + + +# مدل ایجاد فاکتور توسط کشتارگاه برای استان +class KillHouseFactorToProvince(BaseModel): + province_factor = models.ForeignKey( + ProvinceFactorToKillHouse, + on_delete=models.CASCADE, + related_name="province_factor_info", + null=True + ) + + province_factor_id_foreign_key = models.IntegerField(null=True) + kill_house_factor_to_province_id_key = models.IntegerField(null=True) + + payment_code = models.CharField(max_length=100, null=True) + state = models.CharField(max_length=20, default='pending') + payment_state = models.CharField(max_length=50, null=True) + payment_method = models.CharField(max_length=50, null=True) + factor_image = models.CharField(max_length=500, null=True) + message = models.CharField(max_length=500, null=True) + importer = models.CharField(max_length=100, null=True) + archive_state = models.CharField(max_length=50, default='pending') + first_payment = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseFactorToProvince, self).save(*args, **kwargs) + + +# مدل بررسی فاکتور کشتارگاه توسط استان +class ProvinceCheckKillHouseFactor(BaseModel): + kill_house_factor = models.ForeignKey( + KillHouseFactorToProvince, + on_delete=models.CASCADE, + related_name="province_check_factor", + null=True + ) + kill_house_factor_poultry = models.ForeignKey( + KillHouseFactorToPoultry, + on_delete=models.CASCADE, + related_name="province_check_factor_poultry", + null=True + ) + kill_house_factor_id_foreign_key = models.IntegerField(null=True) + province_check_kill_house_factor_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, null=True) + message = models.CharField(max_length=500, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceCheckKillHouseFactor, self).save(*args, **kwargs) + + +class ProvinceImportKillHouseOutFactors(BaseModel): + kill_house_factor = models.ForeignKey( + ProvinceFactorToKillHouse, + on_delete=models.CASCADE, + related_name="province_check_factor_out", + null=True + ) + kill_house_factor_poultry = models.ForeignKey( + ProvinceFactorToKillHouseForPoultry, + on_delete=models.CASCADE, + related_name="province_check_factor_poultry_out", + null=True + ) + province_check = models.ForeignKey( + ProvinceCheckOperatorRequest, + on_delete=models.CASCADE, + related_name="province_check_request", + null=True + ) + image = models.CharField(max_length=500, null=True) + amount = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(ProvinceImportKillHouseOutFactors, self).save(*args, **kwargs) + + +# مدل مریوط به تخصیصات مالی برای مرغدار و شهرستان و استان +class DepositAllocation(BaseModel): + poultry = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="allocations_poultry", + null=True + ) + poultry_request_id_foreign_key = models.IntegerField(null=True) + deposit_allocation_id_key = models.IntegerField(null=True) + + poultry_share = models.FloatField(default=0, null=True) + poultry_share_payment = models.FloatField(default=0, null=True) + poultry_share_payment_info = models.JSONField(default=list, null=True) + city_share = models.FloatField(default=0, null=True) + city_share_payment = models.FloatField(default=0, null=True) + city_share_payment_info = models.JSONField(default=list, null=True) + province_share = models.FloatField(default=0, null=True) + province_share_payment = models.FloatField(default=0, null=True) + province_share_payment_info = models.JSONField(default=list, null=True) + poultry_bank = models.JSONField(default=dict, null=True) + city_bank = models.JSONField(default=dict, null=True) + poultry_image = models.CharField(max_length=200, null=True) + city_image = models.CharField(max_length=200, null=True) + company_share = models.FloatField(default=0, null=True) + company_share_payment = models.FloatField(default=0, null=True) + company_share_payment_info = models.JSONField(default=list, null=True) + company_bank = models.JSONField(default=dict, null=True) + central_union_share = models.FloatField(default=0, null=True) + central_union_share_payment = models.FloatField(default=0, null=True) + central_union_share_payment_info = models.JSONField(default=list, null=True) + fanava_share = models.FloatField(default=0, null=True) + fanava_share_payment = models.FloatField(default=0, null=True) + fanava_share_payment_info = models.JSONField(default=list, null=True) + + deposit_allocation_state = models.CharField(max_length=20, default='pending') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(DepositAllocation, self).save(*args, **kwargs) + + +class InspectorOperator(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="inspector_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="inspector_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="province_inspector_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="inspector_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + inspector_operator_id_key = models.IntegerField(null=True) + wallet_amount = models.BigIntegerField(default=0) + active = models.BooleanField(default=True) + identity_documents = models.JSONField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + id_number = models.IntegerField(default=1) + + def save(self, *args, **kwargs): + super(InspectorOperator, self).save(*args, **kwargs) + + +# مدل مربوط به تایید یا رد پرونده توسط بازرس استان +class PovinceInspector(BaseModel): + inspector_operator = models.ForeignKey( + InspectorOperator, + on_delete=models.CASCADE, + related_name="inspector", + null=True + ) + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_request_inspector", + null=True + ) + inspector_operator_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_foreign_key = models.IntegerField(null=True) + province_inspector_id_key = models.IntegerField(null=True) + state = models.CharField(max_length=20, default='pending') + message = models.CharField(max_length=500, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(PovinceInspector, self).save(*args, **kwargs) + + +class FunctionExecutor(BaseModel): + func_name = models.CharField(max_length=200, null=True) + time_type = models.CharField(max_length=100, null=True) + cycle = models.IntegerField(default=0) + compare_time = models.DateTimeField(default=datetime.now()) + + +class ReportingFieldRoleLimitation(BaseModel): + role_name = models.ForeignKey( + Group, + on_delete=models.CASCADE, + null=True, + related_name="report_role" + ) + fields = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(ReportingFieldRoleLimitation, self).save(*args, **kwargs) + + +# مدل مربوط به آنالیز قیمت مرغ +class PriceAnalysis(models.Model): + corn_percent = models.FloatField(default=0, null=True) + corn_free_price = models.FloatField(default=0, null=True) + corn_Ration_free_price = models.FloatField(default=0, null=True) + corn_total_free_price = models.FloatField(default=0, null=True) + Soy_free_price = models.FloatField(default=0, null=True) + Soy_total_free_price = models.FloatField(default=0, null=True) + Soy_Ration_free_price = models.FloatField(default=0, null=True) + Soy_percent = models.FloatField(default=0, null=True) + Oil_percent = models.FloatField(default=0, null=True) + Oil_free_price = models.FloatField(default=0, null=True) + Oil_total_free_price = models.FloatField(default=0, null=True) + Oil_Ration_free_price = models.FloatField(default=0, null=True) + Dicalcium_free_price = models.FloatField(default=0, null=True) + Dicalcium_total_free_price = models.FloatField(default=0, null=True) + Dicalcium_Ration_free_price = models.FloatField(default=0, null=True) + Dicalcium_percent = models.FloatField(default=0, null=True) + Carbonate_free_price = models.FloatField(default=0, null=True) + Carbonate_total_free_price = models.FloatField(default=0, null=True) + Carbonate_Ration_free_price = models.FloatField(default=0, null=True) + Carbonate_percent = models.FloatField(default=0, null=True) + mineral_supplement_percent = models.FloatField(default=0, null=True) + mineral_Ration_supplement_free_price = models.FloatField(default=0, null=True) + mineral_supplement_free_price = models.FloatField(default=0, null=True) + mineral_supplement_total_free_price = models.FloatField(default=0, null=True) + vitamin_supplement_free_price = models.FloatField(default=0, null=True) + vitamin_supplement_total_free_price = models.FloatField(default=0, null=True) + vitamin_supplement_percent = models.FloatField(default=0, null=True) + vitamin_Ration_free_supplement_percent = models.FloatField(default=0, null=True) + baking_soda_free_price = models.FloatField(default=0, null=True) + baking_soda_total_free_price = models.FloatField(default=0, null=True) + baking_Ration_soda_free_price = models.FloatField(default=0, null=True) + baking_soda_percent = models.FloatField(default=0, null=True) + Salt_Ration_free_price = models.FloatField(default=0, null=True) + Salt_Ration_total_free_price = models.FloatField(default=0, null=True) + Salt_free_total_price = models.FloatField(default=0, null=True) + Salt_free_price = models.FloatField(default=0, null=True) + Salt_percent = models.FloatField(default=0, null=True) + metiunin_Ration_free_price = models.FloatField(default=0, null=True) + metiunin_free_price = models.FloatField(default=0, null=True) + metiunin_total_free_price = models.FloatField(default=0, null=True) + metiunin_percent = models.FloatField(default=0, null=True) + Lysine_Ration_free_price = models.FloatField(default=0, null=True) + Lysine_free_price = models.FloatField(default=0, null=True) + Lysine_total_free_price = models.FloatField(default=0, null=True) + Lysine_percent = models.FloatField(default=0, null=True) + threonine_free_price = models.FloatField(default=0, null=True) + threonine_total_free_price = models.FloatField(default=0, null=True) + threonine_Ration_free_price = models.FloatField(default=0, null=True) + threonine_percent = models.FloatField(default=0, null=True) + Antifungal_free_price = models.FloatField(default=0, null=True) + Antifungal_total_free_price = models.FloatField(default=0, null=True) + Antifungal_Ration_free_price = models.FloatField(default=0, null=True) + Antifungal_percent = models.FloatField(default=0, null=True) + inulin_free_price = models.FloatField(default=0, null=True) + inulin_total_free_price = models.FloatField(default=0, null=True) + inulin_Ration_free_price = models.FloatField(default=0, null=True) + inulin_percent = models.FloatField(default=0, null=True) + Fire_emulsion_free_price = models.FloatField(default=0, null=True) + Fire_total_emulsion_free_price = models.FloatField(default=0, null=True) + Fire_emulsion_Ration_free_price = models.FloatField(default=0, null=True) + Fire_emulsion_percent = models.FloatField(default=0, null=True) + Colleen_free_price = models.FloatField(default=0, null=True) + Colleen_total_free_price = models.FloatField(default=0, null=True) + Colleen_Ration_free_price = models.FloatField(default=0, null=True) + Colleen_percent = models.FloatField(default=0, null=True) + total_price = models.FloatField(default=0, null=True) + total_Ration_free_price = models.FloatField(default=0, null=True) + Vaccination_period = models.FloatField(default=0, null=True) + Multivitamin_course = models.FloatField(default=0, null=True) + period_chicken = models.FloatField(default=0, null=True) + directors_office = models.FloatField(default=0, null=True) + Water_gas_electricity_period = models.FloatField(default=0, null=True) + Water_gas_the_current_cost_of_the_period_unit = models.FloatField(default=0, null=True) + Course_repairs = models.FloatField(default=0, null=True) + Course_loss = models.FloatField(default=0, null=True) + motfar_ga_durah = models.FloatField(default=0, null=True) + Paper_reel = models.FloatField(default=0, null=True) + Course_disinfection = models.FloatField(default=0, null=True) + Lamp = models.FloatField(default=0, null=True) + total_percent = models.FloatField(default=0, null=True) + total_ration = models.FloatField(default=0, null=True) + chicken_price = models.FloatField(default=0, null=True) + + def save(self, *args, **kwargs): + super(PriceAnalysis, self).save(*args, **kwargs) + + +# مدل مربوط به ثیت نماینده دامپزشک برای کشتارگاه + + +class KillHouseVet(BaseModel): + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + null=True, + related_name="kill_house_vet_user" + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + null=True, + related_name="kill_house_vet" + ) + vet_id_foreign_key = models.IntegerField(null=True) + kill_house_id_foreign_key = models.IntegerField(null=True) + kill_house_vet_id_key = models.IntegerField(null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseVet, self).save(*args, **kwargs) + + +# مدل مربوط به تایید بار رسیده به کشتار گاه توسط نماینده دامپزشکی +class VetCheckRequest(BaseModel): + kill_house_vet = models.ForeignKey( + KillHouseVet, + on_delete=models.CASCADE, + null=True, + related_name="kill_house_user_vet" + ) + + kill_house_request = models.ForeignKey( + KillHouseRequest, + on_delete=models.CASCADE, + null=True, + related_name="kill_house_request_vet" + ) + kill_house_vet_id_foreign_key = models.IntegerField(null=True) + kill_house_request_id_foreign_key = models.IntegerField(null=True) + vet_check_request_id_key = models.IntegerField(null=True) + + state = models.CharField(max_length=20, null=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(VetCheckRequest, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت دامپزشک فارم +class VetFarm(BaseModel): + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_farm_vet", + null=True + ) + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="vet_farm_poultry", + null=True + ) + vet_id_foreign_key = models.IntegerField(null=True) + poultry_id_foreign_key = models.IntegerField(null=True) + vet_farm_id_key = models.IntegerField(null=True) + + hall = models.IntegerField(default=0) + vetfarm_losses = models.BigIntegerField(default=0) + state = models.CharField(max_length=20, default='pending') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(VetFarm, self).save(*args, **kwargs) + + +# مدل مربوط به ثبت دامپزشک فارم +class VetFarmInspection(BaseModel): + vet_farm = models.ForeignKey(VetFarm, + on_delete=models.CASCADE, + related_name="vet_farm_inspection", + null=True + ) + poultry_hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="vet_farm_inspection_poultry_hatching", + null=True + ) + + vet_farm_id_foreign_key = models.IntegerField(null=True) + poultry_hatching_id_foreign_key = models.IntegerField(null=True) + vet_farm_inspection_id_key = models.IntegerField(null=True) + + hall = models.IntegerField(default=0) + topic = models.CharField(max_length=500, null=True) + description = models.TextField(null=True) + Losses = models.BigIntegerField(default=0) + image = models.JSONField(null=True) + longitude = models.FloatField(default=0) + latitude = models.FloatField(default=0) + state = models.CharField(max_length=20, default='pending') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(VetFarmInspection, self).save(*args, **kwargs) + + +# مدل مربوط ثبت درخواست مرغ منجمد +class WareHouseFactor(BaseModel): + customer = models.CharField(max_length=50, null=True) + national_code = models.CharField(max_length=20, null=True) + letter_number = models.BigIntegerField(null=True) + letter_number_jahad = models.BigIntegerField(null=True) + date = models.DateTimeField(null=True) + mobile = models.CharField(max_length=11, null=True) + product_type = models.JSONField(default=dict, null=True) + weight = models.FloatField(default=0, null=True) + fee = models.FloatField(default=0, null=True) + wage = models.FloatField(default=0, null=True) + total_wage = models.FloatField(default=0, null=True) + total_fee = models.FloatField(default=0, null=True) + total_cost = models.FloatField(default=0, null=True) + Complications = models.FloatField(default=0, null=True) + tax = models.FloatField(default=0, null=True) + discount = models.FloatField(default=0, null=True) + name_of_bank_user = models.CharField(max_length=200, null=True) + card = models.CharField(max_length=16, null=True) + shaba = models.CharField(max_length=100, null=True) + state = models.CharField(max_length=100, default='pending') + account = models.CharField(max_length=100, null=True) + mark = models.CharField(max_length=100, default='pending') + considerations = models.TextField(null=True) + first_operator = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + null=True, + related_name="user_first_operator" + ) + second_operator = models.ForeignKey( + UserProfile, + on_delete=models.CASCADE, + null=True, + related_name="user_second_operator" + ) + + def save(self, *args, **kwargs): + super(WareHouseFactor, self).save(*args, **kwargs) + + +# مدل مربوط به اضافه کردن راننده به کشتاگاه +class DriverRequestCancel(BaseModel): + Kill_house_add_car = models.ForeignKey( + KillHouseADDCAR, + on_delete=models.CASCADE, + related_name="cancel_request_car", + null=True + ) + kill_house_request = models.ForeignKey( + KillHouseRequest, + on_delete=models.CASCADE, + related_name="cancel_request", + null=True + ) + + message = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(DriverRequestCancel, self).save(*args, **kwargs) + + +class PaymentDeadLine(BaseModel): + days = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(PaymentDeadLine, self).save(*args, **kwargs) + + +class MonthlyProfitPercentage(BaseModel): + days = models.IntegerField(default=0) + percent = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(MonthlyProfitPercentage, self).save(*args, **kwargs) + + +class PercentageOfLosses(BaseModel): + houre = models.IntegerField(default=0) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(PercentageOfLosses, self).save(*args, **kwargs) + + +class KillHousePercentageOfLosses(BaseModel): + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(KillHousePercentageOfLosses, self).save(*args, **kwargs) + + +class KillHouseComplaint(BaseModel): + bar = models.ForeignKey( + KillHouseAssignmentInformation, + on_delete=models.CASCADE, + related_name="bar_information", + null=True + ) + title = models.CharField(max_length=200, null=True) + description = models.TextField() + image = models.JSONField(null=True) + percent = models.FloatField(default=0) + state = models.CharField(max_length=20, default='pending') + message = models.CharField(max_length=20, null=True) + registrar = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(KillHouseComplaint, self).save(*args, **kwargs) + + +class CheckKillHouseComplaint(BaseModel): + camplaint = models.ForeignKey( + KillHouseComplaint, + on_delete=models.CASCADE, + related_name="check_complaint", + null=True + ) + state = models.CharField(max_length=20, null=True) + message = models.CharField(max_length=20, null=True) + + def save(self, *args, **kwargs): + super(CheckKillHouseComplaint, self).save(*args, **kwargs) + + +class Itransaction(BaseModel): + wallet = models.ForeignKey(Wallet, + related_name="itranseaction_wallet", + on_delete=models.CASCADE, + null=True) + transfer_amount = models.FloatField(null=True) + transaction_type = models.CharField(max_length=20, null=True) + payment_code = models.BigIntegerField(null=True, default=0) + state = models.CharField(max_length=20, default='pending') + make_location_state = models.CharField(max_length=20, null=True) + file_id = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(Itransaction, self).save(*args, **kwargs) + + +class Debt(BaseModel): + cost = models.IntegerField(null=True) + description = models.TextField(null=True) + image = models.CharField(max_length=300, null=True) + itransaction = models.ForeignKey(Itransaction, + related_name="debtor_itransaction", + on_delete=models.CASCADE, + null=True) + + def save(self, *args, **kwargs): + super(Debt, self).save(*args, **kwargs) + + +class Penalty(BaseModel): + cost = models.IntegerField(null=True) + description = models.TextField(null=True) + image = models.CharField(max_length=300, null=True) + itransaction = models.ForeignKey(Itransaction, + related_name="penalty_itransaction", + on_delete=models.CASCADE, + null=True) + + def save(self, *args, **kwargs): + super(Penalty, self).save(*args, **kwargs) + + +class Deposit(BaseModel): + cost = models.IntegerField(null=True) + description = models.TextField(null=True) + image = models.CharField(max_length=300, null=True) + itransaction = models.ForeignKey(Itransaction, + related_name="deposit_itransaction", + on_delete=models.CASCADE, + null=True) + + def save(self, *args, **kwargs): + super(Deposit, self).save(*args, **kwargs) + + +class FinancialDocument(BaseModel): + transaction_details = models.JSONField(null=True) + type = models.CharField(max_length=30, null=True) + cost = models.FloatField(null=True) + description = models.TextField(null=True) + payment_code = models.IntegerField(null=True) + image = models.JSONField(null=True) + wallet = models.ForeignKey(Wallet, + related_name="financial_wallet", + on_delete=models.CASCADE, + null=True) + + def save(self, *args, **kwargs): + super(FinancialDocument, self).save(*args, **kwargs) + + +class FinancialTransaction(BaseModel): + type = models.CharField(max_length=50, null=True) + cost = models.IntegerField(null=True) + description = models.TextField(null=True) + image = models.JSONField(null=True) + itransaction = models.ForeignKey(Itransaction, + related_name="financial_transaction", + on_delete=models.CASCADE, + null=True) + + def save(self, *args, **kwargs): + super(FinancialTransaction, self).save(*args, **kwargs) + + +class Admin(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="user_profile_admin" + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="admin_address", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + admin_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Admin, self).save(*args, **kwargs) + + +class CheckUnusualCasualties(BaseModel): + state = models.CharField(max_length=50, null=True) + message = models.TextField(null=True) + complaint = models.ForeignKey(KillHouseComplaint, + on_delete=models.CASCADE, + null=True, + related_name="losses" + ) + role = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(CheckUnusualCasualties, self).save(*args, **kwargs) + + +# مدل کاربر جهاد +class Jahad(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="jahad_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="jahad_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="jahad_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="jahad_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + jahad_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Jahad, self).save(*args, **kwargs) + + +class CityJahad(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_jahad_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_jahad_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="city_jahad_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_jahad_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + city_jahad_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(CityJahad, self).save(*args, **kwargs) + + +class CityPoultry(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_poultry_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_poultry_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="city_poultry_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_poultry_wallet", + null=True + ) + + def save(self, *args, **kwargs): + super(CityPoultry, self).save(*args, **kwargs) + + +class ProteinGuild(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="protein_guild_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="protein_guild_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="protein_guild_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="protein_guild_wallet", + null=True + ) + + def save(self, *args, **kwargs): + super(ProteinGuild, self).save(*args, **kwargs) + + +# مدل کاربر استانداری +class ProvincialGovernment(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="government_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="government_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="government_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="government_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + provincial_government_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvincialGovernment, self).save(*args, **kwargs) + + +class VetSupervisor(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="supervisor_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="supervisor_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="supervisor_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="supervisor_wallet", + null=True + ) + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_supervisor", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + vet_id_foreign_key = models.IntegerField(null=True) + vet_superviser_id_key = models.IntegerField(null=True) + wallet_amount = models.BigIntegerField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(VetSupervisor, self).save(*args, **kwargs) + + +class CityVet(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_vet_user", + null=True + ) + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_city_vet", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_vet_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="city_vet_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_vet_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(CityVet, self).save(*args, **kwargs) + + +class LiveStockSupport(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="live_stock_support_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="live_stock_support_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="live_stock_support_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="live_stock_support_wallet", + null=True + ) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(LiveStockSupport, self).save(*args, **kwargs) + + +class Commerce(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="commerce_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="commerce_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="commerce_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="commerce_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(Commerce, self).save(*args, **kwargs) + + +class CityCommerce(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_commerce_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_commerce_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="city_commerce_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_commerce_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + +class ProvinceSupervisor(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="province_supervisor_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="province_supervisor_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="province_supervisor_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="province_supervisor_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + +class CitySupervisor(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_supervisor_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_supervisor_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="city_supervisor_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_supervisor_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(CitySupervisor, self).save(*args, **kwargs) + + +class JahadInspector(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="jahad_inspector_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="jahad_inspector_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="jahad_inspector_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="jahad_inspector_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(JahadInspector, self).save(*args, **kwargs) + + +class VetCheckAllocations(BaseModel): + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_check", + null=True + ) + + kill_house_request = models.ForeignKey( + KillHouseRequest, + on_delete=models.CASCADE, + related_name="check_kill_house_request", + null=True + ) + vet_id_foreign_key = models.IntegerField(null=True) + kill_house_request_id_foreign_key = models.IntegerField(null=True) + vet_chick_allocations_id_key = models.IntegerField(null=True) + + # + # province_kill_request = models.ForeignKey( + # ProvinceKillRequest, + # on_delete=models.CASCADE, + # related_name="check_province_kill_request", + # null=True + # ) + # poultry_request = models.ForeignKey( + # PoultryRequest, + # on_delete=models.CASCADE, + # related_name="vet_check_poultry_request", + # null=True + # ) + state = models.CharField(max_length=50, default='pending') + reviewer = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(VetCheckAllocations, self).save(*args, **kwargs) + + +class HourLimit(BaseModel): + hour = models.IntegerField(null=True) + active = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(HourLimit, self).save(*args, **kwargs) + + +class KillHouseHourLimit(BaseModel): + hour = models.IntegerField(null=True) + active = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(KillHouseHourLimit, self).save(*args, **kwargs) + + +class SmsLicense(BaseModel): + hatching = models.BooleanField(default=False) + poultry_request = models.BooleanField(default=False) + city_approval = models.BooleanField(default=False) + province_approval = models.BooleanField(default=False) + kill_request = models.BooleanField(default=False) + province_kill_request = models.BooleanField(default=False) + farm_veterinarian_approval = models.BooleanField(default=False) + kill_house_request = models.BooleanField(default=False) + kill_house_house_veterinarian_approval = models.BooleanField(default=False) + assingment_information = models.BooleanField(default=False) + confirmation_of_assingment_information = models.BooleanField(default=False) + invoicing = models.BooleanField(default=False) + invoice_payment = models.BooleanField(default=False) + invoice_payment_confirmation = models.BooleanField(default=False) + inspector_approval = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(SmsLicense, self).save(*args, **kwargs) + + +class KillHouseCreditors(BaseModel): + amount = models.FloatField(default=0) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_creditors", + null=True + ) + + def save(self, *args, **kwargs): + super(KillHouseCreditors, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseRegisterCar(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="province_allow_kill_house_register", + null=True + ) + kill_house_id_foreign_key = models.IntegerField(null=True) + province_allow_kill_house_register_car_id_key = models.IntegerField(null=True) + allow = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseRegisterCar, self).save(*args, **kwargs) + + +class ProvinceAllowPoultryChooseKillHouse(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="province_allow_kill_house_register", + null=True + ) + poultry_id_foreign_key = models.IntegerField(null=True) + province_allow_poultry_choose_kill_house_id_key = models.IntegerField(null=True) + allow = models.BooleanField(default=False) + mandatory = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceAllowPoultryChooseKillHouse, self).save(*args, **kwargs) + + +class ProvinceAllowPoultryChooseKillHouseTotal(BaseModel): + allow = models.BooleanField(default=False) + mandatory = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowPoultryChooseKillHouseTotal, self).save(*args, **kwargs) + + +class FreeSaleWithinprovince(BaseModel): + allow = models.BooleanField(default=False) + type = models.CharField(max_length=20, null=True) + weight = models.FloatField(default=0) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(FreeSaleWithinprovince, self).save(*args, **kwargs) + + +class ProvinceAllowPoultrySellFree(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="province_allow_poultry_sell_free", + null=True + ) + poultry_id_foreign_key = models.IntegerField(null=True) + province_allow_poultry_sell_free_id_key = models.IntegerField(null=True) + allow = models.BooleanField(default=False) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceAllowPoultrySellFree, self).save(*args, **kwargs) + + +class ProvinceAllowPoultrySellFreeTotal(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowPoultrySellFreeTotal, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseDirectBuying(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="province_allow_kill_house_direct_buying", + null=True + ) + allow = models.BooleanField(default=False) + export_status = models.BooleanField(default=False) + freezing_status = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseDirectBuying, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseDirectBuyingTotal(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseDirectBuyingTotal, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseRegisterGuilds(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="province_allow_kill_house_register_guilds", + null=True + ) + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseRegisterGuilds, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseRegisterGuildsTotal(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseRegisterGuildsTotal, self).save(*args, **kwargs) + + +class KillHouseDailyQuota(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="percent_killhouse_daily_quota", + null=True) + kill_request = models.ForeignKey( + KillRequest, + on_delete=models.CASCADE, + related_name="percent_kill_request_daily_quota", + null=True) + killer_kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="killer_kill_house_daily_quota", + null=True) + + kill_house_id_foreign_key = models.IntegerField(null=True) + kill_request_id_foreign_key = models.IntegerField(null=True) + killer_kill_house_id_foreign_key = models.IntegerField(null=True) + kill_house_daily_quota_id_key = models.IntegerField(null=True) + percent = models.FloatField(default=0) + quantity = models.BigIntegerField(default=0) + remain_quantity = models.BigIntegerField(default=0) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseDailyQuota, self).save(*args, **kwargs) + + +# class ProvinceAutomaticAllocation(BaseModel): +# daily_quota = models.ForeignKey( +# KillHouseDailyQuota, +# on_delete=models.CASCADE, +# related_name="percent_killhouse_daily_quota_province", +# null=True) +# +# poultry_request = models.ForeignKey( +# PoultryRequest, +# on_delete=models.CASCADE, +# related_name="poultry_request_quantity_province", +# null=True) +# quantity = models.BigIntegerField(default=0) +# +# def save(self, *args, **kwargs): +# super(ProvinceAutomaticAllocation, self).save(*args, **kwargs) + + +class ProvinceAutoAllocation(BaseModel): + daily_quota = models.ForeignKey( + KillHouseDailyQuota, + on_delete=models.CASCADE, + related_name="percent_auto_killhouse_daily_quota_province", + null=True) + + poultry_request = models.ForeignKey( + PoultryRequest, + on_delete=models.CASCADE, + related_name="poultry_request_auto_quantity_province", + null=True) + province_kill_request = models.ForeignKey( + ProvinceKillRequest, + on_delete=models.CASCADE, + related_name="province_kill_request_auto_quantity_province", + null=True) + + daily_quota_id_foreign_key = models.IntegerField(null=True) + poultry_request_id_foreign_key = models.IntegerField(null=True) + province_kill_request_id_foreign_key = models.IntegerField(null=True) + province_auto_allocation_id_key = models.IntegerField(null=True) + + unauthorized_number = models.BooleanField(default=False) + + quantity = models.BigIntegerField(default=0) + allocation_order_code = models.BigIntegerField(default=0) + state = models.CharField(max_length=50, default='temporary') + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(ProvinceAutoAllocation, self).save(*args, **kwargs) + + +class AutoAcceptProvinceKillRequest(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(AutoAcceptProvinceKillRequest, self).save(*args, **kwargs) + + +class AutoMakeKillHouseRequest(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(AutoMakeKillHouseRequest, self).save(*args, **kwargs) + + +class Hall(models.Model): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="poultry_hall", + null=True + ) + + hall_number = models.IntegerField(default=1) + + def save(self, *args, **kwargs): + super(Hall, self).save(*args, **kwargs) + + +class PoultryHallProfile(models.Model): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="user_poultry_profile", + null=True + ) + hall = models.ForeignKey( + Hall, + on_delete=models.CASCADE, + related_name="hall_poultry_profile", + null=True + ) + start_date = models.DateTimeField(null=True) + end_date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(PoultryHallProfile, self).save(*args, **kwargs) + + +class TypeActivity(BaseModel): + title = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(TypeActivity, self).save(*args, **kwargs) + + +class AreaActivity(BaseModel): + title = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(AreaActivity, self).save(*args, **kwargs) + + +class GuildSteward(BaseModel): + guild = models.ForeignKey('Guilds', on_delete=models.CASCADE, related_name='guild_to_stewards') + steward = models.ForeignKey('Guilds', on_delete=models.CASCADE, related_name='steward_to_guilds') + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + unique_together = ('guild', 'steward') + + def save(self, *args, **kwargs): + super(GuildSteward, self).save(*args, **kwargs) + + +class DistributionUserLevel(BaseModel): + fa_title = models.CharField(max_length=200, null=True) + en_title = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(DistributionUserLevel, self).save(*args, **kwargs) + + +class GuildsGeneralConfigs(BaseModel): + active = models.BooleanField(default=False) + activator = models.CharField(max_length=200, null=True) + out_province_governmental_selling_percent = models.FloatField(default=0) + out_province_free_selling_percent = models.FloatField(default=0) + out_province_free_buying_commitment_percent = models.FloatField(default=0) + in_province_governmental_selling_percent = models.FloatField(default=0) + in_province_free_selling_percent = models.FloatField(default=0) + segmentation_governmental_percent = models.FloatField(default=0) + segmentation_free_selling_percent = models.FloatField(default=0) + cold_house_governmental_percent = models.FloatField(default=0) + cold_house_free_percent = models.FloatField(default=0) + governmental_selling_permission = models.BooleanField(default=False) + free_selling_permission = models.BooleanField(default=False) + free_sale_form_governmental_quota = models.BooleanField(default=False) + free_sale_from_free_quota_in_province = models.BooleanField(default=False) + total_input_warehouse_weight = models.FloatField(default=0) + total_input_warehouse_governmental_weight = models.FloatField(default=0) + total_input_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_governmental_weight = models.FloatField(default=0) + total_remain_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_weight = models.FloatField(default=0) + total_selling_in_province_governmental_weight = models.FloatField(default=0) + total_selling_in_province_free_weight = models.FloatField(default=0) + total_selling_out_province_governmental_weight = models.FloatField(default=0) + total_selling_out_province_free_weight = models.FloatField(default=0) + total_segmentation_governmental_weight = models.FloatField(default=0) + total_segmentation_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_weight = models.FloatField(default=0) + total_in_province_free_bars_weight = models.FloatField(default=0) + total_out_province_buying_bars_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + total_segmentation_weight = models.FloatField(default=0) + total_cold_house_weight = models.FloatField(default=0) + total_cold_house_governmental_weight = models.FloatField(default=0) + total_cold_house_free_weight = models.FloatField(default=0) + total_commitment_governmental_weight = models.FloatField(default=0) + total_commitment_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_commitment_weight = models.FloatField(default=0) + total_in_province_free_bars_commitment_weight = models.FloatField(default=0) + total_out_province_buying_bars_commitment_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_remain_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_remain_weight = models.FloatField(default=0) + total_commitment_selling_out_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_out_province_free_weight = models.FloatField(default=0) + total_commitment_cold_house_governmental_weight = models.FloatField(default=0) + total_commitment_cold_house_free_weight = models.FloatField(default=0) + total_commitment_segmentation_governmental_weight = models.FloatField(default=0) + total_commitment_segmentation_free_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(GuildsGeneralConfigs, self).save(*args, **kwargs) + + +class Guilds(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="guilds_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="guilds_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="guilds_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="guilds_wallet", + null=True + ) + guild_area_activity = models.ForeignKey( + AreaActivity, + on_delete=models.CASCADE, + related_name="guilds_area_activity", + null=True + ) + guild_type_activity = models.ForeignKey( + TypeActivity, + on_delete=models.CASCADE, + related_name="guilds_type_activity", + null=True + ) + cars = models.ManyToManyField( + Car, + related_name='guild_car', + null=True, blank=True) + kill_house = models.ManyToManyField( + KillHouse, + related_name='guild_kill_houses', + null=True, blank=True) + steward_kill_house = models.ManyToManyField( + KillHouse, + related_name='steward_kill_houses', + null=True, blank=True) + stewards = models.ManyToManyField( + 'self', + through='GuildSteward', + symmetrical=False, + related_name='guild_stewards', blank=True) + user_level = models.ManyToManyField( + DistributionUserLevel, + related_name='guild_user_level', + null=True, blank=True) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + provincial_government_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + guilds_id = models.CharField(max_length=50, null=True) + license_number = models.CharField(max_length=50, null=True) + guilds_name = models.CharField(max_length=100, null=True) + phone = models.CharField(max_length=100, null=True) + type_activity = models.CharField(max_length=100, null=True) + area_activity = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + steward = models.BooleanField(default=False) + has_pos = models.BooleanField(default=False) + centers_allocation = models.JSONField(null=True) + kill_house_centers_allocation = models.JSONField(null=True) + allocation_limit = models.BigIntegerField(null=True) + limitation_allocation = models.BooleanField(default=False) + # province_accept = models.BooleanField(default=True) + registerar_role = models.CharField(max_length=50, null=True) + registerar_fullname = models.CharField(max_length=100, null=True) + registerar_mobile = models.CharField(max_length=11, null=True) + kill_house_register = models.BooleanField(default=False) + steward_register = models.BooleanField(default=False) + guilds_room_register = models.BooleanField(default=False) + pos_company_register = models.BooleanField(default=False) + province_accept_state = models.CharField(max_length=20, default='accepted') + province_message = models.CharField(max_length=500, null=True) + condition = models.CharField(max_length=500, null=True) + description_condition = models.TextField(null=True) + steward_active = models.BooleanField(default=True) + steward_allocation_limit = models.BigIntegerField(null=True) + steward_limitation_allocation = models.BooleanField(default=False) + license = models.BooleanField(default=False) + license_form = models.CharField(max_length=500, null=True) + license_file = models.CharField(max_length=500, null=True) + reviewer_role = models.CharField(max_length=50, null=True) + reviewer_fullname = models.CharField(max_length=100, null=True) + reviewer_mobile = models.CharField(max_length=11, null=True) + checker_message = models.TextField(null=True) + final_accept = models.BooleanField(default=False) + temporary_registration = models.BooleanField(default=False) + role_activation = models.CharField(max_length=100, null=True) + register_code = models.CharField(max_length=100, null=True) + logged_register_code = models.CharField(max_length=100, null=True) + active_register_code = models.BooleanField(default=False) + expire_time_register_code = models.DateTimeField(null=True) + register_date_register_code = models.DateTimeField(null=True) + is_registered = models.BooleanField(default=False) + out_province_governmental_selling_percent = models.FloatField(default=0) + out_province_free_selling_percent = models.FloatField(default=0) + out_province_free_buying_commitment_percent = models.FloatField(default=0) + in_province_governmental_selling_percent = models.FloatField(default=0) + in_province_free_selling_percent = models.FloatField(default=0) + segmentation_governmental_percent = models.FloatField(default=0) + segmentation_free_selling_percent = models.FloatField(default=0) + cold_house_governmental_percent = models.FloatField(default=0) + cold_house_free_percent = models.FloatField(default=0) + governmental_selling_permission = models.BooleanField(default=False) + free_selling_permission = models.BooleanField(default=False) + free_sale_form_governmental_quota = models.BooleanField(default=False) + free_sale_from_free_quota_in_province = models.BooleanField(default=False) + total_input_warehouse_weight = models.FloatField(default=0) + total_input_warehouse_governmental_weight = models.FloatField(default=0) + total_input_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_governmental_weight = models.FloatField(default=0) + total_remain_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_weight = models.FloatField(default=0) + total_selling_in_province_governmental_weight = models.FloatField(default=0) + total_selling_in_province_free_weight = models.FloatField(default=0) + total_selling_out_province_governmental_weight = models.FloatField(default=0) + total_selling_out_province_free_weight = models.FloatField(default=0) + total_segmentation_governmental_weight = models.FloatField(default=0) + total_segmentation_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_weight = models.FloatField(default=0) + total_in_province_free_bars_weight = models.FloatField(default=0) + total_out_province_buying_bars_weight = models.FloatField(default=0) + pos_allocated_weight = models.FloatField(default=0) + pos_governmental_allocated_weight = models.FloatField(default=0) + pos_free_allocated_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + total_segmentation_weight = models.FloatField(default=0) + total_cold_house_weight = models.FloatField(default=0) + total_cold_house_governmental_weight = models.FloatField(default=0) + total_cold_house_free_weight = models.FloatField(default=0) + ware_house_archive_weight = models.FloatField(default=0) + ware_house_archive_governmental_weight = models.FloatField(default=0) + ware_house_archive_free_weight = models.FloatField(default=0) + total_commitment_governmental_weight = models.FloatField(default=0) + total_commitment_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_commitment_weight = models.FloatField(default=0) + total_in_province_free_bars_commitment_weight = models.FloatField(default=0) + total_out_province_buying_bars_commitment_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_remain_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_remain_weight = models.FloatField(default=0) + total_commitment_selling_out_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_out_province_free_weight = models.FloatField(default=0) + total_commitment_cold_house_governmental_weight = models.FloatField(default=0) + total_commitment_cold_house_free_weight = models.FloatField(default=0) + total_commitment_segmentation_governmental_weight = models.FloatField(default=0) + total_commitment_segmentation_free_weight = models.FloatField(default=0) + license_type = models.CharField(max_length=100, null=True) # نوع مجوز + license_status = models.CharField(max_length=50, null=True) # وضعیت مجوز + license_issue_date = models.DateTimeField(null=True) # تاریخ صدور مجوز + license_expire_date = models.DateTimeField(null=True) # تاریخ انقضا مجوز + company_name = models.CharField(max_length=200, null=True) # نام شرکت + union_name = models.CharField(max_length=200, null=True) + national_code = models.CharField(max_length=200, null=True) + phone_number = models.CharField(max_length=200, null=True) + company_identifier = models.CharField(max_length=100, null=True) # شناسه شرکت + is_foreign_national = models.BooleanField(default=False) # آیا اتباع است + has_partner = models.BooleanField(default=False) # آیا شریک دارد + has_inquiry = models.BooleanField(default=False) # آیا استعلام دارد + is_real_person = models.BooleanField(default=True) # حقیقی یا حقوقی + + def save(self, *args, **kwargs): + self.total_segmentation_weight = self.total_segmentation_governmental_weight + self.total_segmentation_free_weight + self.total_cold_house_weight = self.total_cold_house_governmental_weight + self.total_cold_house_free_weight + self.total_input_warehouse_governmental_weight = self.total_in_province_governmental_bars_weight + self.total_input_warehouse_free_weight = self.total_in_province_free_bars_weight + self.total_out_province_buying_bars_weight + self.total_input_warehouse_weight = self.total_input_warehouse_governmental_weight + self.total_input_warehouse_free_weight + self.total_selling_warehouse_governmental_weight = self.total_selling_in_province_governmental_weight + self.total_selling_out_province_governmental_weight + self.total_segmentation_governmental_weight + self.total_cold_house_governmental_weight + self.pos_governmental_allocated_weight + self.total_selling_warehouse_free_weight = self.total_selling_in_province_free_weight + self.total_selling_out_province_free_weight + self.total_segmentation_free_weight + self.total_cold_house_free_weight + self.pos_free_allocated_weight + self.total_selling_warehouse_weight = self.total_selling_warehouse_governmental_weight + self.total_selling_warehouse_free_weight + self.total_remain_warehouse_governmental_weight = ( + self.total_input_warehouse_governmental_weight - self.total_selling_warehouse_governmental_weight) - self.ware_house_archive_governmental_weight + self.total_remain_warehouse_free_weight = ( + self.total_input_warehouse_free_weight - self.total_selling_warehouse_free_weight) - self.ware_house_archive_free_weight + self.total_remain_warehouse_weight = self.total_input_warehouse_weight - self.total_selling_warehouse_weight + self.total_commitment_selling_in_province_governmental_weight = int( + self.total_input_warehouse_governmental_weight * (self.in_province_governmental_selling_percent / 100)) + self.total_commitment_selling_out_province_governmental_weight = int(( + self.out_province_governmental_selling_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_cold_house_governmental_weight = int(( + self.cold_house_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_segmentation_governmental_weight = int(( + self.segmentation_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_selling_in_province_free_weight = int( + self.total_input_warehouse_free_weight * (self.in_province_free_selling_percent / 100)) + self.total_commitment_selling_out_province_free_weight = int(( + self.out_province_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_cold_house_free_weight = int(( + self.cold_house_free_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_segmentation_free_weight = int(( + self.segmentation_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_selling_in_province_governmental_remain_weight = self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight if ( + self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight) > 0 else 0 + self.total_commitment_selling_in_province_free_remain_weight = self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight if ( + self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight) > 0 else 0 + super(Guilds, self).save(*args, **kwargs) + + +class GuildLegalPersonDetail(BaseModel): + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="legal_person_details", + null=True, + blank=True, + ) + status = models.BooleanField(default=False) + status_code = models.IntegerField(default=0) + api_log_id = models.CharField(max_length=100, null=True, blank=True) + + legal_person_info_dto_id = models.CharField(max_length=100, null=True, blank=True) + parent_legal_person_id = models.CharField(max_length=100, null=True, blank=True) + successful = models.BooleanField(default=False) + message = models.TextField(null=True, blank=True) + name = models.CharField(max_length=300, null=True, blank=True) + national_code = models.CharField(max_length=20, null=True, blank=True) + post_code = models.CharField(max_length=20, null=True, blank=True) + address = models.TextField(null=True, blank=True) + legal_person_type = models.CharField(max_length=100, null=True, blank=True) + register_number = models.CharField(max_length=100, null=True, blank=True) + register_unit = models.CharField(max_length=100, null=True, blank=True) + register_date = models.CharField(max_length=100, null=True, blank=True) + register_date_unix = models.BigIntegerField(default=0) + residency = models.CharField(max_length=100, null=True, blank=True) + state = models.CharField(max_length=100, null=True, blank=True) + is_settle = models.BooleanField(default=False) + settle_date = models.CharField(max_length=100, null=True, blank=True) + is_break_up = models.BooleanField(default=False) + break_up_date = models.CharField(max_length=100, null=True, blank=True) + is_branch = models.BooleanField(default=False) + branch_list = models.JSONField(null=True, blank=True) + parent_legal_person_raw = models.JSONField(null=True, blank=True) + establishment_date = models.CharField(max_length=100, null=True, blank=True) + is_db_result = models.BooleanField(default=False) + service_type = models.IntegerField(default=0) + + parent_name = models.CharField(max_length=300, null=True, blank=True) + parent_national_code = models.CharField(max_length=20, null=True, blank=True) + parent_post_code = models.CharField(max_length=20, null=True, blank=True) + parent_address = models.TextField(null=True, blank=True) + parent_legal_person_type = models.CharField(max_length=100, null=True, blank=True) + parent_register_number = models.CharField(max_length=100, null=True, blank=True) + parent_register_unit = models.CharField(max_length=100, null=True, blank=True) + parent_register_date = models.CharField(max_length=100, null=True, blank=True) + parent_register_date_unix = models.BigIntegerField(default=0) + parent_residency = models.CharField(max_length=100, null=True, blank=True) + parent_state = models.CharField(max_length=100, null=True, blank=True) + parent_is_settle = models.BooleanField(default=False) + parent_settle_date = models.CharField(max_length=100, null=True, blank=True) + parent_is_break_up = models.BooleanField(default=False) + parent_break_up_date = models.CharField(max_length=100, null=True, blank=True) + parent_is_branch = models.BooleanField(default=False) + parent_branch_list = models.JSONField(null=True, blank=True) + parent_establishment_date = models.CharField(max_length=100, null=True, blank=True) + parent_is_db_result = models.BooleanField(default=False) + parent_service_type = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(GuildLegalPersonDetail, self).save(*args, **kwargs) + + +class GuildsWareHouse(BaseModel): + guilds = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="ware_house_guilds", + null=True) + bar_quantity = models.BigIntegerField(default=0) + allocated_quantity = models.BigIntegerField(default=0) + number_of_carcasses = models.BigIntegerField(default=0) + real_number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + real_weight_of_carcasses = models.FloatField(default=0) + ave_weight_of_carcasses = models.FloatField(default=0) + allocated_total_number_of_carcasses = models.BigIntegerField(default=0) + allocated_total_weight_of_carcasses = models.FloatField(default=0) + remain_total_number_of_carcasses = models.BigIntegerField(default=0) + remain_total_weight_of_carcasses = models.FloatField(default=0) + final_registration = models.BooleanField(default=False) + date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + self.remain_total_number_of_carcasses = ( + self.number_of_carcasses - self.allocated_total_number_of_carcasses) if self.real_number_of_carcasses == 0 else ( + self.real_number_of_carcasses - self.allocated_total_number_of_carcasses) + self.remain_total_weight_of_carcasses = ( + self.weight_of_carcasses - self.allocated_total_weight_of_carcasses) if self.real_weight_of_carcasses == 0 else ( + self.real_weight_of_carcasses - self.allocated_total_weight_of_carcasses) + super(GuildsWareHouse, self).save(*args, **kwargs) + + +class Steward(BaseModel): + guilds = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_guilds", + null=True + ) + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="steward_user", + null=True + ) + active = models.BooleanField(default=True) + allocation_limit = models.BigIntegerField(null=True) + limitation_allocation = models.BooleanField(default=False) + centers_allocation = models.JSONField(null=True) + kill_house_register = models.BooleanField(default=False) + province_accept_state = models.CharField(max_length=20, default='accepted') + city = models.CharField(max_length=100, null=True) + out_province_free_selling_percent = models.FloatField(default=0) + out_province_free_buying_commitment_percent = models.FloatField(default=0) + in_province_governmental_selling_percent = models.FloatField(default=0) + in_province_free_selling_percent = models.FloatField(default=0) + segmentation_governmental_percent = models.FloatField(default=0) + segmentation_free_selling_percent = models.FloatField(default=0) + cold_house_governmental_percent = models.FloatField(default=0) + cold_house_free_percent = models.FloatField(default=0) + governmental_selling_permission = models.BooleanField(default=False) + free_selling_permission = models.BooleanField(default=False) + free_sale_form_governmental_quota = models.BooleanField(default=False) + free_sale_from_free_quota_in_province = models.BooleanField(default=False) + total_input_warehouse_weight = models.FloatField(default=0) + total_input_warehouse_governmental_weight = models.FloatField(default=0) + total_input_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_governmental_weight = models.FloatField(default=0) + total_remain_warehouse_free_weight = models.FloatField(default=0) + total_remain_warehouse_weight = models.FloatField(default=0) + total_selling_in_province_governmental_weight = models.FloatField(default=0) + total_selling_in_province_free_weight = models.FloatField(default=0) + total_selling_out_province_governmental_weight = models.FloatField(default=0) + total_selling_out_province_free_weight = models.FloatField(default=0) + total_segmentation_governmental_weight = models.FloatField(default=0) + total_segmentation_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_weight = models.FloatField(default=0) + total_in_province_free_bars_weight = models.FloatField(default=0) + total_out_province_buying_bars_weight = models.FloatField(default=0) + pos_allocated_weight = models.FloatField(default=0) + pos_governmental_allocated_weight = models.FloatField(default=0) + pos_free_allocated_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + total_segmentation_weight = models.FloatField(default=0) + total_cold_house_weight = models.FloatField(default=0) + total_cold_house_governmental_weight = models.FloatField(default=0) + total_cold_house_free_weight = models.FloatField(default=0) + ware_house_archive_weight = models.FloatField(default=0) + ware_house_archive_governmental_weight = models.FloatField(default=0) + ware_house_archive_free_weight = models.FloatField(default=0) + total_commitment_governmental_weight = models.FloatField(default=0) + total_commitment_free_weight = models.FloatField(default=0) + total_in_province_governmental_bars_commitment_weight = models.FloatField(default=0) + total_in_province_free_bars_commitment_weight = models.FloatField(default=0) + total_out_province_buying_bars_commitment_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_weight = models.FloatField(default=0) + total_commitment_selling_in_province_governmental_remain_weight = models.FloatField(default=0) + total_commitment_selling_in_province_free_remain_weight = models.FloatField(default=0) + total_commitment_selling_out_province_governmental_weight = models.FloatField(default=0) + total_commitment_selling_out_province_free_weight = models.FloatField(default=0) + total_commitment_cold_house_governmental_weight = models.FloatField(default=0) + total_commitment_cold_house_free_weight = models.FloatField(default=0) + total_commitment_segmentation_governmental_weight = models.FloatField(default=0) + total_commitment_segmentation_free_weight = models.FloatField(default=0) + + # province_accept = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + self.total_segmentation_weight = self.total_segmentation_governmental_weight + self.total_segmentation_free_weight + self.total_cold_house_weight = self.total_cold_house_governmental_weight + self.total_cold_house_free_weight + self.total_input_warehouse_governmental_weight = self.total_in_province_governmental_bars_weight + self.total_input_warehouse_free_weight = self.total_in_province_free_bars_weight + self.total_out_province_buying_bars_weight + self.total_input_warehouse_weight = self.total_input_warehouse_governmental_weight + self.total_input_warehouse_free_weight + self.total_selling_warehouse_governmental_weight = self.total_selling_in_province_governmental_weight + self.total_selling_out_province_governmental_weight + self.total_segmentation_governmental_weight + self.total_cold_house_governmental_weight + self.pos_governmental_allocated_weight + self.total_selling_warehouse_free_weight = self.total_selling_in_province_free_weight + self.total_selling_out_province_free_weight + self.total_segmentation_free_weight + self.total_cold_house_free_weight + self.pos_free_allocated_weight + self.total_selling_warehouse_weight = self.total_selling_warehouse_governmental_weight + self.total_selling_warehouse_free_weight + self.total_remain_warehouse_governmental_weight = ( + self.total_input_warehouse_governmental_weight - self.total_selling_warehouse_governmental_weight) - self.ware_house_archive_governmental_weight + self.total_remain_warehouse_free_weight = ( + self.total_input_warehouse_free_weight - self.total_selling_warehouse_free_weight) - self.ware_house_archive_free_weight + self.total_remain_warehouse_weight = self.total_input_warehouse_weight - self.total_selling_warehouse_weight + self.total_commitment_selling_in_province_governmental_weight = int( + self.total_input_warehouse_governmental_weight * (self.in_province_governmental_selling_percent / 100)) + self.total_commitment_selling_out_province_governmental_weight = int(( + self.out_province_governmental_selling_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_cold_house_governmental_weight = int(( + self.cold_house_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_segmentation_governmental_weight = int(( + self.segmentation_governmental_percent / 100) * self.total_input_warehouse_governmental_weight) if self.governmental_selling_permission else 0 + self.total_commitment_selling_in_province_free_weight = int( + self.total_input_warehouse_free_weight * (self.in_province_free_selling_percent / 100)) + self.total_commitment_selling_out_province_free_weight = int(( + self.out_province_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_cold_house_free_weight = int(( + self.cold_house_free_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_segmentation_free_weight = int(( + self.segmentation_free_selling_percent / 100) * self.total_input_warehouse_free_weight) if self.free_selling_permission else 0 + self.total_commitment_selling_in_province_governmental_remain_weight = self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight if ( + self.total_commitment_selling_in_province_governmental_weight - self.total_selling_in_province_governmental_weight) > 0 else 0 + self.total_commitment_selling_in_province_free_remain_weight = self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight if ( + self.total_commitment_selling_in_province_free_weight - self.total_selling_in_province_free_weight) > 0 else 0 + super(Steward, self).save(*args, **kwargs) + + +class StewardWareHouse(BaseModel): + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="ware_house_steward", + null=True) + bar_quantity = models.BigIntegerField(default=0) + allocated_quantity = models.BigIntegerField(default=0) + number_of_carcasses = models.BigIntegerField(default=0) + real_number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + real_weight_of_carcasses = models.FloatField(default=0) + free_bar_quantity = models.BigIntegerField(default=0) + number_of_free_carcasses = models.BigIntegerField(default=0) + weight_of_free_carcasses = models.FloatField(default=0) + ave_weight_of_carcasses = models.FloatField(default=0) + allocated_total_number_of_carcasses = models.BigIntegerField(default=0) + allocated_total_weight_of_carcasses = models.FloatField(default=0) + remain_total_number_of_carcasses = models.BigIntegerField(default=0) + remain_total_weight_of_carcasses = models.FloatField(default=0) + final_registration = models.BooleanField(default=False) + free_sale_quantity = models.BigIntegerField(default=0) + free_sale_weight = models.FloatField(default=0) + + date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(StewardWareHouse, self).save(*args, **kwargs) + + +class Dispenser(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="dispenser_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="dispenser_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="dispenser_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="dispenser_wallet", + null=True + ) + + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="dispenser_kill_house", + null=True + ) + + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="dispenser_guild", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="dispenser_steward", + null=True + ) + dispenser_type = models.CharField(max_length=100, null=True) + limitation_amount = models.FloatField(default=0) + car = models.CharField(max_length=100, null=True) + pelak = models.CharField(max_length=100, null=True) + registrar = models.CharField(max_length=200, null=True) + active = models.BooleanField(default=True) + free_sale = models.BooleanField(default=False) + free_guilds = models.BooleanField(default=False) + free_stewards = models.BooleanField(default=False) + in_use = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(Dispenser, self).save(*args, **kwargs) + + +class DispenserInformation(BaseModel): + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="dispenser_info_user", + null=True + ) + + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="dispenser_info_kill_house", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="dispenser_info_steward", + null=True + ) + fullname = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=200, null=True) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=11, null=True) + city = models.CharField(max_length=300, null=True) + province = models.CharField(max_length=300, null=True) + active = models.BooleanField(default=True) + limitation = models.BooleanField(default=False) + free_limitation = models.BooleanField(default=False) + governmental_limitation = models.BooleanField(default=False) + governmental_limitation_weight = models.FloatField(default=0) + free_limitation_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + def save(self, *args, **kwargs): + super(DispenserInformation, self).save(*args, **kwargs) + + +class NewProduct(BaseModel): + product_id = models.IntegerField(default=0) + name = models.CharField(max_length=200, null=True) + image = models.CharField(max_length=500, null=True) + sale_type = models.CharField(max_length=100, null=True) + sale_type_package_weight = models.FloatField(default=0) + approved_price_status = models.BooleanField(default=False) + approved_price = models.IntegerField(default=0) + sale_limitation_status = models.BooleanField(default=False) + sale_limitation_maximum_weight_status = models.BooleanField(default=False) + sale_limitation_maximum_weight = models.FloatField(default=0) + sale_limitation_maximum_package_status = models.BooleanField(default=False) + sale_limitation_maximum_package = models.FloatField(default=0) + sale_limitation_maximum_number_of_purchases_status = models.BooleanField(default=False) + sale_limitation_maximum_number_of_purchases = models.FloatField(default=0) + sale_limitation_maximum_number_of_purchases_type = models.CharField(max_length=100, null=True) + sale_limitation_maximum_inquiry_status = models.BooleanField(default=False) + sale_limitation_maximum_inquiry_type = models.CharField(max_length=100, null=True) + Conventional_sales_status = models.BooleanField(default=False) + Conventional_sales_weight = models.FloatField(default=0) + Conventional_sales_package = models.FloatField(default=0) + selling_more_than_inventory = models.BooleanField(default=False) + parent = models.ForeignKey( + 'self', + on_delete=models.CASCADE, + related_name="child", + null=True + ) + + def save(self, *args, **kwargs): + super(NewProduct, self).save(*args, **kwargs) + + +class RolesProducts(BaseModel): + parent_product = models.ForeignKey( + NewProduct, + on_delete=models.CASCADE, + related_name="roles_products_new_product", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="roles_products_kill_house", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="roles_products_steward", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="roles_products_guild", + null=True + ) + name = models.CharField(max_length=300, null=True) + province_governmental_carcasses_quantity = models.BigIntegerField(default=0) + province_governmental_carcasses_weight = models.BigIntegerField(default=0) + province_free_carcasses_quantity = models.BigIntegerField(default=0) + province_free_carcasses_weight = models.BigIntegerField(default=0) + receive_governmental_carcasses_quantity = models.BigIntegerField(default=0) + receive_governmental_carcasses_weight = models.BigIntegerField(default=0) + receive_free_carcasses_quantity = models.BigIntegerField(default=0) + receive_free_carcasses_weight = models.BigIntegerField(default=0) + free_buying_carcasses_quantity = models.BigIntegerField(default=0) + free_buying_carcasses_weight = models.BigIntegerField(default=0) + total_governmental_carcasses_quantity = models.BigIntegerField(default=0) + total_governmental_carcasses_weight = models.BigIntegerField(default=0) + total_free_bars_carcasses_quantity = models.BigIntegerField(default=0) + total_free_bars_carcasses_weight = models.BigIntegerField(default=0) + weight_average = models.FloatField(default=0) + total_carcasses_quantity = models.BigIntegerField(default=0) + total_carcasses_weight = models.BigIntegerField(default=0) + freezing_quantity = models.BigIntegerField(default=0) + freezing_weight = models.BigIntegerField(default=0) + loss_weight = models.BigIntegerField(default=0) + out_province_allocated_quantity = models.BigIntegerField(default=0) + out_province_allocated_weight = models.BigIntegerField(default=0) + province_allocated_quantity = models.BigIntegerField(default=0) + province_allocated_weight = models.BigIntegerField(default=0) + province_governmental_allocated_weight = models.BigIntegerField(default=0) + province_free_allocated_weight = models.BigIntegerField(default=0) + real_allocated_quantity = models.BigIntegerField(default=0) + real_allocated_weight = models.BigIntegerField(default=0) + cold_house_allocated_weight = models.BigIntegerField(default=0) + pos_allocated_weight = models.BigIntegerField(default=0) + segmentation_weight = models.BigIntegerField(default=0) + ware_house_archive_weight = models.BigIntegerField(default=0) + total_remain_quantity = models.BigIntegerField(default=0) + total_remain_weight = models.BigIntegerField(default=0) + free_price = models.IntegerField(default=0) + approved_price = models.IntegerField(default=0) + approved_price_status = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + self.total_governmental_carcasses_quantity = self.province_governmental_carcasses_quantity + self.receive_governmental_carcasses_quantity + self.total_governmental_carcasses_weight = self.province_governmental_carcasses_weight + self.receive_governmental_carcasses_weight + self.total_free_bars_carcasses_quantity = self.province_free_carcasses_quantity + self.receive_free_carcasses_quantity + self.free_buying_carcasses_quantity + self.total_free_bars_carcasses_weight = self.province_free_carcasses_weight + self.receive_free_carcasses_weight + self.free_buying_carcasses_weight + self.total_carcasses_quantity = self.total_governmental_carcasses_quantity + self.total_free_bars_carcasses_quantity + self.total_carcasses_weight = self.total_governmental_carcasses_weight + self.total_free_bars_carcasses_weight + self.real_allocated_quantity = self.province_allocated_quantity + self.out_province_allocated_quantity + self.freezing_quantity + self.real_allocated_weight = self.province_allocated_weight + self.out_province_allocated_weight + self.loss_weight + self.cold_house_allocated_weight + self.segmentation_weight + int( + self.pos_allocated_weight / 1000) + self.total_remain_quantity = self.total_carcasses_quantity - self.real_allocated_quantity + self.total_remain_weight = ( + self.total_carcasses_weight - self.real_allocated_weight) - self.ware_house_archive_weight + self.weight_average = round(self.total_carcasses_weight / self.total_carcasses_quantity, + 2) if self.total_carcasses_quantity > 0 else 0 + super(RolesProducts, self).save(*args, **kwargs) + + +class OtherProducts(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="other_products_kill_house", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="other_products_guild", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="other_products_steward", + null=True + ) + name = models.CharField(max_length=300, null=True) + unit = models.CharField(max_length=100, default='kg') + targetunit = models.CharField(max_length=100, default='g') + image = models.CharField(max_length=500, null=True) + price = models.BigIntegerField(default=0) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(OtherProducts, self).save(*args, **kwargs) + + +class BaseOutProvinceCarcassesBuyer(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="base_buyer_user", + null=True) + fullname = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=200, null=True) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=11, null=True) + unit_name = models.CharField(max_length=300, null=True) + city = models.CharField(max_length=300, null=True) + province = models.CharField(max_length=300, null=True) + isRealPerson = models.BooleanField( + default=True, + verbose_name="حقیقی=True / حقوقی=False") + status = models.BooleanField(default=False) + statusCode = models.IntegerField(null=True, blank=True) + legalPersonInfoDtoId = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonId = models.CharField( + max_length=100, + null=True, + blank=True) + successful = models.BooleanField(default=False) + message = models.TextField(null=True, blank=True) + name = models.CharField(max_length=300, null=True, blank=True) + nationalCode = models.CharField( + max_length=20, + null=True, + blank=True) + postCode = models.CharField( + max_length=20, + null=True, + blank=True) + address = models.TextField(null=True, blank=True) + legalPersonType = models.CharField( + max_length=100, + null=True, + blank=True) + registerNumber = models.CharField(max_length=50, null=True, blank=True) + registerUnit = models.CharField(max_length=100, null=True, blank=True) + registerDate = models.CharField(max_length=50, null=True, blank=True) + registerDateUnix = models.BigIntegerField(null=True, blank=True) + residency = models.CharField(max_length=100, null=True, blank=True) + state = models.CharField(max_length=100, null=True, blank=True) + isSettle = models.BooleanField(default=False) + settleDate = models.CharField(max_length=50, null=True, blank=True) + isBreakUp = models.BooleanField(default=False) + breakUpdate = models.CharField(max_length=50, null=True, blank=True) + isBranch = models.BooleanField(default=False) + branchList = models.TextField(null=True, blank=True) + establishmentDate = models.CharField(max_length=50, null=True, blank=True) + isDbResult = models.BooleanField(default=False) + serviceType = models.IntegerField(null=True, blank=True) + parentLegalPersonInfoDtoId = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonParentId = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonSuccessful = models.BooleanField(default=False) + parentLegalPersonMessage = models.TextField(null=True, blank=True) + parentLegalPersonName = models.CharField( + max_length=300, + null=True, + blank=True) + parentLegalPersonNationalCode = models.CharField( + max_length=20, + null=True, + blank=True) + parentLegalPersonPostCode = models.CharField( + max_length=20, + null=True, + blank=True) + parentLegalPersonAddress = models.TextField(null=True, blank=True) + parentLegalPersonType = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonRegisterNumber = models.CharField( + max_length=50, + null=True, + blank=True) + parentLegalPersonRegisterUnit = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonRegisterDate = models.CharField( + max_length=50, + null=True, + blank=True) + parentLegalPersonRegisterDateUnix = models.BigIntegerField( + null=True, + blank=True) + parentLegalPersonResidency = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonState = models.CharField( + max_length=100, + null=True, + blank=True) + parentLegalPersonIsSettle = models.BooleanField(default=False) + parentLegalPersonSettleDate = models.CharField( + max_length=50, + null=True, + blank=True) + parentLegalPersonIsBreakUp = models.BooleanField(default=False) + parentLegalPersonBreakUpdate = models.CharField( + max_length=50, + null=True, + blank=True) + parentLegalPersonIsBranch = models.BooleanField(default=False) + parentLegalPersonBranchList = models.TextField(null=True, blank=True) + parentLegalPersonEstablishmentDate = models.CharField( + max_length=50, + null=True, + blank=True) + parentLegalPersonIsDbResult = models.BooleanField(default=False) + parentLegalPersonServiceType = models.IntegerField( + null=True, + blank=True) + apiLogId = models.CharField(max_length=100, null=True, blank=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + self.fullname = self.first_name + " " + self.last_name + super(BaseOutProvinceCarcassesBuyer, self).save(*args, **kwargs) + + +class OutProvinceCarcassesBuyer(BaseModel): + buyer = models.ForeignKey( + BaseOutProvinceCarcassesBuyer, + on_delete=models.CASCADE, + related_name="base_buyer", + null=True) + type_activity = models.ForeignKey( + TypeActivity, + on_delete=models.CASCADE, + related_name="buyer_activity", + null=True) + Kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_buyer", + null=True) + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_buyer", + null=True) + fullname = models.CharField(max_length=200, null=True) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + national_id = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=11, null=True) + unit_name = models.CharField(max_length=300, null=True) + city = models.CharField(max_length=300, null=True) + province = models.CharField(max_length=300, null=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + self.fullname = self.first_name + " " + self.last_name + super(OutProvinceCarcassesBuyer, self).save(*args, **kwargs) + + +class Representative(BaseModel): + + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_representative", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="steward_representative", + null=True + ) + first_name = models.CharField(max_length=200, null=True) + last_name = models.CharField(max_length=200, null=True) + mobile = models.CharField(max_length=15, null=True) + city = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + limitation = models.BooleanField(default=False) + free_limitation = models.BooleanField(default=False) + governmental_limitation = models.BooleanField(default=False) + governmental_limitation_weight = models.FloatField(default=0) + free_limitation_weight = models.FloatField(default=0) + total_selling_warehouse_governmental_weight = models.FloatField(default=0) + total_selling_warehouse_free_weight = models.FloatField(default=0) + total_selling_warehouse_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(Representative, self).save(*args, **kwargs) + + +class KillHouseFreeSaleBarInformation(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_kill_house", + null=True) + + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_kill_house_product", + null=True) + buyer = models.ForeignKey( + OutProvinceCarcassesBuyer, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_buyer", + null=True) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_representative", + null=True + ) + registerar_fullname = models.CharField(max_length=100, null=True) + permission_type = models.CharField(max_length=100, null=True) + status = models.CharField(max_length=300, default='pending') + buyer_name = models.CharField(max_length=100, null=True) + buyer_mobile = models.CharField(max_length=11, null=True) + province = models.CharField(max_length=50, null=True) + city = models.CharField(max_length=50, null=True) + driver_name = models.CharField(max_length=100, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + type_car = models.CharField(max_length=100, null=True) + pelak = models.CharField(max_length=100, null=True) + clearance_code = models.CharField(max_length=50, null=True) + number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + real_number_of_carcasses = models.BigIntegerField(default=0) + real_weight_of_carcasses = models.FloatField(default=0) + quarantine_weight_of_carcasses = models.FloatField(default=0) + accepted_number_of_carcasses = models.BigIntegerField(default=0) + accepted_weight_of_carcasses = models.FloatField(default=0) + date = models.DateTimeField(null=True) + wage = models.FloatField(default=0) + archive_wage = models.BooleanField(default=False) + total_wage_amount = models.BigIntegerField(default=0) + union_share = models.BigIntegerField(default=0) + union_share_percent = models.FloatField(default=0) + company_share = models.BigIntegerField(default=0) + company_share_percent = models.FloatField(default=0) + guilds_share = models.BigIntegerField(default=0) + guilds_share_percent = models.FloatField(default=0) + city_share = models.BigIntegerField(default=0) + city_share_percent = models.FloatField(default=0) + wallet_share = models.BigIntegerField(default=0) + wallet_share_percent = models.FloatField(default=0) + other_share = models.BigIntegerField(default=0) + other_share_percent = models.FloatField(default=0) + calculate_status = models.BooleanField(default=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + sale_type = models.CharField(max_length=20, null=True) + quota = models.CharField(max_length=20, null=True) + warehouse = models.BooleanField(default=True) + registration_code = models.IntegerField(null=True) + logged_registration_code = models.IntegerField(null=True) + expire_date_time_registration_code = models.DateTimeField(null=True) + register_date_time_registration_code = models.DateTimeField(null=True) + active_expire_date_time = models.BooleanField(default=False) + system_registration_code = models.BooleanField(default=False) + expire_time_ten_minute = models.DateTimeField(null=True) + production_date = models.DateTimeField(null=True) + distribution_type = models.CharField(max_length=20, null=True) + amount = models.BigIntegerField(default=0) + total_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(KillHouseFreeSaleBarInformation, self).save(*args, **kwargs) + + +class KillHouseFreeBarInformation(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="free_bar_info_kill_house", + null=True) + exclusive_killer = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="free_bar_info_exclusive_killer", + null=True) + public_killer = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="free_bar_info_public_killer", + null=True) + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="free_bar_info_kill_house_product", + null=True) + input_warehouse = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="free_bar_input_warehouse", + null=True + ) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="free_bar_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="free_bar_representative", + null=True + ) + poultry_name = models.CharField(max_length=100, null=True) + poultry_mobile = models.CharField(max_length=11, null=True) + seller_name = models.CharField(max_length=100, null=True) + seller_mobile = models.CharField(max_length=11, null=True) + province = models.CharField(max_length=50, null=True) + city = models.CharField(max_length=50, null=True) + vet_farm_name = models.CharField(max_length=100, null=True) + vet_farm_mobile = models.CharField(max_length=11, null=True) + driver_name = models.CharField(max_length=100, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + car = models.JSONField(null=True) + clearance_code = models.JSONField(null=True) + bar_clearance_code = models.CharField(max_length=100, null=True) + quantity = models.BigIntegerField(default=0) + number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + kill_house_vet_quantity = models.BigIntegerField(default=0) + kill_house_vet_weight = models.FloatField(default=0) + kill_house_vet_state = models.CharField(max_length=50, default="pending") + date_of_accept_reject = models.DateTimeField(null=True) + acceptor_rejector = models.CharField(max_length=200, null=True) + live_weight = models.FloatField(default=0) + bar_image = models.CharField(max_length=200, null=True) + buy_type = models.CharField(max_length=50, null=True) + ware_house = models.BooleanField(default=False) + date = models.DateTimeField(null=True) + wage = models.FloatField(default=0) + total_wage_amount = models.BigIntegerField(default=0) + union_share = models.BigIntegerField(default=0) + union_share_percent = models.FloatField(default=0) + company_share = models.BigIntegerField(default=0) + company_share_percent = models.FloatField(default=0) + guilds_share = models.BigIntegerField(default=0) + guilds_share_percent = models.FloatField(default=0) + city_share = models.BigIntegerField(default=0) + city_share_percent = models.FloatField(default=0) + wallet_share = models.BigIntegerField(default=0) + wallet_share_percent = models.FloatField(default=0) + other_share = models.BigIntegerField(default=0) + other_share_percent = models.FloatField(default=0) + archive_wage = models.BooleanField(default=False) + weight_loss = models.FloatField(default=0) + calculate_status = models.BooleanField(default=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + entered_message = models.TextField(null=True) + bar_code = models.BigIntegerField(null=True) + register_type = models.CharField(max_length=250, default='manual') + register_date = models.DateTimeField(null=True) + warehouse = models.BooleanField(default=True) + warehouse_commitment_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(KillHouseFreeBarInformation, self).save(*args, **kwargs) + + +class StewardFreeBarInformation(BaseModel): + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="free_bar_info_steward", + null=True) + stewards = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="free_bar_info_stewards", + null=True) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="free_bar_info_guild", + null=True) + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="free_bar_info_steward_product", + null=True) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="free_bar_info_steward_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="free_bar_info_steward_representative", + null=True + ) + kill_house_name = models.CharField(max_length=100, null=True) + kill_house_mobile = models.CharField(max_length=11, null=True) + kill_house_vet_name = models.CharField(max_length=100, null=True) + kill_house_vet_mobile = models.CharField(max_length=11, null=True) + province = models.CharField(max_length=50, null=True) + city = models.CharField(max_length=50, null=True) + driver_name = models.CharField(max_length=100, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + car = models.CharField(max_length=100, null=True) + pelak = models.CharField(max_length=100, null=True) + number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + bar_image = models.CharField(max_length=200, null=True) + date = models.DateTimeField(null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + warehouse = models.BooleanField(default=True) + quota = models.CharField(max_length=20, null=True) + + def save(self, *args, **kwargs): + super(StewardFreeBarInformation, self).save(*args, **kwargs) + + +class StewardFreeSaleBarInformation(BaseModel): + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_steward", + null=True) + stewards = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_stewards", + null=True) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_guild", + null=True) + + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="free_sale_bar_info_steward_product", + null=True) + buyer = models.ForeignKey( + OutProvinceCarcassesBuyer, + on_delete=models.CASCADE, + related_name="steward_free_sale_bar_info_buyer", + null=True) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="steward_free_sale_bar_info_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="steward_free_sale_bar_info_representative", + null=True + ) + buyer_name = models.CharField(max_length=100, null=True) + buyer_mobile = models.CharField(max_length=11, null=True) + province = models.CharField(max_length=50, null=True) + city = models.CharField(max_length=50, null=True) + driver_name = models.CharField(max_length=100, null=True) + driver_mobile = models.CharField(max_length=11, null=True) + type_car = models.CharField(max_length=100, null=True) + pelak = models.CharField(max_length=100, null=True) + clearance_code = models.CharField(max_length=50, null=True) + number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + date = models.DateTimeField(null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + warehouse = models.BooleanField(default=True) + quota = models.CharField(max_length=20, null=True) + sale_type = models.CharField(max_length=20, null=True) + registration_code = models.IntegerField(null=True) + logged_registration_code = models.IntegerField(null=True) + expire_date_time_registration_code = models.DateTimeField(null=True) + register_date_time_registration_code = models.DateTimeField(null=True) + active_expire_date_time = models.BooleanField(default=False) + system_registration_code = models.BooleanField(default=False) + expire_time_ten_minute = models.DateTimeField(null=True) + production_date = models.DateTimeField(null=True) + distribution_type = models.CharField(max_length=20, null=True) + + def save(self, *args, **kwargs): + super(StewardFreeSaleBarInformation, self).save(*args, **kwargs) + + +class ColdHouse(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="cold_house_kill_house", + null=True + ) + live_stock_support = models.ForeignKey( + LiveStockSupport, + on_delete=models.CASCADE, + related_name="cold_house_live_stock_support", + null=True + ) + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_cold_house", + null=True + ) + + name = models.CharField(max_length=500, null=True) + province = models.CharField(max_length=200, null=True) + city = models.CharField(max_length=200, null=True) + address = models.CharField(max_length=500, null=True) + total_quantity = models.BigIntegerField(default=0) + total_weight = models.FloatField(default=0) + total_input_weight = models.BigIntegerField(default=0) + total_allocated_weight = models.BigIntegerField(default=0) + total_remain_weight = models.BigIntegerField(default=0) + active = models.BooleanField(default=True) + broadcast = models.BooleanField(default=True) + relocate = models.BooleanField(default=True) + capacity = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + self.total_remain_weight = self.total_input_weight - self.total_allocated_weight + super(ColdHouse, self).save(*args, **kwargs) + + +class StewardAllocation(BaseModel): + ware_house = models.ForeignKey( + KillHouseWareHouse, + on_delete=models.CASCADE, + related_name="ware_house_steward_allocation", + null=True + ) + steward_ware_house = models.ForeignKey( + StewardWareHouse, + on_delete=models.CASCADE, + related_name="steward_ware_house_steward_guilds_allocation", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_steward_allocation", + null=True + ) + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_steward_allocation", + null=True + ) + + guilds = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_allocation_guilds", + null=True + ) + to_steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="allocation_to_steward", + null=True + ) + to_guilds = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="allocation_to_guilds", + null=True + ) + to_kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="allocation_to_kill_house", + null=True + ) + + to_cold_house = models.ForeignKey( + ColdHouse, + on_delete=models.CASCADE, + related_name="allocation_to_cold_house", + null=True + ) + other_cold_house = models.ForeignKey( + ColdHouse, + on_delete=models.CASCADE, + related_name="allocation_to_other_cold_house", + null=True + ) + + car = models.ForeignKey( + Car, + on_delete=models.CASCADE, + related_name="steward_allocation_car", + null=True + ) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="allocation_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="allocation_representative", + null=True + ) + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="allocation_product", + null=True + ) + number_of_carcasses = models.BigIntegerField(default=0) + real_number_of_carcasses = models.BigIntegerField(default=0) + receiver_real_number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + real_weight_of_carcasses = models.FloatField(default=0) + receiver_real_weight_of_carcasses = models.FloatField(default=0) + weight_loss_of_carcasses = models.FloatField(default=0) + final_registration = models.BooleanField(default=False) + sell_type = models.CharField(max_length=100, null=True) + product_name = models.CharField(max_length=200, null=True) + seller_type = models.CharField(max_length=100, null=True) + type = models.CharField(max_length=100, null=True) + sale_type = models.CharField(max_length=100, null=True) + allocation_type = models.CharField(max_length=100, null=True) + system_registration_code = models.BooleanField(default=False) + registration_code = models.IntegerField(null=True) + amount = models.BigIntegerField(default=0) + total_amount = models.BigIntegerField(default=0) + total_amount_paid = models.BigIntegerField(default=0) + total_amount_remain = models.BigIntegerField(default=0) + logged_registration_code = models.IntegerField(null=True) + state = models.CharField(max_length=50, default='pending') + receiver_state = models.CharField(max_length=50, default='pending') + allocation_state = models.CharField(max_length=50, default='pending') + date = models.DateTimeField(null=True) + role = models.JSONField(null=True) + steward_temp_key = models.IntegerField(null=True) + approved_price_status = models.BooleanField(default=True) + calculate_status = models.BooleanField(default=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + overhead = models.BooleanField(default=False) + image = models.CharField(max_length=500, null=True) + quota = models.CharField(max_length=20, null=True) + warehouse = models.BooleanField(default=True) + steward_warehouse = models.BooleanField(default=True) + expire_date_time_registration_code = models.DateTimeField(null=True) + register_date_time_registration_code = models.DateTimeField(null=True) + active_expire_date_time = models.BooleanField(default=False) + return_trash = models.BooleanField(default=False) + return_trash_date = models.DateTimeField(null=True) + returner_trash = models.CharField(max_length=200, null=True) + interface_number = models.CharField(max_length=11, null=True) + expire_time_ten_minute = models.DateTimeField(null=True) + production_date = models.DateTimeField(null=True) + distribution_type = models.CharField(max_length=20, null=True) + Settlement_type = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + # allow = AllowRegisterCodeForStewardAllocation.objects.filter(trash=False, active=True).first() + # if allow: + # if allow and self.registration_code and self.expire_date_time_registration_code is None: + # self.expire_date_time_registration_code = datetime.now() + timedelta(minutes=int(allow.time)) + # self.active_expire_date_time = True + self.total_amount_remain = self.total_amount - self.total_amount_paid if self.total_amount - self.total_amount_paid > 0 else 0 + super(StewardAllocation, self).save(*args, **kwargs) + + +class AutomaticStewardAllocation(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_automatic_allocation", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="automatic_steward_allocation", + null=True + ) + guilds = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="automatic_guilds_allocation", + null=True + ) + number_of_carcasses = models.BigIntegerField(default=0) + real_number_of_carcasses = models.BigIntegerField(default=0) + weight_of_carcasses = models.FloatField(default=0) + real_weight_of_carcasses = models.FloatField(default=0) + final_registration = models.BooleanField(default=False) + registration_code = models.IntegerField(null=True) + logged_registration_code = models.IntegerField(null=True) + state = models.CharField(max_length=50, default='pending') + date = models.DateTimeField(null=True) + role = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(AutomaticStewardAllocation, self).save(*args, **kwargs) + + +class ProvinceAllowKillHouseChooseStewardGuilds(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="allow_kill_house_steward_guilds", + null=True + ) + + steward = models.BooleanField(default=False) + guilds = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProvinceAllowKillHouseChooseStewardGuilds, self).save(*args, **kwargs) + + +class LastUpdate(models.Model): + poultry_hatching = models.JSONField(null=True) + update_date = models.DateTimeField(null=True) + + +class HatchingLossesPermission(BaseModel): + percent = models.FloatField(default=0) + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(HatchingLossesPermission, self).save(*args, **kwargs) + + +class WagePayment(BaseModel): + province_kill_request = models.JSONField(null=True) + payment_type = models.CharField(max_length=50, null=True) + type = models.CharField(max_length=100, null=True) + total_amount = models.BigIntegerField(default=0) + total_amount_with_tax = models.BigIntegerField(default=0) + payer = models.JSONField(null=True) + tracking_code = models.CharField(max_length=100, null=True) + refId = models.CharField(max_length=100, null=True) + orderId = models.CharField(max_length=100, null=True) + authority = models.CharField(max_length=100, null=True) + cardHolderPan = models.CharField(max_length=100, null=True) + payer_info = models.CharField(max_length=200, null=True) + state = models.CharField(max_length=20, default='pending') + message = models.TextField(null=True) + link_pay = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(WagePayment, self).save(*args, **kwargs) + + +class KillHousePurchaseRequest(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_purchase_request", + null=True + ) + allow = models.BooleanField(default=True) + limitation = models.BooleanField(default=False) + total_limitation = models.BooleanField(default=False) + limitation_number = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(KillHousePurchaseRequest, self).save(*args, **kwargs) + + +class Observatory(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="observatory_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="observatory_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="observatory_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="observatory_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(Observatory, self).save(*args, **kwargs) + + +class PosCompany(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="pos_company_user", + null=True + ) + name = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + en_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(PosCompany, self).save(*args, **kwargs) + + +class PosDeviceVersion(BaseModel): + company = models.ForeignKey( + PosCompany, + on_delete=models.CASCADE, + related_name="pos_version_company", + null=True + ) + name = models.CharField(max_length=200, null=True) + code = models.IntegerField() + description = models.TextField(null=True) + enable = models.BooleanField(default=True) + remove = models.BooleanField(default=False) + link = models.TextField(null=True) + checksum = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(PosDeviceVersion, self).save(*args, **kwargs) + + class Meta: + unique_together = ('company', 'code') + + +class POSId(BaseModel): + pos_id = models.CharField(max_length=12, null=True) + info = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(POSId, self).save(*args, **kwargs) + + + + +class POSMachine(BaseModel): + pos_id = models.CharField(max_length=12, null=True) + pos_unique_id = models.CharField(max_length=6, unique=True, null=True) + token = models.CharField(max_length=36, null=True) + receiver_number = models.CharField(max_length=100, null=True) + terminal_number = models.CharField(max_length=100, null=True) + active = models.BooleanField(default=True) + multi_device = models.BooleanField(default=False) + server_register = models.BooleanField(default=False) + Lat = models.FloatField(null=True) + Long = models.FloatField(null=True) + company_name = models.CharField(max_length=200, null=True) + last_check = models.DateTimeField(null=True) + serial = models.TextField(default="") + mac = models.CharField(max_length=50, null=True) + password = models.CharField(max_length=10, null=True) + ip = models.CharField(max_length=15, default='0.0.0.0') + name = models.TextField(default="") + sdk = models.TextField(default="") + version = models.IntegerField(default=0) + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="user_pos", + null=True + ) + + owner = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="owned_pos", + null=True + ) + + current_user = models.ForeignKey( + SystemUserProfile, + on_delete=models.SET_NULL, + null=True, + related_name="current_pos" + ) + current_dispenser = models.ForeignKey( + SystemUserProfile, + on_delete=models.SET_NULL, + null=True, + related_name="current_dispenser_pos" + ) + current_representative = models.ForeignKey( + Representative, + on_delete=models.SET_NULL, + null=True, + blank=True, + related_name="representative_pos" + ) + pos_company = models.ForeignKey( + PosCompany, + on_delete=models.CASCADE, + related_name="company_pos", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_pos", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_pos", + null=True + ) + + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="cooperative_pos", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="steward_pos", + null=True + ) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="dispenser_pos", + null=True + ) + + def save(self, *args, **kwargs): + super(POSMachine, self).save(*args, **kwargs) + + +class POSAccessLevel(BaseModel): + pos = models.ForeignKey(POSMachine, on_delete=models.CASCADE, related_name='access_levels') + name = models.CharField(max_length=100, null=True) + in_province_sale = models.BooleanField(default=True) + out_province_sale = models.BooleanField(default=True) + cutting = models.BooleanField(default=True) + freezing = models.BooleanField(default=True) + warehouse = models.BooleanField(default=True) + retail = models.BooleanField(default=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(POSAccessLevel, self).save(*args, **kwargs) + + +class POSAuditLog(models.Model): + ACTION_CHOICES = ( + ('CHANGE_OWNER', 'تغییر مالک'), + ('CHANGE_CURRENT_USER', 'تغییر توزیع کننده'), + ('CHANGE_CURRENT_REPRESENTATIVE', 'تغییر نماینده'), + ('ACCESSLEVEL_UPDATE', 'بروزرسانی سطح دسترسی'), + ) + pos = models.ForeignKey(POSMachine, on_delete=models.CASCADE, related_name='audit_logs') + action = models.CharField(max_length=50, choices=ACTION_CHOICES) + performed = models.ForeignKey(SystemUserProfile, on_delete=models.SET_NULL, null=True) + old_value = models.JSONField(null=True, blank=True) + new_value = models.JSONField(null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + description = models.TextField(null=True, blank=True) + + def save(self, *args, **kwargs): + super(POSAuditLog, self).save(*args, **kwargs) + + +class POSDeviceSession(BaseModel): + pos = models.ForeignKey( + POSMachine, + on_delete=models.CASCADE, + related_name="pos_device_session", + null=True, + ) + pos_unique_id = models.CharField(max_length=6, unique=True, null=True) + version = models.IntegerField() + mac = models.CharField(max_length=50) + name = models.TextField(default="") + sdk = models.TextField(default="") + serial = models.TextField(default="") + ip = models.CharField(max_length=15, default='0.0.0.0') + password = models.CharField(max_length=10) + session_create_date = models.DateTimeField(default=datetime.now()) + session_last_seen_date = models.DateTimeField(default=datetime.now()) + lng = models.FloatField(default=0) + lot = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(POSDeviceSession, self).save(*args, **kwargs) + + +class POSTransactions(BaseModel): + pos_machine = models.ForeignKey( + POSMachine, + on_delete=models.CASCADE, + related_name="pos_machine_transaction", + null=True + ) + + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="user_pos_transaction", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_pos_transaction", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_pos_transaction", + null=True + ) + cooperative = models.ForeignKey( + Cooperative, + on_delete=models.CASCADE, + related_name="cooperative_pos_transaction", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="steward_pos_transaction", + null=True + ) + cart = models.CharField(max_length=20, null=True) + mobile = models.CharField(max_length=20, null=True) + terminal = models.CharField(max_length=100, null=True) + posid = models.CharField(max_length=100, null=True) + result = models.CharField(max_length=500, null=True) + refnum = models.CharField(max_length=200, null=True) + resnum = models.CharField(max_length=200, null=True) + natcode = models.CharField(max_length=20, null=True) + fullname = models.CharField(max_length=200, null=True) + buy_date = models.BigIntegerField(null=True) + date = models.BigIntegerField(null=True) + product = models.JSONField(null=True) + state = models.IntegerField(null=True) + amount = models.FloatField(null=True) + price = models.FloatField(null=True) + lng = models.FloatField(null=True) + lot = models.FloatField(null=True) + checkout = models.BooleanField(null=True) + registered = models.BooleanField(null=True) + paid = models.BooleanField(null=True) + + def save(self, *args, **kwargs): + super(POSTransactions, self).save(*args, **kwargs) + + +class AdditionalProducts(BaseModel): + name = models.CharField(max_length=200, null=True) + image = models.CharField(max_length=500, null=True) + unit_of_measurement = models.CharField(max_length=20, null=True) + selling_free_price = models.BooleanField(default=False) + selling_approved_price = models.BooleanField(default=False) + selling_more_than_inventory = models.BooleanField(default=False) + selling_other_products = models.BooleanField(default=False) + price = models.FloatField(default=0) + priority = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(AdditionalProducts, self).save(*args, **kwargs) + + +class Product(BaseModel): + name = models.CharField(max_length=200, null=True) + image = models.CharField(max_length=500, null=True) + unit_of_measurement = models.CharField(max_length=20, null=True) + quantity = models.BigIntegerField(default=0) + priority = models.IntegerField(default=0) + sale_quantity = models.BigIntegerField(default=0) + extra_sale_quantity = models.BigIntegerField(default=0) + remain_quantity = models.BigIntegerField(default=0) + weight = models.FloatField(default=0) + sale_weight = models.FloatField(default=0) + extra_sale_weight = models.FloatField(default=0) + remain_weight = models.FloatField(default=0) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_product", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_product", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="steward_product", + null=True + ) + selling_free_price = models.BooleanField(default=False) + selling_approved_price = models.BooleanField(default=False) + selling_more_than_inventory = models.BooleanField(default=False) + selling_other_products = models.BooleanField(default=False) + general = models.BooleanField(default=False) + show = models.BooleanField(default=False) + price = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(Product, self).save(*args, **kwargs) + + +class PosVersion(BaseModel): + build_id = models.BigIntegerField(default=0) + latest_downloadlink = models.TextField() + + def save(self, *args, **kwargs): + super(PosVersion, self).save(*args, **kwargs) + + +class PosItem(BaseModel): + name = models.CharField(max_length=100, null=True) + value = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(PosItem, self).save(*args, **kwargs) + + +class GuildRoom(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="guild_room_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="guild_room_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="guild_room_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="guild_room_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(GuildRoom, self).save(*args, **kwargs) + + +class EvacuationPermit(BaseModel): + type = models.CharField(max_length=100, default='optional') + + def save(self, *args, **kwargs): + super(EvacuationPermit, self).save(*args, **kwargs) + + +class SellForFreezing(BaseModel): + permission = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(SellForFreezing, self).save(*args, **kwargs) + + +class ColdHouseAllocations(BaseModel): + cold_house = models.ForeignKey( + ColdHouse, + on_delete=models.CASCADE, + related_name="cold_house_allocations_cold_house", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="cold_house_allocations_kill_house", + null=True + ) + kill_house_request = models.ForeignKey( + KillHouseRequest, + on_delete=models.CASCADE, + related_name="cold_house_allocations_kill_house_request", + null=True + ) + kill_house_ware_house = models.ForeignKey( + KillHouseWareHouse, + on_delete=models.CASCADE, + related_name="cold_house_allocations_kill_house_ware_house", + null=True + ) + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="cold_house_allocations_product", + null=True + ) + quantity = models.BigIntegerField(default=0) + accepted_quantity = models.BigIntegerField(default=0) + real_quantity = models.BigIntegerField(default=0) + weight = models.FloatField(default=0) + accepted_weight = models.FloatField(default=0) + real_weight = models.FloatField(default=0) + state = models.CharField(max_length=20, default='pending') + allocation_type = models.CharField(max_length=50, null=True) + reviewer = models.JSONField(null=True) + date = models.DateTimeField(null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ColdHouseAllocations, self).save(*args, **kwargs) + + +class OperationLimitation(BaseModel): + vet_farm_out_province_limitation = models.BooleanField(default=False) + province_allocation_limitation = models.BooleanField(default=False) + kill_house_allocation_limitation = models.BooleanField(default=False) + kill_house_assignment_limitation = models.BooleanField(default=False) + vet_check_kill_house_assignment_limitation = models.BooleanField(default=False) + kill_house_input_bar_limitation = models.BooleanField(default=False) + kill_house_steward_guild_allocation_limitation = models.BooleanField(default=False) + kill_house_freezing_limitation = models.BooleanField(default=False) + kill_house_free_sale_limitation = models.BooleanField(default=False) + kill_house_free_buy_limitation = models.BooleanField(default=False) + kill_house_vet_limitation = models.BooleanField(default=False) + vet_farm_limitation = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(OperationLimitation, self).save(*args, **kwargs) + + +class ApprovedPrice(BaseModel): + approved = models.BooleanField(default=False) + lowest_price = models.FloatField(default=0) + highest_price = models.FloatField(default=0) + lowest_weight = models.FloatField(default=0) + highest_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(ApprovedPrice, self).save(*args, **kwargs) + + +class Announcements(BaseModel): + active = models.BooleanField(default=False) + description = models.TextField(max_length=2000, null=True) + role = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(Announcements, self).save(*args, **kwargs) + + +class ChickenAgeRange(BaseModel): + active = models.BooleanField(default=False) + maximum = models.IntegerField(default=0) + minimum = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(ChickenAgeRange, self).save(*args, **kwargs) + + +class TimeRange(BaseModel): + time_range = models.JSONField(null=True) + + def save(self, *args, **kwargs): + super(TimeRange, self).save(*args, **kwargs) + + +class SystemWallet(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="system_wallet_kill_house", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="system_wallet_steward", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="system_wallet_guild", + null=True + ) + balance = models.BigIntegerField(default=0) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(SystemWallet, self).save(*args, **kwargs) + + +class SuperAdmin(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="super_admin_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="super_admin_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="super_admin_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="super_admin_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(SuperAdmin, self).save(*args, **kwargs) + + +class PaymentGatewayPercentage(BaseModel): + company = models.IntegerField(default=0) + union = models.IntegerField(default=0) + guilds = models.IntegerField(default=0) + other = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(PaymentGatewayPercentage, self).save(*args, **kwargs) + + +class TotalPaymentGatewayPercentage(BaseModel): + company = models.IntegerField(default=0) + union = models.IntegerField(default=0) + guilds = models.IntegerField(default=0) + other = models.IntegerField(default=0) + type = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(TotalPaymentGatewayPercentage, self).save(*args, **kwargs) + + +class SlaughterHouseTransaction(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="slaughter_house_transaction_kill_house", + null=True + ) + parent_kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="slaughter_house_transaction_parent_kill_house", + null=True + ) + amount = models.BigIntegerField(default=0) + amount_with_tax = models.BigIntegerField(default=0) + transaction = models.IntegerField(null=True) + type = models.CharField(max_length=100, null=True) + state = models.CharField(max_length=20, default='pending') + union_share = models.BigIntegerField(default=0) + company_share = models.BigIntegerField(default=0) + guilds_share = models.BigIntegerField(default=0) + city_share = models.BigIntegerField(default=0) + wallet_share = models.BigIntegerField(default=0) + other_share = models.BigIntegerField(default=0) + pay_type = models.CharField(max_length=200, null=True) + saleReferenceId = models.CharField(max_length=100, null=True) + refId = models.CharField(max_length=100, null=True) + orderId = models.CharField(max_length=100, null=True) + cardHolderPan = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(SlaughterHouseTransaction, self).save(*args, **kwargs) + + +class ShareType(BaseModel): + name = models.CharField(max_length=500, null=True) + en_name = models.CharField(max_length=500, null=True) + account_id = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(ShareType, self).save(*args, **kwargs) + + +class WageType(BaseModel): + name = models.CharField(max_length=500, null=True) + en_name = models.CharField(max_length=500, null=True) + amount = models.BigIntegerField(default=0) + status = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(WageType, self).save(*args, **kwargs) + + +class PercentageOfWageType(BaseModel): + wage_type = models.ForeignKey( + WageType, + on_delete=models.CASCADE, + related_name="wage_type_percentage", + null=True + ) + share_type = models.ForeignKey( + ShareType, + on_delete=models.CASCADE, + related_name="share_type_percentage", + null=True + ) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(PercentageOfWageType, self).save(*args, **kwargs) + + +class SubSectorPercentageOfWageType(BaseModel): + percentage_of_wage_type = models.ForeignKey( + PercentageOfWageType, + on_delete=models.CASCADE, + related_name="sub_sector_wage_type", + null=True + ) + city = models.BooleanField(default=False) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(SubSectorPercentageOfWageType, self).save(*args, **kwargs) + + +class TotalWageInformation(BaseModel): + total_amount = models.BigIntegerField(default=0) + total_unpaid_amount = models.BigIntegerField(default=0) + total_paid_amount = models.BigIntegerField(default=0) + total_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(TotalWageInformation, self).save(*args, **kwargs) + + +class InternalTransaction(BaseModel): + date = models.DateTimeField(auto_now_add=True) + amount = models.BigIntegerField(default=0) + amount_with_tax = models.BigIntegerField(default=0) + status = models.CharField(max_length=100, default='pending') + transaction_type = models.CharField(max_length=100, null=True) + type = models.CharField(max_length=100, null=True) + payer_type = models.CharField(max_length=100, null=True) + message = models.TextField(null=True) + saleReferenceId = models.CharField(max_length=100, null=True) + refId = models.CharField(max_length=100, null=True) + authority = models.CharField(max_length=100, null=True) + orderId = models.CharField(max_length=100, null=True) + cardHolderPan = models.CharField(max_length=100, null=True) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + null=True, + related_name="internal_transaction_kill_house_user" + ) + parent_kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="internal_transaction_parent_kill_house", + null=True + ) + chain_company = models.ForeignKey( + ChainCompany, + on_delete=models.CASCADE, + null=True, + related_name="internal_transaction_chain_company_user" + ) + poultry_request = models.ManyToManyField( + PoultryRequest, + related_name='poutry_request_transactions', + null=True, blank=True) + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + null=True, + related_name="internal_transaction_poultry" + ) + out_province_poultry_request_buyer = models.ForeignKey( + OutProvincePoultryRequestBuyer, + on_delete=models.CASCADE, + null=True, + related_name="internal_transaction_out_province_poultry_request_buyer" + ) + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + null=True, + related_name="internal_transaction_user" + ) + + union_share = models.BigIntegerField(default=0) + union_account = models.CharField(max_length=50, null=True) + company_share = models.BigIntegerField(default=0) + company_account = models.CharField(max_length=50, null=True) + guilds_share = models.BigIntegerField(default=0) + guilds_account = models.CharField(max_length=50, null=True) + city_share = models.BigIntegerField(default=0) + city_account = models.CharField(max_length=50, null=True) + wallet_share = models.BigIntegerField(default=0) + wallet_account = models.CharField(max_length=50, null=True) + other_share = models.BigIntegerField(default=0) + other_account = models.CharField(max_length=50, null=True) + link_pay = models.BooleanField(default=False) + description = models.TextField(null=True) + image = models.CharField(max_length=500, null=True) + payer_fullname = models.CharField(max_length=200, null=True) + payer_mobile = models.CharField(max_length=11, null=True) + temporary_trash = models.BooleanField(default=False) + temporary_deleted = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(InternalTransaction, self).save(*args, **kwargs) + + +class CityLivestock(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_livestock_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_livestock_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="city_livestock_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_livestock_wallet", + null=True + ) + user_id_foreign_key = models.IntegerField(null=True) + address_id_foreign_key = models.IntegerField(null=True) + user_bank_id_foreign_key = models.IntegerField(null=True) + wallet_id_foreign_key = models.IntegerField(null=True) + city_jahad_id_key = models.IntegerField(null=True) + identity_documents = models.JSONField(null=True) + active = models.BooleanField(default=True) + city_number = models.IntegerField(default=0) + city_name = models.CharField(max_length=100, null=True) + province_number = models.IntegerField(default=0) + province_name = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(CityLivestock, self).save(*args, **kwargs) + + +class ImprovingLivestock(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="improving_livestock_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="improving_livestock_address", + null=True + ) + user_bank_info = models.ForeignKey(BankCard, on_delete=models.CASCADE, related_name="improving_livestock_bank_info", + null=True) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="improving_livestock_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(ImprovingLivestock, self).save(*args, **kwargs) + + +class ReportSubmissionTime(BaseModel): + type = models.CharField(max_length=100, null=True) + hour = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(ReportSubmissionTime, self).save(*args, **kwargs) + + +class Reports(BaseModel): + title = models.CharField(max_length=500, null=True) + end_point = models.CharField(max_length=50, null=True) + active = models.BooleanField(default=False) + description = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(Reports, self).save(*args, **kwargs) + + +class ReportsUsers(BaseModel): + active = models.BooleanField(default=True) + firstname = models.CharField(max_length=100, null=True) + lastname = models.CharField(max_length=100, null=True) + fullname = models.CharField(max_length=100, null=True) + city = models.CharField(max_length=100, null=True) + position = models.CharField(max_length=100, null=True) + mobile = models.CharField(max_length=11, null=True) + user_token = models.CharField(max_length=4, null=True, unique=True) + + def save(self, *args, **kwargs): + + self.fullname = self.firstname + " " + self.lastname + if self.user_token is None: + while (True): + res = ''.join(random.choices(string.ascii_lowercase + string.digits, k=3)) + res = base_user_gate_way_id + res + if not ReportsUsers.objects.filter(user_token=res).exists(): + break + self.user_token = res + super(ReportsUsers, self).save(*args, **kwargs) + + +class UserReports(BaseModel): + active = models.BooleanField(default=True) + user = models.ForeignKey( + ReportsUsers, + on_delete=models.CASCADE, + related_name="user_reports_user", + null=True + ) + report = models.ForeignKey( + Reports, + on_delete=models.CASCADE, + related_name="report_user_reports", + null=True + ) + + def save(self, *args, **kwargs): + super(UserReports, self).save(*args, **kwargs) + + +class MovingTextDashboardStatus(BaseModel): + active = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(MovingTextDashboardStatus, self).save(*args, **kwargs) + + +class MovingTextRole(BaseModel): + role = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(MovingTextRole, self).save(*args, **kwargs) + + +class MovingText(BaseModel): + moving_text = models.TextField(null=True) + active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(MovingText, self).save(*args, **kwargs) + + +class MovingTextWithRole(BaseModel): + moving_text = models.ForeignKey( + MovingText, + on_delete=models.CASCADE, + related_name="role_moving_text", + null=True + ) + role = models.ForeignKey( + MovingTextRole, + on_delete=models.CASCADE, + related_name="moving_text_role", + null=True + ) + active = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(MovingTextWithRole, self).save(*args, **kwargs) + + +class AdminX(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="admin_x_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="admin_x_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="admin_x_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="admin_x_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(AdminX, self).save(*args, **kwargs) + + +class Supporter(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="supporter_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="supporter_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="supporter_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="supporter_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(Supporter, self).save(*args, **kwargs) + + +class ZarinPalAccounts(BaseModel): + name = models.CharField(max_length=50, null=True) + en_name = models.CharField(max_length=50, null=True) + account = models.CharField(max_length=50, null=True) + + def save(self, *args, **kwargs): + super(ZarinPalAccounts, self).save(*args, **kwargs) + + +class PoultryExport(BaseModel): + allow = models.BooleanField(default=False) + limitation_status = models.BooleanField(default=False) + limitation = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(PoultryExport, self).save(*args, **kwargs) + + +class PoultryOutProvinceRequest(BaseModel): + allow = models.BooleanField(default=False) + limitation_status = models.BooleanField(default=False) + limitation = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(PoultryOutProvinceRequest, self).save(*args, **kwargs) + + +class VetFarmAggregatePermission(BaseModel): + allow = models.BooleanField(default=False) + limitation = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(VetFarmAggregatePermission, self).save(*args, **kwargs) + + +class KillHouseBarLimitation(BaseModel): + allow = models.BooleanField(default=False) + limitation = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(KillHouseBarLimitation, self).save(*args, **kwargs) + + +class KillHouseStewardGuildRelation(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_relation", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_relation", + null=True + ) + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_relation", + null=True + ) + + allocation_limit = models.IntegerField(default=0) + allocation_type = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(KillHouseStewardGuildRelation, self).save(*args, **kwargs) + + +class OutOfProvinceSellingCarcassesPermission(BaseModel): + active = models.BooleanField(default=False) + type = models.CharField(max_length=100, null=True) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(OutOfProvinceSellingCarcassesPermission, self).save(*args, **kwargs) + + +class ProductPricingType(BaseModel): + province = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(ProductPricingType, self).save(*args, **kwargs) + + +class KillHousePricePermission(BaseModel): + allow = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(KillHousePricePermission, self).save(*args, **kwargs) + + +class IranProvinces(models.Model): + name = models.CharField(max_length=250) + slug = models.CharField(max_length=250) + tel_prefix = models.CharField(max_length=3, null=True) + + +class IranCities(models.Model): + name = models.CharField(max_length=250) + slug = models.CharField(max_length=250) + province_id = models.ForeignKey(IranProvinces, on_delete=models.CASCADE) + + +class AutomaticDirectBuyingPermission(models.Model): + allow = models.BooleanField(default=False) + start_time = models.TimeField(null=True) + end_time = models.TimeField(null=True) + + def save(self, *args, **kwargs): + super(AutomaticDirectBuyingPermission, self).save(*args, **kwargs) + + +class AgeNotificationPoultry(BaseModel): + message = models.TextField() + poultry_age = models.CharField(max_length=2) + losses_percent = models.IntegerField(null=True) + + def save(self, *args, **kwargs): + super(AgeNotificationPoultry, self).save(*args, **kwargs) + + +class PosMachineTransactions(BaseModel): + pos = models.ForeignKey( + POSMachine, + on_delete=models.CASCADE, + related_name="roles_products_pos_transactions", + null=True + ) + + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="roles_products_pos_transactions", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="transaction_kill_house", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="transaction_guild", + null=True + ) + check_id = models.CharField(max_length=100, null=True, unique=True) + mobile = models.CharField(max_length=100, null=True, blank=True) + natcode = models.CharField(max_length=100, null=True, blank=True) + fullname = models.CharField(max_length=100, null=True, blank=True) + date = models.DateTimeField(null=True) + pos_date = models.BigIntegerField(default=0) + price = models.BigIntegerField(default=0) + price_paid = models.BigIntegerField(default=0) + price_type = models.CharField(max_length=50, null=True, blank=True) + paid = models.BooleanField(default=False) + state = models.IntegerField(default=0) + posProvider = models.CharField(max_length=100, null=True) + result = models.CharField(max_length=1000, null=True) + refnum = models.CharField(max_length=100, null=True, blank=True) + terminal = models.CharField(max_length=100, null=True, blank=True) + cart = models.CharField(max_length=100, null=True, blank=True) + lng = models.FloatField(default=0) + lot = models.FloatField(default=0) + # additional = models.CharField(max_length=200, null=True, blank=True) + additional = models.TextField(null=True, blank=True) + current_price = models.IntegerField(default=0) + checkout = models.BooleanField(default=False) + weight = models.IntegerField(default=0) + hasTry = models.BooleanField(default=False) + live_stock = models.BooleanField(default=False) + warehouse = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(PosMachineTransactions, self).save(*args, **kwargs) + + +class ProductsTransactions(BaseModel): + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="products_transactions_product", + null=True + ) + other_product = models.ForeignKey( + OtherProducts, + on_delete=models.CASCADE, + related_name="products_transactions_other_product", + null=True + ) + transaction = models.ForeignKey( + PosMachineTransactions, + on_delete=models.CASCADE, + related_name="transaction_products_transactions", + null=True + ) + live_stack_products = models.ForeignKey( + LiveStockRolseProduct, + on_delete=models.CASCADE, + related_name="products_transactions_live_stack_products", + null=True + ) + price = models.BigIntegerField(default=0) + cur_price = models.BigIntegerField(default=0) + cur_weight = models.BigIntegerField(default=0) + total_price = models.BigIntegerField(default=0) + price_approved = models.BooleanField(default=False) + name = models.CharField(max_length=300, null=True) + image = models.CharField(max_length=500, null=True) + unit = models.CharField(max_length=10, null=True) + targetunit = models.CharField(max_length=10, null=True) + warehouse = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(ProductsTransactions, self).save(*args, **kwargs) + + +class PosAllocationTransactions(BaseModel): + pos = models.ForeignKey( + POSMachine, + on_delete=models.CASCADE, + related_name="steward_allocation_pos_transactions", + null=True + ) + + allocation = models.ForeignKey( + StewardAllocation, + on_delete=models.CASCADE, + related_name="steward_allocation_transactions", + null=True + ) + check_id = models.CharField(max_length=100, null=True) + date = models.DateTimeField(null=True) + price = models.BigIntegerField(default=0) + paid = models.BooleanField(default=False) + state = models.IntegerField(default=0) + posProvider = models.CharField(max_length=100, null=True) + result = models.TextField(null=True) + refnum = models.CharField(max_length=100, null=True, blank=True) + terminal = models.CharField(max_length=100, null=True, blank=True) + cart = models.CharField(max_length=100, null=True, blank=True) + lng = models.FloatField(default=0) + lot = models.FloatField(default=0) + additional = models.CharField(max_length=200, null=True, blank=True) + + def save(self, *args, **kwargs): + super(PosAllocationTransactions, self).save(*args, **kwargs) + + +class BroadcastPrice(BaseModel): + active = models.BooleanField(default=False) + kill_house_price = models.FloatField(default=0) + steward_price = models.FloatField(default=0) + guild_price = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(BroadcastPrice, self).save(*args, **kwargs) + + +class OutProvinceSaleLimitation(BaseModel): + active = models.BooleanField(default=False) + kill_house = models.FloatField(default=0) + steward = models.FloatField(default=0) + guild = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(OutProvinceSaleLimitation, self).save(*args, **kwargs) + + +class ParentCompany(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="parent_company_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="parent_company_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="parent_company_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="parent_company_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(ParentCompany, self).save(*args, **kwargs) + + +class CityGuild(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="city_guild_user", + null=True + ) + address = models.ForeignKey( + SystemAddress, + on_delete=models.CASCADE, + related_name="city_guild_address", + null=True + ) + user_bank_info = models.ForeignKey( + BankCard, + on_delete=models.CASCADE, + related_name="city_guild_bank_info", + null=True + ) + wallet = models.ForeignKey( + Wallet, + on_delete=models.CASCADE, + related_name="city_guild_wallet", + null=True + ) + + wallet_amount = models.BigIntegerField(default=0) + unit_name = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(CityGuild, self).save(*args, **kwargs) + + +class SubSectorTransactions(BaseModel): + city_operator = models.ForeignKey( + CityOperator, + on_delete=models.CASCADE, + related_name="city_operator_transactions", + null=True + ) + vet = models.ForeignKey( + Vet, + on_delete=models.CASCADE, + related_name="vet_transactions", + null=True + ) + city_guild = models.ForeignKey( + CityGuild, + on_delete=models.CASCADE, + related_name="city_guild_transactions", + null=True + ) + date = models.DateTimeField(null=True) + from_account = models.CharField(max_length=200, null=True) + to_account = models.CharField(max_length=200, null=True) + type = models.CharField(max_length=50, null=True) + amount = models.BigIntegerField(default=0) + image = models.CharField(max_length=500, null=True) + + def save(self, *args, **kwargs): + super(SubSectorTransactions, self).save(*args, **kwargs) + + +class PosSegmentation(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_segmentation", + null=True + ) + steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="steward_segmentation", + null=True + ) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_segmentation", + null=True + ) + product = models.ForeignKey( + RolesProducts, + on_delete=models.CASCADE, + related_name="product_segmentation", + null=True + ) + + to_guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="to_guild_segmentation", + null=True + ) + to_steward = models.ForeignKey( + Steward, + on_delete=models.CASCADE, + related_name="to_steward_segmentation", + null=True + ) + dispenser = models.ForeignKey( + Dispenser, + on_delete=models.CASCADE, + related_name="segmentation_dispenser", + null=True + ) + representative = models.ForeignKey( + Representative, + on_delete=models.CASCADE, + related_name="segmentation_representative", + null=True + ) + date = models.DateTimeField(null=True) + weight = models.BigIntegerField(default=0) + sale_type = models.CharField(max_length=20, null=True) + quota = models.CharField(max_length=20, null=True) + warehouse = models.BooleanField(default=True) + production_date = models.DateTimeField(null=True) + distribution_type = models.CharField(max_length=20, null=True) + amount = models.BigIntegerField(default=0) + total_amount = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(PosSegmentation, self).save(*args, **kwargs) + + +class PoultryPrediction(BaseModel): + poultry = models.ForeignKey( + Poultry, + on_delete=models.CASCADE, + related_name="prediction_poultry", + null=True + ) + date = models.DateTimeField(null=True) + killing_ave_age = models.IntegerField(default=1) + active_left_over = models.IntegerField(default=0) + killing_ave_count = models.IntegerField(default=0) + killing_ave_weight = models.IntegerField(default=0) + killing_loss_weight_percent = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(PoultryPrediction, self).save(*args, **kwargs) + + +class BarDifferenceRequest(BaseModel): + hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="difference_hatching", + null=True + ) + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="difference_kill_house", + null=True + ) + state = models.CharField(max_length=20, default='pending') + register_fullname = models.CharField(max_length=200, null=True) + register_mobile = models.CharField(max_length=200, null=True) + register_message = models.TextField(null=True) + quantity = models.IntegerField(default=0) + real_quantity = models.IntegerField(default=0) + weight = models.IntegerField(default=0) + real_weight = models.IntegerField(default=0) + violation_image = models.JSONField(null=True) + acceptor_image = models.JSONField(null=True) + acceptor_fullname = models.CharField(max_length=200, null=True) + acceptor_mobile = models.CharField(max_length=200, null=True) + acceptor_date = models.DateTimeField(null=True) + acceptor_message = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(BarDifferenceRequest, self).save(*args, **kwargs) + + +class CookieSamasat(models.Model): + cookie = models.TextField(null=True) + table_name = models.CharField(max_length=100, null=True, blank=True) + + def save(self, *args, **kwargs): + super(CookieSamasat, self).save(*args, **kwargs) + + +class LiveChickenTransportDetails(BaseModel): + kill_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, null=True) + hatching = models.ForeignKey(PoultryHatching, on_delete=models.CASCADE, null=True) + quarantine_code = models.CharField(max_length=100, null=True) + rejester_date = models.DateTimeField(null=True) + quantity = models.IntegerField(null=True) + state = models.CharField(max_length=100, null=True) + product_name = models.CharField(max_length=200, null=True) + kill_house_unique_identifier = models.CharField(max_length=100, null=True) + kill_house_name = models.CharField(max_length=100, null=True) + status_registration_date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(LiveChickenTransportDetails, self).save(*args, **kwargs) + + +class RequestLimitation(BaseModel): + limitation = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(RequestLimitation, self).save(*args, **kwargs) + + +class PriceConfirmation(BaseModel): + poultry_status = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(PriceConfirmation, self).save(*args, **kwargs) + + +class ArchiveWageInfo(BaseModel): + start_year = models.DateTimeField(null=True) + end_year = models.DateTimeField(null=True) + total_wage = models.BigIntegerField(default=0) + total_paid_wage = models.BigIntegerField(default=0) + total_company_paid_wage = models.BigIntegerField(default=0) + total_union_paid_wage = models.BigIntegerField(default=0) + total_guild_paid_wage = models.BigIntegerField(default=0) + total_vet_paid_wage = models.BigIntegerField(default=0) + + def save(self, *args, **kwargs): + super(ArchiveWageInfo, self).save(*args, **kwargs) + + +class CompanyBeneficiaryAccount(BaseModel): + name = models.CharField(max_length=200, null=True) + shaba = models.CharField(max_length=200, null=True) + percent = models.BigIntegerField(default=0) + in_province = models.BooleanField(default=False) + out_province = models.BooleanField(default=False) + unique_code = models.IntegerField(null=True) + + def save(self, *args, **kwargs): + if self.unique_code is None: + last_uniq = CompanyBeneficiaryAccount.objects.filter().last().unique_code + self.unique_code = last_uniq + 1 + super(CompanyBeneficiaryAccount, self).save(*args, **kwargs) + + +class HatchingIncreaseRequest(BaseModel): + hatching = models.ForeignKey(PoultryHatching, on_delete=models.CASCADE, + related_name="increase_hatching", + null=True) + + hatching_quantity = models.IntegerField(null=True) + quantity = models.IntegerField(null=True) + hatching_kill_quantity = models.IntegerField(null=True) + hatching_left_over = models.IntegerField(null=True) + hatching_losses = models.IntegerField(null=True) + message = models.TextField(null=True) + registerer_name = models.CharField(max_length=250, null=True) + registerer_role = models.CharField(max_length=50, null=True) + registerer_mobile = models.CharField(max_length=20, null=True) + date = models.DateTimeField(auto_now_add=True) + + def save(self, *args, **kwargs): + super(HatchingIncreaseRequest, self).save(*args, **kwargs) + + +class ChickenCommissionPrices(BaseModel): + kill_house_price = models.IntegerField(default=15000) + wholesaler_price = models.IntegerField(default=20000) + retailer_price = models.IntegerField(default=40000) + chicken_average_price = models.IntegerField(default=0) + province_kill_request_amount = models.IntegerField(default=0) + poultry_request_amount = models.IntegerField(default=0) + kill_request_amount = models.IntegerField(default=0) + date = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(ChickenCommissionPrices, self).save(*args, **kwargs) + + +class CommonlyUsed(BaseModel): + kill_house = models.ForeignKey(KillHouse, on_delete=models.CASCADE, + related_name="commonly_used_kill_house", + null=True) + + guild = models.ForeignKey(Guilds, on_delete=models.CASCADE, + related_name="commonly_used_guild", + null=True) + + steward = models.ForeignKey(Guilds, on_delete=models.CASCADE, + related_name="commonly_used_steward", + null=True) + priority = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(CommonlyUsed, self).save(*args, **kwargs) + + +class PercentageDropLimitation(BaseModel): + kill_house_limit_percent_down = models.IntegerField(default=0) + kill_house_limit_percent_up = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(PercentageDropLimitation, self).save(*args, **kwargs) + + +class UploadImageLimitation(BaseModel): + kill_house_allocation = models.BooleanField(default=False) + kill_house_free_sale = models.BooleanField(default=False) + steward_allocation = models.BooleanField(default=False) + steward_free_sale = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(UploadImageLimitation, self).save(*args, **kwargs) + + +class ApkInfo(BaseModel): + info = models.JSONField(null=True) + download_link = models.CharField(max_length=700, null=True, blank=True) + + def save(self, *args, **kwargs): + super(ApkInfo, self).save(*args, **kwargs) + + +class DirectBuyingVerification(BaseModel): + poultry_code_mandatory = models.BooleanField(default=False) + payment_deadline = models.BooleanField(default=False) + payment_deadline_days = models.IntegerField(default=0) + + def save(self, *args, **kwargs): + super(DirectBuyingVerification, self).save(*args, **kwargs) + + +class DirectBuyingPayment(BaseModel): + province_kill_request = models.ForeignKey(ProvinceKillRequest, on_delete=models.CASCADE, + related_name="direct_buying_province_kill_request", + null=True) + amount = models.BigIntegerField(default=0) + image = models.CharField(max_length=700, null=True) + date = models.DateTimeField(null=True) + payment_registrar = models.CharField(max_length=200, null=True) + payment_registrar_mobile = models.CharField(max_length=20, null=True) + payment_deadline_supporter_message = models.TextField(null=True) + + def save(self, *args, **kwargs): + super(DirectBuyingPayment, self).save(*args, **kwargs) + + +class FinePermission(BaseModel): + out_poultry_request = models.BooleanField(default=False) + out_poultry_request_start_time = models.TimeField(null=True) + out_poultry_request_end_time = models.TimeField(null=True) + out_poultry_request_fine_coefficient = models.FloatField(default=0) + direct_buying = models.BooleanField(default=False) + direct_buying_start_time = models.TimeField(null=True) + direct_buying_end_time = models.TimeField(null=True) + direct_buying_fine_coefficient = models.FloatField(default=0) + in_province_allocations = models.BooleanField(default=False) + in_province_allocations_fine_coefficient = models.FloatField(default=0) + in_province_bars = models.BooleanField(default=False) + in_province_bars_fine_coefficient = models.FloatField(default=0) + name = models.CharField(max_length=200, null=True) + start_time = models.TimeField(null=True) + end_time = models.TimeField(null=True) + fine_coefficient = models.FloatField(default=0) + fine = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(FinePermission, self).save(*args, **kwargs) + + +class ManagementSendSms(BaseModel): + name = models.CharField(max_length=100, null=True) + username = models.CharField(max_length=100, null=True) + password = models.CharField(max_length=100, null=True) + + +class ShowMarketRequest(BaseModel): + allow = models.BooleanField(default=False) + start_time = models.TimeField(null=True) + end_time = models.TimeField(null=True) + + def save(self, *args, **kwargs): + super(ShowMarketRequest, self).save(*args, **kwargs) + + +class ManagementHatchingAgeRange(BaseModel): + from_age = models.SmallIntegerField(default=0, max_length=3) + to_age = models.SmallIntegerField(default=0, max_length=3) + from_weight = models.FloatField(default=0) + to_weight = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(ManagementHatchingAgeRange, self).save(*args, **kwargs) + + +class IndexWeightCategory(BaseModel): + name = models.CharField(max_length=100, null=True) + min_value = models.FloatField(default=0) + max_value = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(IndexWeightCategory, self).save(*args, **kwargs) + + +class PoultryScience(BaseModel): + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="poultry_science_user", + null=True + ) + poultry = models.ManyToManyField( + Poultry, + related_name="poultry_entries", + ) + engineering_code = models.CharField(max_length=50, null=True, blank=True) + + def save(self, *args, **kwargs): + super(PoultryScience, self).save(*args, **kwargs) + + +class PoultryScienceReport(BaseModel): + poultry_science = models.ForeignKey( + PoultryScience, + on_delete=models.CASCADE, + related_name="poultry_science_reporter", + null=True + ) + hatching = models.ForeignKey( + PoultryHatching, + on_delete=models.CASCADE, + related_name="poultry_science_hatching", + null=True + ) + user = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="poultry_science_report_user", + null=True + ) + date = models.DateTimeField(null=True) + image = models.JSONField(null=True) + lat = models.FloatField(null=True) + log = models.FloatField(null=True) + reporter_fullname = models.CharField(null=True, max_length=50) + reporter_mobile = models.CharField(null=True, max_length=11) + reporter_role = models.CharField(null=True, max_length=50) + state = models.CharField(default='pending', max_length=50) + real_quantity_ai = models.IntegerField(null=True) + message_ai = models.CharField(null=True, max_length=250) + real_quantity = models.IntegerField(null=True) + message = models.CharField(null=True, max_length=250) + message_registerer_fullname = models.CharField(null=True, max_length=50) + message_registerer_mobile = models.CharField(null=True, max_length=11) + message_registerer_role = models.CharField(null=True, max_length=50) + report_information = models.JSONField(null=True) + report_id = models.IntegerField(null=True) + chicken_age = models.IntegerField(null=True) + + def save(self, *args, **kwargs): + if self.report_id is None: + last = PoultryScienceReport.objects.filter().last() + if last: + last_report = last.report_id + else: + last_report = 1000 + self.report_id = last_report + 1 + super(PoultryScienceReport, self).save(*args, **kwargs) + + +class TokenEitaaForEachVet(models.Model): + token = models.CharField(max_length=250) + vet_fullname = models.CharField(max_length=50) + vet_mobile = models.CharField(max_length=11) + group_name = models.CharField(max_length=250) + + def save(self, *args, **kwargs): + super(TokenEitaaForEachVet, self).save(*args, **kwargs) + + +class UserLoginLog(models.Model): + user_profile = models.ForeignKey( + SystemUserProfile, + on_delete=models.CASCADE, + related_name="login_logs_user" + ) + headers = models.JSONField(null=True, blank=True) + ip_address = models.CharField(max_length=500, null=True, blank=True) + user_agent = models.CharField(max_length=500, null=True, blank=True) + created_at = models.DateTimeField(auto_now_add=True) + + def save(self, *args, **kwargs): + super(UserLoginLog, self).save(*args, **kwargs) + + +class AllowRegisterCodeForStewardAllocation(BaseModel): + active = models.BooleanField(default=False) + time = models.CharField(max_length=50, null=True) + + def save(self, *args, **kwargs): + super(AllowRegisterCodeForStewardAllocation, self).save(*args, **kwargs) + + +class AllowRegisterCodeForGuilds(BaseModel): + active = models.BooleanField(default=False) + time = models.CharField(max_length=50, null=True) + has_time = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(AllowRegisterCodeForGuilds, self).save(*args, **kwargs) + + +class StewardAppLogin(BaseModel): + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_login", + null=True) + created_at = models.DateTimeField(auto_now_add=True) + device_name = models.CharField(max_length=200, null=True) + + def save(self, *args, **kwargs): + super(StewardAppLogin, self).save(*args, **kwargs) + + +class StewardRequest(BaseModel): + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_request", + null=True) + date = models.DateTimeField(null=True) + quantity = models.IntegerField(default=0) + weight = models.IntegerField(default=0) + state = models.CharField(default='pending', max_length=50) + registerer = models.CharField(null=True, max_length=250) + registerer_mobile = models.CharField(null=True, max_length=250) + registerer_role = models.CharField(null=True, max_length=250) + + def save(self, *args, **kwargs): + super(StewardRequest, self).save(*args, **kwargs) + + +class RestrictionCarcassDistribution(BaseModel): + allow = models.BooleanField(default=False) + time = models.TimeField(null=True) + distribution_type = models.CharField(max_length=50, default='KillHouse') + out = models.BooleanField(default=False) + + def save(self, *args, **kwargs): + super(RestrictionCarcassDistribution, self).save(*args, **kwargs) + + +class AllowRegisterCodeForKillHouseFreeSaleBarInformation(BaseModel): + active = models.BooleanField(default=False) + time = models.CharField(max_length=50, null=True) + + def save(self, *args, **kwargs): + super(AllowRegisterCodeForKillHouseFreeSaleBarInformation, self).save(*args, **kwargs) + + +class AllowRegisterCodeForStewardFreeSaleBarInformation(BaseModel): + active = models.BooleanField(default=False) + time = models.CharField(max_length=50, null=True) + + def save(self, *args, **kwargs): + super(AllowRegisterCodeForStewardFreeSaleBarInformation, self).save(*args, **kwargs) + + +class LimitationForDirectPurchaseAndBarInformation(BaseModel): + active = models.BooleanField(default=False) + start_time = models.TimeField(null=True, blank=True) + end_time = models.TimeField(null=True, blank=True) + + def save(self, *args, **kwargs): + super(LimitationForDirectPurchaseAndBarInformation, self).save(*args, **kwargs) + + +class WarehouseArchive(BaseModel): + kill_house = models.ForeignKey( + KillHouse, + on_delete=models.CASCADE, + related_name="kill_house_archive", + null=True) + steward = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="steward_archive", + null=True) + guild = models.ForeignKey( + Guilds, + on_delete=models.CASCADE, + related_name="guild_archive", + null=True) + date = models.DateTimeField(null=True) + weight = models.FloatField(default=0) + image = models.CharField(max_length=500, null=True) + quota = models.CharField(max_length=20, null=True) + description = models.TextField(null=True) + registerer = models.CharField(null=True, max_length=250) + registerer_mobile = models.CharField(null=True, max_length=250) + registerer_role = models.CharField(null=True, max_length=250) + warehouse = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(WarehouseArchive, self).save(*args, **kwargs) + + +class SmsRecipient(BaseModel): + phone_number = models.CharField(max_length=11, unique=True) + name = models.CharField(max_length=100, null=True) + is_active = models.BooleanField(default=True) + + def save(self, *args, **kwargs): + super(SmsRecipient, self).save(*args, **kwargs) + + +class PosDeviceSetting(BaseModel): + pos_machin = models.CharField(max_length=100, null=True) + owner = models.TextField(null=True) + serial = models.TextField(null=True) + key_id = models.TextField(null=True) + key_value = models.TextField(null=True) + last_modify = models.DateTimeField(null=True) + + def save(self, *args, **kwargs): + super(PosDeviceSetting, self).save(*args, **kwargs) + + +class MarketDailyLimitation(BaseModel): + quantity = models.IntegerField(default=0) + active = models.BooleanField(default=False) + register_role = models.CharField(max_length=50, null=True) + register_fullname = models.CharField(max_length=100, null=True) + register_mobile = models.CharField(max_length=100, null=True) + + def save(self, *args, **kwargs): + super(MarketDailyLimitation, self).save(*args, **kwargs) + + +class HatchingArchivePercent(BaseModel): + active = models.BooleanField(default=False) + percent = models.FloatField(default=0) + + def save(self, *args, **kwargs): + super(HatchingArchivePercent, self).save(*args, **kwargs) + + + +class RequestLog(models.Model): + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + null=True, + blank=True, + on_delete=models.SET_NULL + ) + method = models.CharField(max_length=10) + path = models.TextField() + query_params = models.JSONField(null=True, blank=True) + body = models.JSONField(null=True, blank=True) + headers = models.JSONField(null=True, blank=True) + + status_code = models.PositiveIntegerField(null=True) + ip_address = models.GenericIPAddressField(null=True, blank=True) + + duration = models.FloatField(help_text="Request duration in seconds") + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return f"{self.method} {self.path} ({self.status_code})" \ No newline at end of file diff --git a/panel/pos_helper.py b/panel/pos_helper.py new file mode 100644 index 0000000..2f77f67 --- /dev/null +++ b/panel/pos_helper.py @@ -0,0 +1,263 @@ +from rest_framework.decorators import api_view, permission_classes +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from rest_framework import status +from django.views.decorators.csrf import csrf_exempt + +from general_urls import BASE_URL +from .ProvinceOperator.serializers import POSAccessLevelSerializer +from .models import POSMachine, RolesProducts, PosDeviceVersion, POSAccessLevel +import requests +from requests.exceptions import RequestException + +from .validate_headers import PosDeviceValidator + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def Check_server(request): + data = {"server": [ + { + "key": "Test", + "name": "تست", + "address": "https://testbackend.rasadyar.com" + }, + { + "key": "Hamedan", + "name": "همدان", + "address": "https://habackend.rasadyar.com" + }, + { + "key": "Markazi", + "name": "مرکزی", + "address": "https://mabackend.rasadyar.com" + } + ] + } + return Response(data, status=status.HTTP_200_OK) + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def pos_finder(request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + validation_device = validator.validation_device() + if not validation_device: + return Response({"result": "نشست شما منقضی شده لطفا محدد وارد شوید!"}, status=status.HTTP_401_UNAUTHORIZED) + + pos_machine = ( + POSMachine.objects + .select_related('user__province') + .only('pos_id', 'user__fullname', 'user__province__name') + .filter(pos_id=validation_device) + ) + if not pos_machine.exists(): + return Response({"result": "صنفی با این شناسه یافت نشد!"}, status=status.HTTP_404_NOT_FOUND) + url = BASE_URL.replace('api/', '') + pos_machine = pos_machine.first() + version = PosDeviceVersion.objects.filter(company=pos_machine.pos_company).order_by('code').last() + name=version.name if version else None + code=version.code if version else None + link=version.link if version else None + checksum=version.checksum if version else None + if pos_machine.guild: + store_name = pos_machine.guild.guilds_name + phone = pos_machine.guild.phone + key = pos_machine.guild.key + type_activity = pos_machine.guild.type_activity + area_activity = pos_machine.guild.area_activity + seller_type = "Guild" if pos_machine.guild.steward == False else "Steward" + product = RolesProducts.objects.filter(guild=pos_machine.guild, trash=False, name='مرغ گرم').first() + product_name = product.parent_product.name if product else None + product_image = product.parent_product.image if product else None + product_key = product.key if product else None + other_product = True + + + + + elif pos_machine.cooperative: + store_name = pos_machine.cooperative.name + phone = pos_machine.cooperative.mobile + key = pos_machine.cooperative.key + seller_type = "cooperative" + type_activity = "تعاونی" + area_activity = "تعاونی" + product_name = None + product_image = None + product_key = None + other_product = True + else: + store_name = pos_machine.kill_house.name + phone = pos_machine.kill_house.phone + key = pos_machine.kill_house.key + seller_type = "KillHouse" + type_activity = "کشتارگاه" + area_activity = "کشتارگاه" + product = RolesProducts.objects.filter(kill_house=pos_machine.kill_house, trash=False, name='مرغ گرم').first() + product_name = product.parent_product.name if product else None + product_image = product.parent_product.image if product else None + product_key = product.key if product else None + other_product = True + + data = { + "type": seller_type, + "name": store_name, + "type_activity": type_activity, + "area_activity": area_activity, + "phone": phone, + "mobile": pos_machine.user.mobile, + "fullname": pos_machine.user.fullname, + "firstname": pos_machine.user.first_name, + "lastname": pos_machine.user.last_name, + "city": pos_machine.user.city.name, + "province": pos_machine.user.province.name, + "national_code": pos_machine.user.national_code, + "national_id": pos_machine.user.national_id, + "birthday": pos_machine.user.birthday, + "url": url, + "key": key, + "server": "Test", + "segmentation": True, + "product_name": product_name, + "product_image": product_image, + "product_key": product_key, + "other_product": other_product, + "version_name": name, + "code": code, + "link": link, + "checksum": checksum, + + } + return Response(data, status=status.HTTP_200_OK) + + +@api_view(["GET"]) +@csrf_exempt +@permission_classes([AllowAny]) +def pos_get_finder(request): + pos_id = request.GET.get('pos-id') + if not pos_id: + return Response({"result": "شناسه POS مشخص نشده است!"}, status=status.HTTP_400_BAD_REQUEST) + + pos_machine = ( + POSMachine.objects + .select_related('user__province') + .only('pos_id', 'user__fullname', 'user__province__name') + .filter(pos_id=pos_id) + ) + if not pos_machine.exists(): + return Response({"result": "صنفی با این شناسه یافت نشد!"}, status=status.HTTP_404_NOT_FOUND) + url = BASE_URL.replace('api/', '') + pos_machine = pos_machine.first() + if pos_machine.guild: + store_name = pos_machine.guild.guilds_name + phone = pos_machine.guild.guilds_name + key = pos_machine.guild.key + seller_type = "Guild" if pos_machine.guild.steward == False else "Steward" + + + elif pos_machine.cooperative: + store_name = pos_machine.cooperative.name + phone = pos_machine.cooperative.mobile + key = pos_machine.cooperative.key + seller_type = "cooperative" + + + else: + store_name = pos_machine.kill_house.name + phone = pos_machine.kill_house.phone + key = pos_machine.kill_house.key + seller_type = "KillHouse" + data = { + "type": seller_type, + "name": store_name, + "phone": phone, + "mobile": pos_machine.user.mobile, + "fullname": pos_machine.user.fullname, + "firstname": pos_machine.user.first_name, + "lastname": pos_machine.user.last_name, + "city": pos_machine.user.city.name, + "province": pos_machine.user.province.name, + "national_code": pos_machine.user.national_code, + "national_id": pos_machine.user.national_id, + "birthday": pos_machine.user.birthday, + "url": url, + "key": key, + "server": "Test", + } + return Response(data, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def pos_login(request): + validator = PosDeviceValidator(request) + validation_error = validator.validation_version() + if validation_error: + return validation_error + + pos_machine = validator.manage_device() + + if not pos_machine.owner: + return Response({"result": f"برای این دستگاه مالکی تعیین نشده!شناسه پوز:{pos_machine.pos_unique_id}"}, + status=status.HTTP_403_FORBIDDEN) + + if not pos_machine.active: + return Response({"result": f"دستگاه غیر فعال میباشد!شناسه پوز:{pos_machine.pos_unique_id}"}, + status=status.HTTP_403_FORBIDDEN) + url = BASE_URL.replace('api/', '') + version = PosDeviceVersion.objects.filter(company=pos_machine.pos_company).order_by('code').last() + name = version.name if version else None + code = version.code if version else None + link = version.link if version else None + checksum = version.checksum if version else None + access_levels = POSAccessLevel.objects.filter(pos=pos_machine) + access_levels = POSAccessLevelSerializer(access_levels,many=True).data + agent = True if (pos_machine.current_user or pos_machine.current_representative) else False + agent_fullname =None + agent_mobile =None + agent_type =None + if agent: + if pos_machine.current_user: + agent_fullname = pos_machine.current_user.fullname + agent_mobile = pos_machine.current_user.mobile + agent_type = 'dispenser' + + else: + agent_fullname = pos_machine.current_representative.first_name + "" +pos_machine.current_representative.last_name + agent_mobile = pos_machine.current_representative.mobile + agent_type = 'representative' + + data = { + "mobile": pos_machine.owner.mobile, + "fullname": pos_machine.owner.fullname, + "firstname": pos_machine.owner.first_name, + "lastname": pos_machine.owner.last_name, + "city": pos_machine.owner.city.name, + "province": pos_machine.owner.province.name, + "national_code": pos_machine.owner.national_code, + "national_id": pos_machine.owner.national_id, + "birthday": pos_machine.owner.birthday, + "url": url, + "key": pos_machine.key, + "server": "Markazi", + "pos_unique_id": pos_machine.pos_unique_id, + "version_name": name, + "code": code, + "link": link, + "checksum": checksum, + "access_levels": access_levels, + "agent": agent, + "agent_type": agent_type, + "agent_fullname": agent_fullname, + "agent_mobile": agent_mobile, + + } + return Response(data, status=status.HTTP_200_OK) diff --git a/panel/poultry/__init__.py b/panel/poultry/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/poultry/excel_processing.py b/panel/poultry/excel_processing.py new file mode 100644 index 0000000..1e96642 --- /dev/null +++ b/panel/poultry/excel_processing.py @@ -0,0 +1,10772 @@ +import datetime +from io import BytesIO + +import jdatetime +import openpyxl +from django.db.models import Sum, Q, F +from openpyxl import Workbook +from openpyxl.styles import PatternFill, Alignment, Font +from openpyxl.utils import get_column_letter +from django.http import HttpResponse, QueryDict + +from panel.KillHouse.serializers import BarDifferenceRequestSerializer +from panel.convert_date import convert_to_shamsi +from panel.filterset import PoultryHatchingFilterSet, PoultryManageFilterSet, BarDifferenceRequestFilterSet, \ + PoultryRequestDirectBuyingFilterSet +from panel.helper import build_query +from panel.helper_excel import shamsi_date, create_header, excel_description, create_header_freez, create_value, \ + add_chart, convert_str_to_date +from panel.models import Poultry, PoultryHatching, CityOperator, VetFarm, PoultryRequest, KillHouseRequest, \ + ProvinceKillRequest, KillHouseAssignmentInformation, KillHouseVet, VetCheckRequest, BarDifferenceRequest, KillHouse, \ + FreeSaleWithinprovince, ShowMarketRequest +from authentication.models import ( + SystemUserProfile, +) +from panel.poultry.helpers import poultry_prediction_helper +from panel.poultry.serializers import PoultryHatchingForPredictionSerializer, PoultryRequestForDirectBuyingSerializer + + +def management_poultry(request): + filterset_class = PoultryManageFilterSet + poultreis = Poultry.objects.filter(trash=False).select_related('user', 'address__province', 'address__city') + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultrys = poultreis.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultrys = poultreis.filter(poultry__user__city=user.city) + else: + poultrys = Poultry.objects.filter(trash=False).select_related('user', 'address__province', 'address__city') + else: + poultrys = poultreis + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + poultrys = poultreis.filter( + build_query(filterset_class, value) + ) + excel_options = [ + 'ردیف', + 'نام واحد', + 'مالک', + 'تلفن', + 'شناسه یکتا', + 'کد اپیدمیولوژیک', + 'کد بهداشتی', + 'تعداد سالن', + 'ظرفیت فارم', + 'استان/شهر', + 'تعاونی', + 'دامپزشک فارم/موبایل', + 'جوجه ریزی فعال', + 'تعداد دوره جوجه ریزی', + 'مجموع جوجه ریزی', + 'میانگین جوجه ریزی', + 'تعداد درخواست کشتار', + 'حجم درخواست کشتار', + 'تعداد بار', + 'حجم بار', + 'وزن بار', + 'میانگین وزن', + 'تعداد بار مستند', + 'حجم بار مستند', + 'وزن بار مستند', + 'میانگین وزنی بار مستند', + 'تعداد بار خارج استان', + 'حجم بار خارج استان', + 'وزن تقریبی بار', + 'میانگین وزن', + 'تعداد بار ورودی به انبار', + 'حجم ورودی به انبار', + 'وزن ورودی به انبار', + 'میانگین درصد افت', + ] + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[5].height = 18 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + + header_list2 = [ + 'تعداد فارم ها', + 'تعداد کل دوره جوجه ریزی ', + 'میانگین کل دوره جوجه ریزی فارم ها ', + 'حجم کل جوجه ریزی ', + 'جوجه ریزی های فعال', + 'حجم جوجه ریزی فعال ', + 'حجم مانده در سالن فعال', + 'تعداد کل درخواست کشتار', + 'حجم کل درخواست کشتار', + 'تعداد کل بار', + 'حجم کل بار', + 'وزن کل بار', + 'میانگین کل وزن', + 'تعداد کل بار مستند', + 'حجم کل بار مستند', + 'وزن کل بار مستند', + 'میانگین وزنی کل بار مستند', + 'تعداد کل بار خارج استان', + 'حجم کل بار خارج استان', + 'وزن کل تقریبی بار خارج استان', + 'میانگین وزن کل بار خارج استان', + 'تعداد بار ورودی به انبار', + 'حجم ورودی به انبار', + 'وزن ورودی به انبار', + 'میانگین درصد افت', + + ] + for col_num, option in enumerate(header_list2, 3): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + l = 4 + m = 1 + + all_hatching_pending = 0 + all_total_quantity = 0 + all_poultry_request = 0 + all_kill_request = 0 + all_kill_request_quantity = 0 + all_kill_request_weight = 0 + all_kill_request_has_assigment = 0 + all_kill_request_quantity_assigment = 0 + all_kill_request_weight_assigment = 0 + all_total_quantity_poultry_hatching_pending = 0 + all_total_left_over_poultry_hatching_pending = 0 + all_total_quantity_poultry_request = 0 + all_len_out_poultry_request = 0 + all_total_out_quantity_poultry_request = 0 + all_total_out_weight_poultry_request = 0 + all_period = 0 + len_werhouse_enter = 0 + all_werhouse_enter_quantity = 0 + all_werhouse_enter_weight = 0 + all_all_weight_loss = 0 + for poultry in poultrys: + user_mobile = poultry.user.mobile if poultry.user else '-' + user_name = poultry.user.fullname if poultry.user else '-' + city_operator = poultry.city_operator if poultry.city_operator else '-' + health_certificate_number = poultry.health_certificate_number if poultry.health_certificate_number else '-' + epidemiological_code = poultry.epidemiological_code if poultry.epidemiological_code else '-' + vet_farm = VetFarm.objects.filter(poultry=poultry, trash=False).select_related('vet__user').last() + vet_name = '-' + mobile_vet = '-' + if vet_farm: + vet_name = vet_farm.vet.user.fullname + mobile_vet = vet_farm.vet.user.mobile + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, trash=False).only('quantity', 'left_over' + ) + + poultry_hatching_pending = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False).last() + if poultry_hatching_pending: + all_hatching_pending += 1 + hatching = 'ندارد' if not poultry_hatching_pending else f'دارد' + period = 0 + if poultry_hatching_pending: + period = poultry_hatching_pending.period + else: + if poultry_hatching: + period = poultry_hatching.last().period + all_period += period + poultry_hatching_pending1 = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False) + total_quantity = \ + poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_quantity_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_left_over_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + all_total_quantity += total_quantity + all_total_quantity_poultry_hatching_pending += total_quantity_poultry_hatching_pending + all_total_left_over_poultry_hatching_pending += total_left_over_poultry_hatching_pending + poultry_request = PoultryRequest.objects.filter(trash=False, poultry=poultry, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only('quantity', + 'Index_weight') + kill_request = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_request).only( + 'accepted_real_quantity', 'accepted_real_weight') + + out_poultry_request = poultry_request.filter(out=True, out_province_request_cancel=False).only( + 'quantity', 'Index_weight' + ) + total_out_quantity_poultry_request = \ + out_poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_out_weight_poultry_request = \ + out_poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + all_total_out_quantity_poultry_request += total_out_quantity_poultry_request + all_total_out_weight_poultry_request += total_out_weight_poultry_request + all_len_out_poultry_request += len(out_poultry_request) + total_quantity_poultry_request = \ + poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + all_total_quantity_poultry_request += total_quantity_poultry_request + all_poultry_request += len(poultry_request) + all_kill_request += len(kill_request) + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_kill_request_quantity += kill_request_quantity + kill_request_weight = kill_request.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_kill_request_weight += int(kill_request_weight) + kill_request_has_assigment = kill_request.filter(assignment_state_archive='True').only('accepted_real_quantity', + 'accepted_real_weight') + + all_kill_request_has_assigment += len(kill_request_has_assigment) + + kill_request_quantity_assigment = kill_request_has_assigment.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_kill_request_quantity_assigment += kill_request_quantity_assigment + kill_request_weight_assigment = kill_request_has_assigment.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_kill_request_weight_assigment += int(kill_request_weight_assigment) + + werhouse_enter = kill_request.filter(ware_house_confirmation=True).only('ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss') + werhouse_enter_quantity = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + werhouse_enter_weight = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + all_weight_loss = werhouse_enter.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_all_weight_loss += all_weight_loss + + all_weight_loss = round(int(all_weight_loss) / len(werhouse_enter), 2) if len(werhouse_enter) > 0 else 0 + + len_werhouse_enter += len(werhouse_enter) + all_werhouse_enter_quantity += werhouse_enter_quantity + all_werhouse_enter_weight += int(werhouse_enter_weight) + province = poultry.user.province.name if poultry.user else '-' + city = poultry.user.city.name if poultry.user else '-' + list1 = [ + m, + poultry.unit_name, + user_name, + user_mobile, + poultry.breeding_unique_id, + epidemiological_code, + health_certificate_number, + poultry.number_of_halls, + poultry.total_capacity, + province + '/' + city, + city_operator, + vet_name + '/' + mobile_vet, + hatching, + period, + total_quantity, + round(total_quantity / period) if period > 0 else 0, + len(poultry_request), + total_quantity_poultry_request, + len(kill_request), + kill_request_quantity, + int(kill_request_weight), + round(kill_request_weight / kill_request_quantity, 1) if kill_request_weight > 0 else 0, + len(kill_request_has_assigment), + kill_request_quantity_assigment, + int(kill_request_weight_assigment), + round(kill_request_weight_assigment / kill_request_quantity_assigment, + 1) if kill_request_weight_assigment > 0 else 0, + len(out_poultry_request), + total_out_quantity_poultry_request, + int(total_out_weight_poultry_request), + str(round(total_out_weight_poultry_request / total_out_quantity_poultry_request, + 1)) if total_out_quantity_poultry_request > 0 else 0, + + len(werhouse_enter), + werhouse_enter_quantity, + int(werhouse_enter_weight), + f'%{all_weight_loss}', + + ] + l += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + m += 1 + row_1 = m - 1 + + value_header_list = [ + m - 1, + all_period, + round(all_period / row_1) if m > 1 else 0, + all_total_quantity, + all_hatching_pending, + all_total_quantity_poultry_hatching_pending, + all_total_left_over_poultry_hatching_pending, + all_poultry_request, + all_total_quantity_poultry_request, + all_kill_request, + all_kill_request_quantity, + all_kill_request_weight, + (round(all_kill_request_weight / all_kill_request_quantity, 1)) if all_kill_request_quantity > 0 else 0, + + all_kill_request_has_assigment, + all_kill_request_quantity_assigment, + all_kill_request_weight_assigment, + str(round(all_kill_request_weight_assigment / all_kill_request_quantity_assigment, + 1)) if all_kill_request_quantity_assigment > 0 else 0, + + all_len_out_poultry_request, + all_total_out_quantity_poultry_request, + int(all_total_out_weight_poultry_request), + str(round(all_total_out_weight_poultry_request / all_total_out_quantity_poultry_request, + 1)) if all_total_out_quantity_poultry_request > 0 else 0, + len_werhouse_enter, + all_werhouse_enter_quantity, + all_werhouse_enter_weight, + f'%{round(int(all_all_weight_loss) / len_werhouse_enter, 2) if len_werhouse_enter > 0 else 0}', + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_total_quantity, + '', + all_poultry_request, + all_total_quantity_poultry_request, + all_kill_request, + all_kill_request_quantity, + all_kill_request_weight, + '', + all_kill_request_has_assigment, + all_kill_request_quantity_assigment, + all_kill_request_weight_assigment, + '', + all_len_out_poultry_request, + all_total_out_quantity_poultry_request, + int(all_total_out_weight_poultry_request), + str(round(all_total_out_weight_poultry_request / all_total_out_quantity_poultry_request, + 1)) if all_total_out_quantity_poultry_request > 0 else 0, + len_werhouse_enter, + all_werhouse_enter_quantity, + all_werhouse_enter_weight, + f'%{round(int(all_all_weight_loss) / len_werhouse_enter, 2) if len_werhouse_enter > 0 else 0}', + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="مدیریت مرغداران.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_excel(request): + filterset_class = PoultryHatchingFilterSet + unknown = True if 'unknown' in request.GET else False + poultry_hatch = PoultryHatching.objects.filter(archive=False, + allow_hatching='pending', + trash=False,unknown=unknown).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'poultry__breeding_unique_id', + + ] + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_hatch = poultry_hatch.filter(poultry__address__city=user.city) + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filtered_poultry_hatch = poultry_hatch.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] == 'ProvinceOperator': + if 'chain' in request.GET: + filtered_poultry_hatch = poultry_hatch.filter(has_chain_company=True) + else: + filtered_poultry_hatch = poultry_hatch + else: + filtered_poultry_hatch = poultry_hatch + else: + filtered_poultry_hatch = poultry_hatch + if 'age2' in request.GET: + if int(request.GET.get('age2')) > 0: + age1 = int(request.GET.get('age1')) + age2 = int(request.GET.get('age2')) + filtered_poultry_hatch = filtered_poultry_hatch.filter(trash=False, chicken_age__gte=age1, + chicken_age__lte=age2) + else: + filtered_poultry_hatch = filtered_poultry_hatch + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', # وضعیت + '', # شماره مجوز جوجه ریزی + '', # شناسه یکتا + '', # مجوز بهداشتی جوجه ریزی + '', # نام فارم + '', # مرغدار + '', # بهره برداری + '', # مالکیت + '', # ارتباط + '', # شهر/تعاونی + '', # دامپزشک فارم + '', # سالن + '', # دوره جوجه ریزی + '', # تاریخ ثبت جوجه ریزی + '', # تاریخ جوجه ریزی + '', # میانگین سن کشتار + '', # پیش بینی تاریخ کشتار + '', # نژاد + '', # سن ورود به بایگانی + '', # تاریخ ورود به بایگانی + '', # سن فعلی + all_quantity, # حجم جوجه ریزی + '', # حجم افزایشی + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جوجه ریزی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def get_vet_farm_name(poultry): + """Get vet farm name for poultry""" + try: + from panel.models import VetFarm + vet_farm = VetFarm.objects.filter(poultry=poultry, trash=False).first() + if vet_farm and vet_farm.vet: + return vet_farm.vet.user.fullname + except: + pass + return '-' + +def calculate_predicted_kill_date(poultry_hatching): + """Calculate predicted kill date based on age and average kill age""" + try: + if poultry_hatching.poultry.killing_ave_age and poultry_hatching.chicken_age: + remaining_days = poultry_hatching.poultry.killing_ave_age - poultry_hatching.chicken_age + if remaining_days > 0: + predicted_date = poultry_hatching.date + datetime.timedelta(days=remaining_days) + return convert_to_shamsi(year=predicted_date.year, month=predicted_date.month, day=predicted_date.day) + except: + pass + return '-' + +def calculate_current_age(poultry_hatching): + """Calculate current age of chickens""" + try: + if poultry_hatching.date: + current_date = datetime.datetime.now().date() + age = (current_date - poultry_hatching.date.date()).days + return age + except: + pass + return poultry_hatching.chicken_age + +def calculate_governmental_killed_weight(poultry_hatching): + """Calculate governmental killed weight""" + try: + if poultry_hatching.governmental_killed_quantity and poultry_hatching.total_average_killed_weight: + return round(poultry_hatching.governmental_killed_quantity * poultry_hatching.total_average_killed_weight, 2) + except: + pass + return 0 + +def calculate_free_killed_weight(poultry_hatching): + """Calculate free killed weight""" + try: + if poultry_hatching.free_killed_quantity and poultry_hatching.total_average_killed_weight: + return round(poultry_hatching.free_killed_quantity * poultry_hatching.total_average_killed_weight, 2) + except: + pass + return 0 + +def calculate_governmental_commitment_weight(poultry_hatching): + """Calculate governmental commitment weight""" + try: + if poultry_hatching.governmental_quantity and poultry_hatching.total_average_killed_weight: + return round(poultry_hatching.governmental_quantity * poultry_hatching.total_average_killed_weight, 2) + except: + pass + return 0 + +def calculate_unloaded_allocations(poultry_hatching): + """Calculate unloaded allocations count""" + try: + from panel.models import ProvinceKillRequest + unloaded = ProvinceKillRequest.objects.filter( + trash=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching, + first_car_allocated_quantity=0, + return_to_province=False + ).count() + return unloaded + except: + pass + return 0 + +def calculate_unloaded_allocations_quantity(poultry_hatching): + """Calculate unloaded allocations quantity""" + try: + from panel.models import ProvinceKillRequest + from django.db.models import Sum + quantity = ProvinceKillRequest.objects.filter( + trash=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching, + first_car_allocated_quantity=0, + return_to_province=False + ).aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + return quantity + except: + pass + return 0 + +def calculate_unloaded_allocations_weight(poultry_hatching): + """Calculate unloaded allocations weight""" + try: + from panel.models import ProvinceKillRequest + from django.db.models import Sum + weight = ProvinceKillRequest.objects.filter( + trash=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching, + first_car_allocated_quantity=0, + return_to_province=False + ).aggregate(total=Sum('total_killed_weight'))['total'] or 0 + return weight + except: + pass + return 0 + +def calculate_radar_discharge_confirmation(poultry_hatching): + """Calculate radar discharge confirmation""" + # This would need to be implemented based on your specific radar system + return '-' + +def calculate_active_kill_count(poultry_hatching): + """Calculate active kill count""" + try: + from panel.models import PoultryRequest + active_count = PoultryRequest.objects.filter( + trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + hatching=poultry_hatching + ).count() + return active_count + except: + pass + return 0 + +def calculate_kill_request_count(poultry_hatching): + """Calculate total kill request count""" + try: + from panel.models import ProvinceKillRequest, KillHouseRequest + province_count = ProvinceKillRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=poultry_hatching + ).count() + kill_house_count = KillHouseRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=poultry_hatching + ).count() + return province_count + kill_house_count + except: + pass + return 0 + + +def archive_hatching_excel(request): + filterset_class = PoultryHatchingFilterSet + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'poultry__breeding_unique_id', + + ] + filtered_poultry_hatch = PoultryHatching.objects.filter( + Q(allow_hatching=True, state='complete') | Q(archive=True), + trash=False + ).select_related('poultry', 'poultry__user').order_by('-create_date') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + filtered_poultry_hatch = filtered_poultry_hatch.filter(date__date__gte=date1, date__date__lte=date2) + user = SystemUserProfile.objects.get(key=request.GET['key']) + if 'chain' in request.GET: + filtered_poultry_hatch = filtered_poultry_hatch.filter(has_chain_company=True) + + if request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_hatch = filtered_poultry_hatch.filter(poultry__address__city=user.city) + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filtered_poultry_hatch = filtered_poultry_hatch.filter(poultry__city_operator=city_operator.unit_name) + else: + filtered_poultry_hatch = filtered_poultry_hatch + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'دامپزشک فارم', + 'سالن', + 'دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیش بینی تاریخ کشتار', + 'نژاد', + 'سن ورود به بایگانی', + 'تاریخ ورود به بایگانی', + 'سن فعلی', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک', + 'تلفات اتحادیه', + 'تلفات کل', + 'حجم تعهد دولتی', + 'حجم تعهد آزاد', + 'حجم کشتار دولتی', + 'وزن کشتار دولتی', + 'حجم کشتار آزاد', + 'وزن کشتار شده آزاد', + 'حجم فروش به خارج استان', + 'وزن فروش به خارج استان', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'حجم کشتار شده', + 'حجم مانده در سالن', + 'تلفات', + 'کشتار شده', + 'باقی مانده در سالن', + 'تایید تخلیه رصدیار', + 'تایید تخلیه در سماصط', + 'وزن تعهد دولتی', + 'وزن کشتار دولتی', + 'وزن کشتار آزاد', + 'میانگین وزن کشتار', + 'وزن کل کشتار شده', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + 'تعداد بارها', + 'حجم بارها', + 'وزن بارها', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'بارهای ورودی به انبار', + 'حجم لاشه های انبار', + 'وزن لاشه های انبار', + 'درصد افت بارها', + 'آخرین تغییر', + 'سازنده جوجه ریزی' + ] + date1 = datetime.datetime.now().date() + from_date_1 = shamsi_date(date1) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = convert_to_shamsi(year=poultry_hatching.create_date.year, + month=poultry_hatching.create_date.month, + day=poultry_hatching.create_date.day, ) + + date = convert_to_shamsi( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = poultry_hatching.chicken_age + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + + list1 = [ + m, # ردیف + farm_state, # وضعیت + poultry_hatching.licence_number, # شماره مجوز جوجه ریزی + poultry_hatching.poultry.breeding_unique_id, # شناسه یکتا + poultry_hatching.poultry.health_certificate_number if poultry_hatching.poultry.health_certificate_number else '-', # مجوز بهداشتی جوجه ریزی + poultry_hatching.poultry.unit_name, # نام فارم + poultry_hatching.poultry.user.fullname, # مرغدار + poultry_hatching.poultry.person_type if poultry_hatching.poultry.person_type else '-', # بهره برداری + 'مالک' if not poultry_hatching.poultry.has_tenant else 'مستاجر', # مالکیت + poultry_hatching.poultry.communication_type if poultry_hatching.poultry.communication_type else '-', # ارتباط + f"{poultry_hatching.poultry.user.city.name}/{poultry_hatching.poultry.city_operator}" if poultry_hatching.poultry.city_operator else poultry_hatching.poultry.user.city.name, # شهر/تعاونی + get_vet_farm_name(poultry_hatching.poultry), # دامپزشک فارم + poultry_hatching.hall, # سالن + poultry_hatching.period, # دوره جوجه ریزی + str(create_date), # تاریخ ثبت جوجه ریزی + str(date), # تاریخ جوجه ریزی + poultry_hatching.poultry.killing_ave_age, # میانگین سن کشتار + calculate_predicted_kill_date(poultry_hatching), # پیش بینی تاریخ کشتار + poultry_hatching.chicken_breed, # نژاد + poultry_hatching.chicken_age, # سن ورود به بایگانی + convert_to_shamsi(year=poultry_hatching.archive_date.year, month=poultry_hatching.archive_date.month, day=poultry_hatching.archive_date.day) if poultry_hatching.archive_date else '-', # تاریخ ورود به بایگانی + calculate_current_age(poultry_hatching), # سن فعلی + poultry_hatching.quantity, # حجم جوجه ریزی + poultry_hatching.increase_quantity if hasattr(poultry_hatching, 'increase_quantity') else 0, # حجم افزایشی + poultry_hatching.losses, # تلفات دامپزشک + poultry_hatching.direct_losses, # تلفات اتحادیه + poultry_hatching.total_losses, # تلفات کل + poultry_hatching.total_commitment, # حجم تعهد دولتی + poultry_hatching.free_quantity, # حجم تعهد آزاد + poultry_hatching.governmental_killed_quantity, # حجم کشتار دولتی + calculate_governmental_killed_weight(poultry_hatching), # وزن کشتار دولتی + poultry_hatching.free_killed_quantity, # حجم کشتار آزاد + calculate_free_killed_weight(poultry_hatching), # وزن کشتار شده آزاد + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else 0, # حجم فروش به خارج استان + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else 0, # وزن فروش به خارج استان + calculate_unloaded_allocations(poultry_hatching), # تخصیصات بدون بار + calculate_unloaded_allocations_quantity(poultry_hatching), # حجم تخصیصات بدون بار + calculate_unloaded_allocations_weight(poultry_hatching), # وزن تخصیصات بدون بار + poultry_hatching.killed_quantity, # حجم کشتار شده + poultry_hatching.left_over, # حجم مانده در سالن + poultry_hatching.total_losses, # تلفات + poultry_hatching.killed_quantity, # کشتار شده + poultry_hatching.left_over, # باقی مانده در سالن + calculate_radar_discharge_confirmation(poultry_hatching), # تایید تخلیه رصدیار + poultry_hatching.samasat_discharge_percentage if hasattr(poultry_hatching, 'samasat_discharge_percentage') else 0, # تایید تخلیه در سماصط + calculate_governmental_commitment_weight(poultry_hatching), # وزن تعهد دولتی + calculate_governmental_killed_weight(poultry_hatching), # وزن کشتار دولتی + calculate_free_killed_weight(poultry_hatching), # وزن کشتار آزاد + str(poultry_hatching.total_average_killed_weight), # میانگین وزن کشتار + poultry_hatching.total_killed_weight, # وزن کل کشتار شده + calculate_active_kill_count(poultry_hatching), # تعداد کشتار فعال + calculate_kill_request_count(poultry_hatching), # تعداد درخواست کشتار + len(kill_house_requests), # تعداد بارها + first_quantity, # حجم بارها + first_weight, # وزن بارها + accepted_real_quantity_final, # حجم بارهای تحویلی + accepted_real_wight_final, # وزن بارهای تحویلی + poultry_hatching.chain_killed_quantity if hasattr(poultry_hatching, 'chain_killed_quantity') else 0, # حجم زنجیره + poultry_hatching.chain_killed_weight if hasattr(poultry_hatching, 'chain_killed_weight') else 0, # وزن زنجیره + poultry_hatching.export_killed_quantity if hasattr(poultry_hatching, 'export_killed_quantity') else 0, # حجم صادرات + poultry_hatching.export_killed_weight if hasattr(poultry_hatching, 'export_killed_weight') else 0, # وزن صادرات + len(ware_house_bars), # بارهای ورودی به انبار + ware_house_bars_quantity, # حجم لاشه های انبار + ware_house_bars_weight, # وزن لاشه های انبار + str(round(ware_house_bars_weight_lose / len(ware_house_bars), 2) if ware_house_bars else 0), # درصد افت بارها + shamsi_date(convert_str_to_date(poultry_hatching.last_change.get('date', ''))) if poultry_hatching.last_change and poultry_hatching.last_change.get('date') else '', # آخرین تغییر + creator, # سازنده جوجه ریزی + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename=" جوجه ریزی بایگانی شده.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_age_range_excel(request): + filtered_poultry_hatchs = PoultryHatching.objects.filter(state__in=('pending', 'complete'), archive=False, + allow_hatching='pending', + trash=False).order_by('-create_date').select_related( + 'poultry') + + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + filtered_poultry_hatch = filtered_poultry_hatchs.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_hatch = filtered_poultry_hatchs.filter(poultry__user__city=user.city) + else: + filtered_poultry_hatch = filtered_poultry_hatchs + else: + filtered_poultry_hatch = filtered_poultry_hatchs + + excel_options = [ + 'ردیف', + 'نام فارم', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'کشتار شده', + 'مانده در سالن', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد کل فارم ها', + 'مجموع جوجه ریزی', + 'مجموع کشتار شده', + 'مجموع مانده در سالن', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + ] + for col_num, option in enumerate(header_list, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=10, bold=True, color='FFFFFF') + worksheet.row_dimensions[2].height = 30 + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=5, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + worksheet.column_dimensions[col_letter].width = 20.01 + worksheet.row_dimensions[1].height = 18 + worksheet.freeze_panes = worksheet['A6'] + max_col = worksheet.max_column + range_str = f'A5:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + l = 4 + m = 1 + for poultry_hatching in filtered_poultry_hatch: + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + poultry_requests = PoultryRequest.objects.filter(hatching=poultry_hatching, trash=False).only('quantity') + age = (datetime.datetime.now().date() - poultry_hatching.date.date()).days + 1 + quantity_sum = 0 + for poultry_request in poultry_requests: + if poultry_request and hasattr(poultry_request, 'quantity'): + quantity_sum += poultry_request.quantity + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + list1 = [ + m, + poultry_hatching.poultry.unit_name, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.left_over, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + cell.alignment = Alignment(horizontal='center') + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + m += 1 + total_poultry_hatchings_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + total_poultry_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity') or 0 + total_poultry_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity') or 0 + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + value_list = [ + m - 1, + total_poultry_hatchings_quantity, + total_poultry_killed_quantity, + total_poultry_left_over, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + + ] + for item in range(len(value_list)): + cell = worksheet.cell(row=3, column=item + 3, value=value_list[item]) + cell.alignment = Alignment(horizontal='center') + value = value_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="موجودی جوجه ریزی (مانده در سالن) بر اساس بازه سنی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_monitoring_excel(request): + poultreis = Poultry.objects.filter(trash=False, key=request.GET['key']).select_related('user', 'address__province', + 'address__city').first() + hatchings = PoultryHatching.objects.filter(trash=False, poultry=poultreis).order_by('id') + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = ['اطلاعات کلی', 'مدیریت بارها'] + for sheet_names in sheet_name: + worksheet = workbook.create_sheet(sheet_names) + if sheet_names == 'اطلاعات کلی': + excel_options = [ + ' جوجه ریزی مرحله', + 'نام واحد', + 'نام مالک', + 'تاریخ جوجه ریزی', + 'تعداد جوجه ریزی', + 'نود درصد جوجه ریزی', + + 'مجموع تلفات', + 'مانده در سالن', + 'متوسط سن کشتار', + 'تعداد ثبت سفارش', + 'تعداد درخواست کشتار (قطعه)', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار(کیلوگرم)', + 'درصد کشتار نسبت به نود درصد', + 'مجموع تخصیصی به ماشین(قطعه)', + 'مجموع وزن تخصیصی به ماشین(کیلوگرم)', + 'تعداد تخلیه شده دامپزشک', + 'وزن تخلیه شده دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + 'حجم کشتار', + 'وزن کشتار', + 'عملکرد فارم', + + ] + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + for col_num, option in enumerate(excel_options, 3): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=3, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="31869B", fill_type="solid") + cell.font = Font(size=9, bold=True, color='FFFFFF') + worksheet.row_dimensions[3].height = 36 + worksheet.column_dimensions[col_letter].width = 14 + + now = datetime.datetime.now().date() + now_date = jdatetime.date.fromgregorian( + year=now.year, + month=now.month, + day=now.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(now_date.split("-")) + separate = "-" + date_now = separate.join(reversed_date) + + row_list2 = len(hatchings) + 10 + row_city = len(hatchings) + 8 + + province = poultreis.user.province.name + worksheet[ + f'F1'] = f'گزارش پایش اطلاعاتی {poultreis.unit_name} سامانه رصدیار استان {province} در تاریخ{date_now} ' + worksheet[f'F1'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'F1'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'F1:I2' + worksheet.merge_cells(merge_range1) + l = 4 + + all_quantity_of_car1 = 0 + average_age_list1 = [] + all_weight1 = [] + + all_weight_of_car1 = 0 + all_main_quantity1 = 0 + sum_all_quantity_vet_kill1 = 0 + sum_all_wight_vet_kill1 = 0 + sum_net_weight1 = 0 + sum_real_quantity_assigment1 = 0 + sum_accepted_real_quantity1 = 0 + sum_accepted_real_weight1 = 0 + all_loses1 = 0 + all_all_quantity_of_request1 = 0 + len_werhouse_enter1 = 0 + all_werhouse_enter_quantity1 = 0 + all_werhouse_enter_weight1 = 0 + all_all_weight_loss1 = 0 + + for hatching in hatchings: + final_left_over = [] + all_quantity_of_car = 0 + average_age_list = [] + all_percent = 0 + m = 1 + all_weight = [] + all_quantity_of_car_vet_state_accepted = 0 + request_weight = [] + all_request_weight = [] + all_free_sale_in_province_true = 0 + all_kill_province_request_poultry_request_Index_weight = [] + all_weight_of_car = 0 + all_weight_of_car_vet_state_accepted = 0 + all_main_quantity = 0 + sum_quantity_qarantineh = 0 + sum_all_quantity_vet_kill = 0 + sum_all_wight_vet_kill = 0 + sum_net_weight = 0 + sum_real_quantity_assigment = 0 + sum_accepted_real_quantity = 0 + sum_accepted_real_weight = 0 + all_free_sale_in_province_false = 0 + all_loses = 0 + all_province_quantity = 0 + quantity = hatching.quantity + ninety_percent = hatching.quantity + all_len_werhouse_enter = 0 + all_werhouse_enter_quantity = 0 + all_werhouse_enter_weight = 0 + all_all_weight_loss = 0 + killed = 0 + hatch_date = jdatetime.date.fromgregorian( + day=hatching.date.day, + month=hatching.date.month, + year=hatching.date.year + ) + poultry_requests = PoultryRequest.objects.filter(out_province_request_cancel=False, trash=False, + hatching=hatching, + archive=False, + state_process__in=('accepted', 'pending')).order_by( + 'id') + + werhouse_enter1 = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=hatching, + ware_house_confirmation=True) + werhouse_enter_quantity1 = werhouse_enter1.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + werhouse_enter_weight1 = werhouse_enter1.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + all_weight_loss2 = werhouse_enter1.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_all_weight_loss1 += all_weight_loss2 + + all_weight_loss1 = round(int(all_weight_loss2) / len(werhouse_enter1), 2) if len( + werhouse_enter1) > 0 else 0 + + len_werhouse_enter1 += len(werhouse_enter1) + all_werhouse_enter_quantity1 += werhouse_enter_quantity1 + all_werhouse_enter_weight1 += int(werhouse_enter_weight1) + excel_options = [ + 'ردیف', + 'کد سفارش', + 'تاریخ ثبت درخواست', + 'تاریخ کشتار', + 'سن کشتار', + 'نوع درخواست', + 'فروش', + 'تعداد درخواست کشتار', + 'میانگین وزنی درخواست', + 'وزن کل درخواست ', + 'ماهیت خریدار', + 'خریدار', + 'تلفن خریدار', + 'تعداد تخصیصی استان به خریدار(قطعه)', + 'وزن تخصیصی استان به خریدار', + 'مانده در سالن', + ' تعداد بار', + 'تعداد بار قطعه', + 'وزن بار', + 'تعداد قطعه وارد شده در قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'تعداد بار ورود به انبار', + 'حجم بار ورود به انبار', + 'وزن بار ورود به انبار', + 'درصد افت', + 'حجم کشتار', + 'وزن کشتار', + + ] + + if poultry_requests: + worksheet[f'E{row_list2 - 2}'] = f'اطلاعات جوجه ریزی {hatching.period}' + worksheet[f'E{row_list2 - 2}'].font = Font(color="C00000", bold=True, size=12) + worksheet[f'E{row_list2 - 2}'].alignment = Alignment(horizontal='center', vertical='center', + wrap_text=True) + merge_range1 = f'E{row_list2 - 2}:I{row_list2 - 1}' + worksheet.merge_cells(merge_range1) + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=row_list2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + + worksheet.column_dimensions[col_letter].width = 20 + + worksheet.row_dimensions[row_list2].height = 36 + for poultry_request in poultry_requests: + + all_loses += poultry_request.hatching.losses + all_loses1 += poultry_request.hatching.losses + kill_request = ProvinceKillRequest.objects.filter( + province_request__poultry_request=poultry_request, + trash=False, + state__in=('pending', 'accepted'), + return_to_province=False).select_related( + 'killhouse_user', 'province_request__poultry_request').order_by('-create_date') + + car_date = jdatetime.date.fromgregorian( + day=poultry_request.send_date.day, + month=poultry_request.send_date.month, + year=poultry_request.send_date.year + ) + create_date = jdatetime.date.fromgregorian( + day=poultry_request.create_date.day, + month=poultry_request.create_date.month, + year=poultry_request.create_date.year + ) + average_age = (poultry_request.send_date.date() - hatching.date.date()).days + 1 + average_age_list.append(average_age) + average_age_list1.append(average_age) + + if poultry_request.direct_buying == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + free_sale_in_province_false = 0 + Index_weight_sale_in_province_false = 0 + free_sale_in_province_true = 0 + + all_province_quantity += poultry_request.quantity + if poultry_request.out == True: + sale_type = 'خارج از استان' + elif poultry_request.free_sale_in_province == False: + free_sale_in_province_false = poultry_request.quantity + all_free_sale_in_province_false += free_sale_in_province_false + Index_weight_sale_in_province_false = poultry_request.Index_weight + sale_type = 'دولتی' + else: + sale_type = 'آزاد' + free_sale_in_province_true = poultry_request.quantity + + all_free_sale_in_province_true += free_sale_in_province_true + + all_request_weight.append(poultry_request.Index_weight * poultry_request.quantity) + list1 = [ + m, + str(poultry_request.order_code), + str(create_date), + str(car_date), + average_age, + type, + sale_type, + poultry_request.quantity, + poultry_request.Index_weight, + round(poultry_request.quantity * poultry_request.Index_weight, 2), + # poultry_request.quantity, + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=row_list2 + 1, column=item + 1, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 1)].width = 17.01 + worksheet.row_dimensions[row_list2 + 1].height = 21 + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + # l += 1 + if kill_request.exists(): + o = row_list2 + 1 + if len(kill_request) > 1: + s = len(kill_request) - 1 + + for col in range(ord('A'), ord('J') + 1): + # rng = chr(col) + '7:{}'.format(r) + rng = f'{chr(col)}{o}:{chr(col)}{o + s}' + worksheet.merge_cells(rng) + worksheet[chr(col) + f'{o}'].alignment = Alignment(horizontal='center', + vertical='center') + for kill in kill_request: + + all_main_quantity += kill.main_quantity + all_main_quantity1 += kill.main_quantity + state_s = '' + if kill.state == 'pending': + state_s = 'درانتظار تایید' + elif kill.state == 'accepted': + state_s = ' تایید شده' + quantity_of_car_vet_state_accepted = 0 + weight_of_car_vet_state_accepted = 0 + quantity_of_car = 0 + weight_of_car = 0 + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request=kill).order_by( + 'id').only('create_date', 'vet_state') + all_net_weight = 0 + all_real_quantity_assigment = 0 + werhouse_enter = kill_house_requests.filter(ware_house_confirmation=True).only( + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss') + len_werhouse_enter = len(werhouse_enter) + werhouse_enter_quantity = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + werhouse_enter_weight = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + all_weight_loss = werhouse_enter.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + + all_len_werhouse_enter += len_werhouse_enter + all_werhouse_enter_quantity += werhouse_enter_quantity + all_werhouse_enter_weight += werhouse_enter_weight + all_all_weight_loss += all_weight_loss + all_weight_loss = round(int(all_weight_loss) / len(werhouse_enter), 2) if len( + werhouse_enter) > 0 else 0 + + if kill_house_requests: + for kill_house_request in kill_house_requests: + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False).only('net_weight', + 'real_quantity').first() + if assignment: + all_net_weight += assignment.net_weight if assignment.net_weight != None else 0 + all_real_quantity_assigment += assignment.real_quantity if assignment.real_quantity != None else 0 + quantity_of_car += kill_house_request.quantity + all_quantity_of_car += kill_house_request.quantity + all_quantity_of_car1 += kill_house_request.quantity + weight_of_car += int( + kill_house_request.quantity * kill_house_request.province_request.poultry_request.Index_weight) + + if kill_house_request.vet_state == 'accepted': + quantity_of_car_vet_state_accepted += kill_house_request.quantity + weight_of_car_vet_state_accepted += kill_house_request.accepted_real_weight + all_quantity_of_car_vet_state_accepted += kill_house_request.quantity + + killed += kill.main_quantity + all_quantity_qarantineh = kill_house_requests.aggregate( + total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + + all_quantity_vet_kill = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity', 0) + all_weight_vet_kill = kill_house_requests.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity', 0) + all_accepted_real_quantity = kill_house_requests.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) + all_accepted_real_weight = kill_house_requests.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity', 0) + sum_all_wight_vet_kill += all_weight_vet_kill if all_weight_vet_kill != None else 0 + sum_all_wight_vet_kill1 += all_weight_vet_kill if all_weight_vet_kill != None else 0 + sum_all_quantity_vet_kill += all_quantity_vet_kill if all_quantity_vet_kill != None else 0 + sum_all_quantity_vet_kill1 += all_quantity_vet_kill if all_quantity_vet_kill != None else 0 + sum_quantity_qarantineh += all_quantity_qarantineh if all_quantity_qarantineh != None else 0 + sum_accepted_real_quantity += all_accepted_real_quantity if all_accepted_real_quantity != None else 0 + sum_accepted_real_quantity1 += all_accepted_real_quantity if all_accepted_real_quantity != None else 0 + sum_accepted_real_weight += all_accepted_real_weight if all_accepted_real_weight != None else 0 + sum_accepted_real_weight1 += all_accepted_real_weight if all_accepted_real_weight != None else 0 + left_over = (quantity - killed) + final_left_over.append(left_over) + percent_after_assigment = (quantity_of_car_vet_state_accepted * 100) / quantity + all_percent += percent_after_assigment + + all_weight.append( + kill.main_quantity * kill.province_request.poultry_request.Index_weight) + all_weight1.append( + kill.main_quantity * kill.province_request.poultry_request.Index_weight) + killer = 'کشتارکن' if kill.killhouse_user.killer == True else 'کشتارگاه' + + request_weight.append(Index_weight_sale_in_province_false) + all_kill_province_request_poultry_request_Index_weight.append( + kill.province_request.poultry_request.Index_weight) + + all_weight_of_car_vet_state_accepted += weight_of_car_vet_state_accepted + all_weight_of_car += weight_of_car + all_weight_of_car1 += weight_of_car + list1 = [ + killer, + kill.killhouse_user.name, + kill.killhouse_user.kill_house_operator.user.mobile, + kill.main_quantity, + kill.province_request.poultry_request.Index_weight, + left_over, + len(kill_house_requests) if kill_house_requests else 0, + quantity_of_car, + weight_of_car, + all_quantity_qarantineh if all_quantity_qarantineh else '-', + all_quantity_vet_kill if all_quantity_vet_kill else '-', + all_weight_vet_kill if all_weight_vet_kill else '-', + all_real_quantity_assigment if all_real_quantity_assigment > 0 else '-', + all_net_weight if all_net_weight > 0 else '-', + len_werhouse_enter, + werhouse_enter_quantity, + int(werhouse_enter_weight), + f'%{all_weight_loss}', + all_accepted_real_quantity if all_accepted_real_quantity else '-', + all_accepted_real_weight if all_accepted_real_weight else '-', + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row_list2 + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + row_list2 += 1 + + sum_net_weight += all_net_weight + sum_net_weight1 += all_net_weight + sum_real_quantity_assigment += all_real_quantity_assigment + sum_real_quantity_assigment1 += all_real_quantity_assigment + else: + if poultry_request.out == True: + left_over = (quantity - killed) + list1 = [ + 'خارج از استان', + poultry_request.buyer_fullname, + poultry_request.buyer_mobile, + poultry_request.quantity, + int(poultry_request.Index_weight), + left_over, + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + poultry_request.quantity, + int(poultry_request.quantity * poultry_request.Index_weight), + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row_list2 + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + sum_accepted_real_weight += int( + poultry_request.quantity * poultry_request.Index_weight) + sum_accepted_real_weight1 += int( + poultry_request.quantity * poultry_request.Index_weight) + sum_accepted_real_quantity += poultry_request.quantity + sum_accepted_real_quantity1 += poultry_request.quantity + else: + list1 = [ + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + '-', + + ] + for item in range(len(list1)): + cell = worksheet.cell(row=row_list2 + 1, column=item + 11, value=list1[item]) + value = list1[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + + if m % 2 == 0: + cell.fill = PatternFill(start_color="DAE1F6", fill_type="solid") + row_list2 += 1 + try: + dd = round(sum(all_kill_province_request_poultry_request_Index_weight) / len( + all_kill_province_request_poultry_request_Index_weight)) + except: + dd = 0 + list2 = [ + 'مجموع==>', + '', + '', + '', + f'', + '', + '', + int(all_province_quantity), + '', + int(sum(all_request_weight)), + '', + '', + '', + int(all_main_quantity), + int(dd), + f'', + '', + + int(all_quantity_of_car), + int(all_weight_of_car), + int(sum_quantity_qarantineh), + int(sum_all_quantity_vet_kill), + int(sum_all_wight_vet_kill), + int(sum_real_quantity_assigment), + int(sum_net_weight), + all_len_werhouse_enter, + all_werhouse_enter_quantity, + all_werhouse_enter_weight, + f'%{round(int(all_all_weight_loss) / all_len_werhouse_enter, 2) if all_len_werhouse_enter > 0 else 0}', + int(sum_accepted_real_quantity), + int(sum_accepted_real_weight), + + ] + + for item in range(len(list2)): + cell = worksheet.cell(row=row_list2 + 2, column=item + 1, value=list2[item]) + value = list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + row_list2 += 8 + row_city += 6 + + try: + avrage_age1 = round((sum(average_age_list) / len(average_age_list))) + except: + avrage_age1 = 0 + all_quantity_of_request = poultry_requests.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + row_header = 1 + all_all_quantity_of_request1 += all_quantity_of_request + value_header_list = [ + hatching.period, + hatching.poultry.unit_name, + hatching.poultry.user.fullname, + str(hatch_date), + quantity, + ninety_percent, + + all_loses, + hatching.left_over, + avrage_age1, + len(poultry_requests), + all_quantity_of_request, + hatching.out_province_killed_quantity, + hatching.out_province_killed_weight, + all_main_quantity, + sum(all_weight), + round((hatching.killed_quantity * 100) / ninety_percent), + all_quantity_of_car, + all_weight_of_car, + sum_all_quantity_vet_kill, + sum_all_wight_vet_kill, + sum_real_quantity_assigment, + int(sum_net_weight), + len(werhouse_enter1), + werhouse_enter_quantity1, + werhouse_enter_weight1, + f'%{round(all_weight_loss2 / len(werhouse_enter1), 2) if len(werhouse_enter1) > 0 else 0}', + sum_accepted_real_quantity, + sum_accepted_real_weight, + f'%{int((sum_accepted_real_quantity * 100) / quantity if quantity > 0 else 0)}', + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=l, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center', vertical='center') + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + # worksheet.column_dimensions[get_column_letter(item + 11)].width = 17.01 + # worksheet.column_dimensions[get_column_letter(item + 11)].height = 20.01 + + l += 1 + row_header += 1 + else: + all_left_over = hatchings.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity') or 0 + all_quantity = hatchings.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + out_province_killed_quantity = hatchings.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity') or 0 + out_province_killed_weight = hatchings.aggregate(total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity') or 0 + + ninety_percent = (all_quantity * 90) / 100 + value_header_list = [ + 'مجموع==>', + '', + '', + '', + all_quantity, + ninety_percent, + + all_loses1, + all_left_over, + '', + '', + all_all_quantity_of_request1, + out_province_killed_quantity, + out_province_killed_weight, + all_main_quantity1, + sum(all_weight1), + '', + all_quantity_of_car1, + all_weight_of_car1, + sum_all_quantity_vet_kill1, + sum_all_wight_vet_kill1, + sum_real_quantity_assigment1, + int(sum_net_weight1), + len_werhouse_enter1, + all_werhouse_enter_quantity1, + all_werhouse_enter_weight1, + '', + sum_accepted_real_quantity1, + sum_accepted_real_weight1, + '', + + ] + nn = len(hatchings) + 4 + for item in range(len(value_header_list)): + cell = worksheet.cell(row=nn, column=item + 3, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int, float)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.border = openpyxl.styles.Border( + left=openpyxl.styles.Side(style='thin'), + right=openpyxl.styles.Side(style='thin'), + top=openpyxl.styles.Side(style='thin'), + bottom=openpyxl.styles.Side(style='thin') + ) + else: + filtered_kill_request = KillHouseRequest.objects.filter( + trash=False, province_request__poultry_request__poultry=poultreis + ).order_by( + '-create_date').select_related( + 'killhouse_user', 'province_request__poultry_request__poultry__user', + 'province_request__poultry_request', + 'province_request__poultry_request__poultry', 'add_car__driver', + 'killhouse_user__system_address__city', + 'kill_request__slaughter_house').only('ware_house_confirmation', + 'document_status', 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', 'weight_loss', 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', 'traffic_code', + 'assignment_state_archive', + 'province_request__poultry_request__hatching__chicken_age', + 'killhouse_user__kill_house_operator__user__province__name', + 'killhouse_user', + 'killhouse_user__name', + 'province_request__poultry_request__amount', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', 'quarantine_quantity', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', 'killer').values('document_status', + 'ware_house_confirmation', + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss', + 'message', + 'province_request__poultry_request__freezing', + 'province_request__poultry_request', + 'killhouse_user', + 'killhouse_user__name', + 'killhouse_user__kill_house_operator__user__mobile', + 'killhouse_user__system_address__city__name', + 'killhouse_user__killer', + 'kill_request__slaughter_house', + 'kill_request__slaughter_house__name', + 'province_request__poultry_request__poultry', + 'province_request__poultry_request__order_code', + 'province_request__poultry_request__chicken_breed', + 'province_request__poultry_request__poultry__user__city__name', + 'province_request__poultry_request__poultry__unit_name', + 'province_request__poultry_request__poultry__user__mobile', + 'province_request__poultry_request__send_date', + 'add_car__driver__driver_name', + 'add_car__driver__driver_mobile', + 'add_car__driver__type_car', + 'add_car__driver__health_code', + 'key', + 'province_kill_request__province_request__poultry_request__Index_weight', + 'clearance_code', + 'quantity', + 'bar_code', + 'accepted_real_weight', + 'accepted_real_quantity', + 'vet_state', + 'vet_accepted_real_quantity', + 'vet_accepted_real_weight', + 'quarantine_quantity', + 'killhouse_user__kill_house_operator__user__province__name', + 'province_request__poultry_request__hatching__chicken_age', + 'province_request__poultry_request__amount', + 'assignment_state_archive', + 'traffic_code', + 'province_kill_request__province_request__poultry_request__free_sale_in_province', + 'province_kill_request__province_request__poultry_request__union', + 'province_kill_request__province_request__poultry_request__direct_buying', + 'quarantine_code_state', + 'province_request__poultry_request__send_date', + 'province_request__poultry_request__hatching__date', + 'killer__kill_house_operator__user__mobile', + 'killer__name', + 'killhouse_user__type', + 'killer', + ) + + filtered_kill_reqs = filtered_kill_request + + poultry_request = (PoultryRequest.objects.filter(trash=False, pk__in=filtered_kill_reqs.values( + 'province_request__poultry_request')) + .only('quantity', 'Index_weight')).annotate( + total_quantity=Sum('quantity'), + total_weight=Sum(F('quantity') * F('Index_weight')) + ) + + total_requests_quantity = poultry_request.aggregate(total=Sum('total_quantity'))['total'] or 0 + total_requests_weight = poultry_request.aggregate(total=Sum('total_weight'))['total'] or 0 + excel_options = [ + 'ردیف', + 'کد بار', + ' تاریخ کشتار', + 'کشتار', + 'کدسفارش مرغدار', + 'مرغدار', + 'تلفن مرغدار', + ' شهر مرغدار', + 'فروش', + + 'سن مرغ', + 'قیمت پیشنهادی مرغدار(ریال)', + ' نژاد', + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + ' ماهیت خریدار', + 'خریدار', + ' تلفن خریدار', + ' آدرس ', + 'کشتارکن اختصاصی', + 'تلفن کشتارکن اختصاصی', + ' محل کشتار ', + 'نوع تخصیص', + 'دامپزشک کشتارگاه ', + ' تلفن دامپزشک کشتارگاه ', + 'راننده', + 'موبایل راننده', + 'نوع خودرو', + 'کد بهداشتی حمل و نقل', + 'تعداد قطعه بار ', + 'وزن بار', + 'کد رهگیری سامانه قرنطینه', + 'تعداد قطعه وارد شده در قرنطینه', + 'وضعیت تخلیه', + 'تاریخ تخلیه (کشتارگاه)', + 'تعداد تخلیه شده دامپزشک', + 'وزن بار تخلیه شده(کیلوگرم)دامپزشک', + 'تعداد نهایی در کشتارگاه', + 'وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'وضعیت', + 'وضعیت سند', + 'وضعیت ورود انبار', + 'تعداد لاشه', + 'وزن لاشه', + 'درصد افت', + + ] + + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + for col_num, option in enumerate(excel_options, 1): + col_letter = get_column_letter(col_num) + cell = worksheet.cell(row=6, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = blue_fill + cell.font = Font(size=10, bold=True, color='D9FFFFFF') + if len(option) > worksheet.column_dimensions[col_letter].width: + worksheet.column_dimensions[col_letter].width = len(option) + 3 + + # تنظیم ارتفاع سطر + # ارتفاع سطر را برابر با ارتفاع آخرین سطر قرار می‌دهیم + worksheet.row_dimensions[6].height = 19 + worksheet.freeze_panes = worksheet['A7'] + max_col = worksheet.max_column + range_str = f'A6:{get_column_letter(max_col)}{worksheet.max_row}' + worksheet.auto_filter.ref = range_str + header_list = [ + 'تعداد بارهای ایجاد شده', + 'تعداد بارهای دارای کشتارکن اختصاصی', + 'مجموع تعداد قطعه بارها', + 'مجموع وزن بارها', + 'تعداد بارهای دارای کد قرنطینه', + 'تعداد بار احراز شده از قرنطینه', + 'مجموع تعداد قطعه احراز شده از قرنطینه', + 'تعداد تخلیه شده دامپزشک', + 'مجموع تعداد تخلیه شده دامپزشک', + 'مجموع وزن تخلیه شده دامپزشک', + 'تعداد بارهای تکمیل شده', + 'مجموع تعداد نهایی در کشتارگاه', + 'مجموع وزن نهایی در کشتار گاه', + 'ملاک قطعه کشتار شده', + 'ملاک وزن کشتار شده', + 'تعداد بار های وارد شده در انبار', + 'مجموع تعداد لاشه', + 'مجموع وزن لاشه', + 'میانگین درصد افت لاشه', + + ] + for col_num, option in enumerate(header_list, 9): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="0070C0", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + header_list2 = [ + 'تعداد درخواست مرغداران', + ' مجموع تعداد قطعه درخواست مرغداران', + ' مجموع وزن درخواست مرغداران', + + ] + for col_num, option in enumerate(header_list2, 6): + cell = worksheet.cell(row=2, column=col_num, value=option) + cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + cell.font = Font(size=9, bold=True, color='D9FFFFFF') + worksheet.row_dimensions[2].height = 20.8 + + worksheet['B1'] = f'گزارش بارهای ایجاد شده در فرآیند کشتار مرغ گوشتی' + + if filtered_kill_reqs.exists(): + name = filtered_kill_reqs.first()['killhouse_user__kill_house_operator__user__province__name'] + worksheet['B2'] = f'استان {name}' + + # worksheet['B3'] = f'از تاریخ:({from_date_1}) تا تاریخ:({to_date_1})' + + worksheet['B3'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B1'].alignment = Alignment(horizontal='center', vertical='center') + worksheet['B2'].alignment = Alignment(horizontal='center', vertical='center') + merge_range1 = 'B1:D1' + merge_range2 = 'B2:D2' + merge_range = 'B3:D3' + worksheet.merge_cells(merge_range1) + worksheet.merge_cells(merge_range) + worksheet.merge_cells(merge_range2) + worksheet['B1'].font = red_font + worksheet['B3'].font = Font(size=11) + worksheet['B2'].font = Font(size=10, bold=True, color="C00000") + + l = 5 + m = 1 + all_quantity = 0 + all_real_quantity = 0 + all_net_weighte = 0 + all_weighte = 0 + all_vet_state_accepted = len( + filtered_kill_reqs.filter(vet_state='accepted')) + bar_complete = filtered_kill_reqs.filter(assignment_state_archive='True') + accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + accepted_real_wight = filtered_kill_reqs.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + all_kill_request_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_vet_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('vet_accepted_real_weight')).get( + 'total_quantity') or 0 + killer_exclusive = 0 + all_assignment_state_archive_state = 0 + len_weight_loss = 0 + all_state_ware_house_confirmation = 0 + if filtered_kill_reqs: + for kill in filtered_kill_reqs: + if (kill['assignment_state_archive'] == 'True' and kill['vet_state'] == 'pending') or kill[ + 'vet_state'] == 'accepted': + state = 'تخلیه شده' + else: + state = 'درانتظار تخلیه' + l += 1 + date_of_inner_bar = '-' + vet_farm = VetFarm.objects.filter( + poultry=kill.get('province_request__poultry_request__poultry'), + trash=False).select_related('vet__user').only('vet__user__fullname', + 'vet__user__mobile').values( + 'vet__user__fullname', + 'vet__user__mobile').first() + vet_farm_name = vet_farm.get('vet__user__fullname') if vet_farm else '-' + vet_farm_mobile = vet_farm.get('vet__user__mobile') if vet_farm else '-' + kil_house_vet = KillHouseVet.objects.filter(kill_house=kill.get('killhouse_user'), + trash=False).select_related( + 'vet__user').only('vet__user__fullname', + 'vet__user__mobile').values('vet__user__fullname', + 'vet__user__mobile').first() + vet_checks = VetCheckRequest.objects.filter(trash=False, + kill_house_request__key=kill.get('key')).only( + 'create_date').values( + 'create_date').first() + kill_house_vet_name = kil_house_vet.get('vet__user__fullname') if kil_house_vet else '-' + kill_house_vet_mobile = kil_house_vet.get('vet__user__mobile') if kil_house_vet else '-' + code = kill.get('clearance_code') if kill.get('clearance_code') else '-' + if kill.get('quantity'): + quantity = kill.get('quantity') + + else: + quantity = '-' + send_date = kill.get('province_request__poultry_request__send_date') + date_of_poultry_request = jdatetime.date.fromgregorian( + day=send_date.day, + month=send_date.month, + year=send_date.year + ) + killers = 'کشتارکن' + name_killer_exclusive = '-' + mobile_killer_exclusive = '-' + if kill.get('killhouse_user__killer') == False: + killers = 'کشتارگاه' + if kill.get('killer') != None: + name_killer_exclusive = kill['killer__name'] + mobile_killer_exclusive = str(kill['killer__kill_house_operator__user__mobile']) + killer_exclusive += 1 + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request__key=kill.get('key'), trash=False).only('create_date', 'net_weight', + 'real_quantity').values( + 'net_weight', 'real_quantity', 'create_date').first() + if assignment: + net_weighte = int(assignment.get('net_weight')) + real_quantity = assignment.get('real_quantity') + + vet_check_date = assignment.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + else: + net_weighte = '-' + real_quantity = '-' + if vet_checks: + vet_check_date = vet_checks.get('create_date') + date_of_inner_bar = convert_to_shamsi( + datetime=vet_check_date + ) + + if kill.get('kill_request__slaughter_house') is not None: + kill_place = kill.get('kill_request__slaughter_house__name') + else: + kill_place = '-' + + vet_quantity = kill['vet_accepted_real_quantity'] if kill['vet_accepted_real_quantity'] else '-' + vet_wight = int(kill['vet_accepted_real_weight']) if kill['vet_accepted_real_weight'] else '-' + + weight = int(kill.get('quantity') * kill.get( + 'province_kill_request__province_request__poultry_request__Index_weight')) + + quarantine_quantity = '-' + + if kill['quarantine_quantity'] != None: + quarantine_quantity = kill['quarantine_quantity'] + else: + if kill['quarantine_code_state'] == 'contradiction': + quarantine_quantity = 'مغایرت کد رهگیری' + elif kill['quarantine_code_state'] == 'noclearance': + quarantine_quantity = 'فاقد کد رهگیری' + elif kill['quarantine_code_state'] == 'notconfirmed': + quarantine_quantity = 'عدم تایید راهداری' + + sale_type = 'دولتی' if kill[ + 'province_kill_request__province_request__poultry_request__free_sale_in_province'] == False else 'آزاد' + + if kill['province_kill_request__province_request__poultry_request__union'] == True: + type = 'فروش آزاد' + elif kill['province_kill_request__province_request__poultry_request__direct_buying'] == True: + type = 'خرید مستقیم' + else: + type = 'اتحادیه' + age = (kill.get('province_request__poultry_request__send_date').date() - + kill.get('province_request__poultry_request__hatching__date').date()).days + 1 + + freez_state = 'منجمد' if kill['province_request__poultry_request__freezing'] == True else 'عادی' + if kill['message'] is not None: + state_delete = 'بار حذف شده' + else: + state_delete = 'فعال' + all_quantity += quantity + all_weighte += weight + all_real_quantity += real_quantity if real_quantity != '-' else 0 + all_net_weighte += net_weighte if net_weighte != '-' else 0 + + ware_house_accepted_real_quantity = kill['ware_house_accepted_real_quantity'] + ware_house_accepted_real_weight = kill['ware_house_accepted_real_weight'] + weight_loss = round(kill['weight_loss'], 2) if kill['weight_loss'] > 0 else 0 + if weight_loss > 0: + len_weight_loss += 1 + if kill['ware_house_confirmation'] == True: + state_ware_house_confirmation = 'ورود به انبار' + all_state_ware_house_confirmation += 1 + + else: + state_ware_house_confirmation = '-' + list1 = [ + m, + str(kill.get('bar_code')), + str(date_of_poultry_request), + freez_state, + str(kill.get('province_request__poultry_request__order_code')), + kill.get('province_request__poultry_request__poultry__unit_name'), + str(kill.get('province_request__poultry_request__poultry__user__mobile')), + kill.get('province_request__poultry_request__poultry__user__city__name'), + sale_type, + age, + kill.get('province_request__poultry_request__amount') if kill.get( + 'province_request__poultry_request__amount') else '-', + kill.get('province_request__poultry_request__chicken_breed'), + vet_farm_name, + vet_farm_mobile, + killers, + kill.get('killhouse_user__name'), + kill.get('killhouse_user__kill_house_operator__user__mobile'), + kill.get('killhouse_user__system_address__city__name'), + name_killer_exclusive, + mobile_killer_exclusive, + kill_place, + type, + kill_house_vet_name, + kill_house_vet_mobile, + kill.get('add_car__driver__driver_name'), + kill.get('add_car__driver__driver_mobile'), + kill.get('add_car__driver__type_car'), + str(kill.get('traffic_code')), + quantity, + weight, + code, + quarantine_quantity, + state, + str(date_of_inner_bar), + vet_quantity, + vet_wight, + real_quantity, + net_weighte, + kill['accepted_real_quantity'], + int(kill['accepted_real_weight']), + state_delete, + kill['document_status'] if kill['document_status'] else '-', + state_ware_house_confirmation, + ware_house_accepted_real_quantity, + int(ware_house_accepted_real_weight), + f'{weight_loss}%', + + ] + m += 1 + for item in range(len(list1)): + cell = worksheet.cell(row=l + 1, column=item + 1, value=list1[item]) + value = list1[item] + + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + if list1[40] == 'بار حذف شده': + cell.fill = PatternFill(start_color="FCDFDC", fill_type="solid") + worksheet.row_dimensions[l + 1].height = 20 + cell.alignment = Alignment(horizontal='center', vertical='center') + + has_code = len(filtered_kill_reqs.filter(clearance_code__isnull=False)) + all_quarantine_quantity = filtered_kill_reqs.aggregate(total_quantity=Sum('quarantine_quantity')).get( + 'total_quantity', 0) + has_qarantine = len(filtered_kill_reqs.filter(quarantine_quantity__isnull=False)) + all_ware_house_accepted_real_quantity = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_quantity')).get( + 'total_quantity') or 0 + all_ware_house_accepted_real_weight = filtered_kill_reqs.aggregate( + total_quantity=Sum('ware_house_accepted_real_weight')).get( + 'total_quantity', 0) or 0 + all_weight_loss = filtered_kill_reqs.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_weight_loss = round(int(all_weight_loss) / len_weight_loss, 2) if len_weight_loss > 0 else 0 + value_header_list = [ + len(filtered_kill_reqs), + killer_exclusive, + all_quantity, + int(all_weighte), + has_code, + has_qarantine, + + all_quarantine_quantity if all_quarantine_quantity != None else 0, + all_vet_state_accepted, + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + len(bar_complete), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + all_state_ware_house_confirmation, + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(value_header_list)): + cell = worksheet.cell(row=3, column=item + 9, value=value_header_list[item]) + value = value_header_list[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + value_header_list2 = [ + len(poultry_request), + total_requests_quantity, + int(total_requests_weight) + + ] + for item in range(len(value_header_list2)): + cell = worksheet.cell(row=3, column=item + 6, value=value_header_list2[item]) + value = value_header_list2[item] + # Check if the value is a number before formatting + if isinstance(value, (int)): + if value != 0: + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_kill_request_quantity, + int(all_weighte), + '', + all_quarantine_quantity if all_quarantine_quantity != None else 0, + '', + '', + all_vet_accepted_real_quantity, + int(all_vet_accepted_real_weight), + all_real_quantity, + int(all_net_weighte), + accepted_real_quantity if accepted_real_quantity != None else 0, + int(accepted_real_wight) if accepted_real_wight != None else 0, + '', + '', + '', + all_ware_house_accepted_real_quantity, + int(all_ware_house_accepted_real_weight), + f'%{all_weight_loss}' + + ] + for item in range(len(list2)): + cell = worksheet.cell(row=l + 3, column=item + 1, value=list2[item]) + value = list2[item] + if isinstance(value, (int)): + cell.number_format = '#,###' # Apply general number format + else: + cell.value = value # Keep as text for other values + + cell.alignment = Alignment(horizontal='center') + cell.font = Font(size=10, bold=True) + cell.font = Font(bold=True) + cell.fill = PatternFill(start_color="00B050", fill_type="solid") + + name = poultreis.unit_name + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش کلی اطلاعاتی مرغدار {name}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_hatching_prediction_chart_excel(request): + consumption_limit_type = request.GET.get('consumption_limit_type') + consumption_limit = request.GET.get('consumption_limit') + killing_age_external_type = request.GET.get('killing_age_external_type') + killing_age_internal_type = request.GET.get('killing_age_internal_type') + killing_age = request.GET.get('killing_age') + time_frame_type = request.GET.get('time_frame_type') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + date_list = [] + final_list = [] + + poultries = Poultry.objects.filter(killing_ave_age__gt=1, trash=False) + if killing_age_external_type == 'poultry_ave_killing_age': + if killing_age_internal_type == 'poultry': + if time_frame_type == 'all': + hatchings = PoultryHatching.objects.filter(trash=False, state='pending', + archive=False, temporary_trash=False, + temporary_deleted=False, predicate_date__isnull=False) + date_list = hatchings.values_list('predicate_date', flat=True).distinct() + for date in date_list: + n_hatchings = hatchings.filter(predicate_date=date) + poultries = Poultry.objects.filter(pk__in=n_hatchings.values_list('poultry', flat=True)) + ages = poultries.values_list('killing_ave_age', flat=True).distinct() + + index_weight = poultries.aggregate(total=Sum('real_killing_ave_weight'))[ + 'total'] or 0 + quantity = n_hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + + result = { + "date": date, + "quantity": quantity, + "poultry": len(poultries), + "age": ages, + "hatchings": n_hatchings.values_list('id', flat=True), + "weight": int(quantity * index_weight) if consumption_limit_type in ( + 'quantity', 'live_weight') else int((quantity * index_weight) * 0.75), + } + final_list.append(result) + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + hatchings = PoultryHatching.objects.filter(trash=False, state='pending', + archive=False, temporary_trash=False, + temporary_deleted=False, predicate_date__date__gte=date1, + predicate_date__date__lte=date2) + # poultries = poultries.filter(date__gte=date1,date__lte=date2).order_by('date') + date_list = poultries.values_list('date', flat=True).distinct() + + for date in date_list: + n_hatchings = hatchings.filter(predicate_date__date=date) + poultries = Poultry.objects.filter(pk__in=n_hatchings.values_list('poultry', flat=True)) + ages = poultries.values_list('killing_ave_age', flat=True).distinct() + + index_weight = poultries.aggregate(total=Sum('real_killing_ave_weight'))[ + 'total'] or 0 + quantity = n_hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + result = { + "date": date, + "quantity": quantity, + "poultry": len(poultries.filter(date=date)), + "age": ages, + "hatchings": n_hatchings.values_list('id', flat=True), + "weight": int(quantity * index_weight) if consumption_limit_type in ( + 'quantity', 'live_weight') else int((quantity * index_weight) * 0.75), + } + final_list.append(result) + + else: + sum_of_ages = poultries.aggregate(total=Sum('killing_ave_age'))[ + 'total'] or 0 + ave_killing_age = int(sum_of_ages / len(poultries)) + if time_frame_type == 'all': + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type) + + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1, date2) + + else: + if killing_age_internal_type == 'poultry': + if time_frame_type == 'all': + final_list = poultry_prediction_helper(int(killing_age), consumption_limit_type) + # poultries = poultries.filter(killing_ave_age=int(killing_age)) + # date_list = poultries.values_list('date', flat=True).distinct() + # for date in date_list: + # index_weight = poultries.filter(date=date).aggregate(total=Sum('killing_ave_weight'))[ + # 'total'] or 0 + # quantity = poultries.filter(date=date).aggregate(total=Sum('active_left_over'))[ + # 'total'] or 0 + # + # result = { + # "date": date, + # "quantity": quantity, + # "poultry": len(poultries.filter(date=date)), + # "age": int(killing_age), + # "wight": quantity * index_weight, + # } + # final_list.append(result) + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(int(killing_age), consumption_limit_type, date1, date2) + + # poultries = poultries.filter(killing_ave_age=int(killing_age),date__gte=date1,date__lte=date2) + # date_list = poultries.values_list('date', flat=True) + # for date in date_list: + # index_weight = poultries.filter(date=date).aggregate(total=Sum('killing_ave_weight'))[ + # 'total'] or 0 + # quantity = poultries.filter(date=date).aggregate(total=Sum('active_left_over'))[ + # 'total'] or 0 + # + # result = { + # "date": date, + # "quantity": quantity, + # "poultry": len(poultries.filter(date=date)), + # "age": int(killing_age), + # "wight": quantity * index_weight, + # } + # final_list.append(result) + + else: + + ave_killing_age = int(killing_age) + + if time_frame_type == 'all': + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type) + + + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1, date2) + + excel_options = [ + 'ردیف', + 'تاریخ', + 'تعداد مرغداران', + 'حجم(قطعه)', + 'وزن(کیلوگرم)', + 'سن', + + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد مرغداران', + 'مجموع حجم', + 'مجموع وزن', + + ] + + create_header(worksheet, header_list, 4, 2, height=20) + if "date1" in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + excel_description(worksheet, 'B1', + f'پیشبینی موجودی از تاریخ {shamsi_date(date1)} تا تاریخ {shamsi_date(date2)}', color='red', + row2='C3') + else: + excel_description(worksheet, 'B1', f'پیشبینی موجودی', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + + if final_list: + for data in final_list: + if type(data['age']) is str or type(data['age']) is int: + age = data['age'] + + else: + if len(data['age']) > 1: + age = '-'.join(map(str, data['age'])) + elif len(data['age']) == 1: + age = str(data['age'][0]) + else: + age = '' + if type(data['date']) is str: + try: + str_date = datetime.datetime.strptime(str(data['date']), "%Y-%m-%dT%H:%M:%S").date() + except: + str_date = datetime.datetime.strptime(str(data['date']), '%Y-%m-%d').date() + date = convert_to_shamsi(date=str_date) + elif data['date'] is None: + date = '-' + else: + date = convert_to_shamsi(date=data['date']) + list1 = [ + m, + date, + data['poultry'], + data['quantity'], + data['weight'], + age, + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', width=15) + poultry = sum(item['poultry'] for item in final_list) + quantity = sum(item['quantity'] for item in final_list) + weight = sum(item['weight'] for item in final_list) + value_header_list = [ + poultry, + quantity, + weight, + ] + create_value(worksheet, value_header_list, 3, 4) + + list2 = [ + 'مجموع==>', + '', + poultry, + quantity, + weight, + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + if consumption_limit_type == 'quantity': + data_columns = 4 + y_axis_title = 'حجم موجودی (قطعه)' + else: + data_columns = 5 + y_axis_title = "وزن موجودی (کیلوگرم)" + add_chart( + worksheet=worksheet, + chart_type='line', + data_columns=data_columns, + category_column=2, + start_row=7, + end_row=l + 1, + chart_position="H7", + chart_title="داده های تجمیعی", + x_axis_title="تاریخ", + y_axis_title=y_axis_title + ) + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پیشبینی موجودی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_report_from_age_excel(request): + input_age1 = int(request.GET['age1']) + input_age2 = int(request.GET['age2']) + filtered_poultry_hatch = PoultryHatching.objects.filter(chicken_age__gte=input_age1, chicken_age__lte=input_age2, + archive=False, + allow_hatching='pending', + trash=False).select_related('poultry', + 'poultry__user').order_by( + 'create_date') + user = SystemUserProfile.objects.get(key=request.GET['key']) + + if 'chain' in request.GET: + filtered_poultry_hatch = filtered_poultry_hatch.filter(has_chain_company=True) + + if request.GET['role'] in ['CityJahad', 'CityPoultry']: + filtered_poultry_hatch = filtered_poultry_hatch.filter(poultry__address__city=user.city) + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filtered_poultry_hatch = filtered_poultry_hatch.filter(poultry__city_operator=city_operator.unit_name) + else: + filtered_poultry_hatch = filtered_poultry_hatch + excel_options = [ + 'ردیف', + 'وضعیت فارم', + 'زنجیره/شرکت', + 'نام و خانوادگی', + 'نام فارم', + 'موبایل', + 'شهرستان', + 'کد یکتا', + 'کد سیستمی واحد', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'نژاد', + 'سن', + 'تعداد جوجه ریزی', + 'تلفات دوره', + 'تعداد کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'تعداد کشتار خارج از استان(قطعه)', + 'وزن کشتار خارج از استان(کیلوگرم)', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ ثبت گزارش', + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + blue_fill = PatternFill(start_color="1E487B", fill_type="solid") + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + red_font = Font(color="C00000", bold=True) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(وجود فارم فعال دیگر)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + list1 = [ + m, + farm_state, + chain_company, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.mobile, + poultry_hatching.poultry.user.city.name, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.poultry.system_code, + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.losses, + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + all_quantity, + all_losses, + all_killed_quantity, + all_total_killed_weight, + all_left_over, + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جوجه ریزی بر اساس بازه {input_age1} تا {input_age2} روز.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def poultry_hatching_prediction_excel(request): + filterset_class = PoultryHatchingFilterSet + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'poultry__breeding_unique_id', + + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + if 'hatching_list' in request.GET: + poultry_hatchings = PoultryHatching.objects.filter(id__in=(request.GET['hatching_list']).split(',')).order_by( + 'date') + else: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + poultry__city_operator=city_operator.unit_name, + trash=False).order_by('date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + poultry__address__city=user.city, + trash=False).order_by('date') + + else: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + trash=False).order_by('date') + if 'search' in request.GET: + hatching_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=poultry_hatchings + ) + ).filter(): + ps = filterset_class(data=query, queryset=poultry_hatchings) + hatching_list = ps.filter() + poultry_hatchings = [] if len(hatching_list) == 0 else hatching_list + excel_options = [ + 'ردیف', + 'نام واحد', + 'مالک', + 'موبایل', + 'شهر', + 'میانگین سن کشتار', + 'میانگین وزن کشتار', + 'دوره', + 'تاریخ جوجه ریزی', + 'حجم جوجه ریزی', + 'سن', + 'نژاد', + 'حجم کشتار شده', + 'وزن کشتار شده', + 'تخصیص بدون بار', + 'حجم تخصیص بدون بار', + 'وزن تخصیص بدون بار', + 'مانده سالن(حجم)', + 'مانده سالن(وزن زنده)', + 'مانده سالن(وزن لاشه)', + + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + '', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'جزئیات پایش اطلاعات تاریخ {from_date_1}', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + serializer = PoultryHatchingForPredictionSerializer(poultry_hatchings, many=True).data + if serializer: + for data in serializer: + datetime_object = datetime.datetime.strptime(data['date'], "%Y-%m-%dT%H:%M:%S") + + list1 = [ + m, + data['poultry']['unit_name'], + data['poultry']['fullname'], + data['poultry']['mobile'], + data['poultry']['city'], + data['general_info']['ave_age'], + data['general_info']['ave_weight'], + data['period'], + convert_to_shamsi(date=datetime_object), + data['quantity'], + data['general_info']['age'], + data['chicken_breed'], + data['general_info']['total_quantity'], + data['general_info']['total_weight'], + data['general_info']['province_kill_requests'], + data['general_info']['province_kill_requests_quantity'], + data['general_info']['province_kill_requests_weight'], + data['left_over'], + round(data['left_over'] * data['poultry']['killing_ave_weight']), + round(data['left_over'] * data['poultry']['killing_ave_weight'] * 0.75), + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + quantity = sum( + item['quantity'] for item in serializer) + + total_quantity = sum( + item['general_info'].get('total_quantity', 0) for item in serializer) + total_weight = sum( + item['general_info'].get('total_weight', 0) for item in serializer) + province_kill_requests = sum( + item['general_info'].get('province_kill_requests', 0) for item in serializer) + province_kill_requests_quantity = sum( + item['general_info'].get('province_kill_requests_quantity', 0) for item in serializer) + province_kill_requests_weight = sum( + item['general_info'].get('province_kill_requests_weight', 0) for item in serializer) + killing_ave_weight = sum( + item['poultry'].get('killing_ave_weight', 0) for item in serializer) + killing_ave_weight = killing_ave_weight / len(serializer) if serializer else 0 + + left_over = sum( + item['left_over'] for item in serializer) + + value_header_list = [ + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + '', + '', + total_quantity, + total_weight, + province_kill_requests, + province_kill_requests_quantity, + province_kill_requests_weight, + left_over, + round(left_over * killing_ave_weight), + round(left_over * killing_ave_weight * 0.75), + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="جزئیات پایش اطلاعات تاریخ {from_date_1}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def bar_difference_reques_excel(request): + filterset_class = BarDifferenceRequestFilterSet + filterset_fields = [ + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__mobile', + 'hatching__poultry__user__fullname', + 'hatching__poultry__user__mobile' + ] + user = SystemUserProfile.objects.get(key=request.GET['key'], trash=False) + if request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + if request.GET['state'] == 'pending': + state = 'جدید' + bar_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, + state='pending').order_by('id') + else: + state = 'بایگانی شده' + bar_requests = BarDifferenceRequest.objects.filter(kill_house=kill_house, trash=False, + state__in=('accepted', 'rejected')).order_by('id') + else: + if request.GET['state'] == 'pending': + state = 'جدید' + bar_requests = BarDifferenceRequest.objects.filter(trash=False, state='pending').order_by('id') + else: + bar_requests = BarDifferenceRequest.objects.filter(trash=False, + state__in=('accepted', 'rejected')).order_by('id') + state = 'بایگانی شده' + + if 'search' in request.GET: + bar_requests_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=bar_requests + ) + ).filter(): + ps = filterset_class(data=query, queryset=bar_requests) + bar_requests_list = ps.filter() + bar_requests = [] if len(bar_requests_list) == 0 else bar_requests_list + excel_options = [ + 'ردیف', + 'وضعیت', + 'ثبت کننده', + 'تاریخ ثبت', + 'مرغدار', + 'کشتارگاه', + 'حجم', + 'حجم کم شده از سالن مرغدار', + 'وزن تقریبی کشتار(کیلوگرم)', + 'حجم سفارشات دریافتی توسط کشتارگاه', + 'اختلاف کشتار(حجم)', + + ] + date1 = datetime.datetime.now().date() + from_date = jdatetime.date.fromgregorian( + year=date1.year, + month=date1.month, + day=date1.day + ).strftime('%Y-%m-%d') + reversed_date = reversed(from_date.split("-")) + separate = "-" + from_date_1 = separate.join(reversed_date) + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'حجم', + 'حجم کم شده از سالن مرغدار', + 'وزن تقریبی کشتار(کیلوگرم)', + 'حجم سفارشات دریافتی توسط کشتارگاه', + 'اختلاف کشتار(حجم)', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'اختلاف کشتار {state}', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + serializer = BarDifferenceRequestSerializer(bar_requests, many=True).data + if serializer: + for data in serializer: + datetime_object = datetime.datetime.strptime(data['create_date'], "%Y-%m-%dT%H:%M:%S.%f") + if data['state'] == 'pending': + status = 'در انتظار تایید' + elif data['state'] == 'accepted': + status = 'تایید شده' + else: + status = 'رد شده' + list1 = [ + m, + status, + data['register_fullname'], + str(convert_to_shamsi(date=datetime_object.date())), + data['hatching']['poultry']['unit_name'] + '(' + data['hatching']['poultry']['user']['mobile'] + ')', + data['kill_house']['name'] + '(' + data['kill_house']['kill_house_operator']['user']['mobile'] + ')', + data['quantity'], + data['bar_info']['total_quantity'], + data['bar_info']['total_weight'], + data['bar_info']['first_total_quantity'], + data['bar_info']['difference_quantity'], + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + quantity = sum( + item['quantity'] for item in serializer) + + total_quantity = sum( + item['bar_info'].get('total_quantity', 0) for item in serializer) + total_weight = sum( + item['bar_info'].get('total_weight', 0) for item in serializer) + first_total_quantity = sum( + item['bar_info'].get('first_total_quantity', 0) for item in serializer) + difference_quantity = sum( + item['bar_info'].get('difference_quantity', 0) for item in serializer) + + value_header_list = [ + quantity, + total_quantity, + total_weight, + first_total_quantity, + difference_quantity, + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + quantity, + total_quantity, + total_weight, + first_total_quantity, + difference_quantity, + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="اختلاف کشتار {state}.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def direct_buying_poultry_requests(request): + filterset_class = PoultryRequestDirectBuyingFilterSet + role = request.GET.get('role') + now = datetime.datetime.now() + + show_market = ShowMarketRequest.objects.filter(trash=False, allow=True).first() + now_time = now.time().replace(second=0, microsecond=0) + if show_market and role == 'KillHouse': + if show_market.start_time < \ + now_time < show_market.end_time: + + queryset = PoultryRequest.objects.filter( + send_date__date=now.date(), + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state='pending', + market=True, + ) + else: + + queryset = [] + else: + queryset = PoultryRequest.objects.filter( + send_date__date=now.date(), + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state='pending', + market=True, + ) + + breed = request.GET.get('breed') + city = request.GET.get('city') + remain = request.GET.get('remain') + min_amount = request.GET.get('min_amount') + max_amount = request.GET.get('max_amount') + weight = request.GET.get('weight') + min_age = request.GET.get('min_age') + max_age = request.GET.get('max_age') + value = request.GET.get('value') + search = request.GET.get('search') + + if breed: + queryset = queryset.filter(chicken_breed__in=breed.split(',')) + + if city: + queryset = queryset.filter(poultry__user__city__name__in=city.split(',')) + + if remain == 'true': + queryset = queryset.filter(remain_quantity__gt=0) + + if min_amount: + queryset = queryset.filter(amount__gte=min_amount) + if max_amount: + queryset = queryset.filter(amount__lte=max_amount) + + if weight: + if weight == 'سبک': + queryset = queryset.filter(Index_weight__gte=2, Index_weight__lt=2.7) + elif weight == 'متوسط': + + queryset = queryset.filter(Index_weight__gte=2.7, Index_weight__lt=3) + elif weight == 'سنگین': + queryset = queryset.filter(Index_weight__gte=3) + + if min_age: + queryset = queryset.filter(hatching__chicken_age__gte=min_age) + if max_age: + queryset = queryset.filter(hatching__chicken_age__lte=max_age) + + if value and search == 'filter' and value.strip() and value != 'undefined': + queryset = queryset.filter(build_query(filterset_class, value)) + + excel_options = [ + "ردیف", + "نام و نام خانوادگی", + "تلفن", + "استان", + "شهر", + "نژاد", + "سن جوجه", + "میانگین وزنی (کیلوگرم)", + "تاریخ کشتار", + "تعداد قطعه", + "مانده قابل خرید", + "فروش رفته", + "مبلغ هر کیلو (ریال)", + ] + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + cell = worksheet.cell(row=1, column=1) + cell.alignment = Alignment(horizontal='center', vertical='center') + + header_list = [ + 'تعداد قطعه', + 'مانده قابل خرید', + 'فروش رفته', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'لیست اعلام کشتار های مرغداران', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + l = 5 + m = 1 + serializer = PoultryRequestForDirectBuyingSerializer(queryset, many=True).data + if serializer: + for data in serializer: + if type(data['send_date']) is str: + try: + str_date = datetime.datetime.strptime(str(data['send_date']), "%Y-%m-%dT%H:%M:%S").date() + except: + str_date = datetime.datetime.strptime(str(data['send_date']), '%Y-%m-%d').date() + date = shamsi_date(str_date, in_value=True) + elif data['send_date'] is None: + date = '-' + else: + date = shamsi_date(data['send_date'], in_value=True) + + list1 = [ + m, + data['poultry']['unit_name'], + data['poultry']['mobile'], + data['poultry']['province'], + data['poultry']['city'], + data['chicken_breed'], + data['age']['age'], + str(data['Index_weight']), + str(date), + data['quantity'], + data['remain_quantity'], + data['total_allocated'], + data['amount'], + + ] + m += 1 + l += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin') + + quantity = sum( + item['quantity'] for item in serializer) + remain_quantity = sum( + item['remain_quantity'] for item in serializer) + total_allocated = sum( + item['total_allocated'] for item in serializer) + + value_header_list = [ + quantity, + remain_quantity, + total_allocated, + + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + quantity, + remain_quantity, + total_allocated, + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="لیست اعلام کشتار های مرغداران.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response + + +def hatching_for_every_age_range(request): + filterset_class = PoultryHatchingFilterSet + poultry_hatch = PoultryHatching.objects.filter(archive=False, + allow_hatching='pending', + trash=False).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'poultry__breeding_unique_id', + + ] + + date1 = datetime.datetime.now().date() + + output = BytesIO() + workbook = Workbook() + worksheet = workbook.active + workbook.remove(worksheet) + + sheet_name = [ + "کمتر از 35 روز", + "بین 35 تا 40 روز", + "بین 40 تا 45 روز", + "بین 45 تا 50 روز", + "بین 50 تا 55 روز", + "بین 55 تا 60 روز", + "بین 60 تا 65 روز", + "بین 65 تا 70 روز", + "بیش از 70 روز" + ] + for sheet_names in sheet_name: + worksheet = workbook.create_sheet(sheet_names) + worksheet.sheet_view.rightToLeft = True + worksheet.insert_rows(1) + if sheet_names == 'کمتر از 35 روز': + filtered_poultry_hatch =poultry_hatch.filter(chicken_age__lt=35).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 35 تا 40 روز': + filtered_poultry_hatch =poultry_hatch.filter(chicken_age__range=(35, 39)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 40 تا 45 روز': + filtered_poultry_hatch =poultry_hatch.filter(chicken_age__range=(40, 44)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 45 تا 50 روز': + filtered_poultry_hatch =poultry_hatch.filter(chicken_age__range=(45, 49)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 45 تا 50 روز': + filtered_poultry_hatch =poultry_hatch.filter(chicken_age__range=(45, 49)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 50 تا 55 روز': + filtered_poultry_hatch = poultry_hatch.filter(chicken_age__range=(50, 54)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 55 تا 60 روز': + filtered_poultry_hatch = poultry_hatch.filter(chicken_age__range=(55, 59)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 60 تا 65 روز': + filtered_poultry_hatch = poultry_hatch.filter(chicken_age__range=(60, 64)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بین 65 تا 70 روز': + filtered_poultry_hatch = poultry_hatch.filter(chicken_age__range=(65, 70)).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + elif sheet_names == 'بیش از 70 روز': + filtered_poultry_hatch = poultry_hatch.filter(chicken_age__gt=70).select_related('poultry', + 'poultry__user').order_by( + '-chicken_age') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (filterset_class( + data=query, + queryset=filtered_poultry_hatch + ) + ).filter(): + ps = filterset_class(data=query, queryset=filtered_poultry_hatch) + filtered_poultry_hatch = ps.filter() + date1 = datetime.datetime.now().date() + excel_options = [ + 'ردیف', + 'وضعیت', + 'شماره مجوز جوجه ریزی', + 'شناسه یکتا', + 'مجوز بهداشتی جوجه ریزی', + 'نام فارم', + 'مرغدار', + 'تلفن مرغدار', + 'بهره برداری', + 'مالکیت', + 'ارتباط', + 'شهر/تعاونی', + 'سالن', + ' دوره جوجه ریزی', + 'تاریخ ثبت جوجه ریزی', + 'تاریخ جوجه ریزی', + 'میانگین سن کشتار', + 'پیشبینی تاریخ کشتار', + 'نژاد', + 'سن', + 'حجم جوجه ریزی', + 'حجم افزایشی', + 'تلفات دامپزشک(قطعه)', + 'تلفات اتحادیه(قطعه)', + 'تلفات کل(قطعه)', + + 'زنجیره/شرکت', + + 'دامپزشک فارم', + 'تلفن دامپزشک فارم', + 'کد سیستمی واحد', + + 'حجم کشتار شده(قطعه)', + 'وزن کل کشتارشده(کیلوگرم)', + 'مانده در سالن', + 'درصد مانده در سالن', + 'نود درصد جوجه ریزی', + 'وزن تعهد دولتی(کیلوگرم)', + 'تعداد کشتار دولتی(قطعه)', + 'وزن کشتار دولتی(کیلوگرم)', + 'وزن تعهد آزاد(کیلوگرم)', + 'تعداد کشتار آزاد(قطعه)', + 'وزن کشتار آزاد(کیلوگرم)', + 'میانگین وزن کشتار(کیلوگرم)', + 'سازنده جوجه ریزی', + 'کد اپیدمیولوژیک', + 'حجم فروش به خارج از استان(قطعه)', + 'حجم فروش به خارج از استان(کیلوگرم)', + 'تخصیصات بدون بار', + 'حجم تخصیصات بدون بار', + 'وزن تخصیصات بدون بار', + 'تایید تخلیه در سماصط', + 'تعداد کشتار فعال', + 'تعداد درخواست کشتار', + + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بارهای تحویلی', + 'حجم بارهای تحویلی', + 'وزن بارهای تحویلی', + + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + 'ثبت کننده گزارش', + 'متن گزارش', + 'تاریخ گزارش', + ] + from_date_1 = shamsi_date(date1) + + header_list = [ + 'تعداد فارم فعال', + 'تعداد فارم دارای زنجیره فعال', + 'مجموع جوجه ریزی', + 'مجموع تلفات دامپزشک(قطعه)', + 'مجموع تلفات اتحادیه(قطعه)', + 'مجموع تلفات کل(قطعه)', + 'مجموع قطعه کشتار شده', + 'مجموع وزن کل کشتارشده', + 'مانده در سالن(قطعه)', + 'مانده در سالن از نود درصد(قطعه)', + 'کمترین سن', + 'بیشترین سن', + 'مجموع وزن تعهد دولتی', + ' مجموع قطعه کشتار دولتی', + ' مجموع وزن کشتار دولتی', + ' مجموع قطعه کشتار آزاد', + ' مجموع وزن کشتار آزاد', + 'مجموع تعداد کشتار خارج از استان', + 'مجموع وزن کشتار خارج از استان', + 'تعداد فارم های متخلف', + 'تعداد بار ایجاد شده', + 'حجم بار ایجاد شده', + 'وزن بار ایجاد شده', + 'تعداد بار کشتار شده', + 'حجم بار کشتار شده', + 'وزن بار کشتار شده', + 'حجم زنجیره', + 'وزن زنجیره', + 'حجم صادرات', + 'وزن صادرات', + 'تعداد بار ورودی به انبار', + 'حجم لاشه ها', + 'وزن لاشه ها', + 'درصد افت بارها', + + ] + + create_header(worksheet, header_list, 5, 2, height=20) + + excel_description(worksheet, 'B1', f'این گزارش در مورخ {from_date_1} صادر شده است.', color='red', row2='C3') + + create_header_freez(worksheet, excel_options, 1, 6, 7, height=22) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + poultry_ids = poultry_hatch.values_list('poultry', flat=True).distinct() + vet_farms = VetFarm.objects.filter(poultry__in=poultry_ids, trash=False).select_related('vet__user') + vet_farm_mapping = { + vet_farm.poultry: (vet_farm.vet.user.fullname, vet_farm.vet.user.mobile) + for vet_farm in vet_farms + } + l = 5 + m = 1 + all_poultry_hatching_quantity = 0 + all_poultry_hatching_killed_quantity = 0 + all_poultry_hatching_left_over = 0 + min_list = [] + all_left_over_ninty_percent = 0 + violation = 0 + all_chain_company = 0 + for poultry_hatching in filtered_poultry_hatch: + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=poultry_hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, + final_state='archive', + hatching=poultry_hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = poultry_hatching.left_over + + elif poultry_hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if poultry_hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = poultry_hatching.left_over + else: + left_total_free_commitment_quantity = poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + poultry_hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + # return { + # "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + # "total_commitment_quantity": obj.total_commitment_quantity, + # "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + # "total_free_commitment_quantity": obj.total_free_commitment_quantity, + # "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + # + # } + + vet_farm_id = poultry_hatching.poultry + vet_farm_name, vet_farm_mobile = vet_farm_mapping.get(vet_farm_id, ('-', '-')) + all_poultry_hatching_quantity += poultry_hatching.quantity + all_poultry_hatching_killed_quantity += poultry_hatching.killed_quantity + all_poultry_hatching_left_over += poultry_hatching.left_over + if poultry_hatching.chicken_age not in min_list: + min_list.append(poultry_hatching.chicken_age) + + l += 1 + create_date = jdatetime.date.fromgregorian( + day=poultry_hatching.create_date.day, + month=poultry_hatching.create_date.month, + year=poultry_hatching.create_date.year + ) + date = jdatetime.date.fromgregorian( + day=poultry_hatching.date.day, + month=poultry_hatching.date.month, + year=poultry_hatching.date.year + ) + predicate_date = jdatetime.date.fromgregorian( + day=poultry_hatching.predicate_date.day, + month=poultry_hatching.predicate_date.month, + year=poultry_hatching.predicate_date.year + ) if poultry_hatching.predicate_date else '-' + date1 = datetime.datetime.strptime(str(poultry_hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.datetime.now() - date1).days + 1 + + creator = '-' + if poultry_hatching.registrar: + if poultry_hatching.registrar['fullname'] != '': + creator = poultry_hatching.registrar['fullname'] + else: + creator = 'پنجره واحد' + left_over_ninty_percent = ((poultry_hatching.quantity * 90) / 100) + all_left_over_ninty_percent += left_over_ninty_percent + farm_state = 'عادی' + if poultry_hatching.violation == True: + farm_state = 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' + violation += 1 + if poultry_hatching.chain_company: + chain_company = poultry_hatching.chain_company.name + all_chain_company += 1 + else: + chain_company = '-' + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + violation_report_date = shamsi_date( + poultry_hatching.violation_report_date.date()) if poultry_hatching.violation_report_date else '-' + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + wothout_bar = province_kill_requests.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0) + province_kill_requests_quantity_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight_wothout_bar = \ + wothout_bar.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + active_kill = 'ندارد' + count_of_request = 0 + + province_kill_request_active = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='accepted') + if province_kill_request_active.count() > 0: + count_of_request = province_kill_request_active.count() + + if ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=poultry_hatching, + state='pending').exists(): + active_kill = 'دارد' + + list1 = [ + m, + farm_state, + poultry_hatching.licence_number, + poultry_hatching.poultry.breeding_unique_id, + poultry_hatching.CertId, + poultry_hatching.poultry.unit_name, + poultry_hatching.poultry.user.fullname, + poultry_hatching.poultry.user.mobile, + poultry_hatching.InteractTypeName, + poultry_hatching.PersonTypeName, + poultry_hatching.UnionTypeName, + f'{poultry_hatching.poultry.user.city.name if poultry_hatching.poultry.user.city else "-"} ' + f'/ {poultry_hatching.poultry.city_operator if poultry_hatching.poultry.city_operator else "-"}', + poultry_hatching.hall, + poultry_hatching.period, + str(create_date), + str(date), + poultry_hatching.poultry.killing_ave_age, + str(predicate_date), + poultry_hatching.chicken_breed, + age, + poultry_hatching.quantity, + poultry_hatching.increase_quantity, + poultry_hatching.losses, + poultry_hatching.direct_losses, + poultry_hatching.total_losses, + + chain_company, + # poultry_hatching.poultry.city_operator, + # + # + # + vet_farm_name, + vet_farm_mobile, + poultry_hatching.poultry.system_code, + + poultry_hatching.killed_quantity, + poultry_hatching.total_killed_weight, + poultry_hatching.left_over, + f'{int(poultry_hatching.left_over * 100 / poultry_hatching.quantity)}%', + left_over_ninty_percent, + poultry_hatching.total_commitment, + poultry_hatching.governmental_quantity, + poultry_hatching.governmental_killed_quantity, + poultry_hatching.total_free_commitment_quantity, + poultry_hatching.free_quantity, + poultry_hatching.free_killed_quantity, + str(poultry_hatching.total_average_killed_weight), + creator, + poultry_hatching.poultry.epidemiological_code if poultry_hatching.poultry.epidemiological_code else '-', + poultry_hatching.out_province_killed_quantity if poultry_hatching.out_province_killed_quantity > 0 else '-', + poultry_hatching.out_province_killed_weight if poultry_hatching.out_province_killed_weight > 0 else '-', + len(wothout_bar), + province_kill_requests_quantity_wothout_bar, + province_kill_requests_weight_wothout_bar, + poultry_hatching.samasat_discharge_percentage, + active_kill, + count_of_request, + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + poultry_hatching.chain_killed_quantity, + poultry_hatching.chain_killed_weight, + poultry_hatching.export_killed_quantity, + poultry_hatching.export_killed_weight, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + poultry_hatching.violation_reporter if poultry_hatching.violation_reporter else '-', + poultry_hatching.violation_report if poultry_hatching.violation_report else '-', + str(violation_report_date), + + ] + m += 1 + create_value(worksheet, list1, l + 1, 1, border_style='thin', different_cell=1, + different_value='متخلف' + ' ' + '(وجود فارم فعال دیگر)') + + min_list = sorted(min_list) + all_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + all_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity', 0) + all_direct_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity', 0) + all_total_losses = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity', 0) + all_killed_quantity = filtered_poultry_hatch.aggregate(total_quantity=Sum('killed_quantity')).get( + 'total_quantity', 0) + all_left_over = filtered_poultry_hatch.aggregate(total_quantity=Sum('left_over')).get( + 'total_quantity', 0) + all_total_commitment = filtered_poultry_hatch.aggregate(total_quantity=Sum('total_commitment')).get( + 'total_quantity', 0) + all_governmental_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_killed_quantity')).get( + 'total_quantity', 0) + all_free_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_killed_quantity')).get( + 'total_quantity', 0) + all_total_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_killed_weight')).get( + 'total_quantity', 0) + all_governmental_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('governmental_quantity')).get( + 'total_quantity', 0) + all_free_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('free_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_quantity')).get( + 'total_quantity', 0) + all_out_province_killed_weight = filtered_poultry_hatch.aggregate( + total_quantity=Sum('out_province_killed_weight')).get( + 'total_quantity', 0) + all_increase_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('increase_quantity')).get( + 'total_quantity', 0) + all_total_free_commitment_quantity = filtered_poultry_hatch.aggregate( + total_quantity=Sum('total_free_commitment_quantity')).get( + 'total_quantity', 0) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=filtered_poultry_hatch) + + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + chain_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_weight')).get( + 'total_quantity', 0) or 0 + chain_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('chain_killed_quantity')).get( + 'total_quantity', 0) or 0 + extra_killed_quantity_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_quantity')).get( + 'total_quantity', 0) or 0 + export_killed_weight_final = filtered_poultry_hatch.aggregate( + total_quantity=Sum('export_killed_weight')).get( + 'total_quantity', 0) or 0 + value_header_list = [ + len(filtered_poultry_hatch), + all_chain_company, + all_poultry_hatching_quantity, + all_losses, + all_direct_losses, + all_total_losses, + all_poultry_hatching_killed_quantity, + all_total_killed_weight, + all_poultry_hatching_left_over, + all_left_over_ninty_percent, + min_list[0] if len(min_list) > 0 else '-', + min_list[len(min_list) - 1] if len(min_list) > 0 else '-', + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_free_quantity, + all_free_killed_quantity, + all_out_province_killed_quantity, + all_out_province_killed_weight, + violation, + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0) + ] + create_value(worksheet, value_header_list, 3, 5) + + list2 = [ + 'مجموع==>', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + + all_quantity, + all_increase_quantity, + all_losses, + all_direct_losses, + all_total_losses, + + '', + '', + '', + '', + all_killed_quantity, + all_total_killed_weight, + all_left_over, + '', + all_left_over_ninty_percent, + all_total_commitment, + all_governmental_quantity, + all_governmental_killed_quantity, + all_total_free_commitment_quantity, + all_free_quantity, + all_free_killed_quantity, + '', + '', + '', + all_out_province_killed_quantity, + all_out_province_killed_weight, + '', + '', + '', + '', + '', + '', + + len(kill_house_requests), + first_quantity, + first_weight, + len(bar_complete_with_kill_house), + accepted_real_quantity_final, + accepted_real_wight_final, + chain_killed_quantity_final, + chain_killed_weight_final, + extra_killed_quantity_final, + export_killed_weight_final, + len(ware_house_bars), + ware_house_bars_quantity, + ware_house_bars_weight, + str(round(ware_house_bars_weight_lose / len( + ware_house_bars), 2) if ware_house_bars else 0), + '', + '', + '', + + ] + create_value(worksheet, list2, l + 3, 1, color='green') + + workbook.save(output) + output.seek(0) + + response = HttpResponse( + content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') + response[ + 'Content-Disposition'] = f'attachment; filename="پایش کلی اطلاعاتی مرغداران با بازه سنی.xlsx"'.encode( + 'utf-8') + response.write(output.getvalue()) + return response \ No newline at end of file diff --git a/panel/poultry/helpers.py b/panel/poultry/helpers.py new file mode 100644 index 0000000..c84777e --- /dev/null +++ b/panel/poultry/helpers.py @@ -0,0 +1,304 @@ +import datetime +from collections import defaultdict +from datetime import timedelta + +from django.db.models import Sum, Q +from django.http import HttpResponse + +from authentication.sahandsms.sms import kill_house_price +from panel.models import PoultryRequest, PoultryHatching, KillHouseRequest, ProvinceKillRequest, \ + HatchingIncreaseRequest, ChickenCommissionPrices, KillRequest, PoultryRequestQuarantineCode, MarketDailyLimitation + + +def poultry_prediction(poultry): + total_quantity = 0 + total_weight = 0 + total_count = 0 + killing_ave_weight = 0 + + hatchings = PoultryHatching.objects.filter(poultry=poultry, trash=False, state='pending', + archive=False, temporary_trash=False, + temporary_deleted=False) + + poultry_requests = PoultryRequest.objects.filter(poultry=poultry, trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, killing_age__gt=30, + killing_age__lte=70, temporary_trash=False, + temporary_deleted=False) + sum_killing_ages = poultry_requests.aggregate(total=Sum('killing_age'))[ + 'total'] or 0 + ave_killing_age = int(sum_killing_ages / len(poultry_requests)) if len(poultry_requests) > 0 else 1 + if hatchings: + for hatching in hatchings: + if hatching.now_age <= ave_killing_age: + difference = ave_killing_age - hatching.now_age + predicate_date = datetime.datetime.now().date() + timedelta(days=difference) + hatching.predicate_date = predicate_date + hatching.save() + poultry.killing_ave_age = ave_killing_age + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__poultry=poultry, + state__in=('pending', 'accepted'), + return_to_province=False, first_car_allocated_quantity=0 + , temporary_trash=False, + temporary_deleted=False) + + sum_province_kill_requests_quantity = province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + sum_kill_province_kill_requests_weight = province_kill_requests.aggregate(total=Sum('total_killed_weight'))[ + 'total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__poultry=poultry, + temporary_trash=False, + temporary_deleted=False) + sum_kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + sum_kill_house_requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + loss_percent = kill_house_requests.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + ave_loss_percent = round(loss_percent / len(kill_house_requests), 2) if len(kill_house_requests) > 0 else 0 + total_quantity = sum_province_kill_requests_quantity + sum_kill_house_requests_quantity + total_weight = sum_kill_province_kill_requests_weight + sum_kill_house_requests_weight + total_count = len(province_kill_requests) + len(kill_house_requests) + killing_ave_count = total_quantity / total_count if total_count > 0 else 0 + killing_ave_weight = round(total_weight / total_quantity, 2) if total_quantity > 0 else 0 + + poultry.killing_ave_count = killing_ave_count + poultry.real_killing_ave_weight = killing_ave_weight + poultry.real_killing_loss_weight_percent = ave_loss_percent + poultry.save() + + +def poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1=None, date2=None): + # دریافت جوجه‌ریزی‌ها + hatchings = PoultryHatching.objects.filter( + trash=False, state='pending', archive=False, now_age__lte=ave_killing_age + ).order_by('date').select_related('poultry').only('poultry', 'left_over', 'now_age') + + grouped_data = defaultdict(lambda: { + "quantity": 0, + "weight": 0, + "poultry_count": 0, + "poultry_ids": set(), + "hatching_ids": set(), + }) + + for hatching in hatchings: + if hatching.now_age <= ave_killing_age: + if date1: + target_date = ( + datetime.datetime.now().date() + timedelta(days=ave_killing_age - hatching.now_age)).isoformat() + obj_date = datetime.datetime.strptime(target_date, '%Y-%m-%d').date() + if obj_date > date2 or obj_date < date1: + continue + else: + target_date = ( + datetime.datetime.now().date() + timedelta(days=ave_killing_age - hatching.now_age)).isoformat() + grouped_data[target_date]["quantity"] += hatching.left_over + grouped_data[target_date]["weight"] += int( + hatching.left_over * hatching.poultry.real_killing_ave_weight) if consumption_limit_type in ( + 'quantity', 'live_weight') else int( + (hatching.left_over * hatching.poultry.real_killing_ave_weight) * 0.75) + grouped_data[target_date]["hatching_ids"].add(hatching.id) + grouped_data[target_date]["poultry_ids"].add(hatching.poultry.id) + grouped_data[target_date]["poultry_count"] = len(grouped_data[target_date]["poultry_ids"]) + + result = [ + { + "age": ave_killing_age, + "poultry": data['poultry_count'], + "quantity": data["quantity"], + "weight": data["weight"], + "hatchings": data["hatching_ids"], + "date": date + } + for date, data in grouped_data.items() + ] + + return result + + +def calculate_hatching_increase(hatching): + hatching_increase = HatchingIncreaseRequest.objects.filter(trash=False, hatching=hatching) + quantity = hatching_increase.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + hatching.increase_quantity = quantity + hatching.save() + + +def create_update_chicken_commission_prices(): + now = datetime.datetime.now().date() + chicken_commission = ChickenCommissionPrices.objects.get_or_create(date__date=now, + defaults={'date': datetime.datetime.now(), + 'kill_house_price': kill_house_price})[ + 0] + # poultry_request + poultry_request = PoultryRequest.objects.filter(trash=False, send_date__date=now, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=False, + amount__gt=0).only( + 'amount') + poultry_request_amount = poultry_request.aggregate(total=Sum('amount'))[ + 'total'] or 0 + # ProvinceKillRequest + province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request__recive_date__date=now, + state__in=('pending', 'accepted'), + kill_house_price__gt=0).only( + 'kill_house_price') + + province_kill_req_kill_house_price = province_kill_req.aggregate(total=Sum('kill_house_price'))[ + 'total'] or 0 + + # KillRequest + kill_req = KillRequest.objects.filter(trash=False, recive_date__date=now, province_state__in=('accepted', 'pending') + , poultry__isnull=False, + direct_buying_state__in=('accepted', 'pending'), amount__gt=0).only( + 'amount') + kill_req_amount = kill_req.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + kill_request_amount = round( + kill_req_amount / kill_req.count()) if kill_req.count() > 0 else 0 + + province_kill_request_amount = round(province_kill_req_kill_house_price / province_kill_req.count()) \ + if province_kill_req.count() > 0 else 0 + + poultry_req_amount = round(poultry_request_amount / poultry_request.count()) if poultry_request.count() > 0 \ + else 0 + + amount = round( + kill_req_amount + province_kill_req_kill_house_price + poultry_request_amount) + + counts = poultry_request.count() + province_kill_req.count() + kill_req.count() + + chicken_commission.chicken_average_price = round(amount / counts) if counts > 0 else 0 + chicken_commission.kill_request_amount = kill_request_amount + chicken_commission.province_kill_request_amount = province_kill_request_amount + chicken_commission.poultry_request_amount = poultry_req_amount + + chicken_commission.save() + + +def create_update_chicken_commission_prices_manual(request): + now = datetime.datetime.now().date() + for day in range(7): + past_date = now - timedelta(days=day) + past_datetime = datetime.datetime.combine(past_date, datetime.time.min) + + chicken_commission = ChickenCommissionPrices.objects.get_or_create(date__date=past_date, + defaults={'date': past_datetime, + 'kill_house_price': kill_house_price})[ + 0] + # # poultry_request + poultry_request = PoultryRequest.objects.filter(trash=False, send_date__date=past_date, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=False, + amount__gt=0).only( + 'amount') + print(len(poultry_request)) + poultry_request_amount = poultry_request.aggregate(total=Sum('amount'))[ + 'total'] or 0 + # ProvinceKillRequest + province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request__recive_date__date=past_date, + state__in=('pending', 'accepted'), + kill_house_price__gt=0).only( + 'kill_house_price') + + province_kill_req_kill_house_price = province_kill_req.aggregate(total=Sum('kill_house_price'))[ + 'total'] or 0 + + # KillRequest + kill_req = KillRequest.objects.filter(trash=False, recive_date__date=past_date, + province_state__in=('accepted', 'pending') + , poultry__isnull=False, + direct_buying_state__in=('accepted', 'pending'), amount__gt=0).only( + 'amount') + kill_req_amount = kill_req.aggregate(total=Sum('amount'))[ + 'total'] or 0 + + kill_request_amount = round( + kill_req_amount / kill_req.count()) if kill_req.count() > 0 else 0 + + province_kill_request_amount = round(province_kill_req_kill_house_price / province_kill_req.count()) \ + if province_kill_req.count() > 0 else 0 + + poultry_req_amount = round(poultry_request_amount / poultry_request.count()) if poultry_request.count() > 0 \ + else 0 + + amount = round( + kill_req_amount + province_kill_req_kill_house_price + poultry_request_amount) + + counts = poultry_request.count() + province_kill_req.count() + kill_req.count() + + chicken_commission.chicken_average_price = round(amount / counts) if counts > 0 else 0 + chicken_commission.kill_request_amount = kill_request_amount + chicken_commission.province_kill_request_amount = province_kill_request_amount + chicken_commission.poultry_request_amount = poultry_req_amount + + chicken_commission.save() + + +def add_poultry_request_quarantine_code(request): + poultry_requests = PoultryRequest.objects.filter( + trash=False, + quarantine_code__isnull=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted') + ).only('id', 'quarantine_code', 'quarantine_quantity') + + codes = [ + PoultryRequestQuarantineCode( + poultry_request=poultry_request, + quarantine_code=poultry_request.quarantine_code, + system_quarantine_quantity=poultry_request.quarantine_quantity, + quarantine_quantity=poultry_request.quarantine_quantity, + ) + for poultry_request in poultry_requests + ] + + PoultryRequestQuarantineCode.objects.bulk_create(codes) + + return HttpResponse('ok') + + +def update_archive_date_poultry_hatching(request): + poultry_hatchings = PoultryHatching.objects.filter(Q(allow_hatching='True', state='complete') | Q(archive=True), + trash=False, + ) + for p in poultry_hatchings: + p.archive_date = p.date + timedelta(p.chicken_age) + p.save() + return HttpResponse('ok') + + +def market_daily_limitation_info(): + limitation_quantity = 0 + market_request_quantity = 0 + limitation = MarketDailyLimitation.objects.filter().first() + if limitation: + limitation_quantity = limitation.quantity + + poultry_Requests = PoultryRequest.objects.filter( + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + temporary_trash=False, + trash=False, + out=False, + send_date__date=datetime.datetime.now().date(), + final_state='pending', + market=True + ).aggregate( + total_quantity=Sum('quantity') + ) + market_request_quantity = poultry_Requests['total_quantity'] or 0 + + result = { + "max_limitation_quantity": limitation_quantity, + "market_request_quantity": market_request_quantity, + "remain_quantity" : limitation_quantity - market_request_quantity if (limitation_quantity - market_request_quantity) else 0 + + } + return result diff --git a/panel/poultry/serializers.py b/panel/poultry/serializers.py new file mode 100644 index 0000000..e7c835c --- /dev/null +++ b/panel/poultry/serializers.py @@ -0,0 +1,3367 @@ +from django.contrib.auth.models import Group +from django.db.models import Sum, Q, F, Prefetch +from rest_framework import serializers +# from rest_framework.response import Response +from rest_framework.response import Response +from authentication.models import UserProfile, SystemUserProfile, CityUnit, SystemAddress +from authentication.serializer.serializer import SystemUserProfileSerializer, \ + SystemUserProfileForAutoAllocationSerializer, SystemUserProfileForPoultryLocSerializer, \ + SystemUserProfileForGuildSerializer, SystemUserProfileForPoultryScienceWithoutRoleSerializer +from authentication.serializers import UserProfileSerializer, SystemAddressSerializer, \ + SystemAddressForLocSerializer, CityForLocSerializer +from authentication.serializer.serializer import BankCardSerializer +# from panel.KillHouse.serializers import KillHouseRequestExchangeReserveSerializer +# from panel.VetFarm.serializers import VetFarmForPoultrySerializer +from panel.models import PoultryRequest, PoultryAssignmentInformation, KillHouseRequest, KillHouseCheckRequest, \ + CityOperatorCheckRequest, ProvinceCheckOperatorRequest, KillHouseAssignmentInformation, ProvinceFactorToKillHouse, \ + KillHouseFactorToProvince, DepositAllocation, PovinceInspector, VetCheckRequest, PoultryRequestExchange, \ + ProvinceKillRequest, Poultry, PoultryTenant, PoultryHatching, PoultryRequestAuction, Pricing, \ + KillHouseRequestAction, ProvinceRequestAction, ProvinceOperator, VetFarmInspection, InspectorOperator, \ + KillHouseRequestActionWinner, CityOperator, VetFarm, ShareOfAllocation, ProvinceFactorToKillHouseForPoultry, \ + KillHouseFactorToPoultry, KillHouseComplaint, CheckUnusualCasualties, PercentageOfLosses, \ + ProvinceImportKillHouseOutFactors, TotalPoultryRequestQuantity, PoultryAllowCityProvince, \ + ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultrySellFree, Vet, LastUpdate, ChainCompany, ChainAllocation, \ + ChainCompanyTransaction, InternalTransaction, KillHouseOperator, KillHouse, OutProvincePoultryRequestBuyer, \ + PoultryExport, PoultryOutProvinceRequest, FreeSaleWithinprovince, PoultryPrediction, HatchingIncreaseRequest, \ + ChickenCommissionPrices, PoultryRequestQuarantineCode, ManagementHatchingAgeRange, PoultryScienceReport, \ + EvacuationHatchingDetail +# PoultryRequestExchangeAccept +from datetime import datetime +import pytz +from num2fawords import words, ordinal_words + +utc = pytz.UTC + + +class OutProvincePoultryRequestBuyerSerializer(serializers.ModelSerializer): + class Meta: + model = OutProvincePoultryRequestBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + +class OutProvincePoultryRequestBuyerForBuyerRequestSerializer(serializers.ModelSerializer): + requests_info = serializers.SerializerMethodField('get_requests_info') + + class Meta: + model = OutProvincePoultryRequestBuyer + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + def get_requests_info(self, obj): + total_quantity = 0 + total_weight = 0 + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True, out_province_request_cancel=False) | Q(state_process='accepted', province_state='accepted', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False), trash=False, + out=True, out_province_poultry_request_buyer=obj) + + total_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + return { + "number_of_requests": len(poultry_requests), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + + +class ChainCompanySerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + + class Meta: + model = ChainCompany + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + +class ChainCompanyForCompanyRequestSerializer(serializers.ModelSerializer): + user = SystemUserProfileSerializer(read_only=True) + user_bank_info = BankCardSerializer(required=False) + requests_info = serializers.SerializerMethodField('get_requests_info') + + class Meta: + model = ChainCompany + exclude = ( + 'id', + 'create_date', + 'modify_date', + 'created_by', + 'modified_by' + ) + + def get_requests_info(self, obj): + total_quantity = 0 + total_weight = 0 + chain_allocations = ChainAllocation.objects.filter(chain_company=obj, state='accepted', trash=False).order_by( + '-id') + + total_quantity = chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + + return { + "number_of_requests": len(chain_allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + } + + +class ChainCompanyForTotalWageAllocationWithDAteSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = ChainCompany + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + role = self.context.get('request').GET['role'] + if role in ['ChainCompany', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + trash=False).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + trash=False).order_by('id') + + total_quantity += chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight += chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_wage += chain_allocations.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "company": obj.name, + "company_user_fullname": obj.user.fullname, + "company_user_mobile": obj.user.mobile, + "company_user_city": obj.user.city.name, + "total_count": len(chain_allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_wage": total_wage, + + } + + +class ChainCompanyForTotalWageTransactionSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = ChainCompany + fields = ['key', 'info'] + + def get_info(self, obj): + total_paid_wage = 0 + role = self.context.get('request').GET['role'] + if role in ['ChainCompany', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + status='completed', + trash=False).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + status='completed', + union_share__gt=0, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + status='completed', + company_share__gt=0, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + status='completed', + guilds_share__gt=0, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + + total_paid_wage += transactions.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "company": obj.name, + "company_user_fullname": obj.user.fullname, + "company_user_mobile": obj.user.mobile, + "company_user_city": obj.user.city.name, + "total_paid_count": len(transactions), + "total_paid_wage": total_paid_wage, + + } + + +class ChainCompanyForTotalWageTransactionTransactionWithDAteSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = ChainCompany + fields = ['key', 'info'] + + def get_info(self, obj): + total_paid_wage = 0 + date1 = datetime.strptime(str(self.context.get('request').GET['date1']), '%Y-%m-%d').date() + date2 = datetime.strptime(str(self.context.get('request').GET['date2']), '%Y-%m-%d').date() + role = self.context.get('request').GET['role'] + if role in ['ChainCompany', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'amount' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + trash=False).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + union_share__gt=0, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + company_share__gt=0, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + transactions = InternalTransaction.objects.filter( + chain_company=obj, + date__date__gte=date1, + date__date__lte=date2, + status='completed', + guilds_share__gt=0, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + + total_paid_wage += transactions.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "company": obj.name, + "company_user_fullname": obj.user.fullname, + "company_user_mobile": obj.user.mobile, + "company_user_city": obj.user.city.name, + "total_paid_count": len(transactions), + "total_paid_wage": total_paid_wage, + + } + + +class ChainCompanyForTotalWageAllocationSerializer(serializers.ModelSerializer): + info = serializers.SerializerMethodField('get_info') + + class Meta: + model = ChainCompany + fields = ['key', 'info'] + + def get_info(self, obj): + total_quantity = 0 + total_weight = 0 + total_wage = 0 + role = self.context.get('request').GET['role'] + if role in ['ChainCompany', 'SuperAdmin', 'AdminX', 'Supporter']: + wage_type = 'total_wage_amount' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + archive_wage=False, + trash=False).order_by('id') + elif role == 'ProvinceOperator': + wage_type = 'union_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + union_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif role == 'Company': + wage_type = 'company_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + company_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + elif role == 'Guilds': + wage_type = 'guilds_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + guilds_share__gt=0, + archive_wage=False, + trash=False).order_by('id') + else: + wage_type = 'wallet_share' + chain_allocations = ChainAllocation.objects.filter( + chain_company=obj, + archive_wage=False, + trash=False).order_by('id') + + total_quantity += chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_weight += chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + total_wage += chain_allocations.aggregate(total=Sum(wage_type))[ + 'total'] or 0 + + return { + "company": obj.name, + "company_user_fullname": obj.user.fullname, + "company_user_mobile": obj.user.mobile, + "company_user_city": obj.user.city.name, + "total_count": len(chain_allocations), + "total_quantity": total_quantity, + "total_weight": total_weight, + "total_wage": total_wage, + + } + + +class PoultryForAutoAllocationSerializer(serializers.ModelSerializer): + class Meta: + model = Poultry + fields = ['unit_name'] + + +class PoultryForPoultryRequestLetterSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Poultry + fields = ['unit_name', 'user', 'breeding_unique_id'] + + +class PoultryForBarDifferenceRequestSerializer(serializers.ModelSerializer): + user = SystemUserProfileForGuildSerializer(read_only=True) + + class Meta: + model = Poultry + fields = ['unit_name', 'user'] + + +class PoultryForBarManagementSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(required=False) + + class Meta: + model = Poultry + fields = ['unit_name', 'city_operator', 'user', 'total_capacity', 'address', 'breeding_unique_id', + 'system_code'] + + +class TotalPoultrySerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(required=False) + hatching_info = serializers.SerializerMethodField('get_hatching_info') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + + class Meta: + model = Poultry + fields = ['key', 'user', 'address', 'unit_name', 'breeding_unique_id', 'epidemiological_code', 'system_code', + 'total_capacity', 'number_of_halls', 'health_certificate_number', 'city_operator', 'hatching_info', + 'vet_farm', 'order_limit'] + + def get_hatching_info(self, obj): + hatching = PoultryHatching.objects.filter(poultry__exact=obj, state='pending', archive=False, + trash=False).last() + period = None + active_hatching = False + if hatching: + period = hatching.period + if hatching.state == 'pending': + active_hatching = True + return {"period": period, "active_hatching": active_hatching} + + def get_vet_farm(self, obj): + vet_farm_name = None + vet_farm_mobile = None + vet_farm = VetFarm.objects.filter(poultry__exact=obj, trash=False).select_related('vet__user').last() + if vet_farm: + vet_farm_name = vet_farm.vet.user.fullname + vet_farm_mobile = vet_farm.vet.user.mobile + + return {"vet_farm_name": vet_farm_name, "vet_farm_mobile": vet_farm_mobile} + + +class PoultryForPoultryHatchingForKillInformationSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + last_hatching_remain_quantity = serializers.SerializerMethodField('get_last_hatching_remain_quantity') + last_hatching_diffrent_request_quantity = serializers.SerializerMethodField( + 'get_last_hatching_diffrent_request_quantity') + chain_company = serializers.SerializerMethodField('get_chain_company') + province_allow_sell_free = serializers.SerializerMethodField('get_allow_sell_free') + free_governmental_info = serializers.SerializerMethodField('get_free_governmental_info') + + address = SystemAddressSerializer(required=False) + + class Meta: + model = Poultry + fields = ['user', 'key', 'unit_name', 'address', + 'last_hatching_remain_quantity', 'province_allow_sell_free', 'chain_company', + 'last_hatching_diffrent_request_quantity', 'free_governmental_info'] + + def get_last_hatching_remain_quantity(self, obj): + hatching = PoultryHatching.objects.filter(poultry=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + remain = hatching.left_over if hatching else 0 + return remain + + def get_last_hatching_diffrent_request_quantity(self, obj): + left_export_quantity = None + left_poultry_out_province = None + age = None + breed = None + left_over = 0 + + hatching = PoultryHatching.objects.filter(poultry=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + poultry_export = PoultryExport.objects.get(trash=False) + if poultry_export.limitation_status == True: + total_export = int(hatching.quantity * (poultry_export.limitation / 100)) + hatching_export_quantity = hatching.export_killed_quantity + left_export_quantity = hatching.left_over if hatching.left_over <= ( + total_export - hatching_export_quantity) else total_export - hatching_export_quantity + + poultry_out_province = PoultryOutProvinceRequest.objects.get(trash=False) + if poultry_out_province.limitation_status == True: + total_poultry_out_province = int(hatching.quantity * (poultry_out_province.limitation / 100)) + hatching_poultry_out_province_quantity = hatching.out_province_killed_quantity + left_poultry_out_province = hatching.left_over if hatching.left_over <= ( + total_poultry_out_province - hatching_poultry_out_province_quantity) else total_poultry_out_province - hatching_poultry_out_province_quantity + if hatching: + age = hatching.chicken_age + breed = hatching.chicken_breed + left_over = hatching.left_over + return { + "left_export_quantity": left_export_quantity, + "left_poultry_out_province": left_poultry_out_province, + "age": age, + "breed": breed, + "left_over": left_over, + } + + def get_chain_company(self, obj): + hatching = PoultryHatching.objects.filter(poultry=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + chain_company = False if hatching.has_chain_company == False else True + return { + "chain_company": chain_company, + "hatching-key": hatching.key + } + + def get_allow_sell_free(self, instance): + allow_state = None + province_allow = ProvinceAllowPoultrySellFree.objects.filter(poultry=instance).first() + if province_allow: + allow_state = province_allow.allow + return allow_state + + def get_free_governmental_info(self, obj): + left_total_free_commitment_quantity = 0 + hatching = PoultryHatching.objects.filter(poultry=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=hatching) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, final_state='archive', + hatching=hatching) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = hatching.left_over + elif hatching.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if hatching.total_commitment_quantity == 0: + left_total_free_commitment_quantity = hatching.left_over + else: + left_total_free_commitment_quantity = hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + hatching.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + return { + "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + "total_commitment_quantity": hatching.total_commitment_quantity, + "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + "total_free_commitment_quantity": hatching.total_free_commitment_quantity, + "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + + } + + +class PoultryForPoultryHatchingSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + address = SystemAddressSerializer(required=False) + province_allow_choose_kill_house = serializers.SerializerMethodField('get_allow_choose_kill_house') + last_hatching_remain_quantity = serializers.SerializerMethodField('get_last_hatching_remain_quantity') + province_allow_sell_free = serializers.SerializerMethodField('get_allow_sell_free') + hatching_age = serializers.SerializerMethodField('get_hatching_age') + + class Meta: + model = Poultry + fields = ['user', 'key', 'address', 'province_allow_choose_kill_house', 'unit_name', + 'last_hatching_remain_quantity', 'province_allow_sell_free', + 'hatching_age'] + + def get_last_hatching_remain_quantity(self, obj): + hatching = PoultryHatching.objects.filter(poultry__exact=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + remain = hatching.left_over if hatching else 0 + return remain + + def get_hatching_age(self, obj): + hatching = PoultryHatching.objects.filter(poultry__exact=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).last() + if hatching: + date = datetime.strptime(str(hatching.date), '%Y-%m-%d %H:%M:%S') + age = (datetime.now() - date).days + 1 + breed = hatching.chicken_breed + else: + age = None + breed = None + return {"age": age, "breed": breed} + + def get_allow_choose_kill_house(self, instance): + allow_state = None + mandatory = None + province_allow = ProvinceAllowPoultryChooseKillHouse.objects.filter(poultry=instance).first() + if province_allow: + allow_state = province_allow.allow + mandatory = province_allow.mandatory + return {"allow_state": allow_state, "mandatory": mandatory} + + def get_allow_sell_free(self, instance): + allow_state = None + province_allow = ProvinceAllowPoultrySellFree.objects.filter(poultry=instance).first() + if province_allow: + allow_state = province_allow.allow + return allow_state + + +# class PoultryForAllUserSerializer(serializers.ModelSerializer): +# user_bank_info = BankCardSerializer(required=False) +# address = SystemAddressSerializer(required=False) +# +# class Meta: +# model = Poultry +# fields = ['breeding_unique_id', 'unit_name', 'address', 'number_of_halls', 'total_capacity', +# 'user_bank_info', 'city_operator','active','identity_documents'] + + +class VetForPoultrySerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = Vet + fields = ['user'] + + +class VetFarmForPoultrySerializer(serializers.ModelSerializer): + vet = VetForPoultrySerializer(read_only=True) + + class Meta: + model = VetFarm + fields = ['vet'] + + +class PoultryForAllUserSerializer(serializers.ModelSerializer): + user_bank_info = BankCardSerializer(required=False) + address = SystemAddressSerializer(required=False) + tenants = serializers.SerializerMethodField('get_tenants') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + + class Meta: + model = Poultry + + fields = ['breeding_unique_id', 'unit_name', 'address', 'number_of_halls', 'total_capacity', + 'user_bank_info', 'city_operator', 'active', 'identity_documents', 'tenants', 'vet_farm'] + + def get_tenants(self, obj): + owner_poultry = Poultry.objects.filter(owner__exact=obj) + return PoultryForAllUserSerializer(owner_poultry, many=True).data + + def get_vet_farm(self, obj): + vet_farm = VetFarm.objects.filter(poultry__exact=obj, trash=False) + return VetFarmForPoultrySerializer(vet_farm, many=True).data + + +# سریالایزر مربوط به درخواست بورسی مرغدار +class PoultrySerializer(serializers.ModelSerializer): + userprofile = serializers.SerializerMethodField('get_userprofile') + address = SystemAddressSerializer(read_only=True) + poultry_owner = serializers.SerializerMethodField('get_owner') + poultry_tenant = serializers.SerializerMethodField('get_poultry_tenant') + hatching = serializers.SerializerMethodField('get_hatching') + register_vet_halls = serializers.SerializerMethodField('get_busy_halls') + allow = serializers.SerializerMethodField('get_allow_city_province') + province_allow_choose_kill_house = serializers.SerializerMethodField('get_allow_choose_kill_house') + province_allow_sell_free = serializers.SerializerMethodField('get_allow_sell_free') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + last_hatching_diffrent_request_quantity = serializers.SerializerMethodField( + 'get_last_hatching_diffrent_request_quantity') + user_bank_info = BankCardSerializer(required=False) + left_over_own_hatching = serializers.SerializerMethodField('get_left_over_own_hatching') + + class Meta: + model = Poultry + exclude = ( + 'user', + 'id', + 'create_date', + 'modify_date', + # 'trash', + 'password', + 'created_by', + 'modified_by', + ) + + def get_userprofile(self, instance): + user = SystemUserProfile.objects.get(id=instance.user.id, trash=False) + internal_dictionary = { + "user_key": user.key, + "base_order": user.base_order, + "full_name": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "breeding_unique_id": instance.breeding_unique_id, + + } + + return internal_dictionary + + def get_vet_farm(self, instance): + internal_dictionary = {} + vet_farm = VetFarm.objects.filter(poultry=instance, trash=False) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + + internal_dictionary = { + "full_name": vet_farm.vet.user.fullname, + "mobile": vet_farm.vet.user.mobile, + "city": vet_farm.vet.user.city.name, + "province": vet_farm.vet.user.province.name, + + } + + return internal_dictionary + + def get_allow_choose_kill_house(self, instance): + allow_state = None + mandatory = None + province_allow = ProvinceAllowPoultryChooseKillHouse.objects.filter(poultry=instance).first() + if province_allow: + allow_state = province_allow.allow + mandatory = province_allow.mandatory + return {"allow_state": allow_state, "mandatory": mandatory} + + def get_allow_sell_free(self, instance): + allow_state = None + province_allow = ProvinceAllowPoultrySellFree.objects.filter(poultry=instance).first() + if province_allow: + allow_state = province_allow.allow + return allow_state + + def get_allow_city_province(self, instance): + internal_dictionary = {} + allow = PoultryAllowCityProvince.objects.filter(poultry=instance, trash=False) + if allow.count() > 0: + allow = allow.last() + internal_dictionary = { + "city": allow.city, + "province": allow.province, + } + + return internal_dictionary + + def get_last_hatching_diffrent_request_quantity(self, obj): + left_export_quantity = None + left_poultry_out_province = None + + hatching = PoultryHatching.objects.filter(poultry=obj, state='pending', archive=False, + allow_hatching='pending', trash=False).order_by('left_over').last() + if hatching: + poultry_export = PoultryExport.objects.get(trash=False) + if poultry_export.limitation_status == True: + total_export = int(hatching.quantity * (poultry_export.limitation / 100)) + hatching_export_quantity = hatching.export_killed_quantity + left_export_quantity = hatching.left_over if hatching.left_over <= ( + total_export - hatching_export_quantity) else total_export - hatching_export_quantity + + poultry_out_province = PoultryOutProvinceRequest.objects.get(trash=False) + if poultry_out_province.limitation_status == True: + total_poultry_out_province = int(hatching.quantity * (poultry_out_province.limitation / 100)) + hatching_poultry_out_province_quantity = hatching.out_province_killed_quantity + left_poultry_out_province = hatching.left_over if hatching.left_over <= ( + total_poultry_out_province - hatching_poultry_out_province_quantity) else total_poultry_out_province - hatching_poultry_out_province_quantity + remain = hatching.left_over if hatching else 0 + + return { + "left_export_quantity": left_export_quantity, + "left_poultry_out_province": left_poultry_out_province, + "last_hatching_remain_quantity": remain, + } + + def get_busy_halls(self, instance): + list1 = [] + vet_farms = VetFarm.objects.filter(poultry=instance, state='pending', trash=False) + if vet_farms.count() > 0: + for vet_farm in vet_farms: + list1.append(vet_farm.hall) + + return list1 + + def get_owner(self, instance): + if instance.owner != None: + owner = Poultry.objects.filter(id=instance.owner.id, trash=False) + if owner.count() > 0: + owner = owner.last() + internal_dictionary = { + "full_name": owner.user.fullname, + "mobile": owner.user.mobile, + "unit_name": owner.unit_name, + "number_of_halls": owner.number_of_halls, + "breeding_unique_id": owner.breeding_unique_id, + + } + else: + internal_dictionary = {} + + return internal_dictionary + + def get_poultry_tenant(self, instance): + tenant = Poultry.objects.filter(owner_id=instance.id, trash=False) + if tenant.count() > 0: + tenant = tenant.last() + internal_dictionary = { + "key": tenant.key, + "first_name": tenant.user.first_name, + "last_name": tenant.user.last_name, + "full_name": tenant.user.first_name + " " + tenant.user.last_name, + "mobile": tenant.user.mobile, + "national_id": tenant.user.national_id, + "breeding_unique_id": tenant.breeding_unique_id, + } + else: + internal_dictionary = {} + + return internal_dictionary + + def get_hatching(self, instance): + hatching_list = [] + for hatching in PoultryHatching.objects.filter(poultry=instance, trash=False): + age = (datetime.now().date() - hatching.date.date()).days + 1 + internal_dictionary = { + "poultry_key": hatching.poultry.key, + "poultry_hatching_key": hatching.key, + "poultry": hatching.poultry.unit_name, + "quantity": hatching.quantity, + "losses": hatching.losses, + "left_over": hatching.left_over, + "out_province_killed_quantity": hatching.out_province_killed_quantity, + "export_killed_quantity": hatching.export_killed_quantity, + "hall": hatching.hall, + "date": hatching.date, + "period": hatching.period, + "state": hatching.state, + "age": age, + + } + hatching_list.append(internal_dictionary) + + return hatching_list + + def get_left_over_own_hatching(self, instance): + hatching = PoultryHatching.objects.filter(state='pending', archive=False, + allow_hatching='pending', poultry=instance, trash=False).order_by( + 'chicken_age').first() + if hatching: + left_over = hatching.left_over + else: + left_over = None + return left_over + + +class PoultryForPredictionSerializer(serializers.ModelSerializer): + fullname = serializers.CharField(source='user.fullname') + mobile = serializers.CharField(source='user.mobile') + city = serializers.CharField(source='user.city.name') + userprofile = serializers.SerializerMethodField('get_userprofile') + + + class Meta: + model = Poultry + fields = ['key', 'fullname', 'mobile', 'city', 'unit_name', 'killing_ave_age', 'active_left_over', + 'killing_ave_count', 'real_killing_ave_weight', 'real_killing_live_weight', + 'real_killing_carcasses_weight', 'real_killing_loss_weight_percent','userprofile'] + + def get_userprofile(self, instance): + user = SystemUserProfile.objects.get(id=instance.user.id, trash=False) + internal_dictionary = { + "user_key": user.key, + "base_order": user.base_order, + "full_name": user.fullname, + "mobile": user.mobile, + "city": user.city.name, + "province": user.province.name, + "breeding_unique_id": instance.breeding_unique_id, + + } + + return internal_dictionary + + +class PoultryForDirectBuyingSerializer(serializers.ModelSerializer): + fullname = serializers.CharField(source='user.fullname') + mobile = serializers.CharField(source='user.mobile') + province = serializers.CharField(source='user.province.name') + city = serializers.CharField(source='user.city.name') + + class Meta: + model = Poultry + fields = ['key', 'fullname', 'mobile', 'province', 'city', 'unit_name'] + + +# سریالایزر مربوط به مستاجر مرغدار +class PoultryTenantSerializer(serializers.ModelSerializer): + poultry = PoultrySerializer(read_only=True) + + class Meta: + model = PoultryTenant + fields = '__all__' + + +class TotalPoultryRequestQuantitySerializer(serializers.ModelSerializer): + class Meta: + model = TotalPoultryRequestQuantity + fields = '__all__' + + +# سریالایزر مربوط به درخواست بورسی مرغدار +class PoultryRequestExchangeSerializer(serializers.ModelSerializer): + user = UserProfileSerializer(read_only=True) + chicken_age = serializers.SerializerMethodField('age') + + class Meta: + model = PoultryRequestExchange + fields = '__all__' + + +# سریالایزر مربوط به ثبت جوجه ریزی مرغدار +class PoultryHatchingSerializer(serializers.ModelSerializer): + poultry = PoultrySerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + age = serializers.SerializerMethodField('get_age') + inspection_losses = serializers.SerializerMethodField('get_inspection') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + active_kill = serializers.SerializerMethodField('get_active_kill') + killing_info = serializers.SerializerMethodField('get_killing_info') + free_governmental_info = serializers.SerializerMethodField('get_free_governmental_info') + management_hatching_age_range = serializers.SerializerMethodField('get_management_hatching_age_range') + + class Meta: + model = PoultryHatching + fields = '__all__' + + def get_management_hatching_age_range(self, obj): + + age_range = ManagementHatchingAgeRange.objects.filter(from_age__lte=obj.chicken_age,to_age__gte=obj.chicken_age).first() + if age_range: + return { + 'from_weight': age_range.from_weight, + 'to_weight': age_range.to_weight, + } + else: + return { + 'from_weight': 0, + 'to_weight': 5, + } + + # تابع برای بدست آوردن سن مرع + def get_age(self, instance): + # date = datetime.strptime(str(instance.date), '%Y-%m-%d %H:%M:%S') + # age = (datetime.now() - date).days + 1 + # hatching = PoultryHatching.objects.get(key=instance.key) + # if hatching.archive == False and hatching.allow_hatching == 'pending': + # hatching.chicken_age = age + # hatching.save() + return instance.chicken_age + + def get_inspection(self, instance): + inspection = VetFarmInspection.objects.filter(poultry_hatching=instance) + if inspection.count() > 0: + inspections = 0 + for ins in inspection: + if ins.Losses == 0: + pass + else: + inspections += int(ins.Losses) + return inspections + + def get_vet_farm(self, instance): + vet = { + "vet_farm_full_name": 'ندارد', + "vet_farm_mobile": '', + } + vet_farm = VetFarm.objects.filter(poultry=instance.poultry) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + vet = { + "vet_farm_full_name": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile, + } + + return vet + + def get_active_kill(self, instance): + + active_kill = False + count_of_request = 0 + + province_kill_request = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=instance, + state='accepted') + if province_kill_request.count() > 0: + count_of_request = province_kill_request.count() + + if ProvinceKillRequest.objects.filter(trash=False, province_request__poultry_request__hatching=instance, + state='pending').exists(): + active_kill = True + info = { + "active_kill": active_kill, + "count_of_request": count_of_request, + } + + return info + + def get_killing_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + province_request__poultry_request__hatching=obj) + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=obj) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + return { + "violation_message": 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' if obj.violation else 'عادی', + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests": len(kill_house_requests), + "kill_house_requests_first_quantity": first_quantity, + "kill_house_requests_first_weight": first_weight, + "bar_complete_with_kill_house": len(bar_complete_with_kill_house), + "accepted_real_quantity_final": accepted_real_quantity_final, + "accepted_real_wight_final": accepted_real_wight_final, + "ware_house_bars": len(ware_house_bars), + "ware_house_bars_quantity": ware_house_bars_quantity, + "ware_house_bars_weight": ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + } + + def get_free_governmental_info(self, obj): + left_total_free_commitment_quantity = 0 + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=obj) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, final_state='archive', + hatching=obj) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = obj.left_over + + elif obj.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if obj.total_commitment_quantity == 0: + left_total_free_commitment_quantity = obj.left_over + else: + left_total_free_commitment_quantity = obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + return { + "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + "total_commitment_quantity": obj.total_commitment_quantity, + "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + "total_free_commitment_quantity": obj.total_free_commitment_quantity, + "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + + } + + +class PoultryHatchingForPredictionSerializer(serializers.ModelSerializer): + poultry = PoultryForPredictionSerializer(read_only=True) + general_info = serializers.SerializerMethodField('get_general_info') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + + + class Meta: + model = PoultryHatching + fields = ['poultry', 'general_info', 'chicken_breed', 'date', 'quantity', 'left_over', 'period','chicken_age', + 'losses','violation','vet_farm','licence_number'] + + def get_general_info(self, obj): + now_age = (datetime.now().date() - obj.date.date()).days + 1 + sum_age = 0 + ave_age = 0 + ave_weight = 0 + counter = 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + hatching=obj) + for poultry_request in poultry_requests: + sum_age += (poultry_request.send_date.date() - obj.date.date()).days + 1 + counter += 1 + ave_age = int(sum_age / counter) if counter > 0 else 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=obj, + first_car_allocated_quantity=0, + return_to_province=False) + + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=obj) + + kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house__requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + + total_quantity = province_kill_requests_quantity + kill_house_requests_quantity + total_weight = province_kill_requests_weight + kill_house__requests_weight + + ave_weight = round(total_weight / total_quantity, 2) if total_quantity > 0 else 0 + + return { + "ave_age": ave_age, + "age": now_age, + "ave_weight": ave_weight, + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests_quantity": kill_house_requests_quantity, + "kill_house_requests": len(kill_house_requests), + "kill_house__requests_weight": kill_house__requests_weight, + "total_quantity": total_quantity, + "total_weight": total_weight + } + + def get_vet_farm(self, obj): + + vet_farm = VetFarm.objects.filter(poultry=obj.poultry, trash=False).first() + vet_farm_fullname = vet_farm.vet.user.fullname if vet_farm else None + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else None + + return { + "vet_farm_fullname": vet_farm_fullname, + "vet_farm_mobile": vet_farm_mobile, + } + + +class PoultryRequestForAutoAllocationSerializer(serializers.ModelSerializer): + # user = SystemUserProfileSerializer(read_only=True) + poultry = PoultryForAutoAllocationSerializer(read_only=True) + + class Meta: + model = PoultryRequest + fields = ['poultry', 'payer_fullname'] + + +class PoultryRequestForOutRequestTransactionsSerializer(serializers.ModelSerializer): + poultry = PoultryForAutoAllocationSerializer(read_only=True) + + class Meta: + model = PoultryRequest + fields = ['poultry', 'order_code'] + + +class PoultryRequestForMarketSerializer(serializers.ModelSerializer): + + class Meta: + model = PoultryRequest + fields = ['killing_age'] + + +class PoultryHatchingForChainAllocationSerializer(serializers.ModelSerializer): + poultry = PoultryForPoultryRequestLetterSerializer(read_only=True) + + class Meta: + model = PoultryHatching + fields = '__all__' + + +class PoultryHatchingForBarDifferenceRequestSerializer(serializers.ModelSerializer): + poultry = PoultryForBarDifferenceRequestSerializer(read_only=True) + + class Meta: + model = PoultryHatching + fields = ['key', 'poultry', 'quantity', 'left_over', 'chicken_age', 'now_age'] + + +class ChainAllocationForWageSerializer(serializers.ModelSerializer): + poultry_hatching = PoultryHatchingForChainAllocationSerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + total_wage_amount = serializers.SerializerMethodField('get_total_wage_amount') + + class Meta: + model = ChainAllocation + fields = '__all__' + + def get_total_wage_amount(self, obj): + role = self.context.get('request').GET['role'] + + if role in ['SuperAdmin', 'ChainCompany', 'AdminX', 'Supporter']: + amount = obj.total_wage_amount + elif role == 'ProvinceOperator': + amount = obj.union_share + + elif role == 'Guilds': + amount = obj.guilds_share + elif role == 'Company': + amount = obj.company_share + else: + amount = obj.total_wage_amount + + return amount + + +class KillHouseOperatorForChainAllocationsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializer(read_only=True) + + class Meta: + model = KillHouseOperator + fields = ['user'] + + +class KillHouseForChainAllocationSerializer(serializers.ModelSerializer): + kill_house_operator = KillHouseOperatorForChainAllocationsSerializer(read_only=True) + + class Meta: + model = KillHouse + fields = ['kill_house_operator', 'name', 'killer', 'key'] + + +class ChainAllocationSerializer(serializers.ModelSerializer): + poultry_hatching = PoultryHatchingForChainAllocationSerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + kill_house = KillHouseForChainAllocationSerializer(read_only=True) + + class Meta: + model = ChainAllocation + fields = '__all__' + + +class ChainCompanyTransactionSerializer(serializers.ModelSerializer): + chain_company = ChainCompanySerializer(read_only=True) + + class Meta: + model = ChainCompanyTransaction + fields = '__all__' + + +class PoultryRequestForKillingInformationSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + city_check_request = serializers.SerializerMethodField('get_city_check_request') + + class Meta: + model = PoultryRequest + fields = ['key', 'id', 'poultry', 'order_code', 'create_date', 'send_date', 'kill_house_list', 'first_quantity', + 'quantity', 'direct_buying', 'union', 'amount', 'financial_operation', + 'remain_quantity', 'Index_weight', 'hatching', 'final_state', 'losses', 'province_state', + 'state_process', 'registrar', 'vet_farm', 'free_sale_in_province', 'freezing', 'export', + 'city_check_request','market','killing_age'] + + def get_hatching(self, obj): + file_state = 'pending' + if obj.province_state == 'pending': + file_state = 'province_state_pending' + + elif obj.price_confirmation and not obj.input_price_confirmation_code: + file_state = 'confirmation_code_pending' + + else: + file_state = 'allocated_pending' + hatching = PoultryHatching.objects.filter(Q(trash=False) | Q(trash=True), key=obj.hatching.key).first() + inspections = VetFarmInspection.objects.filter(poultry_hatching=hatching, trash=False) + losses = 0 + if inspections: + losses = inspections.aggregate(total_quantity=Sum('Losses')).get('total_quantity', 0) + inspection_losses = (losses * 100) / obj.hatching.quantity if losses > 0 else 0 + + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=obj, + state='accepted').exists(): + if obj.remain_quantity == 0: + file_state = 'allocated_completed' + age2 = (obj.send_date - hatching.date).days + 1 + else: + age2 = (datetime.now() - hatching.date).days + 1 + + return { + "age": age2, + "left_over": hatching.left_over, + "file_state": file_state, + "hatching_date": hatching.date, + "allow_hatching": hatching.allow_hatching, + "inspection_losses": losses, + "inspection_losses_percent": inspection_losses, + "total_losses_percent": (hatching.losses * 100) / hatching.quantity, + "poultry_losses_percent": (int(obj.losses) * 100) / hatching.quantity, + "total_weight": obj.Index_weight * obj.quantity + } + + def get_vet_farm(self, obj): + + vet_farm = VetFarm.objects.filter(poultry=obj.poultry, trash=False).first() + vet_farm_fullname = vet_farm.vet.user.fullname if vet_farm else None + vet_farm_mobile = vet_farm.vet.user.mobile if vet_farm else None + + return { + "vet_farm_fullname": vet_farm_fullname, + "vet_farm_mobile": vet_farm_mobile, + } + + def get_city_check_request(self, obj): + try: + city_check = CityOperatorCheckRequest.objects.get(trash=False, poultry_request=obj) + return city_check.key + except: + return None + + +class PoultryRequestForBarMangementSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + age = serializers.SerializerMethodField('get_age') + + class Meta: + model = PoultryRequest + fields = ['key', 'poultry', 'send_date', 'age', 'amount', 'financial_operation', 'chicken_breed', 'order_code', + 'freezing', 'export', 'direct_buying', 'free_sale_in_province'] + + def get_age(self, obj): + age = (obj.send_date.date() - obj.hatching.date.date()).days + 1 + return age + + +class PoultryRequestForGeneralCasestatusSerializer(serializers.ModelSerializer): + poultry = PoultryForBarManagementSerializer(read_only=True) + other_informations = serializers.SerializerMethodField('get_other_informations') + + class Meta: + model = PoultryRequest + fields = ['key', 'id', 'poultry', 'send_date', 'amount', 'financial_operation', 'quantity', 'Index_weight', + 'order_code', 'province_state', + 'state_process', + 'other_informations', 'final_state', 'out', 'free_sale_in_province'] + + def get_other_informations(self, obj): + vet_farm_name = None + vet_farm_mobile = None + vet_farm = VetFarm.objects.filter(poultry=obj.poultry, trash=False).select_related( + 'vet__user').only('vet__user__mobile', 'vet__user__fullname').last() + if vet_farm: + vet_farm_name = vet_farm.vet.user.fullname + vet_farm_mobile = vet_farm.vet.user.mobile + + return { + "vet_farm_name": vet_farm_name, + "vet_farm_mobile": vet_farm_mobile, + "province_kill_request_state": ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request=obj).exists(), + "kill_house_state": KillHouseCheckRequest.objects.filter(trash=False, + province_kill_request__province_request__poultry_request=obj).exists(), + "kill_house_request_state": KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request=obj).exists(), + "receive_bar_state": VetCheckRequest.objects.filter(trash=False, + kill_house_request__province_request__poultry_request=obj).exists(), + "bar_state": KillHouseAssignmentInformation.objects.filter(trash=False, + kill_house_request__province_request__poultry_request=obj).exists(), + "province_factor_state": ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__province_request__poultry_request=obj, + trash=False).exists(), + "kill_house_factor_state": KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__province_request__poultry_request=obj, + trash=False, state='accepted').exists(), + "inspector_state": PovinceInspector.objects.filter(poultry_request=obj, + trash=False).exists(), + } + + +# سریالایزر مربوط به درخواست مرغدار +class PoultryRequestSerializer(serializers.ModelSerializer): + # user = SystemUserProfileSerializer(read_only=True) + poultry = PoultrySerializer(read_only=True) + hatching = PoultryHatchingSerializer(read_only=True) + process = serializers.SerializerMethodField('get_process') + + class Meta: + model = PoultryRequest + fields = '__all__' + # fields = ['id', 'poultry', 'hatching'] + + # تایع برای نمایش ریز جزییات مزبوط به پرونده مرغدار برای پنل های استان + def get_process(self, instance): + process = {} + + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=instance, + state='accepted').exists(): + age2 = (instance.send_date - instance.hatching.date).days + 1 + else: + age2 = (datetime.now() - instance.hatching.date).days + 1 + + file_state = 'pending' + if instance.province_state == 'pending': + file_state = 'province_state_pending' + + if ProvinceKillRequest.objects.filter(province_request__poultry_request__id=instance.id).exists(): + if instance.remain_quantity == 0: + file_state = 'allocated_completed' + + + else: + file_state = 'allocated_pending' + + process.update({"file_state": file_state}) + + process.update({"poultry": { + "poultry_unit_name": instance.poultry.unit_name, + "breeding_unique_id": instance.poultry.breeding_unique_id, + "halls": instance.poultry.number_of_halls, + "tenant": instance.poultry.tenant, + "has_tenant": instance.poultry.has_tenant, + "poultry_request_id": instance.id, + "base_order": instance.poultry.user.base_order, + + "awaiting_payment": instance.awaiting_payment, + "poultry_request_key": instance.key, + "general_order_code": instance.general_order_code, + "kill_house_list": instance.kill_house_list, + "poultry_request_final_state": instance.final_state, + "poultry_order_code": instance.order_code, + "poultry_send_date": instance.send_date, + "poultry_name": instance.poultry.user.fullname, + "poultry_mobile": instance.poultry.user.mobile, + "poultry_city": instance.poultry.address.city.name, + "poultry_province": instance.poultry.address.province.name, + "poultry_address": instance.poultry.address.address, + "national_id": instance.poultry.user.national_id, + "poultry_gis_code": instance.poultry.gis_code, + 'age': age2, + 'chicken_date': None, + "poultry_quantity": instance.quantity, + "poultry_remain_quantity": instance.remain_quantity, + "poultry_previous_quantity": instance.previous_quantity, + "poultry_first_quantity": instance.first_quantity, + "poultry_chicken_breed": instance.chicken_breed, + "poultry_request_losses": instance.losses, + "poultry_Index_weight": "{} کیلوگرم".format(instance.Index_weight), + "Index_weight": instance.Index_weight, + "total_weight": instance.Index_weight * instance.quantity, + "poultry_register_date": instance.create_date, + "poultry_auction": instance.auction, + "sell_type": instance.cell_type, + "buyer": instance.buyer, + "quarantine_code": instance.quarantine_code, + + } + }) + poultry_hatching = PoultryHatching.objects.filter(key=instance.hatching.key, trash=False) + if poultry_hatching.count() > 0: + poultry_hatching = poultry_hatching.last() + inspections = VetFarmInspection.objects.filter(poultry_hatching=poultry_hatching) + losses = 0 + if inspections.count() > 0: + for ins in inspections: + if ins.Losses > 0: + losses += ins.Losses + else: + pass + + if losses > 0: + process.update({"inspection_losses": losses + }) + process.update({ + "inspection_losses_percent": (losses * 100) / instance.hatching.quantity + }) + else: + process.update({"inspection_losses": losses + }) + process.update({ + "inspection_losses_percent": losses + }) + + process.update({"poultry_hatching": { + "poultry_key": instance.poultry.key, + "poultry_hatching_key": instance.hatching.key, + "poultry_name": instance.poultry.unit_name, + "quantity": instance.hatching.quantity, + "losses": instance.hatching.losses, + "total_losses_percent": (instance.hatching.losses * 100) / instance.hatching.quantity, + "poultry_losses_percent": (int(instance.losses) * 100) / instance.hatching.quantity, + "left_over": instance.hatching.left_over, + "hall": instance.hatching.hall, + "date": instance.hatching.date, + "allow_hatching": instance.hatching.allow_hatching, + "period": instance.hatching.period, + "state": instance.hatching.state, + } + }) + else: + process.update({"poultry_hatching": None + }) + + vetfarm_inspection = VetFarmInspection.objects.filter(vet_farm__poultry=instance.poultry, trash=False) + if vetfarm_inspection.count() > 0: + vetfarm_inspection = vetfarm_inspection.last() + process.update({"vetfarm_inspection": { + "vet_name": vetfarm_inspection.vet_farm.vet.user.fullname, + "hall": vetfarm_inspection.hall, + "topic": vetfarm_inspection.topic, + "description": vetfarm_inspection.description, + "image": vetfarm_inspection.image, + "losses": vetfarm_inspection.Losses, + "longitude": vetfarm_inspection.longitude, + "latitude": vetfarm_inspection.latitude, + } + }) + else: + process.update({"vetfarm_inspection": None + }) + + auctions = PoultryRequestAuction.objects.filter(poultry_request=instance, state='active', trash=False).order_by( + 'auction_date') + if auctions.count() > 0: + auctions_list = [] + for auction in auctions: + if auction.state == 'active': + index = list(auctions).index(auction) + 1 + pricing = Pricing.objects.get(id=auction.pricing.id, trash=False) + internal_dict_auction = { + "ceiling_price": pricing.ceiling_price, + "floor_price": pricing.floor_price, + "fee": auction.fee, + "hour": auction.hour, + "date": auction.auction_date, + "index": index, + "total_index": auctions.count() + } + auctions_list.append(internal_dict_auction) + process.update({"auctions_list": auctions_list}) + # else: + # break + # process['poultry'].update({"auctions_list":auctions_list}) + process.update({"auctions_list": auctions_list}) + else: + process.update({"auctions_list": None}) + kill_house_auctions = KillHouseRequestAction.objects.filter(poultry_request=instance, state='pending', + trash=False) + if kill_house_auctions.count() > 0: + kill_house_auctions_list = [] + for kill_house_auction in kill_house_auctions: + internal_dict_kill_house_auction = { + "kill_house_name": kill_house_auction.kill_house.name, + "fullname": kill_house_auction.kill_house.kill_house_operator.user.fullname, + "mobile": kill_house_auction.kill_house.kill_house_operator.user.mobile, + "city": kill_house_auction.kill_house.system_address.city.name, + "province": kill_house_auction.kill_house.system_address.province.name, + "fee": kill_house_auction.fee, + } + kill_house_auctions_list.append(internal_dict_kill_house_auction) + process.update({"kill_house_auctions_list": kill_house_auctions_list}) + else: + process.update({"kill_house_auctions_list": None}) + kill_house_auction_winner = KillHouseRequestActionWinner.objects.filter( + kill_house_request_auction__poultry_request=instance, trash=False) + if kill_house_auction_winner.count() > 0: + kill_house_auction_winner = kill_house_auction_winner.last() + process.update({"kill_house_winner": { + "kill_house_winner_key": kill_house_auction_winner.key, + "kill_house_name": kill_house_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_user_name": kill_house_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.fullname, + "kill_house_user_mobile": kill_house_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "kill_house_city": kill_house_auction_winner.kill_house_request_auction.kill_house.system_address.city.name, + "kill_house_province": kill_house_auction_winner.kill_house_request_auction.kill_house.system_address.province.name, + "fee": kill_house_auction_winner.fee, + "quantity": kill_house_auction_winner.quantity + } + }) + else: + process.update({"kill_house_winner": None + }) + + province_request_auctions = ProvinceRequestAction.objects.filter(poultry_request=instance, state='active', + trash=False) + if province_request_auctions.count() > 0: + province_request_auction_list = [] + for province_request_auction in province_request_auctions: + internal_dict_province_request_auction_list = { + "fullname": province_request_auction.province_operator_system.user.fullname, + "mobile": province_request_auction.province_operator_system.user.mobile, + "city": province_request_auction.province_operator_system.user.city.name, + "province": province_request_auction.province_operator_system.user.province.name, + } + province_request_auction_list.append(internal_dict_province_request_auction_list) + process.update({"province_request_auction_list": province_request_auction_list}) + else: + process.update({"province_request_auction_list": None}) + + poultry_assignment = PoultryAssignmentInformation.objects.filter(poultry_request=instance, trash=False) + + if poultry_assignment.count() > 0: + poultry_bar_list = [] + for bar in poultry_assignment: + internal_poultry_bar = { + "poultry_bar_info_key": bar.key, + "car_weight_without_load": bar.car_weight_without_load, + "car_weight_without_load_image": bar.car_weight_without_load_image, + "car_weight_with_load": bar.car_weight_with_load, + "car_weight_with_load_image": bar.car_weight_with_load_image, + "net_weight": bar.net_weight, + } + poultry_bar_list.append(internal_poultry_bar) + + process.update({"poultry_bar_info": poultry_bar_list}) + if not poultry_assignment: + process.update({"poultry_bar_info": None}) + + city = CityOperatorCheckRequest.objects.filter(poultry_request=instance, trash=False) + if city: + process.update({"city": { + "city_operator_name": city[0].city_operator_system.user.fullname, + "city_operator_mobile": city[0].city_operator_system.user.mobile, + "city_operator_province": city[0].city_operator_system.address.province.name, + "city_operator_city": city[0].city_operator_system.address.city.name, + "city_operator_address": city[0].city_operator_system.address.address, + "city_operator_national_id": city[0].city_operator_system.user.national_id, + "city_state": city[0].state, + "province_accept": city[0].province_accept, + "accepted_rejected_date": city[0].create_date, + "city_operator_message": city[0].message, + "unit_name": city[0].city_operator_system.unit_name, + + }}) + if not city: + process.update({"city": None}) + # cit = CityUnit.objects.filter(name=instance.poultry.address.city.name, trash=False) + # if cit.count() > 0: + # city_operator = CityOperator.objects.get(address__city=cit[0].city, trash=False) + city_operator = CityOperator.objects.get(key=instance.city_operator.key, trash=False) + + process.update({"city_operator": { + "city_operator_name": city_operator.user.fullname, + "city_operator_mobile": city_operator.user.mobile, + "city_operator_province": city_operator.address.province.name, + "city_operator_city": city_operator.address.city.name, + "city_operator_address": city_operator.address.address, + "city_operator_national_id": city_operator.user.national_id, + "unit_name": city_operator.unit_name, + + }}) + + province = ProvinceCheckOperatorRequest.objects.filter(poultry_request=instance, + trash=False) + if province: + process.update({"province": { + "province_check_request_key": province[0].key, + "province_operator_name": province[0].province_operator_system.user.fullname, + "province_operator_mobile": province[0].province_operator_system.user.mobile, + "province_operator_provinc": province[0].province_operator_system.address.province.name, + "province_operator_city": province[0].province_operator_system.address.city.name, + "province_operator_address": province[0].province_operator_system.address.address, + "province_operator_national_id": province[0].province_operator_system.user.national_id, + "province_state": province[0].state, + "chicken_price": province[0].fee, + "province_message": province[0].message, + "accepted_rejected_date": province[0].create_date, + }}) + if not province: + process.update({"province": None}) + role = Group.objects.get(name='ProvinceOperator') + province_operator = ProvinceOperator.objects.get(address__province__name=instance.poultry.address.province.name, + user__role=role, trash=False) + process.update({"province_operator": { + "province_operator_name": province_operator.user.fullname, + "province_operator_mobile": province_operator.user.mobile, + "province_operator_provinc": province_operator.address.province.name, + "province_operator_city": province_operator.address.city.name, + "province_operator_address": province_operator.address.address, + "province_operator_national_id": province_operator.user.national_id, + }}) + + if ProvinceFactorToKillHouseForPoultry.objects.filter(province_check_req=province.last()).exists(): + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_req=province.last()).last() + if poultry_factor.bank != None: + name_of_bank_user_poultry = poultry_factor.bank.name_of_bank_user + bank_name_poultry = poultry_factor.bank.bank_name + card_poultry = poultry_factor.bank.card + shaba_poultry = poultry_factor.bank.shaba + account_poultry = poultry_factor.bank.account + else: + name_of_bank_user_poultry = None + bank_name_poultry = None + card_poultry = None + shaba_poultry = None + account_poultry = None + process.update({"poultry_factor": { + "poultry_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_req.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_req.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares, + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "name_of_bank_user": name_of_bank_user_poultry, + "bank_name": bank_name_poultry, + "card": card_poultry, + "shaba": shaba_poultry, + "account": account_poultry, + }}) + else: + process.update({"poultry_factor": None}) + + if ProvinceFactorToKillHouse.objects.filter(province_check_req=province.last()).exists(): + province_factor = ProvinceFactorToKillHouse.objects.filter(province_check_req=province.last()).last() + if province_factor.bank != None: + name_of_bank_user_province_factor = province_factor.bank.name_of_bank_user + bank_name_province_factor = province_factor.bank.bank_name + card_province_factor = province_factor.bank.card + shaba_province_factor = province_factor.bank.shaba + account_province_factor = province_factor.bank.account + else: + name_of_bank_user_province_factor = None + bank_name_province_factor = None + card_province_factor = None + shaba_province_factor = None + account_province_factor = None + + process.update({"province_factor": { + "province_factor_key": province_factor.key, + "province_factor_fee": province_factor.factor_fee, + "province_operator": province_factor.province_check_req.province_operator_system.user.fullname, + "province_mobile": province_factor.province_check_req.province_operator_system.user.mobile, + "weight": province_factor.total_weight, + "cost": province_factor.total_price, + "union_share_with_profit": province_factor.shares, + "total_amount_char": words(province_factor.total_price) + " " + "ریال", + "name_of_bank_user": name_of_bank_user_province_factor, + "bank_name": bank_name_province_factor, + "card": card_province_factor, + "shaba": shaba_province_factor, + "account": account_province_factor, + }}) + else: + process.update({"province_factor": None}) + + if ProvinceImportKillHouseOutFactors.objects.filter(province_check=province.last()).exists(): + payment_out_factors = ProvinceImportKillHouseOutFactors.objects.filter(province_check=province.last()) + interal_factor_list = [] + for payment_out_factor in payment_out_factors: + internal_dict = { + "key": payment_out_factor.key, + "amount": payment_out_factor.amount, + "image": payment_out_factor.image, + } + interal_factor_list.append(internal_dict) + process.update({"out_factors": interal_factor_list}) + else: + process.update({"out_factors": None}) + + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=instance, trash=False) + + if province_kill_reqs.count() > 0: + state_list = [] + for province_kill_req in province_kill_reqs: + state_list.append(province_kill_req.payment_type) + l1 = set(state_list) + if len(l1) > 1: + process.update({"file_payment_type": "cash_credit"}) + else: + process.update({"file_payment_type": state_list[0]}) + + province_kill_reqs_list = [] + for province_kill_req in province_kill_reqs: + internal_province_kill_dict_infos = { + "province_kill_req_key": province_kill_req.key, + "payment_type": province_kill_req.payment_type, + "payment_dead_line": province_kill_req.payment_dead_line, + "kill_req_key": province_kill_req.kill_request.key, + "province_kill_req_state": province_kill_req.state, + "kill_house_name": province_kill_req.kill_request.kill_house.name, + "kill_house_user_name": province_kill_req.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": province_kill_req.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_mobile": province_kill_req.kill_request.kill_house.kill_house_operator.user.mobile, + "kill_house_user_province": province_kill_req.kill_request.kill_house.kill_house_operator.user.province.name, + "kill_house_user_national_id": province_kill_req.kill_request.kill_house.kill_house_operator.user.national_id, + "quantity": province_kill_req.quantity, + "time": province_kill_req.kill_request.recive_time, + "date": province_kill_req.kill_request.recive_date, + "automatic_state": province_kill_req.automatic, + "fee": province_kill_req.fee, + "province_kill_req_message": province_kill_req.message + } + + kill_house_requests = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=instance, + province_kill_request=province_kill_req, trash=False) + if kill_house_requests.count() > 0: + reqs = [] + for kill_house_request in kill_house_requests: + province_req = kill_house_request.province_request + internal_dict_infos = { + "kill_house_req_key": kill_house_request.key, + "payment_type": province_kill_req.payment_type, + "payment_dead_line": province_kill_req.payment_dead_line, + "province_fee": province_kill_req.fee, + "kill_house_vet_state": kill_house_request.vet_state, + "kill_req_key": kill_house_request.kill_request.key, + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_request.kill_house.name, + "kill_house_user_name": kill_house_request.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_province": kill_house_request.kill_request.kill_house.kill_house_operator.user.province.name, + "kill_house_user_city": kill_house_request.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_user_address": kill_house_request.kill_request.kill_house.system_address.address, + "kill_house_mobile": kill_house_request.kill_request.kill_house.kill_house_operator.user.mobile, + "kill_house_national_id": kill_house_request.kill_request.kill_house.kill_house_operator.user.national_id, + "quantity": kill_house_request.quantity, + "fee": kill_house_request.province_kill_request.fee, + "time": kill_house_request.kill_request.recive_time, + "date": kill_house_request.kill_request.recive_date, + "cars": kill_house_request.car, + "driver_name": kill_house_request.add_car.driver.driver_name, + "capocity": kill_house_request.add_car.driver.capocity, + "type_car": kill_house_request.add_car.driver.type_car, + "pelak": kill_house_request.add_car.driver.pelak, + "clearance_code": kill_house_request.clearance_code, + "traffic_code": kill_house_request.traffic_code, + "show_kill_house": kill_house_request.show_kill_house, + "kill_house_message": kill_house_request.kill_house_message + } + + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request, trash=False) + if vet_check: + internal_dict_infos.update({ + "vet_check_info": { + "vet_user": vet_check[0].kill_house_vet.vet.user.fullname, + "vet_user_mobile": vet_check[0].kill_house_vet.vet.user.mobile, + "vet_check_state": vet_check[0].state, + "vet_check_accept_date": vet_check[0].create_date, + } + }) + if not vet_check: + internal_dict_infos.update({ + "vet_check_info": None + }) + kill_house_assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_check__province_kill_request__province_request=province_req, + kill_house_request=kill_house_request, trash=False) + if kill_house_assignment: + internal_dict_infos.update({ + "bar_info": { + "kill_house_assignment_key": kill_house_assignment[0].key, + "real_quantity": kill_house_assignment[0].real_quantity, + "kill_house_weight_without_load": kill_house_assignment[0].car_weight_without_load, + "kill_house_weight_with_load": kill_house_assignment[0].car_weight_with_load, + "kill_house_image_without_load": kill_house_assignment[ + 0].car_weight_without_load_image, + "kill_house_image_with_load": kill_house_assignment[0].car_weight_with_load_image, + "kill_house_net_weight": kill_house_assignment[0].net_weight, + "expire_time": kill_house_assignment[0].protest_time, + "kill_house_assignment_state": kill_house_assignment[0].state, + "kill_house_assignment_message": kill_house_assignment[0].message, + "accept_reject_date": kill_house_assignment[0].modify_date, + "unusual_casualties": kill_house_assignment[0].unusual_casualties, + + } + }) + complaint = KillHouseComplaint.objects.filter(bar=kill_house_assignment[0], trash=False) + percentage_losses = PercentageOfLosses.objects.all() + if percentage_losses.count() > 0: + percentage_losses = percentage_losses.last().percent + else: + percentage_losses = None + + if complaint.count() > 0: + complaint = complaint.last() + check_complaint = CheckUnusualCasualties.objects.filter(complaint=complaint) + if check_complaint.count() > 0: + reviewer = check_complaint.last().role + else: + reviewer = None + internal_dict_infos.update({ + "complaint": { + "complaint_key": complaint.key, + "create_date": complaint.create_date, + "title": complaint.title, + "description": complaint.description, + "percent": complaint.percent, + "image": complaint.image, + "state": complaint.state, + "message": complaint.message, + "registrar": complaint.registrar, + "reviewer": reviewer, + "real_weight": kill_house_assignment[0].net_weight, + "losses_weight": kill_house_assignment[0].weight_withs_losses, + "percentage_losses": percentage_losses, + } + }) + else: + internal_dict_infos.update({ + "complaint": None + }) + if not kill_house_assignment: + internal_dict_infos.update({ + "bar_info": None + }) + internal_dict_infos.update({ + "complaint": None + }) + + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if poultry_factor.count() > 0: + poultry_factor = poultry_factor.last() + if poultry_factor.bank != None: + name_of_bank_user = poultry_factor.bank.name_of_bank_user + bank_name = poultry_factor.bank.bank_name + card = poultry_factor.bank.card, + shaba = poultry_factor.bank.shaba, + account = poultry_factor.bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": { + "province_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "bar_code": poultry_factor.factor_bar_code, + "kill_house_name": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares[ + 'poultryShareWithProfit'], + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "total_share_allocation": poultry_factor.total_weight * total, + "total_share_allocation_char": words( + poultry_factor.total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not poultry_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": None + }) + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if province_factor: + if province_factor[0].bank != None: + name_of_bank_user = province_factor[0].bank.name_of_bank_user + bank_name = province_factor[0].bank.bank_name + card = province_factor[0].bank.card, + shaba = province_factor[0].bank.shaba, + account = province_factor[0].bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + if province_factor[0].poultry_factor == None: + poultry_share_with_profit = province_factor[0].shares['poultryShareWithProfit'] + else: + poultry_share_with_profit = province_factor[0].poultry_factor.total_price + + internal_dict_infos.update({ + "province_factor_to_kill_house": { + "province_factor_key": province_factor[0].key, + "province_factor_fee": province_factor[0].factor_fee, + "province_operator": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": province_factor[0].total_weight, + "bar_code": province_factor[0].factor_bar_code, + "kill_house_name": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": province_factor[0].total_price, + "poultry_share_with_profit": poultry_share_with_profit, + "union_share_with_profit": province_factor[0].shares['unionShareWithProfit'], + "total_amount_char": words(province_factor[0].total_price) + " " + "ریال", + "total_share_allocation": province_factor[0].total_weight * total, + "total_share_allocation_char": words( + province_factor[0].total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not province_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house": None + }) + kill_house_factor_poultry = KillHouseFactorToPoultry.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor_poultry.count(): + kill_house_factor_poultry = kill_house_factor_poultry.last() + internal_dict_infos.update({ + "kill_house_factor_to_poultry": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor_poultry.create_date, + "payment_code": kill_house_factor_poultry.payment_code, + "factor_image": kill_house_factor_poultry.factor_image, + "factor_key": kill_house_factor_poultry.key, + "factor_state": kill_house_factor_poultry.state, + "total_money": kill_house_factor_poultry.province_factor.total_price, + "factor_message": kill_house_factor_poultry.message + } + }) + if not kill_house_factor_poultry: + internal_dict_infos.update({ + "kill_house_factor_to_poultry": None + }) + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor[0].create_date, + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "factor_key": kill_house_factor[0].key, + "factor_state": kill_house_factor[0].state, + "total_money": kill_house_factor[0].province_factor.total_price, + "factor_message": kill_house_factor[0].message + } + }) + if not kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": None + }) + + reqs.append(internal_dict_infos) + internal_province_kill_dict_infos.update({"kill_house_requests": reqs + + }) + if not kill_house_requests: + internal_province_kill_dict_infos.update({"kill_house_requests": None + + }) + + province_kill_reqs_list.append(internal_province_kill_dict_infos) + process.update({"province_kill_requests": province_kill_reqs_list}) + + if not province_kill_reqs: + process.update({"province_kill_requests": None + + }) + + kill_house_reqs = KillHouseRequest.objects.filter( + kill_house_request_auction_winner__kill_house_request_auction__poultry_request=instance, trash=False) + if kill_house_reqs.count() > 0: + + reqs = [] + for kill_house_request in kill_house_reqs: + province_req = kill_house_request.province_request + internal_dict_infos = { + "kill_house_req_key": kill_house_request.key, + "kill_house_vet_state": kill_house_request.vet_state, + "order_code": instance.order_code, + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_user_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.fullname, + "kill_house_user_province": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.province.name, + "kill_house_user_city": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.city.name, + "kill_house_user_address": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.system_address.address, + "kill_house_mobile": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "kill_house_national_id": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.national_id, + "quantity": kill_house_request.quantity, + # "time": kill_house_request.kill_request.recive_time, + # "date": kill_house_request.kill_request.recive_date, + "cars": kill_house_request.car, + "driver_name": kill_house_request.add_car.driver.driver_name, + "type_car": kill_house_request.add_car.driver.type_car, + "pelak": kill_house_request.add_car.driver.pelak, + "clearance_code": kill_house_request.clearance_code, + "traffic_code": kill_house_request.traffic_code, + "show_kill_house": kill_house_request.show_kill_house, + "kill_house_message": kill_house_request.kill_house_message + } + + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request, trash=False) + if vet_check: + internal_dict_infos.update({ + "vet_check_info": { + "vet_user": vet_check[0].kill_house_vet.vet.user.fullname, + "vet_user_mobile": vet_check[0].kill_house_vet.vet.user.mobile, + "vet_check_state": vet_check[0].state, + "vet_check_accept_date": vet_check[0].create_date, + } + }) + if not vet_check: + internal_dict_infos.update({ + "vet_check_info": None + }) + kill_house_assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False) + if kill_house_assignment: + internal_dict_infos.update({ + "bar_info": { + "kill_house_assignment_key": kill_house_assignment[0].key, + "real_quantity": kill_house_assignment[0].real_quantity, + "kill_house_weight_without_load": kill_house_assignment[0].car_weight_without_load, + "kill_house_weight_with_load": kill_house_assignment[0].car_weight_with_load, + "kill_house_image_without_load": kill_house_assignment[ + 0].car_weight_without_load_image, + "kill_house_image_with_load": kill_house_assignment[0].car_weight_with_load_image, + "kill_house_net_weight": kill_house_assignment[0].net_weight, + "expire_time": kill_house_assignment[0].protest_time, + "kill_house_assignment_state": kill_house_assignment[0].state, + "kill_house_assignment_message": kill_house_assignment[0].message, + "accept_reject_date": kill_house_assignment[0].modify_date + + } + }) + complaint = KillHouseComplaint.objects.filter(bar=kill_house_assignment[0], trash=False) + if complaint.count() > 0: + complaint = complaint.last() + internal_dict_infos.update({ + "complaint": { + "complaint_key": complaint.key, + "title": complaint.title, + "description": complaint.description, + "percent": complaint.percent, + "image": complaint.image, + "state": complaint.state, + "message": complaint.message, + } + }) + else: + internal_dict_infos.update({ + "complaint": None + }) + if not kill_house_assignment: + internal_dict_infos.update({ + "bar_info": None + }) + internal_dict_infos.update({ + "complaint": None + }) + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=instance, + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, trash=False) + if poultry_factor.count() > 0: + poultry_factor = poultry_factor.last() + if poultry_factor.bank != None: + name_of_bank_user = poultry_factor.bank.name_of_bank_user + bank_name = poultry_factor.bank.bank_name + card = poultry_factor.bank.card, + shaba = poultry_factor.bank.shaba, + account = poultry_factor.bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": { + "province_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "bar_code": poultry_factor.factor_bar_code, + "kill_house_name": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares[ + 'poultryShareWithProfit'], + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "total_share_allocation": poultry_factor.total_weight * total, + "total_share_allocation_char": words( + poultry_factor.total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not poultry_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": None + }) + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=instance, + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, trash=False) + if province_factor: + if province_factor[0].bank != None: + name_of_bank_user = province_factor[0].bank.name_of_bank_user + bank_name = province_factor[0].bank.bank_name + card = province_factor[0].bank.card, + shaba = province_factor[0].bank.shaba, + account = province_factor[0].bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + # if poultry_factor == None: + if province_factor[0].poultry_factor == None: + poultry_share_with_profit = province_factor[0].shares['poultryShareWithProfit'] + else: + poultry_share_with_profit = province_factor[0].poultry_factor.total_price + province_operator = province_factor[0].province_check_info.province_operator + internal_dict_infos.update({ + "province_factor_to_kill_house": { + "province_factor_key": province_factor[0].key, + "province_factor_fee": province_factor[0].factor_fee, + "province_operator": province_operator.user.fullname, + "province_mobile": province_operator.user.mobile, + "weight": province_factor[0].total_weight, + "bar_code": province_factor[0].factor_bar_code, + "kill_house_name": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "cost": province_factor[0].total_price, + "poultry_share_with_profit": poultry_share_with_profit, + "union_share_with_profit": province_factor[0].shares['unionShareWithProfit'], + "total_amount_char": words(province_factor[0].total_price) + " " + "ریال", + "total_share_allocation": province_factor[0].total_weight * total, + "total_share_allocation_char": words( + province_factor[0].total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not province_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house": None + }) + + kill_house_factor_poultry = KillHouseFactorToPoultry.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=instance, + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor_poultry.count(): + kill_house_factor_poultry = kill_house_factor_poultry.last() + internal_dict_infos.update({ + "kill_house_factor_to_poultry": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor_poultry.create_date, + "payment_code": kill_house_factor_poultry.payment_code, + "factor_image": kill_house_factor_poultry.factor_image, + "factor_key": kill_house_factor_poultry.key, + "factor_state": kill_house_factor_poultry.state, + "total_money": kill_house_factor_poultry.province_factor.total_price, + "factor_message": kill_house_factor_poultry.message + } + }) + if not kill_house_factor_poultry: + internal_dict_infos.update({ + "kill_house_factor_to_poultry": None + }) + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=instance, + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor[0].create_date, + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "factor_key": kill_house_factor[0].key, + "factor_state": kill_house_factor[0].state, + "total_money": kill_house_factor[0].province_factor.total_price, + "factor_message": kill_house_factor[0].message + } + }) + if not kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": None + }) + + reqs.append(internal_dict_infos) + process.update({"auction": reqs}) + + if not kill_house_reqs: + process.update({"auction": None}) + + allocation = DepositAllocation.objects.filter(poultry=instance, trash=False) + if instance.poultry.user_bank_info != None: + poultry_bank_info = instance.poultry.user_bank_info.name_of_bank_user + poultry_bank_name = instance.poultry.user_bank_info.bank_name + poultry_card_number = instance.poultry.user_bank_info.card + poultry_shaba = instance.poultry.user_bank_info.shaba + else: + poultry_bank_info = None + poultry_bank_name = None + poultry_card_number = None + poultry_shaba = None + + if city_operator.user_bank_info != None: + city_bank_info = city_operator.user_bank_info.name_of_bank_user + city_bank_name = city_operator.user_bank_info.bank_name + city_card_number = city_operator.user_bank_info.card + city_shaba = city_operator.user_bank_info.shaba + else: + city_bank_info = None + city_bank_name = None + city_card_number = None + city_shaba = None + financial_operator = SystemUserProfile.objects.filter(role__name='ProvinceFinancial', + province__name=instance.poultry.address.province.name) + if financial_operator.count() > 0: + operator = ProvinceOperator.objects.get(user=financial_operator.last()) + if operator.user_bank_info != None: + province_bank_info = operator.user_bank_info.name_of_bank_user + province_bank_name = operator.user_bank_info.bank_name + province_card_number = operator.user_bank_info.card + province_shaba = operator.user_bank_info.shaba + else: + province_bank_info = None + province_bank_name = None + province_card_number = None + province_shaba = None + + if allocation.count() > 0: + fee = 0 + process.update({"allocation": {"allocation_key": allocation[0].key, + "fee": fee, + "total_money": allocation[0].poultry_share + allocation[ + 0].city_share + allocation[0].province_share + allocation[ + 0].company_share + allocation[ + 0].central_union_share + allocation[ + 0].fanava_share, + "total_money_char": words( + allocation[0].poultry_share + allocation[ + 0].city_share + allocation[0].province_share + + allocation[ + 0].company_share + allocation[ + 0].central_union_share + allocation[ + 0].fanava_share) + " " + 'ریال', + "poultry_share_digit": allocation[0].poultry_share, + "poultry_share_char": words( + allocation[0].poultry_share) + " " + 'ریال', + "poultry_share_payment": allocation[0].poultry_share_payment, + "poultry_remaining": (allocation[0].poultry_share - allocation[ + 0].poultry_share_payment), + "poultry_payment_documents": allocation[0].poultry_share_payment_info, + "poultry_bank_info": poultry_bank_info, + "poultry_bank_name": poultry_bank_name, + "poultry_card_number": poultry_card_number, + "poultry_shaba": poultry_shaba, + "poultry_image": allocation[0].poultry_image, + "city_share_digit": allocation[0].city_share, + "city_share_char": words( + allocation[0].city_share) + " " + 'ریال', + "city_image": allocation[0].city_image, + "city_bank_info": city_bank_info, + "city_bank_name": city_bank_name, + "city_card_number": city_card_number, + "city_shaba": city_shaba, + "city_share_payment": allocation[0].city_share_payment, + "city_share_remaining": ( + allocation[0].city_share - allocation[0].city_share_payment), + "city_payment_documents": allocation[0].city_share_payment_info, + "province_share_digit": allocation[0].province_share, + "province_share_char": words( + allocation[0].province_share) + " " + 'ریال', + "province_share_payment": allocation[0].province_share_payment, + "province_share_remaining": (allocation[0].province_share - allocation[ + 0].province_share_payment), + "province_payment_documents": allocation[0].province_share_payment_info, + "province_bank_info": province_bank_info, + "province_bank_name": province_bank_name, + "province_card_number": province_card_number, + "province_shaba": province_shaba, + "company_share_digit": allocation[0].company_share, + "company_share_char": words( + allocation[0].company_share) + " " + 'ریال', + "company_share_payment": allocation[0].company_share_payment, + "company_share_remaining": (allocation[0].company_share - allocation[ + 0].company_share_payment), + "company_payment_documents": allocation[0].company_share_payment_info, + "company_bank_info": '************', + "company_bank_name": '************', + "company_card_number": '**************', + "company_shaba": '************', + "central_union_share_digit": allocation[0].central_union_share, + "central_union_share_char": words( + allocation[0].central_union_share) + " " + 'ریال', + "central_union_share_payment": allocation[0].central_union_share_payment, + "central_union_share_remaining": ( + allocation[0].central_union_share - allocation[ + 0].central_union_share_payment), + "central_union_payment_documents": allocation[ + 0].central_union_share_payment_info, + "central_union_bank_info": '************', + "central_union_bank_name": '************', + "central_union_card_number": '**************', + "central_union_shaba": '************', + "fanava_share_digit": allocation[0].fanava_share, + "fanava_share_share_char": words( + allocation[0].fanava_share) + " " + 'ریال', + "fanava_share_payment": allocation[0].fanava_share_payment, + "fanava_share_remaining": ( + allocation[0].fanava_share - allocation[0].fanava_share_payment), + "fanava_payment_documents": allocation[0].fanava_share_payment_info, + "fanava_bank_info": '************', + "fanava_bank_name": '************', + "fanava_card_number": '**************', + "fanava_shaba": '************', + + }}) + + if not allocation: + process.update({"allocation": None}) + + province_incpector = PovinceInspector.objects.filter(poultry_request=instance, trash=False) + if province_incpector: + process.update( + {"province_incpector": {"inspector_name": province_incpector[0].inspector_operator.user.fullname, + "state": province_incpector[0].state, + "message": province_incpector[0].message, + "accept-reject-date": province_incpector[0].create_date, }}) + if not province_incpector: + province_name = instance.poultry.address.province.name + inspector = InspectorOperator.objects.get(address__province__name=province_name, trash=False) + process.update({"province_incpector": {"province_incpector": None, + "state": 'pending', + "inspector_name": inspector.user.fullname, + "inspector_mobile": inspector.user.mobile, + "inspector_address": inspector.address.province.name}}) + + return process + + +# سریالایزر مربوط به درخواست مزایده مرغدار +class PoultryRequestAuctionSerializer(serializers.ModelSerializer): + poultry_request = PoultryRequestSerializer(read_only=True) + + class Meta: + model = PoultryRequestAuction + fields = '__all__' + + +# سریالایزر مربوط به ورود اطلاعات بار برای بارهای اختصاص یافته به درخواست مرغدار + +class PoultryAssignmentInformationSerializer(serializers.ModelSerializer): + class Meta: + model = PoultryAssignmentInformation + fields = '__all__' + + +class LastUpdateSerializer(serializers.ModelSerializer): + class Meta: + model = LastUpdate + fields = '__all__' + + +class PoultryHatchingForLocSerializer(serializers.ModelSerializer): + class Meta: + model = PoultryHatching + fields = ('left_over', 'chicken_age', 'date', + 'licence_number','killed_quantity','total_losses','quantity') + + +class PoultryLocationSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryLocSerializer(read_only=True) + address = SystemAddressForLocSerializer(required=False) + hatching = serializers.SerializerMethodField() + + class Meta: + model = Poultry + fields = [ + 'id', 'unit_name', 'Lat', 'Long', 'user', 'hatching', 'address', 'breeding_unique_id' + ] + + def get_hatching(self, instance): + serilizer = PoultryHatchingForLocSerializer(instance.poultry_hatching_user, many=True).data + return serilizer + + +class SystemUserProfileForAutoAllocationSerializerForGetAllPoultry(serializers.ModelSerializer): + class Meta: + model = SystemUserProfile + fields = ['fullname', 'mobile'] + + +class SystemAddressSerializerForGetAllPoultry(serializers.ModelSerializer): + city = CityForLocSerializer(required=False) + + class Meta: + model = SystemAddress + fields = ['city'] + + +class GetAllPoultrySerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializerForGetAllPoultry(read_only=True) + address = SystemAddressSerializerForGetAllPoultry(required=False) + last_hatching_remain_quantity = serializers.SerializerMethodField() + province_allow_sell_free = serializers.SerializerMethodField() + chain_company = serializers.SerializerMethodField() + + class Meta: + model = Poultry + fields = ['user', 'key', 'unit_name', 'address', 'last_hatching_remain_quantity', 'province_allow_sell_free', + 'chain_company'] + + def get_last_hatching_remain_quantity(self, obj): + poultry_data = self.context.get('poultry_remain_dict', {}).get(obj.id, {}) + return poultry_data.get('last_hatching_remain_quantity', 0) + + def get_province_allow_sell_free(self, obj): + poultry_data = self.context.get('poultry_remain_dict', {}).get(obj.id, {}) + return poultry_data.get('allow_sell_free') + + def get_chain_company(self, obj): + poultry_data = self.context.get('poultry_remain_dict', {}).get(obj.id, {}) + return poultry_data.get('chain_company') + + +class PoultryPredictionSerializer(serializers.ModelSerializer): + poultry = PoultryForPredictionSerializer(required=False) + + class Meta: + model = PoultryPrediction + fields = ['key', 'poultry', 'date', 'killing_ave_age', 'active_left_over', 'killing_ave_count', + 'killing_ave_weight', + 'killing_loss_weight_percent'] + + +class HatchingIncreaseRequestSerializer(serializers.ModelSerializer): + hatching = PoultryHatchingForChainAllocationSerializer(read_only=True) + + class Meta: + model = HatchingIncreaseRequest + fields = "__all__" + + +class EvacuationHatchingDetailSerializer(serializers.ModelSerializer): + hatching = PoultryHatchingSerializer(read_only=True) + + class Meta: + model = EvacuationHatchingDetail + fields = '__all__' + + +class ChickenCommissionPricesSerializer(serializers.ModelSerializer): + price_info = serializers.SerializerMethodField() + + class Meta: + model = ChickenCommissionPrices + fields = "__all__" + + def get_price_info(self, obj): + kill_house_price = round( + ((obj.chicken_average_price + obj.kill_house_price) / 750) * 1000) if obj.chicken_average_price else 0 + return { + "killHousePrice": kill_house_price, + "wholesalePrice": kill_house_price + obj.wholesaler_price if obj.chicken_average_price else 0, + "retailPrice": kill_house_price + obj.retailer_price if obj.chicken_average_price else 0, + } + + +class ChickenCommissionPricesForDashboardSerializer(serializers.ModelSerializer): + price_info = serializers.SerializerMethodField() + + class Meta: + model = ChickenCommissionPrices + fields = ['chicken_average_price', 'price_info', 'date'] + + def get_price_info(self, obj): + kill_house_price = round( + ((obj.chicken_average_price + obj.kill_house_price) / 750) * 1000) if obj.chicken_average_price else 0 + return { + "killHousePrice": kill_house_price, + "wholesalePrice": kill_house_price + obj.wholesaler_price if obj.chicken_average_price else 0, + "retailPrice": kill_house_price + obj.retailer_price if obj.chicken_average_price else 0, + } + + +class PoultryRequestQuarantineCodeSerializer(serializers.ModelSerializer): + class Meta: + model = PoultryRequestQuarantineCode + fields = ['key', 'quarantine_code', 'traffic_code', 'quarantine_quantity', 'registrar', 'register_date', + 'system_quarantine_quantity'] + + +class PoultryForDetailsSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryLocSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + class Meta: + model = Poultry + fields = [ + 'unit_name', 'user', 'address', 'breeding_unique_id' + ] + + +class PoultryHatchingForDetailsSerializer(serializers.ModelSerializer): + killing_info = serializers.SerializerMethodField() + active_kill = serializers.SerializerMethodField() + vet_farm = serializers.SerializerMethodField() + killing_ave_age = serializers.SerializerMethodField() + poultry = PoultryForDetailsSerializer(read_only=True) + + class Meta: + model = PoultryHatching + fields = ('violation', 'licence_number', 'breeding_unique_id', 'CertId', 'poultry', 'InteractTypeName', + 'UnionTypeName', 'hall', 'period', 'create_date', 'date', 'predicate_date', 'chicken_breed', + 'chicken_age', + 'quantity', 'PersonTypeName', 'increase_quantity', 'losses', 'direct_losses', 'total_losses', + 'total_commitment_quantity', 'total_free_commitment_quantity', 'governmental_quantity', + 'free_quantity', 'free_killed_quantity', 'out_province_killed_quantity', 'out_province_killed_weight', + 'killing_info', 'killed_quantity', 'left_over', 'samasat_discharge_percentage', 'total_commitment', + 'total_average_killed_weight', 'total_killed_weight', 'active_kill', 'export_killed_quantity', + 'export_killed_weight', 'vet_farm', 'latest_hatching_change', 'violation', 'killing_ave_age', + 'poultry','bar_difference_request_quantity','bar_difference_request_weight') + + def get_vet_farm(self, instance): + vet = { + "vet_farm_full_name": 'ندارد', + "vet_farm_mobile": '', + } + vet_farm = VetFarm.objects.filter(poultry=instance.poultry) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + vet = { + "vet_farm_full_name": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile, + } + + return vet + + def get_killing_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + province_request__poultry_request__hatching=obj) + return_province_kill_requests = ProvinceKillRequest.objects.filter(trash=True, return_trash=True,return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + province_request__poultry_request__hatching=obj) + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + + return_province_kill_requests_quantity = \ + return_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + return_province_kill_requests_weight = \ + return_province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=obj) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + return_kill_house_requests = KillHouseRequest.objects.filter(trash=True, return_trash=True,province_request__poultry_request__hatching=obj) + + return_kill_house_weight = return_kill_house_requests.aggregate( + total_quantity=Sum('accepted_real_weight')).get('total_quantity') or 0 + + return_kill_house_quantity = return_kill_house_requests.aggregate( + total_quantity=Sum('accepted_real_quantity')).get('total_quantity') or 0 + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + return { + "violation_message": 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' if obj.violation else 'عادی', + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests": len(kill_house_requests), + "kill_house_requests_first_quantity": first_quantity, + "kill_house_requests_first_weight": first_weight, + "bar_complete_with_kill_house": len(bar_complete_with_kill_house), + "accepted_real_quantity_final": accepted_real_quantity_final, + "accepted_real_wight_final": accepted_real_wight_final, + "ware_house_bars": len(ware_house_bars), + "ware_house_bars_quantity": ware_house_bars_quantity, + "ware_house_bars_weight": ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + 'return_province_kill_requests_count': return_province_kill_requests.count(), + 'return_kill_house_requests_count': return_kill_house_requests.count(), + 'return_kill_house_weight': return_kill_house_weight, + 'return_kill_house_quantity': return_kill_house_quantity, + 'return_province_kill_requests_weight': return_province_kill_requests_weight, + 'return_province_kill_requests_quantity': return_province_kill_requests_quantity, + 'total_return_weight': return_province_kill_requests_weight + return_kill_house_weight, + 'total_return_quantity': return_province_kill_requests_quantity + return_kill_house_quantity, + 'total_sale_in_province_weight': int(province_kill_requests_weight + first_weight), + 'total_sale_in_province_quantity': province_kill_requests_quantity + first_quantity, + } + + def get_killing_ave_age(self, obj): + return obj.poultry.killing_ave_age + + def get_active_kill(self, instance): + + active_kill = False + count_of_request = 0 + + province_kill_request = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=instance, + state='accepted') + if province_kill_request.count() > 0: + count_of_request = province_kill_request.count() + + if ProvinceKillRequest.objects.filter(trash=False, province_request__poultry_request__hatching=instance, + state='pending').exists(): + active_kill = True + info = { + "active_kill": active_kill, + "count_of_request": count_of_request, + } + + return info + + +class PoultryRequestForHatchingDetailSerializer(serializers.ModelSerializer): + weight = serializers.SerializerMethodField() + + class Meta: + model = PoultryRequest + fields = ['order_code', 'send_date', 'buyer_fullname', 'buyer_mobile', 'buyer_province', 'buyer_city', + 'quarantine_code', 'quarantine_quantity', 'quantity', 'weight','killing_age'] + + def get_weight(self, obj): + return int(obj.quantity * obj.Index_weight) + + +class ChainAllocationForHatchingDetailSerializer(serializers.ModelSerializer): + chain_company = ChainCompanySerializer(read_only=True) + kill_house = KillHouseForChainAllocationSerializer(read_only=True) + + class Meta: + model = ChainAllocation + fields = '__all__' + + +class PoultryHatchingForBazrasiSerializer(serializers.ModelSerializer): + # poultry = PoultrySerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + age = serializers.SerializerMethodField('get_age') + inspection_losses = serializers.SerializerMethodField('get_inspection') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + active_kill = serializers.SerializerMethodField('get_active_kill') + killing_info = serializers.SerializerMethodField('get_killing_info') + free_governmental_info = serializers.SerializerMethodField('get_free_governmental_info') + + class Meta: + model = PoultryHatching + fields = '__all__' + + # تابع برای بدست آوردن سن مرع + def get_age(self, instance): + return instance.chicken_age + + def get_inspection(self, instance): + inspection = VetFarmInspection.objects.filter(poultry_hatching=instance) + if inspection.count() > 0: + inspections = 0 + for ins in inspection: + if ins.Losses == 0: + pass + else: + inspections += int(ins.Losses) + return inspections + + def get_vet_farm(self, instance): + vet = { + "vet_farm_full_name": 'ندارد', + "vet_farm_mobile": '', + } + vet_farm = VetFarm.objects.filter(poultry=instance.poultry).select_related('vet').only( + 'vet__user__fullname', 'vet__user__mobile' + ) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + vet = { + "vet_farm_full_name": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile, + } + + return vet + + def get_active_kill(self, instance): + active_kill = False + + count_of_request = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=instance, + state='accepted').count() + + if ProvinceKillRequest.objects.filter(trash=False, province_request__poultry_request__hatching=instance, + state='pending').exists(): + active_kill = True + info = { + "active_kill": active_kill, + "count_of_request": count_of_request, + } + + return info + + def get_killing_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + province_request__poultry_request__hatching=obj).only( + 'total_killed_quantity', + 'total_killed_weight' + ) + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=obj) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + return { + "violation_message": 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' if obj.violation else 'عادی', + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests": len(kill_house_requests), + "kill_house_requests_first_quantity": first_quantity, + "kill_house_requests_first_weight": first_weight, + "bar_complete_with_kill_house": len(bar_complete_with_kill_house), + "accepted_real_quantity_final": accepted_real_quantity_final, + "accepted_real_wight_final": accepted_real_wight_final, + "ware_house_bars": len(ware_house_bars), + "ware_house_bars_quantity": ware_house_bars_quantity, + "ware_house_bars_weight": ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + } + + def get_free_governmental_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=obj) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, final_state='archive', + hatching=obj) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = obj.left_over + + elif obj.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if obj.total_commitment_quantity == 0: + left_total_free_commitment_quantity = obj.left_over + else: + left_total_free_commitment_quantity = obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + return { + "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + "total_commitment_quantity": obj.total_commitment_quantity, + "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + "total_free_commitment_quantity": obj.total_free_commitment_quantity, + "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + + } + + + + +class PoultryRequestForDirectBuyingSerializer(serializers.ModelSerializer): + poultry = PoultryForDirectBuyingSerializer(read_only=True) + age = serializers.SerializerMethodField() + total_allocated = serializers.SerializerMethodField() + + class Meta: + model = PoultryRequest + fields = [ + 'key', + 'poultry', + 'age', + 'total_allocated', + 'Index_weight', + 'quantity', + 'chicken_breed', + 'send_date', + 'remain_quantity', + 'amount' + ] + + def get_age(self, obj): + age = (obj.send_date.date() - obj.hatching.date.date()).days + 1 + hatching_key = obj.hatching.key + return { + 'age':age, + 'hatching_key':hatching_key + } + + def get_total_allocated(self, obj): + return obj.quantity - obj.remain_quantity + + +class ManagementHatchingAgeRangeSerializer(serializers.ModelSerializer): + class Meta: + model = ManagementHatchingAgeRange + fields = '__all__' + + +class GetAllPoultryForPoultryScienceSerializer(serializers.ModelSerializer): + user = SystemUserProfileForAutoAllocationSerializerForGetAllPoultry(read_only=True) + address = SystemAddressSerializerForGetAllPoultry(required=False) + + class Meta: + model = Poultry + fields = ['id', 'user', 'key', 'unit_name', 'address'] + + +class PoultryDetailForPoultryScienceSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryScienceWithoutRoleSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + hatching = serializers.SerializerMethodField('get_hatching') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + hatching_info = serializers.SerializerMethodField('get_hatching_info') + + + class Meta: + model = Poultry + exclude = ( + 'create_date', + 'modify_date', + 'password', + 'created_by', + 'modified_by', + ) + + def get_vet_farm(self, instance): + internal_dictionary = {} + vet_farm = VetFarm.objects.filter(poultry=instance, trash=False) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + + internal_dictionary = { + "full_name": vet_farm.vet.user.fullname, + "mobile": vet_farm.vet.user.mobile, + "city": vet_farm.vet.user.city.name, + "province": vet_farm.vet.user.province.name, + + } + + return internal_dictionary + + def get_hatching(self, instance): + hatching_list = [] + for hatching in PoultryHatching.objects.filter(poultry=instance, state='pending', + allow_hatching='pending', archive=False, + trash=False): + age = (datetime.now().date() - hatching.date.date()).days + 1 + internal_dictionary = { + "poultry_key": hatching.poultry.key, + "poultry_hatching_key": hatching.key, + "poultry": hatching.poultry.unit_name, + "quantity": hatching.quantity, + "losses": hatching.losses, + "left_over": hatching.left_over, + "out_province_killed_quantity": hatching.out_province_killed_quantity, + "export_killed_quantity": hatching.export_killed_quantity, + "hall": hatching.hall, + "date": hatching.date, + "period": hatching.period, + "state": hatching.state, + "age": age, + "licence_number": hatching.licence_number, + + } + hatching_list.append(internal_dictionary) + + return hatching_list + + def get_hatching_info(self, obj): + hatching = PoultryHatching.objects.filter(poultry__exact=obj, state='pending', archive=False, + trash=False).last() + period = 0 + active_hatching = False + if hatching: + period = hatching.period + if hatching.state == 'pending': + active_hatching = True + return {"period": period, "active_hatching": active_hatching} + + +class PoultryDetailForPoultryAndHatchingForPoultryScienceSerializer(serializers.ModelSerializer): + user = SystemUserProfileForPoultryScienceWithoutRoleSerializer(read_only=True) + address = SystemAddressSerializer(read_only=True) + + + class Meta: + model = Poultry + exclude = ( + 'create_date', + 'modify_date', + 'password', + 'created_by', + 'modified_by', + ) + + +class PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer(serializers.ModelSerializer): + poultry = PoultryDetailForPoultryAndHatchingForPoultryScienceSerializer(read_only=True) + chain_company = ChainCompanySerializer(read_only=True) + age = serializers.SerializerMethodField('get_age') + inspection_losses = serializers.SerializerMethodField('get_inspection') + vet_farm = serializers.SerializerMethodField('get_vet_farm') + active_kill = serializers.SerializerMethodField('get_active_kill') + killing_info = serializers.SerializerMethodField('get_killing_info') + free_governmental_info = serializers.SerializerMethodField('get_free_governmental_info') + report_info = serializers.SerializerMethodField('get_report_info') + + class Meta: + model = PoultryHatching + fields = '__all__' + + def get_report_info(self, instance): + poultry_science = PoultryScienceReport.objects.filter(trash=False, hatching=instance).only('image').first() + image= False + has_poultry_science = False + if poultry_science: + has_poultry_science = True + if poultry_science.image: + image = True + result={ + 'poultry_science': has_poultry_science, + 'image':image, + } + return result + # تابع برای بدست آوردن سن مرع + def get_age(self, instance): + return instance.chicken_age + + def get_inspection(self, instance): + inspection = VetFarmInspection.objects.filter(poultry_hatching=instance) + if inspection.count() > 0: + inspections = 0 + for ins in inspection: + if ins.Losses == 0: + pass + else: + inspections += int(ins.Losses) + return inspections + + def get_vet_farm(self, instance): + vet = { + "vet_farm_full_name": 'ندارد', + "vet_farm_mobile": '', + } + vet_farm = VetFarm.objects.filter(poultry=instance.poultry).select_related('vet').only( + 'vet__user__fullname', 'vet__user__mobile' + ) + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + vet = { + "vet_farm_full_name": vet_farm.vet.user.fullname, + "vet_farm_mobile": vet_farm.vet.user.mobile, + } + + return vet + + def get_active_kill(self, instance): + active_kill = False + + count_of_request = ProvinceKillRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=instance, + state='accepted').count() + + if ProvinceKillRequest.objects.filter(trash=False, province_request__poultry_request__hatching=instance, + state='pending').exists(): + active_kill = True + info = { + "active_kill": active_kill, + "count_of_request": count_of_request, + } + + return info + + def get_killing_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + first_car_allocated_quantity=0, + province_request__poultry_request__hatching=obj).only( + 'total_killed_quantity', + 'total_killed_weight' + ) + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching=obj) + first_quantity = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity') or 0 + first_weight = kill_house_requests.aggregate(total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + ware_house_bars = kill_house_requests.filter(ware_house_confirmation=True) + ware_house_bars_quantity = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + ware_house_bars_weight = ware_house_bars.aggregate(total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + + ware_house_bars_weight_lose = ware_house_bars.aggregate(total=Sum('weight_loss'))[ + 'total'] or 0 + bar_complete_with_kill_house = kill_house_requests.filter( + assignment_state_archive='True') + + accepted_real_wight_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_weight')).get( + 'total_quantity') or 0 + + accepted_real_quantity_final = bar_complete_with_kill_house.aggregate( + total_quantity=Sum('accepted_real_quantity')).get( + 'total_quantity', 0) or 0 + + return { + "violation_message": 'متخلف' + ' ' + '(مانده در سالن بیش از حد مجاز)' if obj.violation else 'عادی', + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests": len(kill_house_requests), + "kill_house_requests_first_quantity": first_quantity, + "kill_house_requests_first_weight": first_weight, + "bar_complete_with_kill_house": len(bar_complete_with_kill_house), + "accepted_real_quantity_final": accepted_real_quantity_final, + "accepted_real_wight_final": accepted_real_wight_final, + "ware_house_bars": len(ware_house_bars), + "ware_house_bars_quantity": ware_house_bars_quantity, + "ware_house_bars_weight": ware_house_bars_weight, + 'ware_house_bars_weight_lose': ware_house_bars_weight_lose / len( + ware_house_bars) if ware_house_bars else 0, + } + + def get_free_governmental_info(self, obj): + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, return_to_province=False, + state__in=('pending', 'accepted'), + province_request__poultry_request__hatching=obj) + + governmental_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=False) + governmental_province_kill_requests_quantity = \ + governmental_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + free_province_kill_requests = province_kill_requests.filter( + Q(province_request__poultry_request__direct_buying=False) | Q( + province_request__poultry_request__direct_buying=True), + province_request__poultry_request__free_sale_in_province=True) + + free_province_kill_requests_quantity = \ + free_province_kill_requests.aggregate(total=Sum('total_killed_quantity'))[ + 'total'] or 0 + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, state_process='accepted', + province_state='accepted', + out_province_request_cancel=False, final_state='archive', + hatching=obj) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + free_sale_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if free_sale_province.allow == False: + left_total_free_commitment_quantity = obj.left_over + + elif obj.total_free_commitment_quantity == 0: + left_total_free_commitment_quantity = 0 + else: + if obj.total_commitment_quantity == 0: + left_total_free_commitment_quantity = obj.left_over + else: + left_total_free_commitment_quantity = obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity) if ( + obj.total_free_commitment_quantity - ( + free_province_kill_requests_quantity + out_poultry_requests_quantity)) > 0 else 0 + + return { + "governmental_allocated_quantity": governmental_province_kill_requests_quantity, + "total_commitment_quantity": obj.total_commitment_quantity, + "free_allocated_quantity": free_province_kill_requests_quantity + out_poultry_requests_quantity, + "total_free_commitment_quantity": obj.total_free_commitment_quantity, + "left_total_free_commitment_quantity": left_total_free_commitment_quantity, + + } diff --git a/panel/poultry/views.py b/panel/poultry/views.py new file mode 100644 index 0000000..b1b598c --- /dev/null +++ b/panel/poultry/views.py @@ -0,0 +1,10383 @@ +import math +import threading +from io import BytesIO +from typing import List, Dict + +import openpyxl +import requests +from django.contrib.auth.models import Group +from django.db.models import Q, Prefetch, Min, Max, Avg, Case, When, IntegerField, ExpressionWrapper, FloatField +from rest_framework.generics import GenericAPIView +from rest_framework.views import APIView + +from authentication.sahandsms.sms import kill_house_price +from general_urls import base_url_for_sms_report +from panel.ReportingPanel.views import ( + get_gid_poultry_request, + get_gid_poultry_request_quarantine_code, +) +from panel.admin import PROJECT_API_KEY +from panel.helper import build_query +from panel.helper_excel import percent_of_losses +from panel.poultry.helpers import poultry_prediction_helper, calculate_hatching_increase, \ + create_update_chicken_commission_prices, market_daily_limitation_info +from ticket.bucket import upload_to_liara, delete_file_from_liara + +ARTA_URL_REGISTER = "https://userbackend.rasadyar.com/api/register/" + +ARTA_URL_CHANGE_MOBILE_NUMBER = "https://userbackend.rasadyar.com/change_mobile_number/" +from authentication.models import User, Province +import random +import string +from datetime import datetime, timedelta +from django.http import QueryDict +from django.views.decorators.csrf import csrf_exempt +from django_filters.rest_framework import DjangoFilterBackend +from num2fawords import words +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from django.utils import timezone +from django.db.models import F +from rest_framework import status +from rest_framework import viewsets +from rest_framework.decorators import permission_classes, api_view +from rest_framework.permissions import AllowAny +from rest_framework.response import Response +from rest_framework.pagination import PageNumberPagination + +from ticket.helper import send_image_to_server +from authentication.models import UserProfile, UserMessage, SystemUserProfile, CityUnit, City +from authentication.serializer.serializer import SystemUserProfileSerializer +from django.db.models import Sum +from authentication.sms_management import operator_hatching_sms, operator_poultry_request_sms, \ + operator_out_poultry_request_sms, sms_chain_company_for_ver_farm, \ + confirm_price_poultry_request_sms, send_sms_for_poultry_market +from panel.KillHouse.serializers import PoultryRequestExchangeAcceptSerializer, ProvinceKillRequestSerializer, \ + KillHouseRequestSerializer, KillHouseRequestForBarManagementSerializer, \ + PoultryRequestLetterTotalSerializer, \ + PoultryRequestoutProvinceSerializer, KillHouseRequestForHatchingDetailSerializer, \ + ReturnProvinceKillRequestSerializer, BarDifferenceRequestSerializer +from panel.convert_date import * +from panel.filterset import PoultryRequestExchangeFilterSet, PoultryFilterSet, PoultryHatchingFilterSet, \ + PoultryRequestFilterSet, ChainAllocationFilterSet, ChainCompanyFilterSet, OutProvincePoultryRequestBuyerFilterSet, \ + DashboardPoultryRequestFilterSet, PoultryManageFilterSet, HatchingIncreaseRequestFilterSet, \ + PoultryRequestDirectBuyingFilterSet, EvacuationHatchingDetailFilterSet +from panel.models import ( + PoultryRequest, + PoultryAssignmentInformation, + KillHouseRequest, + CityOperatorCheckRequest, + ProvinceCheckOperatorRequest, + DepositAllocation, + PovinceInspector, + KillHouseAssignmentInformation, + KillHouseFactorToProvince, + ProvinceFactorToKillHouse, + VetCheckRequest, + PoultryRequestExchange, + PoultryRequestExchangeAccept, + KillHouseRequestExchangeReserve, + KillHouseCheckRequest, + ProvinceKillRequest, + PoultryHatching, + Poultry, + PoultryTenant, CityOperator, PoultryRequestAuction, Pricing, KillHouseRequestAction, KillHouseRequestActionWinner, + ProvinceRequestAction, VetFarmInspection, InspectorOperator, ProvinceOperator, + KillHouseOperator, KillHouse, Vet, KillHouseVet, VetFarm, ShareOfAllocation, ProvinceFactorToKillHouseForPoultry, + KillHouseFactorToPoultry, KillHouseComplaint, KillHouseDriver, KillRequest, CheckUnusualCasualties, + PercentageOfLosses, ProvinceImportKillHouseOutFactors, TotalPoultryRequestQuantity, HourLimit, KillHousePercentage, + SmsLicense, ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultrySellFree, LastUpdate, FreeSaleWithinprovince, + OperationLimitation, ChickenAgeRange, TimeRange, ChainCompany, Wallet, ChainAllocation, WageType, + PercentageOfWageType, ChainCompanyTransaction, InternalTransaction, OutProvincePoultryRequestBuyer, + PoultryOutProvinceRequest, PoultryPrediction, PriceConfirmation, HatchingIncreaseRequest, + ChickenCommissionPrices, PoultryRequestQuarantineCode, FinePermission, ShowMarketRequest, + ManagementHatchingAgeRange, IndexWeightCategory, PoultryScience, BarDifferenceRequest, EvacuationHatchingDetail, + MarketDailyLimitation, HatchingArchivePercent +) +from panel.poultry.serializers import ( + PoultryRequestSerializer, + PoultryAssignmentInformationSerializer, + PoultryRequestExchangeSerializer, + PoultryHatchingSerializer, + PoultrySerializer, + PoultryTenantSerializer, TotalPoultryRequestQuantitySerializer, PoultryForPoultryHatchingSerializer, + TotalPoultrySerializer, LastUpdateSerializer, PoultryRequestForKillingInformationSerializer, + PoultryForPoultryHatchingForKillInformationSerializer, ChainCompanySerializer, ChainAllocationSerializer, + ChainCompanyTransactionSerializer, ChainCompanyForTotalWageAllocationWithDAteSerializer, + ChainCompanyForTotalWageAllocationSerializer, ChainAllocationForWageSerializer, + ChainCompanyForTotalWageTransactionSerializer, ChainCompanyForTotalWageTransactionTransactionWithDAteSerializer, + OutProvincePoultryRequestBuyerSerializer, OutProvincePoultryRequestBuyerForBuyerRequestSerializer, + ChainCompanyForCompanyRequestSerializer, PoultryLocationSerializer, GetAllPoultrySerializer, + PoultryHatchingForPredictionSerializer, PoultryPredictionSerializer, HatchingIncreaseRequestSerializer, + ChickenCommissionPricesSerializer, PoultryRequestQuarantineCodeSerializer, PoultryHatchingForDetailsSerializer, + PoultryRequestForHatchingDetailSerializer, ChainAllocationForHatchingDetailSerializer, + PoultryHatchingForBazrasiSerializer, PoultryRequestForDirectBuyingSerializer, ManagementHatchingAgeRangeSerializer, + EvacuationHatchingDetailSerializer, PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer, + PoultryDetailForPoultryAndHatchingForPoultryScienceSerializer +) + +# آدرس پایه برای ذخیره عکس در گالری مرغدار بر روی استوریج آروان +ARVAN_poultry_URL = 'https://profileimagedefault.s3.ir-thr-at1.arvanstorage.ir/' + + +# ARVAN_poultry_URL = 'https://poultry-gallery.s3.ir-thr-at1.arvanstorage.ir/' + + +def update_chain_hatching(poultry_hatching): + chain_allocations = ChainAllocation.objects.filter(trash=False, state='accepted', poultry_hatching=poultry_hatching) + total_killed_quantity = chain_allocations.aggregate(total=Sum('quantity'))['total'] or 0 + total_killed_weight = chain_allocations.aggregate(total=Sum('weight'))['total'] or 0 + + poultry_hatching.chain_killed_quantity = total_killed_quantity + poultry_hatching.chain_killed_weight = total_killed_weight + poultry_hatching.save() + + +class CustomPagination(PageNumberPagination): + page_size = 10 + + +class OutProvincePoultryRequestBuyerViewSet(viewsets.ModelViewSet): + queryset = OutProvincePoultryRequestBuyer.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = OutProvincePoultryRequestBuyerSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = OutProvincePoultryRequestBuyerFilterSet + filterset_fields = [ + 'mobile', + 'kill_house_unique_id', + 'user__national_id', + 'user__base_order', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'unit_name', + + ] + + def create(self, request, *args, **kwargs): + operator_user = SystemUserProfile.objects.get(user=request.user, trash=False) + if SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).exists(): + return Response({"result": "این کاربر قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "00100" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code in (200, 400): + user = User(username=request.data['mobile'], first_name=request.data['fullname']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['fullname'], + fullname=request.data['fullname'], + user=user, + base_order=base_id, + password=password, + city=operator_user.city, + province=operator_user.province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + buyer = serializer.create(validated_data=request.data) + buyer.user = system_profile + buyer.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + buyer_list = [] + if 'state' in request.GET: + buyers = OutProvincePoultryRequestBuyer.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=buyers + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=buyers) + buyer_list = ps.filter() + buyers = [] if len(buyer_list) == 0 else buyer_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(buyers) + if page is not None: + serializer = OutProvincePoultryRequestBuyerForBuyerRequestSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + else: + buyers = OutProvincePoultryRequestBuyer.objects.filter(active=True, trash=False).order_by('id') + serializer = self.get_serializer(buyers, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + buyer = OutProvincePoultryRequestBuyer.objects.get(key=request.data['buyer_key'], trash=False) + request.data.pop('buyer_key') + system_user_profile = SystemUserProfile.objects.get(key=buyer.user.key, trash=False) + if 'fullname' in request.data.keys(): + system_user_profile.first_name = request.data['fullname'] + system_user_profile.fullname = request.data['fullname'] + system_user_profile.save() + if 'mobile' in request.data.keys(): + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + serializer = self.serializer_class(buyer) + serializer.update(instance=buyer, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + buyer = OutProvincePoultryRequestBuyer.objects.get(key=request.GET["buyer_key"], trash=False) + buyer.trash = True + buyer.save() + return Response({"result": "با موفقیت حذف شد."}, status=status.HTTP_200_OK) + + +class TotalPoultryViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = TotalPoultrySerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryManageFilterSet + filterset_fields = [ + 'breeding_unique_id', + 'user__national_id', + 'user__base_order', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'address__city__name', + 'unit_name', + + ] + + def list(self, request, *args, **kwargs): + poultries = [] + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'search' in request.GET: + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultries = Poultry.objects.filter(city_operator=city_operator.unit_name, trash=False).order_by( + 'id') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultries = Poultry.objects.filter(address__city=user.city, trash=False).order_by('id') + else: + poultries = Poultry.objects.filter(trash=False).order_by('id') + else: + poultries = Poultry.objects.filter(trash=False).order_by('id') + + value = request.GET.get('value') + search = request.GET.get('search') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + poultries = poultries.filter( + build_query(self.filterset_class, value)) + + else: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultries = Poultry.objects.filter(city_operator=city_operator.unit_name, trash=False).order_by('id') + + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultries = Poultry.objects.filter(address__city=user.city, trash=False).order_by('id') + else: + poultries = Poultry.objects.filter(address__province=user.province, trash=False).order_by('id') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultries) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(poultries, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به ثبت و نمایش و ... مرغداری +class PoultryViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultrySerializer + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryFilterSet + filterset_fields = [ + 'breeding_unique_id', + 'user__national_id', + 'user__base_order', + 'user__mobile', + + ] + + # تابع مربوط به ویرایش مرغداری + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + poultry = Poultry.objects.get(key=request.data["key"], trash=False) + request.data.pop('key') + serializer = self.serializer_class(poultry) + serializer.update(instance=poultry, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش مرغداری + def list(self, request, *args, **kwargs): + + # refresh(request.user.id) + + # list of self poultry houses + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'type' in request.GET: + if request.GET['type'] == 'filter': + poultry_list = [] + # for poultry in self.queryset.filter(trash=False): + # if PoultryHatching.objects.filter(poultry=poultry, + # allow_hatching='pending', left_over__gt=0, state='pending', + # archive=False, trash=False).exists(): + # poultry_list.append(poultry.key) + poultry_list = self.queryset.filter(address__province=user.province, trash=False) + + for item in self.filterset_fields: + query = QueryDict('{0}={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + # queryset=self.queryset.filter(address__province=user.province, trash=False) + queryset=poultry_list + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_list) + filtered_poultry = ps.filter() + serializer = self.serializer_class(filtered_poultry, many=True) + return Response(serializer.data) + return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN) + + elif 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + if 'active_hatching' in request.GET: + poultry = [] + poultry_ids = PoultryHatching.objects.filter( + allow_hatching='pending', + left_over__gt=0, + state='pending', + poultry__city_operator=city_operator.unit_name, + archive=False, + trash=False + ).select_related('poultry').only('poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + serializer = PoultryForPoultryHatchingForKillInformationSerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + poultry = Poultry.objects.filter(city_operator=city_operator.unit_name) + elif request.GET['role'] == 'Poultry': + poultry = Poultry.objects.filter(user=user, trash=False) + else: + if 'active_hatching' in request.GET: + poultry_ids = PoultryHatching.objects.filter( + poultry__address__province=user.province, + allow_hatching='pending', + left_over__gt=0, + state='pending', + archive=False, + trash=False + ).select_related('poultry').only('poultry').values_list('poultry', flat=True).distinct() + age_range = ChickenAgeRange.objects.filter(trash=False).first() + if 'min_age' in request.GET or 'direct_buying' in request.GET: + if age_range.active: + poultry_ids = poultry_ids.filter(chicken_age__range=(age_range.minimum, age_range.maximum)) + else: + if 'min_age' in request.GET: + min_age = int(request.GET['min_age']) + max_age = int(request.GET.get('max_age', min_age)) # برای اطمینان از وجود 'max_age' + poultry_ids = poultry_ids.filter(chicken_age__range=(min_age, max_age)) + else: + poultry_ids = poultry_ids + poultry = Poultry.objects.filter(id__in=poultry_ids) + serializer = PoultryForPoultryHatchingForKillInformationSerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + # poultry=PoultryHatching.objects.filter(trash=False,allow_hatching='pending',archive=False).values_list( + # 'poultry',flat=True + # ).distinct() + poultry = Poultry.objects.filter(trash=False, address__province=user.province).select_related( + 'user', 'address' + ).order_by('id') + + serializer = PoultryForPoultryHatchingSerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + elif 'info' in request.GET: + list1 = [] + # list2 = [] + poultries = Poultry.objects.filter(user=user, trash=False) + if poultries.count() > 0: + for poultry in poultries: + halls = int(poultry.number_of_halls) + inspections_count = 0 + hatching_state = None + hatching_date = None + for hall in range(halls): + hatching = PoultryHatching.objects.filter(poultry=poultry, hall=hall + 1).order_by('date') + if hatching.count() > 0: + hatching = hatching.last() + hatching_date = hatching.date + if hatching.state == 'pending': + hatching_state = 'active' + else: + hatching_state = 'inactive' + + vet_farms = VetFarm.objects.filter(poultry=poultry, hall=hall + 1) + if vet_farms.count() > 0: + for vet_farm in vet_farms: + inspections = VetFarmInspection.objects.filter(vet_farm=vet_farm) + if inspections.count() > 0: + inspections_count += inspections.count() + internal_dict = { + "poultry_name": poultry.unit_name, + "poultry_key": poultry.key, + "hall": hall + 1, + "hatching_state": hatching_state, + "hatching_date": hatching_date, + "inspections": inspections_count + } + list1.append(internal_dict) + inspections_count = 0 + + return Response(list1, status=status.HTTP_200_OK) + + elif 'operator' in request.GET: + if request.GET['operator'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry = Poultry.objects.filter(city_operator=city_operator.unit_name, trash=False) + serializer = PoultrySerializer(poultry, many=True) + # + # elif 'id' in request.GET: + # poultry = Poultry.objects.get(breeding_unique_id=request.GET['id']) + # serializer = PoultrySerializer(poultry) + elif 'all' in request.GET: + poultry_list = [] + poultries = Poultry.objects.filter(address__province=user.province, trash=False) + if poultries.count() > 0: + for poultry in poultries: + allow_state = None + allow_sell_state = None + allow = ProvinceAllowPoultryChooseKillHouse.objects.filter(poultry=poultry, trash=False) + allow_sell = ProvinceAllowPoultrySellFree.objects.filter(poultry=poultry, trash=False) + if allow.count() > 0: + allow_state = allow.last().allow + if allow_sell.count() > 0: + allow_sell_state = allow_sell.last().allow + poultry_dict = { + "name": poultry.unit_name, + "key": poultry.key, + "allow_state": allow_state, + "allow_sell_state": allow_sell_state + } + poultry_list.append(poultry_dict) + return Response(poultry_list, status=status.HTTP_200_OK) + + + else: + poultry = Poultry.objects.filter(user=user, trash=False) + serializer = PoultrySerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def retrieve(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + + # get self - poultry profile information + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + user_serializer = SystemUserProfileSerializer(user) + poultry = Poultry.objects.filter(user=user, trash=False) + serializer = PoultrySerializer(poultry, many=True) + profile_info = { + 'profile': user_serializer.data, + 'aviculture': serializer.data + } + return Response(profile_info, status=status.HTTP_200_OK) + + # get special poultry information + if 'partial_key' in request.GET: + poultry_object = Poultry.objects.get(key=request.GET['partial_key'], trash=False) + serializer = PoultrySerializer(poultry_object) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + # refresh(request.user.id) + poultry = self.queryset.get(key=request.data['poultry_key']) + poultry.trash = True + poultry.save() + return Response(status=status.HTTP_200_OK) + + +class ChainCompanyViewSet(viewsets.ModelViewSet): + queryset = ChainCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainCompanySerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainCompanyFilterSet + filterset_fields = [ + 'user__national_id', + 'user__mobile', + 'user__first_name', + 'user__last_name', + 'user__fullname', + 'name', + + ] + + def retrieve(self, request, pk=None, *args, **kwargs): + if 'profile' in request.GET: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + chain_company = user.chain_company_user.all() + + serializer = self.serializer_class(chain_company[0]) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact="ChainCompany") + city = City.objects.get(province_center=True) + province = Province.objects.get(trash=False) + system_profile = SystemUserProfile.objects.filter(mobile=request.data['mobile'], trash=False).last() + if system_profile: + if ChainCompany.objects.filter(user=system_profile, trash=False).exists(): + return Response({"result": "این شرکت قبلا ثبت شده است"}, status=status.HTTP_403_FORBIDDEN) + + else: + password = "00100" + data = { + "username": request.data['mobile'], + "password": password, + "api_key": PROJECT_API_KEY + } + req = requests.post( + url=ARTA_URL_REGISTER, + data=data, + verify=False + ) + + if req.status_code == 200: + user = User(username=request.data['mobile'], first_name=request.data['first_name'], + last_name=request.data['last_name']) + user.save() + base_id = SystemUserProfile.objects.all() + if base_id.count() > 0: + base_id = int(base_id.last().base_order) + 1 + else: + base_id = 1000 + system_profile = SystemUserProfile( + mobile=request.data['mobile'], + first_name=request.data['first_name'], + last_name=request.data['last_name'], + fullname=request.data['first_name'] + " " + request.data['last_name'], + user=user, + base_order=base_id, + password=password, + national_id=request.data['national_id'], + city=city, + province=province + ) + system_profile.save() + else: + return Response({"result": "در ثبت کاربر مشکلی بوجود آمده است "}, status=status.HTTP_403_FORBIDDEN) + + system_profile.role.add(group) + wallet = Wallet() + wallet.save() + request.data.pop('mobile') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('national_id') + request.data.pop('postal_code') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + chain_company = serializer.create(validated_data=request.data) + chain_company.user = system_profile + chain_company.wallet = wallet + chain_company.save() + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) + + def list(self, request, *args, **kwargs): + + company_list = [] + if 'state' in request.GET: + chain_companies = ChainCompany.objects.filter(trash=False).order_by('id') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_companies + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_companies) + company_list = ps.filter() + chain_companies = [] if len(company_list) == 0 else company_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_companies) + if page is not None: + serializer = ChainCompanyForCompanyRequestSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + else: + chain_companies = ChainCompany.objects.filter(trash=False).order_by('id') + serializer = self.serializer_class(chain_companies, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + company = ChainCompany.objects.get(key=request.data['company_key'], trash=False) + system_user_profile = SystemUserProfile.objects.get(key=company.user.key, trash=False) + system_user_profile.first_name = request.data['first_name'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.fullname = request.data['first_name'] + " " + request.data['last_name'] + system_user_profile.national_id = request.data['national_id'] + system_user_profile.save() + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + request.data.pop('mobile') + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + + request.data.pop('company_key') + request.data.pop('first_name') + request.data.pop('last_name') + request.data.pop('national_id') + + serializer = self.serializer_class(company) + serializer.update(instance=company, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChainCompanyForTotalWageAllocationViewSet(viewsets.ModelViewSet): + queryset = ChainCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainCompanyForTotalWageAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainCompanyFilterSet + filterset_fields = [ + 'name', + 'user__fullname', + 'user__mobile', + 'address__city__name', + 'address__province__name', + + ] + + def list(self, request, *args, **kwargs): + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Guilds': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + else: + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOperator': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + union_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + company_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Guilds': + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + guilds_share__gt=0, + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + else: + chain_companies = ChainCompany.objects.filter(pk__in=ChainAllocation.objects.filter( + archive_wage=False, + trash=False).values( + 'chain_company'), trash=False) + + if 'search' in request.GET: + chain_companies_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_companies + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_companies) + chain_companies_list = ps.filter() + chain_companies = [] if len(chain_companies_list) == 0 else chain_companies_list + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_companies) + if page is not None: + if 'date1' in request.GET: + serializer = ChainCompanyForTotalWageAllocationWithDAteSerializer(page, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = ChainCompanyForTotalWageAllocationWithDAteSerializer(chain_companies, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(chain_companies, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChainCompanyForTotalWageTransactionViewSet(viewsets.ModelViewSet): + queryset = ChainCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainCompanyForTotalWageTransactionSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainCompanyFilterSet + filterset_fields = [ + 'name', + 'user__fullname', + 'user__mobile', + 'address__city__name', + 'address__province__name', + + ] + + def list(self, request, *args, **kwargs): + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='chain_company', + union_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='chain_company', + company_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Guilds': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='chain_company', + guilds_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + else: + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + date__date__gte=date1, + date__date__lte=date2, + status='completed', + payer_type='chain_company', + trash=False).values( + 'chain_company'), trash=False) + else: + + if request.GET['role'] == 'ProvinceOperator': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='chain_company', + union_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Company': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='chain_company', + company_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + elif request.GET['role'] == 'Guilds': + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='chain_company', + guilds_share__gt=0, + trash=False).values( + 'chain_company'), trash=False) + else: + chain_companies = ChainCompany.objects.filter(pk__in=InternalTransaction.objects.filter( + status='completed', + payer_type='chain_company', + trash=False).values( + 'chain_company'), trash=False) + + if 'search' in request.GET: + chain_companies_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_companies + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_companies) + chain_companies_list = ps.filter() + chain_companies = [] if len(chain_companies_list) == 0 else chain_companies_list + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_companies) + if page is not None: + if 'date1' in request.GET: + serializer = ChainCompanyForTotalWageTransactionTransactionWithDAteSerializer(page, many=True, context={ + 'request': request}) + else: + + serializer = self.get_serializer(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + if 'date1' in request.GET: + serializer = ChainCompanyForTotalWageTransactionTransactionWithDAteSerializer(chain_companies, many=True, + context={'request': request}) + else: + + serializer = self.get_serializer(chain_companies, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChainCompanyTransactionViewSet(viewsets.ModelViewSet): + queryset = ChainCompanyTransaction.objects.all() + serializer_class = ChainCompanyTransactionSerializer + permission_classes = [TokenHasReadWriteScope] + + +class PoultryChooseChainCompanyViewSet(viewsets.ModelViewSet): + queryset = ChainCompany.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainCompanySerializer + + def create(self, request, *args, **kwargs): + poultry_hitchings = request.data['poultry_hitchings'] + chain_company = ChainCompany.objects.get(key=request.data['chain_company'], trash=False) + hatchings = PoultryHatching.objects.filter(key__in=poultry_hitchings, trash=False) + for hatching in hatchings: + hatching.chain_company = chain_company + hatching.has_chain_company = True + hatching.save() + + return Response({"result": "با موفقیت ثبت شد"}, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + hatching = PoultryHatching.objects.get(key=request.data['hatching_key'], trash=False) + + if 'type' in request.data.keys(): + if request.data['type'] == 'delete': + hatching.chain_company = None + hatching.has_chain_company = False + hatching.save() + else: + company = ChainCompany.objects.get(key=request.data['company_key'], trash=False) + hatching.chain_company = company + hatching.has_chain_company = True + hatching.save() + + return Response({"result": "با موفقیت ثبت شد!"}, status=status.HTTP_200_OK) + + +class ChainAllocationForWageViewSet(viewsets.ModelViewSet): + queryset = ChainAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainAllocationForWageSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + + def list(self, request, *args, **kwargs): + chain_allocations_list = [] + if request.GET['role'] == 'ChainCompany': + user = SystemUserProfile.objects.get(user=request.user, trash=False) + chain_company = ChainCompany.objects.get(user=user, trash=False) + else: + + chain_company = ChainCompany.objects.get(key=request.GET['chain_company_key'], trash=False) + + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'ProvinceOperator': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, date__date__gte=date1, + date__date__lte=date2, + union_share__gt=0, + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, date__date__gte=date1, + date__date__lte=date2, + company_share__gt=0, + trash=False).order_by('id') + elif request.GET['role'] == 'Guilds': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, date__date__gte=date1, + date__date__lte=date2, + guilds_share__gt=0, + trash=False).order_by('id') + else: + + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, date__date__gte=date1, + date__date__lte=date2, + trash=False).order_by('id') + else: + + if request.GET['role'] == 'ProvinceOperator': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, + union_share__gt=0, + trash=False).order_by('id') + elif request.GET['role'] == 'Company': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, + company_share__gt=0, + trash=False).order_by('id') + elif request.GET['role'] == 'Guilds': + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, + guilds_share__gt=0, + trash=False).order_by('id') + else: + + chain_allocations = ChainAllocation.objects.filter(chain_company=chain_company, + trash=False).order_by('id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_allocations) + chain_allocations_list = ps.filter() + chain_allocations = [] if len(chain_allocations_list) == 0 else chain_allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_allocations) + if page is not None: + serializer = self.serializer_class(page, many=True, context={'request': request}) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(chain_allocations, many=True, context={'request': request}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ChainAllocationViewSet(viewsets.ModelViewSet): + queryset = ChainAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + if base_url_for_sms_report == 'ma': + return Response({ + 'result': "امکان ثبت بار برای زنجیره وجود ندارد جهت فروش زنجیره به قسمت فروش خارج استان مراجعه فرمایید"}, + status=status.HTTP_403_FORBIDDEN) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = None + hatching = PoultryHatching.objects.get(key=request.data['hatching_key'], trash=False) + chain_company = ChainCompany.objects.get(key=hatching.chain_company.key, trash=False) + role = request.data['role'] + request.data.pop('hatching_key') + request.data.pop('role') + now = datetime.datetime.now() + if 'kill_house_key' in request.data.keys(): + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + request.data.pop('kill_house_key') + input_date = datetime.datetime.strptime(request.data['date'], '%Y-%m-%d').date() + date = datetime.datetime(year=input_date.year, month=input_date.month, day=input_date.day, hour=now.hour, + minute=now.minute, + second=now.second) + request.data.pop('date') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + chain_allocation = serializer.create(validated_data=request.data) + chain_allocation.poultry_hatching = hatching + chain_allocation.chain_company = chain_company + chain_allocation.date = date + chain_allocation.company_name = chain_company.name + chain_allocation.company_user_fullname = chain_company.user.fullname + chain_allocation.company_user_mobile = chain_company.user.mobile + chain_allocation.company_user_province = chain_company.user.province.name + chain_allocation.company_user_city = chain_company.user.city.name + chain_allocation.registerer = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.datetime.now()), + } + if kill_house != None: + chain_allocation.kill_house = kill_house + chain_allocation.save() + # update_chain_hatching(hatching) + wage = 0 + wage_type = WageType.objects.filter(en_name='chain', trash=False).first() + if wage_type.status == True: + wage = wage_type.amount + chain_allocation.wage = wage + chain_allocation.total_wage_amount = wage * int(chain_allocation.weight) + chain_allocation.save() + + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, trash=False) + + if wage_type and wage_type.status == True and percentages_wage_type: + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + chain_allocation.union_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.union_share_percent = percentage_wage_type.percent + chain_allocation.save() + elif percentage_wage_type.share_type.en_name == 'company': + chain_allocation.company_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.company_share_percent = percentage_wage_type.percent + chain_allocation.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + chain_allocation.guilds_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.guilds_share_percent = percentage_wage_type.percent + chain_allocation.save() + elif percentage_wage_type.share_type.en_name == 'city': + chain_allocation.city_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.city_share_percent = percentage_wage_type.percent + chain_allocation.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + chain_allocation.wallet_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.wallet_share_percent = percentage_wage_type.percent + chain_allocation.save() + + else: + chain_allocation.other_share = int( + (percentage_wage_type.percent / 100) * chain_allocation.total_wage_amount) + chain_allocation.other_share_percent = percentage_wage_type.percent + chain_allocation.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + chain_allocations_list = [] + + if request.GET['role'] == "ChainCompany": + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(chain_company__user=user, date__date__gte=date1, + date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(chain_company__user=user, date__date__gte=date1, + date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(poultry_hatching__poultry__address__city=user.city, + date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + else: + + chain_allocations = ChainAllocation.objects.filter(poultry_hatching__poultry__address__city=user.city, + date__date__gte=date1, date__date__lte=date2, + state='accepted', + trash=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + city_operator = CityOperator.objects.get(user=user, trash=False) + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, date__date__gte=date1, + date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, temporary_deleted=False).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, date__date__gte=date1, + date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + elif request.GET['role'] == "VetFarm": + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + poultry_hatching__poultry__in=poultry, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + else: + + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + poultry_hatching__poultry__in=poultry, + state='accepted', + trash=False).order_by('-id') + else: + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True), temporary_trash=False, + temporary_deleted=False).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_allocations) + chain_allocations_list = ps.filter() + chain_allocations = [] if len(chain_allocations_list) == 0 else chain_allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(chain_allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + chain_allocation = ChainAllocation.objects.get(key=request.data['chain_allcation_key'], trash=False) + request.data.pop('chain_allcation_key') + if 'check_allocation' in request.data.keys(): + chain_allocation.seconder = { + "role": None, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.datetime.now()), + } + chain_allocation.save() + request.data.pop('check_allocation') + if request.data['state'] == 'accepted': + poultry_name = chain_allocation.poultry_hatching.poultry.unit_name + poultry_mobile = chain_allocation.poultry_hatching.poultry.user.mobile + quantity = chain_allocation.quantity + Index_weight = chain_allocation.index_weight + if chain_allocation.kill_house is not None: + kill_house_name = chain_allocation.kill_house.name + kill_house_mobile = chain_allocation.kill_house.kill_house_operator.user.mobile + + else: + kill_house_name = chain_allocation.buyer_name + kill_house_mobile = chain_allocation.buyer_mobile + city = chain_allocation.poultry_hatching.poultry.user.city.name + province = chain_allocation.poultry_hatching.poultry.user.province.name + date_str = str( + chain_allocation.date) + send_date = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + vet_farm = VetFarm.objects.filter( + poultry=chain_allocation.poultry_hatching.poultry).first() + sms_chain_company_for_ver_farm(poultry_name, poultry_mobile, + quantity, Index_weight, kill_house_name, kill_house_mobile, city, + send_date, + vet_farm.vet.user.mobile, province) + + if 'quarantine_code' in request.data.keys(): + chain_allocation.quarantine_code_registrar = { + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.datetime.now()), + } + chain_allocation.save() + if 'kill_house_key' in request.data.keys() and request.data['kill_house_key'] is not None: + kill_house = KillHouse.objects.get(key=request.data['kill_house_key']) + chain_allocation.kill_house = kill_house + chain_allocation.save() + request.data.pop('kill_house_key') + + serializer = self.serializer_class(chain_allocation) + serializer.update(instance=chain_allocation, validated_data=request.data) + if chain_allocation.state == 'accepted': + update_chain_hatching(chain_allocation.poultry_hatching) + chain_allocation.total_wage_amount = chain_allocation.wage * int(chain_allocation.weight) + chain_allocation.save() + + union_percent = chain_allocation.union_share_percent / 100 if chain_allocation.union_share_percent > 0 else 0 + company_percent = chain_allocation.company_share_percent / 100 if chain_allocation.company_share_percent > 0 else 0 + guilds_percent = chain_allocation.guilds_share_percent / 100 if chain_allocation.guilds_share_percent > 0 else 0 + city_share_percent = chain_allocation.city_share_percent / 100 if chain_allocation.city_share_percent > 0 else 0 + wallet_share_percent = chain_allocation.wallet_share_percent / 100 if chain_allocation.wallet_share_percent > 0 else 0 + other_share_percent = chain_allocation.other_share_percent / 100 if chain_allocation.other_share_percent > 0 else 0 + chain_allocation.union_share = int(union_percent * chain_allocation.total_wage_amount) + chain_allocation.company_share = int(company_percent * chain_allocation.total_wage_amount) + chain_allocation.guilds_share = int(guilds_percent * chain_allocation.total_wage_amount) + chain_allocation.city_share = int(city_share_percent * chain_allocation.total_wage_amount) + chain_allocation.wallet_share = int(wallet_share_percent * chain_allocation.total_wage_amount) + chain_allocation.other_share = int(other_share_percent * chain_allocation.total_wage_amount) + chain_allocation.save() + + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET['role'] + chain_allocation = ChainAllocation.objects.get(key=request.GET['chain_allcation_key'], trash=False) + if chain_allocation.quarantine_code is None == False: + return Response({"result": "به علت ورود کد قرنطینه امکان حذف وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + chain_allocation.trash = True + chain_allocation.state = 'deleted' + chain_allocation.remover = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.datetime.now()), + } + chain_allocation.save() + update_chain_hatching(chain_allocation.poultry_hatching) + return Response(status=status.HTTP_200_OK) + + +class ParentCompanyChainAllocationViewSet(viewsets.ModelViewSet): + queryset = ChainAllocation.objects.all() + permission_classes = [AllowAny] + serializer_class = ChainAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + + def list(self, request, *args, **kwargs): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + chain_allocations_list = [] + + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=chain_allocations + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=chain_allocations) + chain_allocations_list = ps.filter() + chain_allocations = [] if len(chain_allocations_list) == 0 else chain_allocations_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(chain_allocations) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(chain_allocations, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class ForecastPoultryHatchingViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + age = int(request.GET['age']) + days_interval = (date2 - date1).days + hatching_list = [] + hatches = PoultryHatching.objects.filter(state='pending', + allow_hatching='pending', archive=False, + trash=False) + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchings = hatches.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatchings = hatches.filter(poultry__address__city=user.city) + else: + hatchings = hatches + else: + hatchings = hatches + + if hatchings: + for i in range(days_interval + 1): + hatching_left_over = 0 + first_date = date1 + timedelta(days=i) + for hatch in hatchings: + if (first_date - hatch.date.date()).days + 1 == age: + hatching_left_over += hatch.left_over + hatching_list.append({"date": first_date, "hatching_left_over": hatching_left_over}) + if days_interval == 0: + break + + return Response(hatching_list, status=status.HTTP_200_OK) + + +class PoultryHatchingForDashBoardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + filterset_class = PoultryHatchingFilterSet + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'licence_number', + 'poultry__breeding_unique_id', + 'CertId', + 'PersonTypeName', + 'InteractTypeName', + 'UnionTypeName', + 'poultry__city_operator', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + hatching_filters = { + 'trash': False + } + if request.GET['type'] == 'date-dashboard': + date1 = datetime.datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = PoultryHatching.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, + # allow_hatching='pending', + # state='pending', + # archive=False, + poultry__city_operator=city_operator.unit_name, + ) + elif request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = PoultryHatching.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, + # allow_hatching='pending', + # state='pending', + # archive=False, + poultry__address__city=user.city, + ) + else: + poultry_hatchings = PoultryHatching.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, + # allow_hatching='pending', + # state='pending', + # archive=False + ) + if 'search' in request.GET: + value = request.GET.get('value') + if request.GET['search'] == 'filter': + if value != 'undefined' and value.strip(): + poultry_hatchings = poultry_hatchings.filter( + build_query(self.filterset_class, value) + ) + poultries = Poultry.objects.filter(pk__in=poultry_hatchings.values('poultry'), trash=False) + total_hatching_quantity = poultry_hatchings.aggregate(total=Sum('quantity'))['total'] or 0 + total_hatching_left_over_quantity = poultry_hatchings.aggregate(total=Sum('left_over'))['total'] or 0 + total_hatching_killed_quantity = poultry_hatchings.aggregate(total=Sum('killed_quantity'))['total'] or 0 + total_hatching_killed_weight = poultry_hatchings.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + all_vet_losses = poultry_hatchings.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity') or 0 + all_union_losses = poultry_hatchings.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity') or 0 + all_total_losses = poultry_hatchings.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity') or 0 + return Response({ + "poultries": len(poultries), + "total_hatching_quantity": total_hatching_quantity, + "total_hatching_left_over_quantity": total_hatching_left_over_quantity, + "total_hatching_killed_quantity": total_hatching_killed_quantity, + "total_hatching_killed_weight": total_hatching_killed_weight, + "total_hatching_vet_losses": all_vet_losses, + "total_hatching_union_losses": all_union_losses, + "total_hatching_all_losses": all_total_losses, + }) + else: + tab = request.GET.get('tab') + age1 = request.GET.get('age1') + age2 = request.GET.get('age2') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + role = request.GET.get('role') + if tab == 'unknown': + hatching_filters['unknown'] = True + elif tab == 'archive': + hatching_filters['unknown'] = False + elif tab == 'active': + hatching_filters['unknown'] = False + hatching_filters['allow_hatching'] = 'pending' + hatching_filters['state'] = 'pending' + hatching_filters['archive'] = False + else: + hatching_filters['unknown'] = False + + if age1 and age2: + if int(age2) > 0: + hatching_filters['chicken_age__gte'] = int(age1) + hatching_filters['chicken_age__lte'] = int(age2) + + if date1: + hatching_filters['date__date__gte'] = date1 + hatching_filters['date__date__lte'] = date2 + + if role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + hatching_filters['poultry__city_operator'] = city_operator.unit_name + + + + elif role in ['CityJahad', 'CityPoultry', 'CityVet']: + hatching_filters['poultry__address__city'] = user.city + + poultry_hatchings = PoultryHatching.objects.filter(**hatching_filters).order_by('date') + + if tab == 'archive': + poultry_hatchings = poultry_hatchings.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True)) + + if 'search' in request.GET: + value = request.GET.get('value') + if request.GET['search'] == 'filter': + if value != 'undefined' and value.strip(): + poultry_hatchings = poultry_hatchings.filter( + build_query(self.filterset_class, value) + ) + + total_hatching_quantity = poultry_hatchings.aggregate(total=Sum('quantity'))['total'] or 0 + total_hatching_left_over_quantity = poultry_hatchings.aggregate(total=Sum('left_over'))['total'] or 0 + total_hatching_killed_quantity = poultry_hatchings.aggregate(total=Sum('killed_quantity'))['total'] or 0 + total_hatching_killed_weight = poultry_hatchings.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + all_vet_losses = poultry_hatchings.aggregate(total_quantity=Sum('losses')).get( + 'total_quantity') or 0 + all_union_losses = poultry_hatchings.aggregate(total_quantity=Sum('direct_losses')).get( + 'total_quantity') or 0 + all_total_losses = poultry_hatchings.aggregate(total_quantity=Sum('total_losses')).get( + 'total_quantity') or 0 + now = timezone.now().date() + age_distribution = {"age-20-30": 0, "age-30-40": 0, "age-40-50": 0, "age-50-60": 0, "age-more-than-60": 0} + + for poultry_hatching in poultry_hatchings: + age = (now - poultry_hatching.date.date()).days + 1 + if 20 <= age <= 30: + age_distribution["age-20-30"] += poultry_hatching.left_over + elif age <= 40: + age_distribution["age-30-40"] += poultry_hatching.left_over + elif age <= 50: + age_distribution["age-40-50"] += poultry_hatching.left_over + elif age <= 60: + age_distribution["age-50-60"] += poultry_hatching.left_over + else: + age_distribution["age-more-than-60"] += poultry_hatching.left_over + + return Response({ + "poultries": poultry_hatchings.values('poultry').distinct().count(), + "hatchings": poultry_hatchings.count(), + "total_hatching_quantity": total_hatching_quantity, + "total_hatching_left_over_quantity": total_hatching_left_over_quantity, + **age_distribution, + "total_hatching_killed_quantity": total_hatching_killed_quantity, + "total_hatching_killed_weight": total_hatching_killed_weight, + "total_hatching_vet_losses": all_vet_losses, + "total_hatching_union_losses": all_union_losses, + "total_hatching_all_losses": all_total_losses, + }) + + +# ویوست مربوط به ثبت و نمایش و ... جوجه ریزی مرغدار +class PoultryHatchingViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + pagination_class = CustomPagination + filterset_class = PoultryHatchingFilterSet + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'licence_number', + 'poultry__breeding_unique_id', + 'CertId', + 'PersonTypeName', + 'InteractTypeName', + 'UnionTypeName', + 'poultry__city_operator', + + ] + + def generate_random_filename(self, extension="jpg", length=15): + """Generates a random filename with the given extension.""" + random_str = ''.join(random.choices(string.ascii_uppercase + string.digits, k=length)) + return f"{random_str}.{extension}" + + def process_violation_images(self, images): + """Uploads images to Arvan Cloud and returns the URLs.""" + violation_images = [] + for image in images: + file_url = upload_to_liara(image, image.name) + violation_images.append(file_url) + return violation_images + + # تابع مربوط به ثبت جوجه ریزی مرغدار + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + if 'role' in request.data.keys(): + role = request.data['role'] + request.data.pop('role') + else: + role = None + poultry = Poultry.objects.get(key=request.data["key"], trash=False) + request.data.pop("key") + if role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + if city_operator.unit_name != poultry.city_operator: + return Response({"result": "مرغدار زیر مجموعه تعاونی دیگری دیگری است !"}, + status=status.HTTP_403_FORBIDDEN) + hatching = PoultryHatching.objects.filter(poultry=poultry, trash=False) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + if PoultryHatching.objects.filter(poultry=poultry, hall=int(request.data['hall']), + state__in=('pending', 'complete'), allow_hatching='pending', + archive=False, + trash=False).exists(): + return Response({"result": "برای شما دوره فعال جوجه ریزی وجود دارد !"}, + status=status.HTTP_403_FORBIDDEN) + hatch = PoultryHatching.objects.filter(poultry=poultry, hall=int(request.data['hall']), + state__in=('pending', 'complete'), allow_hatching='pending', + archive=False, + trash=False) + if hatch.count() > 0: + hatch = hatch.last() + hatch.quantity += int(request.data['quantity']) + # hatch.left_over += int(request.data['quantity']) + hatch.state = 'pending' + counter = 1 + for chicken_breed in hatch.breed: + if request.data['chicken_breed'] == chicken_breed['breed']: + chicken_breed['main_quantity'] += int(request.data['quantity']) + chicken_breed['remain_quantity'] += int(request.data['quantity']) + break + counter += 1 + if counter == 1: + pass + else: + hatch.breed.append({ + 'breed': request.data['chicken_breed'], + 'main_quantity': int(request.data['quantity']), + 'remain_quantity': int(request.data['quantity']) + }) + + if hatch.chicken_breed == request.data['chicken_breed']: + pass + else: + hatch.chicken_breed = hatch.chicken_breed + " " + "-" + " " + request.data[ + 'chicken_breed'] + + hatch.save() + if SmsLicense.objects.filter(hatching=True).exists(): + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + poultry_fullname = hatch.poultry.unit_name + quantity = hatch.quantity + chicken_breed = hatch.chicken_breed + date_str = str(hatch.date) + date = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + date = jdatetime.datetime.fromgregorian(year=date.year, month=date.month, + day=date.day).strftime( + '%Y-%m-%d') + date_list = reversed(date.split('-')) + separate = "-" + date = separate.join(date_list) + + province = hatch.poultry.user.province.name + city = hatch.poultry.user.city.name + province_operator_mobile = province_operator.user.mobile + + operator_hatching_sms(province_operator_mobile, poultry_fullname, quantity, date, chicken_breed, + province, city) + free_sale = FreeSaleWithinprovince.objects.filter(trash=False, allow=True).first() + if free_sale: + if free_sale.type == 'weight': + hatch.total_commitment = hatch.quantity * free_sale.weight + else: + hatch.total_commitment_quantity = int(hatch.quantity * (free_sale.percent / 100)) + + hatch.save() + serializer = self.serializer_class(hatch) + return Response(serializer.data, status=status.HTTP_201_CREATED) + if int(request.data['quantity']) == 0: + return Response({"result": "you enter zero"}, status=status.HTTP_403_FORBIDDEN) + breed_list = [] + poultry_hatching = serializer.create(validated_data=request.data) + poultry_hatching.poultry = poultry + if hatching.count() > 0: + poultry_hatching.period = hatching.last().period + 1 + else: + poultry_hatching.period = 1 + if role != None: + poultry_hatching.registrar = { + "role": role, + "fullname": user.fullname, + "date": str(poultry_hatching.create_date) + } + + # poultry_hatching.left_over = poultry_hatching.quantity + breed_list.append({ + 'breed': request.data['chicken_breed'], + 'main_quantity': int(request.data['quantity']), + 'remain_quantity': int(request.data['quantity']) + }) + poultry_hatching.breed = breed_list + poultry_hatching.latest_hatching_change = { + "role": role, + "date": str(datetime.datetime.now().date()), + "full_name": user.fullname + } + poultry_hatching.save() + free_sale = FreeSaleWithinprovince.objects.filter(trash=False, allow=True).first() + if free_sale: + if free_sale.type == 'weight': + poultry_hatching.total_commitment = poultry_hatching.quantity * free_sale.weight + else: + poultry_hatching.total_commitment_quantity = int( + poultry_hatching.quantity * (free_sale.percent / 100)) + + poultry_hatching.save() + + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + + poultry_mobile = poultry_hatching.poultry.user.mobile + poultry_fullname = poultry_hatching.poultry.unit_name + quantity = poultry_hatching.quantity + chicken_breed = poultry_hatching.chicken_breed + date_str = poultry_hatching.date + date = datetime.datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S').date() + date = jdatetime.datetime.fromgregorian(year=date.year, month=date.month, day=date.day).strftime( + '%Y-%m-%d') + date_list = reversed(date.split('-')) + separate = "-" + date = separate.join(date_list) + if SmsLicense.objects.filter(hatching=True).exists(): + province = poultry_hatching.poultry.user.province.name + city = poultry_hatching.poultry.user.city.name + base_order = poultry_hatching.poultry.user.base_order + province_operator_mobile = province_operator.user.mobile + province_operator_name = province_operator.user.fullname + # hatching_sms(poultry_mobile, poultry_fullname, quantity, chicken_breed, date, province, city, base_order) + operator_hatching_sms(province_operator_mobile, poultry_fullname, quantity, date, chicken_breed, + province, city) + + serializer = self.serializer_class(poultry_hatching) + return Response(serializer.data, status=status.HTTP_201_CREATED) + + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + hatching = PoultryHatching.objects.get(key=request.data["key"], trash=False) + request.data.pop('key') + if 'violation_check' in request.data.keys(): + if hatching.violation_reporter is not None: + hatching.violation_report_editor = user.fullname + hatching.violation_report_edit_date = datetime.datetime.now() + else: + hatching.violation_reporter = user.fullname + hatching.violation_report_date = datetime.datetime.now() + if request.FILES.get('violation_image_0'): + violation_files = [ + f for i in range(5) + if (f := request.FILES.get(f'violation_image_{i}')) + ] + images = hatching.violation_image + if images: + for image in images: + delete_file_from_liara(image.split('/')[-1]) + violation_images = self.process_violation_images(violation_files) + hatching.violation_image = violation_images + if request.data['archive'] == True: + hatching.allow_hatching = 'True' + hatching.state = 'complete' + hatching.archive_date = datetime.datetime.now() + hatching.archive = True + if hatching.first_date_input_archive is None: + hatching.first_date_input_archive = datetime.datetime.now() + else: + hatching.second_date_input_archive = datetime.datetime.now() + hatching.input_archiver = user.fullname + hatching.save() + request.data.pop('violation_check') + request.data.pop('archive') + if 'unknown' in request.data.keys(): + hatching.poultry.order_limit = False + hatching.poultry.save() + if 'archive_state' in request.data.keys(): + if hatching.left_over > (hatching.quantity * 10): + return Response({'result': 'به دلیل مانده بیش از ده درصد امکان بایگانی کردن این جوجه ریزی را ندارید!'}, + status=status.HTTP_403_FORBIDDEN) + role = request.data['role'] + request.data.pop('role') + request.data.pop('archive_state') + hatching.allow_hatching = True + if hatching.unknown: + hatching.unknown = False + hatching.poultry.order_limit = False + hatching.poultry.save() + hatching.state = 'complete' + hatching.archive_date = datetime.datetime.now() + hatching.archive = True + if hatching.first_date_input_archive is None: + hatching.first_date_input_archive = datetime.datetime.now() + else: + hatching.second_date_input_archive = datetime.datetime.now() + if hatching.left_over > (hatching.quantity * percent_of_losses): + hatching.violation = True + hatching.input_archiver = user.fullname + hatching.last_change = { + "date": str(datetime.datetime.now()), + "full_name": user.fullname, + "role": role, + "type": "manual_archive" + } + hatching.save() + + if 'quantity' in request.data.keys() and request.data['quantity'] != None: + quantity = int(request.data['quantity']) + # poultry_requests_quantity = \ + # PoultryRequest.objects.filter(hatching=hatching, state_process__in=('pending', 'accepted'), + # province_state__in=('pending', 'accepted'), final_state='pending', + # trash=False).aggregate( + # total_quantity=Sum('quantity'))[ + # 'total_quantity'] or 0 + if quantity < hatching.killed_quantity: + # if int(request.data['quantity']) < hatching.left_over: + return Response({"result": "تعداد وارد شده کمتر از تعداد کشتار شده قبلی است."}) + else: + role = request.data['role'] + request.data.pop('role') + # if quantity > hatching.quantity: + # hatching.left_over += quantity - hatching.quantity + # elif quantity < hatching.quantity and hatching.left_over != 0: + # hatching.left_over -= hatching.quantity - quantity + hatching.quantity = quantity + hatching.allow_hatching = 'pending' + hatching.state = 'pending' + # hatching.output_archive_date = datetime.datetime.now() + # hatching.output_archiver = user.fullname + hatching.last_change = { + "date": str(datetime.datetime.now()), + "full_name": user.fullname, + "role": role, + "type": "change_hatching" + } + hatching.save() + free_sale = FreeSaleWithinprovince.objects.filter(trash=False, allow=True).first() + if free_sale: + if free_sale.type == 'weight': + hatching.total_commitment = hatching.quantity * free_sale.weight + else: + hatching.total_commitment_quantity = int(hatching.quantity * (free_sale.percent / 100)) + + hatching.save() + if 'type' in request.data.keys(): + if request.data['type'] == 'return_archive': + if PoultryHatching.objects.filter(poultry=hatching.poultry, hall=hatching.hall, trash=False, + allow_hatching='pending', archive=False + ).exists(): + return Response({"result": "شما در این سالن جوجه ریزی فعال دارید"}, + status=status.HTTP_403_FORBIDDEN) + elif (datetime.datetime.now().date() - hatching.date.date()).days > 85: + return Response({"result": "جوجه ریزی انتخابی بالاتر از 85 روز میباشد،امکان بازگشت وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + else: + hatching.allow_hatching = 'pending' + hatching.state = 'pending' + hatching.archive = False + hatching.chicken_age = (datetime.datetime.now().date() - hatching.date.date()).days + 1 + hatching.output_archive_date = datetime.datetime.now() + hatching.output_archiver = user.fullname + free_sale = FreeSaleWithinprovince.objects.filter(trash=False, allow=True).first() + if free_sale: + if free_sale.type == 'weight': + hatching.total_commitment = hatching.quantity * free_sale.weight + else: + hatching.total_commitment_quantity = int(hatching.quantity * (free_sale.percent / 100)) + + hatching.save() + if 'violation' in request.data.keys(): + if request.data['violation'] == True and hatching.violation == False: + hatching.violation = True + if request.data['violation'] == False and hatching.violation == True: + hatching.violation = False + hatching.save() + request.data.pop('violation') + if 'delete_tenant' in request.data.keys(): + hatching.tenant_fullname = None + hatching.tenant_national_code = None + hatching.tenant_mobile = None + hatching.tenant_city = None + hatching.has_tenant = False + hatching.save() + request.data.pop('delete_tenant') + if 'direct_losses' in request.data.keys(): + if request.data['direct_losses'] > hatching.left_over: + return Response({"result": "تعداد وارد شده از باقی مانده سالن بیشتر است"}, + status=status.HTTP_403_FORBIDDEN) + date = datetime.datetime.now() + if hatching.direct_losses_inputer is None: + hatching.direct_losses_inputer = user.fullname + hatching.direct_losses_date = date + else: + hatching.direct_losses_editor = user.fullname + hatching.direct_losses_last_edit_date = date + hatching.save() + if 'end_period_losses' in request.data.keys(): + if request.data['losses'] > hatching.left_over: + return Response({"result": "تعداد وارد شده از باقی مانده سالن بیشتر است"}, + status=status.HTTP_403_FORBIDDEN) + if request.data['type'] == 'add': + hatching.losses += request.data['losses'] + else: + hatching.losses = request.data['losses'] + + date = datetime.datetime.now() + if hatching.end_period_losses_inputer is None: + hatching.end_period_losses_inputer = user.fullname + hatching.end_period_losses_date = date + else: + hatching.end_period_losses_editor = user.fullname + hatching.end_period_losses_last_edit_date = date + hatching.save() + return Response({"result": "با موفقیت ثبت شد."}, status=status.HTTP_200_OK) + serializer = self.serializer_class(hatching) + serializer.update(instance=hatching, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش دوره جوجه ریزی مرغدار + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + poultry_hatchings = [] + # refresh(request.user.id) + from datetime import datetime + now = datetime.now().date() + user = SystemUserProfile.objects.get(user=request.user) + + if 'all_active_and_archive' in request.GET: + base_query = PoultryHatching.objects.filter( + trash=False + ).select_related( + 'poultry__user', + 'poultry__address__city', + 'poultry__address__province', + 'chain_company' + ) + + if request.GET.get('role') == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = base_query.filter( + poultry__city_operator=city_operator.unit_name, + poultry__address__province=user.province + ) + elif request.GET.get('role') in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = base_query.filter( + poultry__address__city=user.city + ) + elif request.GET.get('role') == 'ChainCompany': + poultry_hatchings = base_query.filter( + chain_company__user=user, + poultry__address__province=user.province + ) + else: + poultry_hatchings = base_query.filter( + poultry__address__province=user.province + ) + + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + poultry_hatchings = poultry_hatchings.filter( + date__date__gte=date1, + date__date__lte=date2 + ) + + if 'age1' in request.GET and int(request.GET.get('age2')) > 0: + age1 = int(request.GET['age1']) + age2 = int(request.GET['age2']) + poultry_hatchings = poultry_hatchings.filter( + chicken_age__gte=age1, + chicken_age__lte=age2 + ) + + if 'search' in request.GET and value and value != 'undefined' and value.strip(): + poultry_hatchings = poultry_hatchings.filter( + build_query(self.filterset_class, value) + ) + + poultry_hatchings = poultry_hatchings.order_by('-date') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_hatchings) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(poultry_hatchings, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + if 'unknown' in request.GET: + base_query = PoultryHatching.objects.filter( + trash=False, unknown=True + ).select_related( + 'poultry__user', + 'poultry__address__city', + 'poultry__address__province', + 'chain_company' + ) + + if request.GET.get('role') == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = base_query.filter( + poultry__city_operator=city_operator.unit_name, + poultry__address__province=user.province + ) + elif request.GET.get('role') in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = base_query.filter( + poultry__address__city=user.city + ) + elif request.GET.get('role') == 'ChainCompany': + poultry_hatchings = base_query.filter( + chain_company__user=user, + poultry__address__province=user.province + ) + else: + poultry_hatchings = base_query.filter( + poultry__address__province=user.province + ) + + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + poultry_hatchings = poultry_hatchings.filter( + date__date__gte=date1, + date__date__lte=date2 + ) + + if 'age1' in request.GET and int(request.GET.get('age2')) > 0: + age1 = int(request.GET['age1']) + age2 = int(request.GET['age2']) + poultry_hatchings = poultry_hatchings.filter( + chicken_age__gte=age1, + chicken_age__lte=age2 + ) + + if 'search' in request.GET and value and value != 'undefined' and value.strip(): + poultry_hatchings = poultry_hatchings.filter( + build_query(self.filterset_class, value) + ) + + poultry_hatchings = poultry_hatchings.order_by('-date') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_hatchings) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(poultry_hatchings, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + if 'role' in request.GET: + if 'age1' in request.GET and int(request.GET.get('age2')) > 0: + age1 = int(request.GET.get('age1')) + age2 = int(request.GET.get('age2')) + poultry_hatch = PoultryHatching.objects.filter(trash=False, chicken_age__range=(age1, age2), + unknown=False) + else: + if 'date1' in request.GET: + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + poultry_hatch = PoultryHatching.objects.filter(trash=False, date__date__gte=date1, + date__date__lte=date2, unknown=False) + else: + poultry_hatch = PoultryHatching.objects.filter(trash=False, unknown=False) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + if 'search' in request.GET: + if 'chain' in request.GET: + if 'archive' in request.GET: + queryset = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + poultry__city_operator=city_operator.unit_name + ).order_by('-archive_date') + else: + queryset = poultry_hatch.filter(archive=False, allow_hatching='pending', + has_chain_company=True, + poultry__city_operator=city_operator.unit_name) + else: + + if 'archive' in request.GET: + queryset = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, + poultry__city_operator=city_operator.unit_name + ).order_by('-archive_date') + else: + queryset = poultry_hatch.filter(archive=False, allow_hatching='pending', + poultry__city_operator=city_operator.unit_name) + if request.GET['search'] == 'filter': + if value != 'undefined' and value.strip(): + poultry_hatchings = queryset.filter( + build_query(self.filterset_class, value) + ) + else: + poultry_hatchings = queryset + + elif 'archive' in request.GET: + if 'chain' in request.GET: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + poultry__city_operator=city_operator.unit_name + ).order_by('-archive_date') + else: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, + poultry__city_operator=city_operator.unit_name + ).order_by('-archive_date') + + + else: + if 'chain' in request.GET: + + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + has_chain_company=True, + allow_hatching='pending', + poultry__city_operator=city_operator.unit_name).order_by( + 'date') + else: + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + allow_hatching='pending', + poultry__city_operator=city_operator.unit_name).order_by( + 'date') + elif request.GET['role'] == 'ChainCompany': + if 'search' in request.GET: + if 'chain' in request.GET: + if 'archive' in request.GET: + queryset = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + chain_company__user=user + ).order_by('-archive_date') + else: + queryset = poultry_hatch.filter(archive=False, allow_hatching='pending', + has_chain_company=True, + chain_company__user=user) + else: + + if 'archive' in request.GET: + queryset = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, + chain_company__user=user + ).order_by('-archive_date') + else: + queryset = poultry_hatch.filter(archive=False, allow_hatching='pending', + chain_company__user=user) + if request.GET['search'] == 'filter': + if value != 'undefined' and value.strip(): + poultry_hatchings = queryset.filter( + build_query(self.filterset_class, value) + ) + else: + poultry_hatchings = queryset + + elif 'archive' in request.GET: + if 'chain' in request.GET: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + chain_company__user=user + ).order_by('-archive_date') + else: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, + chain_company__user=user + ).order_by('-date') + + + else: + if 'chain' in request.GET: + + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + has_chain_company=True, + allow_hatching='pending', + chain_company__user=user).order_by( + 'date') + else: + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + allow_hatching='pending', + chain_company__user=user).order_by( + 'date') + else: + if 'search' in request.GET: + + if 'archive' in request.GET: + if 'chain' in request.GET: + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__city=user.city, has_chain_company=True, + + ).order_by('-archive_date') + else: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + + ).order_by('-archive_date') + else: + + if request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__city=user.city, trash=False + + ).order_by('-archive_date') + else: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, trash=False + ).order_by('-archive_date') + else: + if 'chain' in request.GET: + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter(archive=False, allow_hatching='pending', + poultry__address__city=user.city, + has_chain_company=True, trash=False + ) + else: + + poultry_hatchings = poultry_hatch.filter(archive=False, allow_hatching='pending', + poultry__address__province=user.province, + has_chain_company=True, trash=False + ) + else: + + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter(archive=False, allow_hatching='pending', + poultry__address__city=user.city, + ).order_by('date') + else: + + poultry_hatchings = poultry_hatch.filter(archive=False, allow_hatching='pending', + + ).order_by('date') + + if request.GET['search'] == 'filter': + poultry_hatchings_list = [] + if value != 'undefined' and value.strip(): + poultry_hatchings = poultry_hatchings.filter( + build_query(self.filterset_class, value) + ) + else: + poultry_hatchings = poultry_hatchings + + elif 'archive' in request.GET: + if 'chain' in request.GET: + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__city=user.city, has_chain_company=True, + + ).order_by('-archive_date') + else: + + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, has_chain_company=True, + ).order_by('-archive_date') + else: + + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__city=user.city, + ).order_by('-date') + else: + + poultry_hatchings = poultry_hatch.filter( + Q(allow_hatching='True', state='complete') | Q(archive=True), + poultry__address__province=user.province, + ).order_by('-date') + + else: + if 'chain' in request.GET: + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter(poultry__address__city=user.city, + archive=False, has_chain_company=True, + allow_hatching='pending').order_by( + 'date') + else: + + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + archive=False, has_chain_company=True, + allow_hatching='pending').order_by( + 'date') + else: + + if request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = poultry_hatch.filter(poultry__address__city=user.city, + archive=False, + allow_hatching='pending').order_by( + 'date') + else: + poultry_hatchings = poultry_hatch.filter(poultry__address__province=user.province, + archive=False, + allow_hatching='pending').order_by( + 'date') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_hatchings) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(poultry_hatchings, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + elif 'illegal' in request.GET: + poultry_hatching = PoultryHatching.objects.filter(poultry__address__province=user.province, + archive=True).order_by('date') + serializer = PoultryHatchingSerializer(poultry_hatching, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'forecast' in request.GET: + hatch_quantity = 0 + hatch_losses = 0 + from datetime import datetime + date1 = datetime.strptime(request.GET['date1'], '%Y-%m-%d').date() + date2 = datetime.strptime(request.GET['date2'], '%Y-%m-%d').date() + hatchs = PoultryHatching.objects.filter(state='pending', + poultry__address__province=user.province) + if hatchs.count() > 0: + for hatch in hatchs: + if date1.year <= hatch.date.year and date1.month <= hatch.date.month and date1.day <= hatch.date.day and hatch.date.year >= date2.year and hatch.date.month >= date2.month and hatch.date.day >= date2.day: + hatch_quantity += hatch.quantity - (hatch.quantity * 0.1) + hatch_losses += hatch.losses + return Response({"hatch_quantity": hatch_quantity, "hatch_losses": hatch_losses}) + + elif 'filter' in request.GET: + now = datetime.now().date() + quantity_1_5 = 0 + quantity_5_10 = 0 + quantity_10_15 = 0 + quantity_15_20 = 0 + quantity_20_25 = 0 + quantity_25_30 = 0 + quantity_30_35 = 0 + quantity_35_40 = 0 + quantity_40_45 = 0 + quantity_45_50 = 0 + quantity_50_55 = 0 + quantity_55_60 = 0 + hatching = PoultryHatching.objects.filter(state='pending') + if hatching.count() > 0: + for hatch in hatching: + age = (now - hatch.date.date()).days + 1 + if age >= 1 and age <= 5: + quantity_1_5 += hatch.quantity + elif age >= 5 and age <= 10: + quantity_5_10 += hatch.quantity + elif age >= 10 and age <= 15: + quantity_10_15 += hatch.quantity + elif age >= 15 and age <= 20: + quantity_15_20 += hatch.quantity + elif age >= 20 and age <= 25: + quantity_20_25 += hatch.quantity + elif age >= 25 and age <= 30: + quantity_25_30 += hatch.quantity + elif age >= 30 and age <= 35: + quantity_30_35 += hatch.quantity + elif age >= 35 and age <= 40: + quantity_35_40 += hatch.quantity + elif age >= 40 and age <= 45: + quantity_40_45 += hatch.quantity + elif age >= 45 and age <= 50: + quantity_45_50 += hatch.quantity + elif age >= 50 and age <= 55: + quantity_50_55 += hatch.quantity + elif age >= 55 and age <= 60: + quantity_55_60 += hatch.quantity + out_put = { + 'quantity_1_5': quantity_1_5, + 'quantity_5_10': quantity_5_10, + 'quantity_10_15': quantity_10_15, + 'quantity_15_20': quantity_15_20, + 'quantity_20_25': quantity_20_25, + 'quantity_25_30': quantity_25_30, + 'quantity_30_35': quantity_30_35, + 'quantity_35_40': quantity_35_40, + 'quantity_40_45': quantity_40_45, + 'quantity_45_50': quantity_45_50, + 'quantity_50_55': quantity_50_55, + 'quantity_55_60': quantity_55_60, + + } + return Response(out_put, status=status.HTTP_200_OK) + elif 'age' in request.GET: + poultry = [] + poultry_hatching = PoultryHatching.objects.filter(state='pending') + now = datetime.now().date() + if poultry_hatching.count() > 0: + for hatch in poultry_hatching: + age = (now - hatch.date.date()).days + 1 + if age >= int(request.GET['age1']) and age <= int(request.GET['age2']): + if hatch.poultry in poultry: + pass + else: + poultry.append(hatch.poultry) + serializer = PoultrySerializer(poultry, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'amar' in request.GET: + now = datetime.now().date() + total_list = [] + l1 = [] + chickenbreed_list = ['وارداتی', 'آرین', 'راس', 'آربراکرز(آپلاس)', 'کاب', 'هوبارد', 'ترکیبی'] + for city in City.objects.all(): + for breed in chickenbreed_list: + quantity_1_5 = 0 + quantity_1_5_losses = 0 + quantity_5_10 = 0 + quantity_5_10_losses = 0 + quantity_10_15 = 0 + quantity_10_15_losses = 0 + quantity_15_20 = 0 + quantity_15_20_losses = 0 + quantity_20_25 = 0 + quantity_20_25_losses = 0 + quantity_25_30 = 0 + quantity_25_30_losses = 0 + quantity_30_35 = 0 + quantity_30_35_losses = 0 + quantity_35_40 = 0 + quantity_35_40_losses = 0 + quantity_40_45 = 0 + quantity_40_45_losses = 0 + quantity_45_50 = 0 + quantity_45_50_losses = 0 + quantity_50_55 = 0 + quantity_50_55_losses = 0 + quantity_55_60 = 0 + quantity_55_60_losses = 0 + hatchs = PoultryHatching.objects.filter(state='pending', poultry__address__city=city, + chicken_breed=breed) + if hatchs.count() > 0: + for hatch in hatchs: + age = (now - hatch.date.date()).days + 1 + if age >= 1 and age <= 5: + quantity_1_5 += hatch.quantity + quantity_1_5_losses += hatch.losses + elif age >= 5 and age <= 10: + quantity_5_10 += hatch.quantity + quantity_5_10_losses += hatch.losses + elif age >= 10 and age <= 15: + quantity_10_15 += hatch.quantity + quantity_10_15_losses += hatch.losses + elif age >= 15 and age <= 20: + quantity_15_20 += hatch.quantity + quantity_15_20_losses += hatch.losses + elif age >= 20 and age <= 25: + quantity_20_25 += hatch.quantity + quantity_20_25_losses += hatch.losses + elif age >= 25 and age <= 30: + quantity_25_30 += hatch.quantity + quantity_25_30_losses += hatch.quantity + elif age >= 30 and age <= 35: + quantity_30_35 += hatch.quantity + quantity_30_35_losses += hatch.losses + elif age >= 35 and age <= 40: + quantity_35_40 += hatch.quantity + quantity_35_40_losses += hatch.losses + elif age >= 40 and age <= 45: + quantity_40_45 += hatch.quantity + quantity_40_45_losses += hatch.losses + elif age >= 45 and age <= 50: + quantity_45_50 += hatch.quantity + quantity_45_50_losses += hatch.losses + elif age >= 50 and age <= 55: + quantity_50_55 += hatch.quantity + quantity_50_55_losses += hatch.losses + elif age >= 55 and age <= 60: + quantity_55_60 += hatch.quantity + quantity_55_60_losses += hatch.losses + internal_dict = { + 'quantity_1_5': quantity_1_5, + 'quantity_1_5_losses': quantity_1_5_losses, + 'quantity_5_10': quantity_5_10, + 'quantity_5_10_losses': quantity_5_10_losses, + 'quantity_10_15': quantity_10_15, + 'quantity_10_15_losses': quantity_10_15_losses, + 'quantity_15_20': quantity_15_20, + 'quantity_15_20_losses': quantity_15_20_losses, + 'quantity_20_25': quantity_20_25, + 'quantity_20_25_losses': quantity_20_25_losses, + 'quantity_25_30': quantity_25_30, + 'quantity_25_30_losses': quantity_25_30_losses, + 'quantity_30_35': quantity_30_35, + 'quantity_30_35_losses': quantity_30_35_losses, + 'quantity_35_40': quantity_35_40, + 'quantity_35_40_losses': quantity_35_40_losses, + 'quantity_40_45': quantity_40_45, + 'quantity_40_45_losses': quantity_40_45_losses, + 'quantity_45_50': quantity_45_50, + 'quantity_45_50_losses': quantity_45_50_losses, + 'quantity_50_55': quantity_50_55, + 'quantity_50_55_losses': quantity_50_55_losses, + 'quantity_55_60': quantity_55_60, + 'quantity_55_60_losses': quantity_55_60_losses, + + } + l1.append({breed: internal_dict}) + + total_list.append({city.name: l1}) + l1 = [] + + return Response(total_list, status=status.HTTP_200_OK) + + # list of self poultry houses + elif 'key' in request.GET: + poultry = Poultry.objects.get(key=request.GET['key'], trash=False) + if 'hall' in request.GET: + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, hall=int(request.GET['hall']), + state='pending', trash=False).order_by('date') + elif 'increase' in request.GET: + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, state='pending', + trash=False).order_by('date') + else: + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, state='pending', left_over__gt=0, + trash=False).order_by('date') + + elif 'role' in request.GET: + if 'age1' in request.GET and int(request.GET.get('age2')) > 0: + age1 = int(request.GET.get('age1')) + age2 = int(request.GET.get('age2')) + poultry_hatch = self.queryset.filter(trash=False, chicken_age__range=(age1, age2)) + else: + poultry_hatch = self.queryset.filter(trash=False) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user)) + city = city_operator.address.city + city_unit_list = [] + city_units = CityUnit.objects.filter(city=city) + for city in city_units: + city_unit_list.append(city.name) + poultry_hatching = poultry_hatch.filter(poultry__address__city__name__in=city_unit_list, + state__in=('pending', 'complete'), + trash=False).order_by( + '-create_date') + else: + poultry_hatching = poultry_hatch.filter(poultry__address__province=user.province, + # state__in=('pending', 'complete'), + trash=False).order_by( + '-create_date') + else: + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry = Poultry.objects.filter(user=user, trash=False) + + if poultry.count() > 1: + list1 = [] + for p in poultry: + list1.append(p.id) + poultry_hatching = PoultryHatching.objects.filter(poultry_id__in=list1, trash=False).order_by( + 'date') + + else: + + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry.last(), trash=False).order_by( + 'date') + serializer = PoultryHatchingSerializer(poultry_hatching, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + queryset = PoultryHatching.objects.get(key__exact=request.GET["key"], trash=False) + vet_farm_inspection = VetFarmInspection.objects.filter(poultry_hatching=queryset, trash=False) + poultry_request = PoultryRequest.objects.filter(hatching=queryset, trash=False) + if vet_farm_inspection.count() > 0: + return Response({"result": "object has inspection"}, status=status.HTTP_400_BAD_REQUEST) + elif poultry_request.count() > 0: + return Response({"result": "object has poultry_request"}, status=status.HTTP_403_FORBIDDEN) + queryset.trash = True + queryset.save() + # queryset.delete() + return Response({"result": "object deleted"}, status=status.HTTP_200_OK) + + +class PoultryHatchingForPredictionViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingForPredictionSerializer + pagination_class = CustomPagination + filterset_class = PoultryHatchingFilterSet + filterset_fields = [ + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__user__mobile', + 'poultry__unit_name', + 'poultry__address__city__name', + 'chicken_age', + 'poultry__breeding_unique_id', + 'poultry__city_operator', + + ] + + def list(self, request, *args, **kwargs): + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'hatching_list' in request.GET: + poultry_hatchings = PoultryHatching.objects.filter( + id__in=(request.GET['hatching_list']).split(',')).order_by('date') + else: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', + state='pending', + poultry__city_operator=city_operator.unit_name, + trash=False).order_by('date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', + state='pending', + poultry__address__city=user.city, + trash=False).order_by('date') + + else: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', + state='pending', + trash=False).order_by('date') + + if 'search' in request.GET: + hatching_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_hatchings + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_hatchings) + hatching_list = ps.filter() + poultry_hatchings = [] if len(hatching_list) == 0 else hatching_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_hatchings) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(poultry_hatchings, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryHatchingForPredictionDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingForPredictionSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + poultry__city_operator=city_operator.unit_name, + trash=False).order_by('date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry', 'CityVet']: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + poultry__address__city=user.city, + trash=False).order_by('date') + + else: + poultry_hatchings = PoultryHatching.objects.filter(archive=False, allow_hatching='pending', state='pending', + trash=False).order_by('date') + + now_ages = poultry_hatchings.aggregate(total=Sum('now_age'))['total'] or 0 + total_hatching_quantity = poultry_hatchings.aggregate(total=Sum('quantity'))['total'] or 0 + total_hatching_left_over = poultry_hatchings.aggregate(total=Sum('left_over'))['total'] or 0 + ave_now_age = now_ages / len(poultry_hatchings) if len(poultry_hatchings) > 0 else 0 + sum_age = 0 + ave_age = 0 + ave_weight = 0 + counter = 0 + poultry_requests = PoultryRequest.objects.filter(trash=False, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + out_province_request_cancel=False, + hatching__in=poultry_hatchings) + for poultry_request in poultry_requests: + sum_age += (poultry_request.send_date.date() - poultry_request.hatching.date.date()).days + 1 + counter += 1 + ave_age = int(sum_age / counter) if counter > 0 else 0 + + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), + province_request__poultry_request__hatching__in=poultry_hatchings, + first_car_allocated_quantity=0, + return_to_province=False) + + province_kill_requests_quantity = \ + province_kill_requests.aggregate(total=Sum('total_killed_quantity'))['total'] or 0 + + province_kill_requests_weight = \ + province_kill_requests.aggregate(total=Sum('total_killed_weight'))['total'] or 0 + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__hatching__in=poultry_hatchings) + + kill_house_requests_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house__requests_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + + total_quantity = province_kill_requests_quantity + kill_house_requests_quantity + total_weight = province_kill_requests_weight + kill_house__requests_weight + + ave_weight = round(total_weight / total_quantity, 2) if total_quantity > 0 else 0 + + result = { + "hatchings": len(poultry_hatchings), + "total_hatching_quantity": total_hatching_quantity, + "total_hatching_left_over": total_hatching_left_over, + "ave_age": ave_age, "ave_now_age": ave_now_age, + "ave_weight": ave_weight, + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "kill_house_requests": len(kill_house_requests), + "kill_house_requests_quantity": kill_house_requests_quantity, + "kill_house__requests_weight": kill_house__requests_weight, + "total_quantity": total_quantity, + "total_weight": total_weight + } + + return Response(result, status=status.HTTP_200_OK) + + +class PoultryHatchingForPredictionChartViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingForPredictionSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + consumption_limit_type = request.GET.get('consumption_limit_type') + consumption_limit = request.GET.get('consumption_limit') + killing_age_external_type = request.GET.get('killing_age_external_type') + killing_age_internal_type = request.GET.get('killing_age_internal_type') + killing_age = request.GET.get('killing_age') + time_frame_type = request.GET.get('time_frame_type') + date1 = request.GET.get('date1') + date2 = request.GET.get('date2') + date_list = [] + final_list = [] + + poultries = Poultry.objects.filter(killing_ave_age__gt=1, trash=False) + if killing_age_external_type == 'poultry_ave_killing_age': + if killing_age_internal_type == 'poultry': + if time_frame_type == 'all': + hatchings = PoultryHatching.objects.filter(trash=False, state='pending', + archive=False, temporary_trash=False, + temporary_deleted=False, predicate_date__isnull=False) + date_list = hatchings.values_list('predicate_date', flat=True).distinct() + for date in date_list: + n_hatchings = hatchings.filter(predicate_date=date) + poultries = Poultry.objects.filter(pk__in=n_hatchings.values_list('poultry', flat=True)) + ages = poultries.values_list('killing_ave_age', flat=True).distinct() + + index_weight = poultries.aggregate(total=Sum('real_killing_ave_weight'))[ + 'total'] or 0 + quantity = n_hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + + result = { + "date": date, + "quantity": quantity, + "poultry": len(poultries), + "age": ages, + "hatchings": n_hatchings.values_list('id', flat=True), + "weight": int(quantity * index_weight) if consumption_limit_type in ( + 'quantity', 'live_weight') else int((quantity * index_weight) * 0.75), + } + final_list.append(result) + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + hatchings = PoultryHatching.objects.filter(trash=False, state='pending', + archive=False, temporary_trash=False, + temporary_deleted=False, predicate_date__date__gte=date1, + predicate_date__date__lte=date2) + # poultries = poultries.filter(date__gte=date1,date__lte=date2).order_by('date') + date_list = poultries.values_list('date', flat=True).distinct() + + for date in date_list: + n_hatchings = hatchings.filter(predicate_date__date=date) + poultries = Poultry.objects.filter(pk__in=n_hatchings.values_list('poultry', flat=True)) + ages = poultries.values_list('killing_ave_age', flat=True).distinct() + + index_weight = poultries.aggregate(total=Sum('real_killing_ave_weight'))[ + 'total'] or 0 + quantity = n_hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + result = { + "date": date, + "quantity": quantity, + "poultry": len(poultries.filter(date=date)), + "age": ages, + "hatchings": n_hatchings.values_list('id', flat=True), + "weight": int(quantity * index_weight) if consumption_limit_type in ( + 'quantity', 'live_weight') else int((quantity * index_weight) * 0.75), + } + final_list.append(result) + + else: + sum_of_ages = poultries.aggregate(total=Sum('killing_ave_age'))[ + 'total'] or 0 + ave_killing_age = int(sum_of_ages / len(poultries)) + if time_frame_type == 'all': + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type) + + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1, date2) + + else: + if killing_age_internal_type == 'poultry': + if time_frame_type == 'all': + final_list = poultry_prediction_helper(int(killing_age), consumption_limit_type) + # poultries = poultries.filter(killing_ave_age=int(killing_age)) + # date_list = poultries.values_list('date', flat=True).distinct() + # for date in date_list: + # index_weight = poultries.filter(date=date).aggregate(total=Sum('killing_ave_weight'))[ + # 'total'] or 0 + # quantity = poultries.filter(date=date).aggregate(total=Sum('active_left_over'))[ + # 'total'] or 0 + # + # result = { + # "date": date, + # "quantity": quantity, + # "poultry": len(poultries.filter(date=date)), + # "age": int(killing_age), + # "wight": quantity * index_weight, + # } + # final_list.append(result) + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(int(killing_age), consumption_limit_type, date1, date2) + + # poultries = poultries.filter(killing_ave_age=int(killing_age),date__gte=date1,date__lte=date2) + # date_list = poultries.values_list('date', flat=True) + # for date in date_list: + # index_weight = poultries.filter(date=date).aggregate(total=Sum('killing_ave_weight'))[ + # 'total'] or 0 + # quantity = poultries.filter(date=date).aggregate(total=Sum('active_left_over'))[ + # 'total'] or 0 + # + # result = { + # "date": date, + # "quantity": quantity, + # "poultry": len(poultries.filter(date=date)), + # "age": int(killing_age), + # "wight": quantity * index_weight, + # } + # final_list.append(result) + + else: + + ave_killing_age = int(killing_age) + + if time_frame_type == 'all': + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type) + + + + else: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + final_list = poultry_prediction_helper(ave_killing_age, consumption_limit_type, date1, date2) + + return Response(final_list) + + +class PoultryTenantViewSet(viewsets.ModelViewSet): + queryset = PoultryTenant.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryTenantSerializer + + +# ویوست مربوط به ثبت و نمایش و ... درخواست بورسی مرغدار +class PoultryRequestExchangeViewSet(viewsets.ModelViewSet): + queryset = PoultryRequestExchange.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryRequestExchangeSerializer + + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestExchangeFilterSet + filterset_fields = [ + 'quantity', + 'send_date', + 'chicken_breed', + 'Index_weight', + 'fee', + 'age', + ] + + # تابع مربوط به ثبت درخواست بورسی مرغدار + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + user = UserProfile.objects.get(user=request.user, trash=False) + send_date = request.data['send_date'] + hatching_date = request.data['hatching_date'] + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + poultry_request_exchange = serializer.create(validated_data=request.data) + send_date = datetime.strptime(send_date, '%Y-%m-%d %H:%M:%S').date() + hatching_date = datetime.strptime(hatching_date, '%Y-%m-%d %H:%M:%S').date() + poultry_request_exchange.age = (send_date - hatching_date).days + poultry_request_exchange.user = user + poultry_request_exchange.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به نمایش درخواست بورسی مرغدار + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + queryset = [] + list1 = [] + values_item = [] + query_list = [] + query_dictionary = {} + query_list_obj = [] + filter_list = [] + obj_list = [] + q2 = [] + + if 'operator' in request.GET: + if request.GET['operator'] == 'kill_house': + chicken_breed = request.GET['chicken_breed'].split(",") + send_date1 = request.GET['send_date1'].strip() + send_date2 = request.GET['send_date2'].strip() + send_date1 = datetime.strptime(send_date1, '%Y-%m-%d').date() + send_date2 = datetime.strptime(send_date2, '%Y-%m-%d').date() + q = PoultryRequestExchange.objects.filter(chicken_breed__in=chicken_breed, trash=False).order_by( + 'fee') + for x in q: + if x.send_date.date() >= send_date1 and x.send_date.date() <= send_date2: + q2.append(x) + serializer = self.serializer_class(q2, many=True) + return Response(serializer.data) + + if 'type' in request.GET: + if request.GET['type'] == 'filter': + if request.GET['value'] != "": + d1 = request.GET['value'].split(",") + for item in self.filterset_fields: + for x in d1: + query = QueryDict('{0}__contains={1}'.format(item, x)) + if (self.filterset_class(data=query, queryset=self.queryset.all())).filter(): + query_list.append(query) + + for i in query_list: + for key, value in i.items(): + query_dictionary[key] = value + if len(d1) != len(query_dictionary): + pass + else: + for i in PoultryRequestExchange.objects.filter(**query_dictionary): + query_list_obj.append(i) + + if 'age_period' in request.GET: + if request.GET['age_period'] != "": + age_split = request.GET['age_period'].split(',') + for item in self.queryset: + if int(age_split[0]) <= item.age <= int(age_split[1]): + obj_list.append(item) + for i in obj_list: + for j in query_list_obj: + if i == j: + filter_list.append(i) + query_list_obj.clear() + for i in filter_list: + query_list_obj.append(i) + + serializer = self.serializer_class(query_list_obj, many=True) + return Response(serializer.data) + return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN) + + queryset = PoultryRequestExchange.objects.all() + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data) + + +# ویوست مربوط به تایید یا رد درخواست بورسی رزرو شده توسط کشتارگاه برای درخواست بورسی مرغدار +class PoultryRequestExchangeAcceptViewSet(viewsets.ModelViewSet): + queryset = PoultryRequestExchangeAccept.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryRequestExchangeAcceptSerializer + + # تابع مربوط به تایید یا رد درخواست بورسی رزرو شده توسط کشتارگاه برای درخواست بورسی مرغدار + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + poultry_exchange = PoultryRequestExchange.objects.get(key=request.data['poultry_request_key'], trash=False) + kill_house_exchange_reserve = KillHouseRequestExchangeReserve.objects.get( + key=request.data['kill_house_request_key'], trash=False) + request.data.pop('poultry_request_key') + request.data.pop('kill_house_request_key') + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + poultry_request_exchange_accept = serializer.create(validated_data=request.data) + poultry_request_exchange_accept.poultry_request_exchange = poultry_exchange + poultry_request_exchange_accept.kill_house_request_exchange_reserve = kill_house_exchange_reserve + poultry_request_exchange_accept.save() + if poultry_request_exchange_accept.state == 'accepted': + poultry_exchange.quantity -= kill_house_exchange_reserve.quantity + poultry_exchange.state = 'pending' + poultry_exchange.save() + kill_house_exchange_reserve.state = 'accepted' + else: + kill_house_exchange_reserve.state = 'rejected' + + kill_house_exchange_reserve.save() + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + +# ویوست مربوط به ثبت و نمایش و ... درخواست مرغدار + +class PoultryRequestForLetterViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + date = datetime.datetime.strptime(str(request.GET['date']), '%Y-%m-%d').date() + poultry_requests = PoultryRequest.objects.filter(send_date__date=date, + quantity__gt=F('remain_quantity'), + trash=False) + serializer = PoultryRequestLetterTotalSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class CancelOutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def update(self, request, pk=None, *args, **kwargs): + date = datetime.datetime.now() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.data['role'] + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + if poultry_request.quarantine_code != None: + return Response({"result": "به علت ورود کد قرنطینه امکان لغو وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if poultry_request.wage_pay == True: + return Response({"result": "به علت پرداخت امکان لغو وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + poultry_request.out_province_request_cancel = True + poultry_request.out_province_request_canceller = { + "role": role, + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(date), + } + poultry_request.save() + if poultry_request.province_state == 'accepted': + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + hatching.out_province_killed_weight -= int(poultry_request.quantity * poultry_request.Index_weight) + hatching.out_province_killed_quantity -= poultry_request.quantity + hatching.save() + return Response({"result": "با موفقیت ثیت شد"}, status=status.HTTP_200_OK) + + +class OutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + state = request.GET['state'] + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + if state == 'pending': + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + if request.GET['state'] == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='rejected', + province_state='rejected', + has_wage=True, wage_pay=False, + out_province_request_cancel=True, archive=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=True, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=True, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + + if 'search' in request.GET: + poultry_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_requests) + poultry_request_list = ps.filter() + poultry_requests = [] if len(poultry_request_list) == 0 else poultry_request_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_requests) + if page is not None: + serializer = PoultryRequestoutProvinceSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = PoultryRequestoutProvinceSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + poultry_request.out_province_driver_info['driverhealthCode'] = request.data['driver_health_code'] + poultry_request.save() + return Response({"result": "با موفقیت ثیت شد"}, status=status.HTTP_200_OK) + + +class OutProvincePoultryRequestDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + poultry_requests = PoultryRequest.objects.filter( + poultry__in=poultries, + out=True, + temporary_trash=False, + temporary_deleted=False, + trash=False).order_by('-send_date') + + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_requests = PoultryRequest.objects.filter( + poultry__city_operator=city_operator.unit_name, + temporary_trash=False, + temporary_deleted=False, + out=True, + trash=False).order_by('-send_date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = PoultryRequest.objects.filter( + poultry__address__city=user.city, + temporary_trash=False, + temporary_deleted=False, + out=True, + trash=False).order_by('-send_date') + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX', 'Supporter']: + poultry_requests = PoultryRequest.objects.filter( + out=True, + temporary_trash=False, + temporary_deleted=False, + trash=False).order_by('-send_date') + if 'date1' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_requests = poultry_requests.filter(send_date__date__gte=date1, send_date__date__lte=date2) + + if 'search' in request.GET: + poultry_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_requests) + poultry_request_list = ps.filter() + poultry_requests = [] if len(poultry_request_list) == 0 else poultry_request_list + + poultry = Poultry.objects.filter(trash=False, pk__in=poultry_requests.values_list('poultry', flat=True)) + total_out_province_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_out_province_poultry_request_weight = \ + poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + accepted_poultry_requests_with_out_wage = poultry_requests.filter( + state_process='accepted', province_state='accepted', final_state='archive', + out_province_request_cancel=False, has_wage=False, wage_pay=False, + ) + + total_accepted_poultry_request_quantity_with_out_wage = \ + accepted_poultry_requests_with_out_wage.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + + total_accepted_poultry_request_weight_with_out_wage = \ + accepted_poultry_requests_with_out_wage.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + paid_poultry_requests = poultry_requests.filter( + state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True, out_province_request_cancel=False + ) + + total_paid_poultry_request_quantity = paid_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + + total_paid_poultry_request_weight = \ + paid_poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + result = { + "poultries": len(poultry), + "total_number_of_poultry_request": len(poultry_requests), + "total_poultry_request_quantity": total_out_province_poultry_request_quantity, + "total_poultry_request_weight": total_out_province_poultry_request_weight, + "total_number_of_accepted_poultry_request_with_out_wage": len(accepted_poultry_requests_with_out_wage), + "total_accepted_poultry_request_quantity_with_out_wage": total_accepted_poultry_request_quantity_with_out_wage, + "total_accepted_poultry_request_weight_with_out_wage": total_accepted_poultry_request_weight_with_out_wage, + "total_number_of_accepted_poultry_request_with_wage": len(paid_poultry_requests), + "total_accepted_poultry_request_quantity_with_wage": total_paid_poultry_request_quantity, + "total_accepted_poultry_request_weight_with_wage": total_paid_poultry_request_weight, + "total_number_of_accepted_poultry_request": len(accepted_poultry_requests_with_out_wage) + len( + paid_poultry_requests), + "total_accepted_poultry_request_quantity": total_paid_poultry_request_quantity + total_accepted_poultry_request_quantity_with_out_wage, + "total_accepted_poultry_request_weight": total_paid_poultry_request_weight + total_accepted_poultry_request_weight_with_out_wage, + + } + + return Response(result, status=status.HTTP_200_OK) + + +class ParentCompanyOutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + def list(self, request, *args, **kwargs): + state = request.GET['state'] + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['state'] == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='rejected', + province_state='rejected', + has_wage=True, wage_pay=False, + out_province_request_cancel=True, archive=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=True, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=True, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + + if 'search' in request.GET: + poultry_request_list = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "" and request.GET['value'] != 'undefined': + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (self.filterset_class( + data=query, + queryset=poultry_requests + ) + ).filter(): + ps = self.filterset_class(data=query, queryset=poultry_requests) + poultry_request_list = ps.filter() + poultry_requests = [] if len(poultry_request_list) == 0 else poultry_request_list + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(poultry_requests) + if page is not None: + serializer = PoultryRequestoutProvinceSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + serializer = PoultryRequestoutProvinceSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class TemporaryOutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + + + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif request.GET['role'] in ['ProvinceOperator', 'SuperAdmin', 'AdminX']: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + serializer = PoultryRequestoutProvinceSerializer(poultry_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def update(self, request, pk=None, *args, **kwargs): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + poultry_request.out_province_driver_info['driverhealthCode'] = request.data['driver_health_code'] + poultry_request.save() + return Response({"result": "با موفقیت ثیت شد"}, status=status.HTTP_200_OK) + + +class PoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + pagination_class = CustomPagination + permission_classes = [TokenHasReadWriteScope] + filter_backends = [DjangoFilterBackend] + # filterset_class = PoultryRequestFilterSet + filterset_fields = [ + 'order_code', + 'poultry__user__mobile', + 'poultry__user__fullname', + 'poultry__user__first_name', + 'poultry__user__last_name', + 'poultry__address__city__name', + + ] + + # تابع مربوط به ثبت درخواست مرغدار + def create(self, request, *args, **kwargs): + request_buyer = None + traffic_codes = None + vet = None + if 'kill_req_key' in request.data.keys(): + if request.data['kill_req_key'] is not None: + kill_request = KillRequest.objects.get(key=request.data['kill_req_key']) + if request.data['quantity'] > (kill_request.kill_capacity - kill_request.remain_quantity_for_poultry): + return Response({"result": "تعداد وارد شده از باقی مانده ظرفیت کشتارگاه انتخابی بیشتر است!"}, + status=status.HTTP_403_FORBIDDEN) + kill_request.remain_quantity_for_poultry += request.data['quantity'] + kill_request.save() + request.data.pop('kill_req_key') + wage_type = WageType.objects.filter(en_name='poultry-sell-out-province', trash=False).first() + time_range = TimeRange.objects.filter(trash=False).first() + if time_range: + time = next( + (t for t in time_range.time_range if t.get("name") == "poultry_request" and t.get("active", False)), + None) + if time: + + start_hour = datetime.datetime.strptime(time.get("start", 0), "%H:%M:%S").time() + end_hour = datetime.datetime.strptime(time.get("end", 0), "%H:%M:%S").time() + current_hour = datetime.datetime.now().time().replace(second=0, microsecond=0) + if not (start_hour < current_hour < end_hour): + return Response( + {"result": "لطفا در ساعات مجاز برای ثبت درخواست اقدام نمایید!"}, + status=status.HTTP_403_FORBIDDEN) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + last_poultry_request = PoultryRequest.objects.all() + if last_poultry_request.count() > 0: + general_order_code = last_poultry_request.last().general_order_code + 1 + else: + general_order_code = 1 + + now_request_date = datetime.datetime.now().date() + now = datetime.datetime.now().time() + now_hour = HourLimit.objects.all() + if now_hour.count() > 0: + now_hour = now_hour.last() + if now_hour.active == True: + request_date = datetime.datetime.strptime(request.data['send_date'], '%Y-%m-%d').date() + if request_date.year >= now_request_date.year and request_date.month >= now_request_date.month and request_date.day > now_request_date.day: + pass + + else: + if now.hour >= now_hour.hour: + text = 'زمان ثبت درخواست کشتار درامروز تا ساعت {0} بوده است. شما میتوانید برای تاریخ های آینده درخواست ثبت نمایید ! '.format( + now_hour.hour) + if 'role' not in request.data.keys(): + return Response({'result': text}, status=status.HTTP_403_FORBIDDEN) + poultry_hatching = PoultryHatching.objects.get(key=request.data['poultry_hatching_key'], trash=False) + vet = VetFarm.objects.filter(poultry=poultry_hatching.poultry, trash=False).last() + free_sale_with_province = FreeSaleWithinprovince.objects.filter(trash=False).first() + if poultry_hatching.poultry.order_limit: + return Response( + {"result": "امکان ثبت کشتار برای مرغدار وجود ندارد جهت اطلاعات بیشتر بااتحادیه استان خود هماهنگ کنید!"}, + status=status.HTTP_403_FORBIDDEN) + # if RequestLimitation.objects.filter(trash=False).first().limitation: + # if ('out' in request.data.keys() and request.data['out'] == True) or ( + # 'free_sale_in_province' in request.data.keys() and request.data['free_sale_in_province'] == True): + # free_sale_state = FreeSaleWithinprovince.objects.filter(trash=False).first() + # if free_sale_state and free_sale_state.allow: + # percent = (free_sale_state.percent - 10)/100 + # govermental_quantity = percent * poultry_hatching.quantity + # govermental_poultry_requests = PoultryRequest.objects.filter(state_process__in=('pending','accepted'),province_state__in=('pending','accepted'),out=False,free_sale_in_province=False, trash=False, hatching=poultry_hatching) + # govermental_poultry_requests_sum = \ + # govermental_poultry_requests.aggregate(total=Sum('quantity'))[ + # 'total'] or 0 + # if govermental_poultry_requests_sum < govermental_quantity: + # return Response({"result": "امکان فروش آزاد تا تکمیل تعهد دولتی وجود ندارد!"}, + # status=status.HTTP_403_FORBIDDEN) + + # Q(direct_buying=True) | Q(out=True, wage_pay=True) | Q(free_sale_in_province=True), + # state_process='accepted', province_state='accepted', trash=False, hatching=poultry_hatching) + + if free_sale_with_province.allow == True: + if ('out' in request.data.keys() and request.data['out'] == True) or ( + 'free_sale_in_province' in request.data.keys() and request.data['free_sale_in_province'] == True): + poultry_requests_for_free_sale = PoultryRequest.objects.filter( + Q(direct_buying=True) | Q(out=True, wage_pay=True) | Q(free_sale_in_province=True), + state_process='accepted', province_state='accepted', trash=False, hatching=poultry_hatching) + poultry_requests_for_free_sale_sum = poultry_requests_for_free_sale.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + if poultry_requests_for_free_sale_sum + request.data[ + 'quantity'] > poultry_hatching.total_free_commitment_quantity: + return Response({"result": "مجموع حجم کشتار آزاد از حجم کل تعهد آزاد بیشتر است "}, + status=status.HTTP_403_FORBIDDEN) + if 'role' in request.data.keys() and request.data['role'] not in ('AdminX', 'SuperAdmin'): + + age_range = ChickenAgeRange.objects.filter(trash=False).first() + if age_range.active == True: + chicken_age = (datetime.datetime.strptime(request.data['send_date'], + '%Y-%m-%d').date() - poultry_hatching.date.date()).days + 1 + if chicken_age < age_range.minimum or chicken_age > age_range.maximum: + return Response( + {"result": "به علت استاندارد نبودن سن مرغ برای کشتار امکان ثبت درخواست وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if 'role' in request.data.keys(): + role = request.data['role'] + poultry_object = Poultry.objects.get(key=request.data['poultry_key']) + request.data.pop('role') + request.data.pop('poultry_key') + if role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user, trash=False) + if city_operator.unit_name != poultry_object.city_operator: + poultry_city = poultry_object.city_operator + return Response({"result": "مرغدار زیر مجموعه {0} است !".format(poultry_city)}, + status=status.HTTP_403_FORBIDDEN) + + else: + role = None + poultry_object = None + if 'operator_key' in request.data.keys(): + if request.data['operator_key'] == None or request.data['operator_key'] == "": + c_operator = None + + else: + c_operator = CityOperator.objects.get(key=request.data['operator_key']) + request.data.pop('operator_key') + else: + c_operator = None + auction_list = request.data['auction_list'] + request.data.pop('poultry_hatching_key') + request.data.pop('auction_list') + if auction_list != None: + for auction in auction_list: + pricing = Pricing.objects.get(key=auction['pricing_key'], trash=False) + if pricing.ceiling_price < int(auction['fee']): + return Response({"result": "fee is more than celling price"}, status=status.HTTP_403_FORBIDDEN) + if role != None: + poultry = poultry_object + user = SystemUserProfile.objects.get(key=poultry_object.user.key, trash=False) + else: + poultry = Poultry.objects.get(id=poultry_hatching.poultry.id, trash=False) + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_requests = PoultryRequest.objects.filter(poultry__user=poultry.user, trash=False).order_by( + 'create_date') + if poultry_hatching.left_over < int(request.data['quantity']) or poultry_hatching.left_over < int( + request.data['quantity']) + int(request.data['losses']): + return Response({"result": "تعداد درخواست از باقی مانده سالن بیشتر است!"}, status=status.HTTP_403_FORBIDDEN) + + cash = request.data['cash'] + credit = request.data['credit'] + request.data.pop('cash') + request.data.pop('credit') + dict1 = {} + new_date = datetime.datetime.strptime(request.data['send_date'], '%Y-%m-%d').date() + change_date = datetime.datetime(year=new_date.year, month=new_date.month, day=new_date.day, hour=now.hour, + minute=now.minute, + second=now.second) + request.data.pop('send_date') + if 'out_province_poultry_request_buyer_key' in request.data.keys(): + if request.data['out_province_poultry_request_buyer_key'] != None: + request_buyer = OutProvincePoultryRequestBuyer.objects.get( + key=request.data['out_province_poultry_request_buyer_key']) + out_province_request_limitation = PoultryOutProvinceRequest.objects.filter(trash=False).first() + if role and role not in ('AdminX', 'SuperAdmin'): + if out_province_request_limitation: + if out_province_request_limitation.allow: + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, + hatching=poultry_hatching, + out_province_request_cancel=False, + state_process__in=( + 'pending', 'accepted'), + province_state__in=( + 'pending', 'accepted')) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + if poultry_hatching.quantity * ( + out_province_request_limitation.limitation / 100) < out_poultry_requests_quantity + \ + request.data['quantity']: + return Response( + {"result": " تعداد وارد شده بیشتر از ظرفیت فروش به خارج استان برای مرغدار است ! "}, + status=status.HTTP_403_FORBIDDEN) + # request.data.pop('out_province_poultry_request_buyer_key') + if wage_type and wage_type.status == False: + request.data.pop('payer_type') + request.data.pop('poultry_mobile') + request.data.pop('buyer_mobile') + + else: + if 'poultry_mobile' in request.data.keys() and request.data['poultry_mobile'] is not None: + if poultry_hatching.poultry.user.mobile != request.data['poultry_mobile']: + first_mobile_number = poultry_hatching.poultry.user.mobile + second_mobile_number = request.data['poultry_mobile'] + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + poultry_user = User.objects.get(id=system_user_profile.user.id) + + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + poultry_user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + elif 'buyer_mobile' in request.data.keys() and request.data['buyer_mobile'] is not None: + if request_buyer.user.mobile != request.data['buyer_mobile']: + first_mobile_number = request_buyer.user.mobile + second_mobile_number = request.data['buyer_mobile'] + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + buyer_user = User.objects.get(id=system_user_profile.user.id) + + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + buyer_user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + request_buyer.mobile = second_mobile_number + request_buyer.save() + request.data.pop('poultry_mobile') + request.data.pop('buyer_mobile') + + request.data.pop('out_province_poultry_request_buyer_key') + + if 'confirm_poultry_mobile' in request.data.keys(): + if request.data.get('confirm_poultry_mobile') != "": + first_mobile_number = poultry.user.mobile + second_mobile_number = request.data['confirm_poultry_mobile'] + if first_mobile_number != second_mobile_number: + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + system_person = SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False) + if system_person: + return Response({"result": f'این شماره در سامانه به نام {system_person.first().fullname} است'}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + system_user_profile.user.username = second_mobile_number + system_user_profile.user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + request.data.pop('confirm_poultry_mobile') + if 'traffic_codes' in request.data: + traffic_codes = request.data.get('traffic_codes', []) + request.data.pop('traffic_codes') + if 'market' in request.data and request.data['market']: + if MarketDailyLimitation.objects.filter(active=True).exists(): + market_result = market_daily_limitation_info() + if request.data['quantity'] > market_result['remain_quantity']: + return Response({"result": "تعداد وارد شده از باقی مانده سقف کشتار معاملات بیشتر است!"}, + status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + poultry_request = serializer.create(validated_data=request.data) + price_confirmation = PriceConfirmation.objects.filter(trash=False).first() + price_confirmation = price_confirmation.poultry_status if price_confirmation else False + + poultry_request.general_order_code = general_order_code + poultry_request.send_date = change_date + poultry_request.killing_age = (poultry_request.send_date.date() - poultry_hatching.date.date()).days + 1 + if request_buyer != None: + poultry_request.out_province_poultry_request_buyer = request_buyer + poultry_request.buyer_mobile = request_buyer.mobile + poultry_request.buyer_fullname = request_buyer.fullname + poultry_request.buyer_city = request_buyer.city + poultry_request.buyer_province = request_buyer.province + if int(poultry_request.losses) > 0: + poultry_hatching.losses += int(poultry_request.losses) + poultry_hatching.save() + poultry_request.poultry = poultry + poultry_request.hatching = poultry_hatching + if vet: + poultry_request.vet_farm = vet.vet + city = poultry.address.city.name + city_unit = CityUnit.objects.filter(name=city, trash=False) + if c_operator != None: + main_operator = c_operator.user.first_name + " " + c_operator.user.last_name + city_operator_user = c_operator + + else: + if city_unit.count() > 0: + city_operator_user = CityOperator.objects.filter(address__city__name=city_unit[0].city.name, + trash=False) + if city_operator_user.count() > 0: + city_operator_user = city_operator_user.last() + else: + city_operator_user = CityOperator.objects.filter(address__city__province_center=True, + trash=False) + city_operator_user = city_operator_user.last() + + else: + city_operator_user = CityOperator.objects.filter(address__city__name=city, trash=False) + if city_operator_user.count() > 0: + city_operator_user = city_operator_user.last() + else: + city_operator_user = CityOperator.objects.filter(address__city__province_center=True, + trash=False) + city_operator_user = city_operator_user.last() + + main_operator = city_operator_user.user.first_name + " " + city_operator_user.user.last_name + poultry_request.state = { + "city_operator": main_operator, + "city_state": poultry_request.state_process, + "city_operator_mobile": city_operator_user.user.mobile, + "province_operator": "", + "province_state": "" + } + + if poultry_requests.count() > 0: + poultry_request.order_code = poultry_requests.last().order_code + 1 + else: + poultry_request.order_code = int(str(user.base_order) + '0001') + + poultry_request.save() + if len(auction_list) > 0: + for auction in auction_list: + poultry_request_auction = PoultryRequestAuction( + poultry_request=poultry_request, + pricing=Pricing.objects.all().last(), + fee=auction['fee'], + hour=auction['hour'] + ) + poultry_request_auction.save() + dict1.update({ + 'cash': cash, + 'credit': credit + }) + poultry_request.cell_type = dict1 + poultry_request.city_operator = city_operator_user + if role != None: + system_user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_request.registrar = { + "role": role, + "fullname": system_user.fullname, + "date": str(poultry_request.create_date) + } + if poultry_request.out_province_poultry_request_buyer != None: + poultry_request.out = True + # if role != None and role == 'ProvinceOperator': + # poultry_request.state_process = 'accepted' + # poultry_request.province_state = 'accepted' + # poultry_request.final_state = 'archive' + poultry_request.previous_quantity = int(request.data['quantity']) + poultry_request.remain_quantity = int(request.data['quantity']) + poultry_request.first_quantity = int(request.data['quantity']) + poultry_request.save() + + message = UserMessage(message="درخواست شما با کد سفارش {0} در انتطار تایید کارشناس شهرستان/{1}".format( + poultry_request.order_code, main_operator)) + message.save() + message.users.add(user) + vet_farm = VetFarm.objects.filter(poultry=poultry_hatching.poultry, hall=poultry_hatching.hall, + state='pending') + if vet_farm.count() > 0: + vet_farm = vet_farm.last() + inspections = VetFarmInspection.objects.filter(vet_farm=vet_farm, hall=vet_farm.hall, + state='pending') + for inspection in inspections: + inspection.state = 'complete' + inspection.save() + vet_farm.save() + if SmsLicense.objects.filter(poultry_request=True).exists(): + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + poultry_fullname = poultry_request.poultry.unit_name + poultry_mobile = poultry_request.poultry.user.mobile + quantity = poultry_request.quantity + chicken_breed = poultry_request.chicken_breed + order_code = poultry_request.order_code + request_kill_house = poultry_request.kill_house_list[0] if poultry_request.kill_house_list else "-" + date_str = poultry_request.send_date + send_date = datetime.datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + province_operator_mobile = province_operator.user.mobile + + sms_operator_poultry_request_sms = threading.Thread(target=operator_poultry_request_sms, + args=( + province_operator_mobile, poultry_fullname, + quantity, chicken_breed, + order_code, send_date, + poultry_request.free_sale_in_province, + poultry_request.amount, request_kill_house, + poultry_mobile)) + sms_operator_poultry_request_sms.start() + + if poultry_request.out_province_poultry_request_buyer != None: + vet = VetFarm.objects.filter(trash=False, poultry=poultry_request.poultry).first() + vet_number = vet.vet.user.mobile if vet else None + if wage_type and wage_type.status == False: + sms_operator_out_poultry_request_sms = threading.Thread(target=operator_out_poultry_request_sms, + args=( + province_operator_mobile, + poultry_fullname, + quantity, chicken_breed, + order_code, send_date, + poultry_request.free_sale_in_province, + poultry_request.amount, + vet_number + )) + sms_operator_out_poultry_request_sms.start() + + if role != None and role == 'ProvinceOperator' and poultry_request.out == False: + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=True, + province_state='accept', + allow_hatching=True + + ) + city_operator_check_request.save() + province_operator = ProvinceOperator.objects.filter( + user=SystemUserProfile.objects.get(role__name='ProvinceOperator', province=user.province)) + + if province_operator.count() > 0: + province_operator = province_operator.last() + check = ProvinceCheckOperatorRequest( + province_operator_system=province_operator, + poultry_request=poultry_request, + city_request_Poultry=city_operator_check_request, + quantity=poultry_request.quantity, + + state='accept', + ) + check.save() + poultry_request.state_process = 'accepted' + poultry_request.province_state = 'accepted' + if poultry_request.city_operator.address.city.name == 'فاقد شهرستان': + poultry_request.archive = True + poultry_request.save() + + elif role != None and role == 'CityOperator' and poultry_request.out == False: + + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=False, + province_state='pending', + allow_hatching=True + + ) + city_operator_check_request.save() + poultry_request.state_process = 'accepted' + if poultry_request.city_operator.address.city.name == 'فاقد شهرستان': + poultry_request.archive = True + poultry_request.save() + else: + if poultry_request.city_operator.address.city.name == 'فاقد شهرستان': + city_operator_check_request = CityOperatorCheckRequest( + city_operator_system=poultry_request.city_operator, + poultry_request=poultry_request, + state='accept', + province_accept=False, + province_state='pending', + allow_hatching=True + + ) + city_operator_check_request.save() + if poultry_request.city_operator.address.city.name == 'فاقد شهرستان': + poultry_request.archive = True + poultry_request.state_process = 'accepted' + poultry_request.save() + if poultry_request.out == True: + if wage_type and wage_type.status == True: + poultry_request.has_wage = True + if poultry_request.payer_type == 'buyer': + poultry_request.payer_fullname = poultry_request.out_province_poultry_request_buyer.fullname + else: + poultry_request.payer_fullname = poultry_request.poultry.user.fullname + poultry_request.save() + wage = wage_type.amount + poultry_request.wage = wage + percentages_wage_type = PercentageOfWageType.objects.filter(wage_type=wage_type, percent__gt=0, + trash=False) + + if percentages_wage_type: + poultry_request.total_wage_amount = int( + (poultry_request.Index_weight * poultry_request.quantity) * wage) + # fine = FinePermission.objects.filter(trash=False).first() + # time_for_fine = datetime.datetime.now() + # time_for_fine = time_for_fine.replace(second=0, microsecond=0).time() + # if fine.out_poultry_request: + # if fine.out_poultry_request_start_time < time_for_fine < fine.out_poultry_request_end_time: + # poultry_request.fine = True + # poultry_request.fine_amount = fine.out_poultry_request_fine_coefficient * poultry_request.total_wage_amount + # poultry_request.fine_coefficient = fine.out_poultry_request_fine_coefficient + + for percentage_wage_type in percentages_wage_type: + if percentage_wage_type.share_type.en_name == 'union': + poultry_request.union_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.union_share_percent = percentage_wage_type.percent + poultry_request.save() + elif percentage_wage_type.share_type.en_name == 'company': + poultry_request.company_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.company_share_percent = percentage_wage_type.percent + poultry_request.save() + + elif percentage_wage_type.share_type.en_name == 'guilds': + poultry_request.guilds_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.guilds_share_percent = percentage_wage_type.percent + poultry_request.save() + elif percentage_wage_type.share_type.en_name == 'city': + poultry_request.city_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.city_share_percent = percentage_wage_type.percent + poultry_request.save() + + elif percentage_wage_type.share_type.en_name == 'wallet': + poultry_request.wallet_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.wallet_share_percent = percentage_wage_type.percent + poultry_request.save() + + else: + poultry_request.other_share = int( + (percentage_wage_type.percent / 100) * poultry_request.total_wage_amount) + poultry_request.other_share_percent = percentage_wage_type.percent + poultry_request.save() + # poultry_prediction(poultry_hatching.poultry) + + if price_confirmation and not poultry_request.out: + poultry_fullname = poultry_request.poultry.unit_name + poultry_mobile = poultry_request.poultry.user.mobile + quantity = poultry_request.quantity + chicken_breed = poultry_request.chicken_breed + order_code = poultry_request.order_code + request_kill_house = poultry_request.kill_house_list[0] if poultry_request.kill_house_list else "-" + date_str = poultry_request.send_date + send_date = datetime.datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + day=send_date.day).strftime('%Y-%m-%d') + date_list = reversed(send_date.split('-')) + separate = "-" + send_date = separate.join(date_list) + + # poultry_fullname = poultry_request.poultry.unit_name + # poultry_mobile = poultry_request.poultry.user.mobile + # quantity = poultry_request.quantity + # chicken_breed = poultry_request.chicken_breed + # date_str = poultry_request.send_date + # send_date = datetime.datetime.strptime(str(date_str), '%Y-%m-%d %H:%M:%S').date() + # send_date = jdatetime.datetime.fromgregorian(year=send_date.year, month=send_date.month, + # day=send_date.day).strftime('%Y-%m-%d') + # date_list = reversed(send_date.split('-')) + # separate = "-" + # send_date = separate.join(date_list) + # confirm_code = ''.join(random.choices(string.ascii_lowercase + string.digits, k=5)) + confirm_code = str(random.randint(10000, 99000)) + confirm_price_poultry_request = threading.Thread(target=confirm_price_poultry_request_sms, + args=( + poultry_mobile, poultry_fullname, + quantity, chicken_breed, + order_code, send_date, + poultry_request.free_sale_in_province, + poultry_request.amount, request_kill_house, + confirm_code)) + confirm_price_poultry_request.start() + poultry_request.price_confirmation_code = confirm_code + poultry_request.price_confirmation = True + poultry_request.save() + if poultry_request.market == True: + send_sms_for_poultry_market(poultry_request) + create_update_chicken_commission_prices() + + if traffic_codes and isinstance(traffic_codes, list): + codes_to_create = [] + now = datetime.datetime.now() + for traffic_code in traffic_codes: + if traffic_code and str(traffic_code).strip(): + codes_to_create.append( + PoultryRequestQuarantineCode( + poultry_request=poultry_request, + traffic_code=str(traffic_code).strip(), + registrar=user.fullname, + register_date=now + ) + ) + + if codes_to_create: + PoultryRequestQuarantineCode.objects.bulk_create(codes_to_create) + + serializer_request = self.serializer_class(poultry_request) + return Response(serializer_request.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + # تابع مربوط به ویرایش درخواست ثبت شده مرغدار + def update(self, request, pk=None, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + + if 'confirmation_code' in request.data.keys(): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + if poultry_request.price_confirmation_code != request.data['confirmation_code']: + return Response({"result": "کد وارد شده صحیح نمی باشد!"}, + status=status.HTTP_403_FORBIDDEN) + poultry_request.input_price_confirmation_code = request.data['confirmation_code'] + poultry_request.save() + return Response({"result": "با موفقیت انجام شد!"}, + status=status.HTTP_200_OK) + + if 'quarantine_code' in request.data.keys(): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + + date_time_of_now = datetime.datetime.now().date() + if OperationLimitation.objects.all().first().vet_farm_out_province_limitation == True: + if date_time_of_now > poultry_request.send_date.date() + timedelta(days=1): + return Response( + {"result": "به علت مغایرت در تاریخ ثبت و تاریخ کشتار امکان ثبت اطلاعات وجود ندارد!"}, + status=status.HTTP_403_FORBIDDEN) + if PoultryRequest.objects.filter(quarantine_code=request.data['quarantine_code'], trash=False).exists(): + return Response({"result": "کد وارد شده تکراری میباشد!"}, status=status.HTTP_403_FORBIDDEN) + + poultry_request.quarantine_code = request.data['quarantine_code'] + poultry_request.quarantine_code_registrar = { + "role": request.data['role'], + "fullname": user.fullname, + "mobile": user.mobile, + "date": str(datetime.datetime.now().date()), + } + poultry_request.save() + get_gid_poultry_request(poultry_request.id) + return Response({"result": "با موفقیت ثیت شد"}, status=status.HTTP_200_OK) + if 'edit' in request.data.keys(): + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + request.data.pop('poultry_request_key') + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key, trash=False) + if 'out_province_poultry_request_buyer_key' in request.data.keys(): + request_buyer = OutProvincePoultryRequestBuyer.objects.get( + key=request.data['out_province_poultry_request_buyer_key']) + poultry_request.out_province_poultry_request_buyer = request_buyer + poultry_request.buyer_mobile = request_buyer.mobile + poultry_request.buyer_fullname = request_buyer.fullname + poultry_request.buyer_city = request_buyer.city + poultry_request.buyer_province = request_buyer.province + request.data.pop('out_province_poultry_request_buyer_key') + + if 'quantity' in request.data.keys(): + if poultry_request.market: + if MarketDailyLimitation.objects.filter(active=True).exists(): + market_result = market_daily_limitation_info() + if int(request.data['quantity']) > poultry_request.quantity: + diff_quantity = int(request.data['quantity']) - poultry_request.quantity + + if diff_quantity > market_result['remain_quantity']: + return Response({"result": "تعداد وارد شده از باقی مانده سقف کشتار معاملات بیشتر است!"}, + status=status.HTTP_403_FORBIDDEN) + + if poultry_request.out: + out_province_request_limitation = PoultryOutProvinceRequest.objects.filter(trash=False).first() + if out_province_request_limitation: + if out_province_request_limitation.limitation_status: + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, + hatching=poultry_request.hatching, + out_province_request_cancel=False, + state_process__in=( + 'pending', 'accepted'), + province_state__in=( + 'pending', 'accepted')).exclude( + id=poultry_request.id) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + if poultry_request.hatching.quantity * ( + out_province_request_limitation.limitation / 100) < out_poultry_requests_quantity + \ + int(request.data['quantity']): + return Response( + {"result": " تعداد وارد شده بیشتر از ظرفیت فروش به خارج استان برای مرغدار است ! "}, + status=status.HTTP_403_FORBIDDEN) + if int(request.data['quantity']) > poultry_request.quantity: + diffrent_quantity = int(request.data['quantity']) - poultry_request.quantity + if hatching.left_over < diffrent_quantity: + return Response({"result": "تعداد وارد شده از باقی مانده جوجه ریزی بیشتر است !"}, + status=status.HTTP_403_FORBIDDEN) + if poultry_request.out == True and poultry_request.province_state == 'accepted': + hatching.out_province_killed_quantity += diffrent_quantity + hatching.out_province_killed_weight += int(diffrent_quantity * poultry_request.Index_weight) + hatching.save() + elif int(request.data['quantity']) < poultry_request.quantity: + if poultry_request.out == True and poultry_request.province_state == 'accepted': + diffrent_quantity = poultry_request.quantity - int(request.data['quantity']) + + hatching.out_province_killed_quantity -= diffrent_quantity + hatching.out_province_killed_weight -= int(diffrent_quantity * poultry_request.Index_weight) + hatching.save() + + poultry_request.remain_quantity = int(request.data['quantity']) + poultry_request.save() + + if 'poultry_mobile' in request.data.keys() and request.data['poultry_mobile'] is not None: + if poultry_request.poultry.user.mobile != request.data['poultry_mobile']: + first_mobile_number = poultry_request.poultry.user.mobile + second_mobile_number = request.data['poultry_mobile'] + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + poultry_user = User.objects.get(id=system_user_profile.user.id) + + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + poultry_user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + elif 'buyer_mobile' in request.data.keys() and request.data['buyer_mobile'] is not None: + if poultry_request.out_province_poultry_request_buyer.user.mobile != request.data['buyer_mobile']: + first_mobile_number = poultry_request.out_province_poultry_request_buyer.user.mobile + second_mobile_number = request.data['buyer_mobile'] + system_user_profile = SystemUserProfile.objects.get(mobile=first_mobile_number, trash=False) + buyer_user = User.objects.get(id=system_user_profile.user.id) + + if SystemUserProfile.objects.filter(mobile=second_mobile_number, trash=False).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + buyer_user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + system_user_profile.save() + request_buyer = OutProvincePoultryRequestBuyer.objects.get( + key=poultry_request.out_province_poultry_request_buyer.key) + request_buyer.mobile = second_mobile_number + request_buyer.save() + request.data.pop('poultry_mobile') + request.data.pop('buyer_mobile') + serializer = self.serializer_class(poultry_request) + serializer.update(instance=poultry_request, validated_data=request.data) + poultry_request.total_wage_amount = int( + (poultry_request.Index_weight * poultry_request.quantity) * poultry_request.wage) + poultry_request.save() + union_percent = poultry_request.union_share_percent / 100 if poultry_request.union_share_percent > 0 else 0 + company_percent = poultry_request.company_share_percent / 100 if poultry_request.company_share_percent > 0 else 0 + guilds_percent = poultry_request.guilds_share_percent / 100 if poultry_request.guilds_share_percent > 0 else 0 + city_share_percent = poultry_request.city_share_percent / 100 if poultry_request.city_share_percent > 0 else 0 + wallet_share_percent = poultry_request.wallet_share_percent / 100 if poultry_request.wallet_share_percent > 0 else 0 + other_share_percent = poultry_request.other_share_percent / 100 if poultry_request.other_share_percent > 0 else 0 + poultry_request.union_share = int(union_percent * poultry_request.total_wage_amount) + poultry_request.company_share = int(company_percent * poultry_request.total_wage_amount) + poultry_request.guilds_share = int(guilds_percent * poultry_request.total_wage_amount) + poultry_request.city_share = int(city_share_percent * poultry_request.total_wage_amount) + poultry_request.wallet_share = int(wallet_share_percent * poultry_request.total_wage_amount) + poultry_request.other_share = int(other_share_percent * poultry_request.total_wage_amount) + poultry_request.save() + return Response({"result": "با موفقیت وبرایش شد"}, status=status.HTTP_200_OK) + quantity = 0 + last_check_quantity = 0 + province_kill_request_quantity = 0 + if 'state' in request.data.keys(): + state = request.data['state'] + request.data.pop('state') + else: + state = None + poultry_request = PoultryRequest.objects.get(key=request.data["key"], trash=False) + request.data.pop('key') + province_check = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request) + if 'quantity' in request.data.keys() or 'allocated_number' in request.data.keys(): + if 'quantity' in request.data.keys(): + if poultry_request.out: + out_province_request_limitation = PoultryOutProvinceRequest.objects.filter(trash=False).first() + if out_province_request_limitation: + if out_province_request_limitation.limitation_status: + out_poultry_requests = PoultryRequest.objects.filter(trash=False, out=True, + hatching=poultry_request.hatching, + out_province_request_cancel=False, + state_process__in=( + 'pending', 'accepted'), + province_state__in=( + 'pending', 'accepted')).exclude( + id=poultry_request.id) + out_poultry_requests_quantity = out_poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + if poultry_request.hatching.quantity * ( + out_province_request_limitation.limitation / 100) < out_poultry_requests_quantity + \ + int(request.data['quantity']): + return Response( + {"result": " تعداد وارد شده بیشتر از ظرفیت فروش به خارج استان برای مرغدار است ! "}, + status=status.HTTP_403_FORBIDDEN) + quantity = int(request.data['quantity']) + province_kill_requests = ProvinceKillRequest.objects.filter( + province_request__poultry_request=poultry_request, trash=False) + if province_kill_requests.count() > 0: + for province_kill_request in province_kill_requests: + province_kill_request_quantity += province_kill_request.main_quantity + if quantity < province_kill_request_quantity: + return Response({"result": "درخواست کشتار شما کمتر از مجموع کل تخصیصات داده شده است!"}, + status=status.HTTP_403_FORBIDDEN) + + if (quantity - poultry_request.quantity) > poultry_request.hatching.left_over: + # if quantity > poultry_request.hatching.left_over + poultry_request.remain_quantity: + return Response({"result": "درخواست کشتار شما بزرگتر از کل مانده جوجه ریزی است!"}, + status=status.HTTP_403_FORBIDDEN) + if poultry_request.kill_house_list != None and len(poultry_request.kill_house_list) > 0: + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=poultry_request.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + if quantity > poultry_request.quantity: + if kill_request.remain_quantity_for_poultry + ( + quantity - poultry_request.quantity) > kill_request.kill_capacity: + return Response( + {"result": "مقدار وارد شده از باقی مانده اعلام نیاز کشتارگاه بیشتر است!"}, + status=status.HTTP_403_FORBIDDEN) + kill_request.remain_quantity_for_poultry += quantity - poultry_request.quantity + else: + kill_request.remain_quantity_for_poultry -= poultry_request.quantity - quantity + + kill_request.save() + + + else: + quantity = request.data['allocated_number'] + request.data.pop('allocated_number') + if quantity == 0: + quantity = poultry_request.quantity + poultry_request.final_state = request.data['final_state'] + else: + request.data.pop('final_state') + if province_check.count() > 0: + province_check = province_check.last() + last_check_quantity += province_check.quantity + province_check.quantity = 0 + province_check.save() + + poultry_request.previous_quantity = poultry_request.quantity + if poultry_request.quantity > quantity: + a = -1 * (poultry_request.quantity - quantity) + else: + a = quantity - poultry_request.quantity + + poultry_request.remain_quantity += a + poultry_request.save() + + hatching = PoultryHatching.objects.get(key=poultry_request.hatching.key) + if poultry_request.quantity - quantity == 0: + if state != None: + pass + else: + province_check = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request) + if province_check.count() > 0: + province_check = province_check.last().quantity + if province_check == 0 and last_check_quantity > 0: + if poultry_request.quantity == last_check_quantity: + poultry_request.final_state = 'archive' + poultry_request.archive = True + if poultry_request.kill_house_list != None and len(poultry_request.kill_house_list) > 0: + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=poultry_request.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + kill_request.remain_quantity_for_poultry -= poultry_request.quantity + kill_request.save() + # hatching.left_over += last_check_quantity + hatching.save() + + else: + pass + else: + + poultry_request.final_state = 'archive' + poultry_request.archive = True + if poultry_request.kill_house_list != None and len(poultry_request.kill_house_list) > 0: + for item in poultry_request.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=poultry_request.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + kill_request.remain_quantity_for_poultry -= poultry_request.quantity + kill_request.save() + # hatching.left_over += quantity + + else: + if quantity > poultry_request.quantity: + # hatching.left_over -= quantity - poultry_request.quantity + # hatching.save() + if poultry_request.final_state != 'archive': + province_check = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request) + if province_check.count() > 0: + province_check = province_check.last() + province_check.quantity += quantity - poultry_request.quantity + province_check.save() + + + else: + # hatching.left_over += poultry_request.quantity - quantity + if poultry_request.final_state != 'archive': + province_check = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request) + if province_check.count() > 0: + province_check = province_check.last() + if 'quantity' in request.data.keys(): + # province_check.quantity = (poultry_request.quantity - quantity) - last_check_quantity + # last_province_quantity = province_check.quantity + if quantity < poultry_request.quantity: + if province_check.quantity > 0: + province_check.quantity -= poultry_request.quantity - quantity + + + + else: + province_check.quantity = (poultry_request.quantity - quantity) - last_check_quantity + province_check.save() + if hatching.left_over > 0: + hatching.state = 'pending' + hatching.allow_hatching = 'pending' + hatching.save() + poultry_request.quantity = quantity + poultry_request.save() + serializer = self.serializer_class(poultry_request) + serializer.update(instance=poultry_request, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش درخواست ثبت شده مرغدار + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + breed_list = [] + city_list = [] + quantity_list = [] + total_list = [] + + user = SystemUserProfile.objects.get(user=request.user, trash=False) + if 'role' in request.GET: + if request.GET['role'] == 'Poultry': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__user=user, awaiting_payment=True, + trash=False, out=False).order_by('-send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__user=user, inspector='pending', + trash=False, out=False).order_by('-send_date') + else: + now = datetime.datetime.now().date() + + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + + queryset_lists = PoultryRequest.objects.filter(poultry__user=user, + final_state__in=('pending', 'archive'), + trash=False, out=False).order_by('-send_date') + queryset = [ + queryset_list for queryset_list in queryset_lists + if date1 <= queryset_list.send_date.date() <= date2 + ] + elif request.GET['role'] == 'VetSupervisor': + + if 'check' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + elif request.GET['role'] == 'VetFarm': + vet = Vet.objects.filter(user=user, trash=False) + poultries = [] + if vet.count() > 0: + vet = vet.last() + vet_farms = VetFarm.objects.filter(vet=vet, trash=False) + if vet_farms.count() > 0: + for vet_farm in vet_farms: + if vet_farm.poultry in poultries: + pass + else: + poultries.append(vet_farm.poultry) + if 'check' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__in=poultries, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + elif 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + else: + queryset = PoultryRequest.objects.filter(poultry__in=poultries, + poultry__address__province=user.province, + final_state__in=('pending', 'archive'), + trash=False, out=False).order_by('send_date') + else: + queryset = [] + + elif request.GET['role'] == 'ProvinceInspector': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + # elif 'out' in request.GET: + + else: + + if 'date' in request.GET: + date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + + if 'check' in request.GET: + + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__city_operator=city_operator.unit_name, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + + + # list1 = [] + # for c in CityUnit.objects.filter(city__name=user.city.name, trash=False): + # list1.append(c.name) + elif 'waiting' in request.GET: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # awaiting_payment=True, + # trash=False).order_by('send_date') + + queryset = PoultryRequest.objects.filter(city_operator=city_operator, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # inspector='pending', + # trash=False).order_by('send_date') + queryset = PoultryRequest.objects.filter(city_operator=city_operator, + inspector='pending', + trash=False, out=False).order_by('send_date') + else: + # queryset = PoultryRequest.objects.filter(poultry__address__city__name__in=list1, + # trash=False).order_by( + # 'send_date') + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if 'state' in request.GET: + if request.GET['state'] == 'pending': + queryset = PoultryRequest.objects.filter(poultry__city_operator=city_operator.unit_name, + trash=False, out=False, state_process='pending', + final_state='pending', + send_date__date__gte=date1, + send_date__date__lte=date2 + ).order_by('send_date') + elif request.GET['state'] == 'accepted': + queryset = PoultryRequest.objects.filter(poultry__city_operator=city_operator.unit_name, + trash=False, out=False, state_process='accepted', + final_state='pending', + send_date__date__gte=date1, + send_date__date__lte=date2 + ).order_by('send_date') + else: + queryset = PoultryRequest.objects.filter(poultry__city_operator=city_operator.unit_name, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, final_state='pending', + send_date__date__gte=date1, send_date__date__lte=date2 + ).order_by('send_date') + + if 'search' in request.GET: + poultry_requests = [] + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (PoultryRequestFilterSet( + data=query, + queryset=queryset + ) + ).filter(): + ps = PoultryRequestFilterSet(data=query, queryset=queryset) + poultry_requests = ps.filter() + queryset = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = PoultryRequestForKillingInformationSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForKillingInformationSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + # queryset = [ + # poultry_req for poultry_req in queryset_list + # if date1 <= poultry_req.send_date.date() <= date2 + # ] + elif request.GET['role'] == 'PoultryScience': + poultry_science = PoultryScience.objects.filter(trash=False, user=user).values_list('poultry__id', + flat=True).distinct() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + queryset = PoultryRequest.objects.filter(poultry__id__in=poultry_science, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, final_state='pending', + send_date__date__gte=date1, send_date__date__lte=date2 + ).order_by('send_date') + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (PoultryRequestFilterSet( + data=query, + queryset=queryset + ) + ).filter(): + ps = PoultryRequestFilterSet(data=query, queryset=queryset) + poultry_requests = ps.filter() + queryset = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = PoultryRequestForKillingInformationSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForKillingInformationSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['role'] in ['CityCommerce', 'CityVet', 'CityPoultry', 'CityJahad']: + + if 'check' in request.GET: + + if 'date1' in request.GET and 'date2' in request.GET: + + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + + kill_request__recive_date__date__gte=date1, + + kill_request__recive_date__date__lte=date2, + + province_request__poultry_request__poultry__address__city=user.city, + + trash=True, + + message__isnull=False, temporary_trash=False, temporary_deleted=False + + ).select_related('kill_request') + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + else: + + kill_house_requests = KillHouseRequest.objects.filter( + + kill_request__recive_date__date__gte=date1, + + kill_request__recive_date__date__lte=date2, + + province_request__poultry_request__poultry__address__city=user.city, + + trash=False + + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'date1' in request.GET and 'date2' in request.GET: + + now = datetime.datetime.now().date() + + date1 = datetime.datetime.strptime(str(request.GET['date1']), + + '%Y-%m-%d').date() if 'date1' in request.GET else now + + date2 = datetime.datetime.strptime(str(request.GET['date2']), + + '%Y-%m-%d').date() if 'date2' in request.GET else now + + if 'state_process' in request.GET: + + queryset = PoultryRequest.objects.filter(poultry__address__city=user.city, + + trash=False, state_process='pending', out=False, + + send_date__date__gte=date1, send_date__date__lte=date2 + + ).order_by('-send_date') + + else: + + poultry_requests = [] + + queryset = PoultryRequest.objects.filter(poultry__address__city=user.city, + + state_process__in=('pending', 'accepted'), + + province_state__in=('pending', 'accepted'), + + final_state='pending', + + trash=False, out=False, send_date__date__gte=date1, + + send_date__date__lte=date2 + + ).order_by('-send_date') + + if 'search' in request.GET: + + if request.GET['search'] == 'filter': + + if request.GET['value'] != "": + + for item in self.filterset_fields: + + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + + if (PoultryRequestFilterSet( + + data=query, + + queryset=queryset + + ) + + ).filter(): + ps = PoultryRequestFilterSet(data=query, queryset=queryset) + + poultry_requests = ps.filter() + + queryset = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + + if page is not None: + serializer = PoultryRequestForKillingInformationSerializer(page, many=True) + + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForKillingInformationSerializer(queryset, many=True) + + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['role'] == 'ProvinceFinancial': + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + elif 'all' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + assignment=True, + final_state='pending', + trash=False, out=False).order_by('send_date') + else: + if 'date' in request.GET: + date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + elif request.GET['role'] in ['ProvinceOperator', 'Commerce', 'SuperAdmin', 'AdminX', 'Supporter']: + if 'waiting' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + awaiting_payment=True, + trash=False, out=False).order_by('send_date') + elif 'inspector' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + inspector='pending', + trash=False, out=False).order_by('send_date') + elif 'out' in request.GET: + # if 'date' in request.GET: + # date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # else: + # date = datetime.datetime.now() + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False, out=True).order_by('-send_date') + elif 'check' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + # serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + # return Response(serializer.data, status=status.HTTP_200_OK) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + kill_house_requests = KillHouseRequest.objects.filter( + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif 'date1' in request.GET and 'date2' in request.GET: + + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else now + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date2' in request.GET else now + if 'state_process' in request.GET: + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + trash=False, state_process='pending', out=False, + send_date__date__gte=date1, send_date__date__lte=date2 + ).order_by('-send_date') + else: + poultry_requests = [] + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + final_state='pending', + trash=False, out=False, send_date__date__gte=date1, + send_date__date__lte=date2 + ).order_by('-send_date') + + if 'search' in request.GET: + if request.GET['search'] == 'filter': + if request.GET['value'] != "": + for item in self.filterset_fields: + query = QueryDict('{0}__contains={1}'.format(item, request.GET['value'])) + if (PoultryRequestFilterSet( + data=query, + queryset=queryset + ) + ).filter(): + ps = PoultryRequestFilterSet(data=query, queryset=queryset) + poultry_requests = ps.filter() + queryset = [] if len(poultry_requests) == 0 else poultry_requests + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = PoultryRequestForKillingInformationSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = PoultryRequestForKillingInformationSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # queryset = [ + # queryset_list for queryset_list in queryset_lists + # if date1 <= queryset_list.send_date.date() <= date2 + # ] + + # date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + # date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + # queryset_list = PoultryRequest.objects.filter(poultry__address__province=user.province, + # trash=False, out=False, + # ).order_by('-send_date') + # + # queryset = [] + # queryset = [ + # poultry_req for poultry_req in queryset_list + # if date1 <= poultry_req.send_date.date() <= date2 + # ] + else: + if 'date' in request.GET: + date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.datetime.now() - timedelta(days=2) + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year__gte=date.year, + send_date__month__gte=date.month, + send_date__day__gte=date.day + ).order_by('-send_date') + + elif request.GET['role'] == 'KillHouse': + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False) + if 'check' in request.GET: + if 'date1' in request.GET and 'date2' in request.GET: + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'deleted_requests' in request.GET: + + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=True, + message__isnull=False, temporary_trash=False, temporary_deleted=False + ).select_related('kill_request') + # serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + # return Response(serializer.data, status=status.HTTP_200_OK) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + else: + kill_house_requests = KillHouseRequest.objects.filter( + (Q(killhouse_user__in=kill_house) | Q( + kill_request__slaughter_house__in=kill_house)), + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + province_request__poultry_request__poultry__address__province=user.province, + trash=False + ).select_related('kill_request') + + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(kill_house_requests) + if page is not None: + serializer = KillHouseRequestForBarManagementSerializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + # if 'check' in request.GET: + # kill_house_req_dict = {} + # kill_house_req_list = [] + # bar_remover = None + # + # now = datetime.datetime.now().date() + # date1 = datetime.datetime.strptime(str(request.GET['date1']), + # '%Y-%m-%d').date() if 'date1' in request.GET else now + # date2 = datetime.datetime.strptime(str(request.GET['date2']), + # '%Y-%m-%d').date() if 'date2' in request.GET else now + # queryset_list = PoultryRequest.objects.filter( + # poultry__address__province=user.province, + # final_state__in=('pending', 'archive'), + # trash=False, out=False, + # ).order_by('-send_date') + # + # queryset = [] + # queryset = [ + # poultry_req for poultry_req in queryset_list + # if date1 <= poultry_req.send_date.date() <= date2 + # ] + # if len(queryset) > 0: + # for poultry_req in queryset: + # vet_farm = VetFarm.objects.filter(poultry=poultry_req.poultry) + # if vet_farm.count() > 0: + # vet_farm = vet_farm.last() + # vet_name = vet_farm.vet.user.fullname + # vet_mobile = vet_farm.vet.user.mobile + # else: + # vet_name = None + # vet_mobile = None + # if 'deleted_requests' in request.GET: + # kill_house_requests = KillHouseRequest.objects.filter( + # province_kill_request__province_request__poultry_request=poultry_req, + # killhouse_user__in=kill_house, trash=True, + # message__isnull=False) + # else: + # kill_house_requests = KillHouseRequest.objects.filter( + # province_kill_request__province_request__poultry_request=poultry_req, + # killhouse_user__in=kill_house, trash=False) + # if kill_house_requests.count() > 0: + # for kill_house_request in kill_house_requests: + # kill_house_name = kill_house_request.kill_request.kill_house.name + # if kill_house_request.kill_request.slaughter_house: + # kill_place = kill_house_request.kill_request.slaughter_house.name + # else: + # kill_place = kill_house_name + # + # if kill_house_request.bar_remover != None: + # bar_remover = kill_house_request.bar_remover + # vet_check = VetCheckRequest.objects.filter( + # kill_house_request=kill_house_request) + # if vet_check.count() > 0: + # vet_check_state = vet_check.last().state + # else: + # vet_check_state = 'pending' + # + # kill_house_req_dict.update({ + # "poultry_req_key": poultry_req.key, + # "poultry_req_order_code": poultry_req.order_code, + # "poultry_name": poultry_req.poultry.unit_name, + # "poultry_mobile": poultry_req.poultry.user.mobile, + # "poultry_city": poultry_req.poultry.address.city.name, + # "chicken_breed": poultry_req.chicken_breed, + # "date": poultry_req.send_date, + # "poultry_request_first_quantity": kill_house_request.quantity, + # "poultry_request_final_quantity": kill_house_request.quantity, + # "clearance_code": kill_house_request.clearance_code, + # "traffic_code": kill_house_request.traffic_code, + # "kill_house_name": kill_house_name, + # "buyer_mobile": kill_house_request.kill_request.kill_house.kill_house_operator.user.mobile, + # "driver_mobile": kill_house_request.add_car.driver.driver_mobile, + # "kill_house_request_key": kill_house_request.key, + # "registerar": kill_house_request.registrar_clearance_code, + # "bar_code": kill_house_request.bar_code, + # "health_code": kill_house_request.add_car.driver.health_code, + # "message": kill_house_request.message, + # "date_of_reject": kill_house_request.modify_date, + # "vet_name": vet_name, + # "vet_mobile": vet_mobile, + # "driver_name": kill_house_request.add_car.driver.driver_name, + # "pelak": kill_house_request.add_car.driver.pelak, + # "type_car": kill_house_request.add_car.driver.type_car, + # "quantity": kill_house_request.add_car.driver.type_car, + # "vet_check_state": vet_check_state, + # "bar_remover": bar_remover, + # "kill_place": kill_place, + # + # }) + # kill_house_req_list.append(kill_house_req_dict) + # kill_house_req_dict = {} + # + # return Response(kill_house_req_list, status=status.HTTP_200_OK) + + else: + if 'date' in request.GET: + date = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d') + else: + date = datetime.datetime.now() + + queryset = PoultryRequest.objects.filter(poultry__address__province=user.province, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, + send_date__year=date.year, send_date__month=date.month, + send_date__day=date.day + ).order_by('-send_date') + + else: + + if 'type' in request.GET: + if request.GET['type'] == 'auction': + queryset = [] + poultry_req_auctions = PoultryRequestAuction.objects.filter(state='active', + trash=False).order_by( + 'fee').order_by( + 'create_date') + for poultry_req_auction in poultry_req_auctions: + queryset.append( + PoultryRequest.objects.get(id=poultry_req_auction.poultry_request.id, auction=True)) + + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + queryset = PoultryRequest.objects.get(id=pk, trash=False) + if queryset.province_state == 'accepted': + role = Group.objects.get(name='ProvinceOperator') + if role not in user.role.all(): + return Response({"result": " بدلیل تایید درخواست از طرف استان امکان حذف وجود ندارد!"}, + status=status.HTTP_400_BAD_REQUEST) + if ProvinceKillRequest.objects.filter(province_request__poultry_request=queryset, trash=False, + ).exists(): + return Response({"result": " بدلیل وجود تخصیص به کشتارگاه امکان حذف وجود ندارد!"}, + status=status.HTTP_400_BAD_REQUEST) + + # if queryset.state_process == 'pending' and queryset.province_state == 'pending': + # + # + # # if 'role' in request.GET: + # # if request.GET['role'] == 'ProvinceOperator': + # + # hatching = queryset.hatching + # hatching.left_over += queryset.quantity + queryset.losses + # hatching.losses -= queryset.losses + # hatching.state = 'pending' + # hatching.save() + # try: + # city = CityOperatorCheckRequest.objects.get(poultry_request=queryset, trash=False) + # city.trash = True + # city.save() + # except: + # pass + # queryset.trash = True + # queryset.save() + # if queryset.kill_house_list != None and len(queryset.kill_house_list) > 0: + # for item in queryset.kill_house_list: + # parts = item.split("(") + # name = parts[0].strip() + # kill_request = KillRequest.objects.filter(kill_house__name=name, + # recive_date__date=queryset.send_date.date(), + # trash=False, poultry__isnull=True, + # province_state='accepted').first() + # if kill_request: + # kill_request.remain_quantity_for_poultry -= queryset.quantity + # kill_request.save() + # return Response(queryset.trash, status=status.HTTP_200_OK) + # else: + + # if ProvinceOperator.objects.filter(user=user).exists(): + # hatching = queryset.hatching + # hatching.left_over += queryset.quantity + queryset.losses + # hatching.losses -= queryset.losses + # hatching.state = 'pending' + # hatching.save() + try: + city = CityOperatorCheckRequest.objects.get(poultry_request=queryset, trash=False) + city.trash = True + city.save() + except: + pass + queryset.trash = True + queryset.save() + if queryset.kill_house_list != None and len(queryset.kill_house_list) > 0: + for item in queryset.kill_house_list: + parts = item.split("(") + name = parts[0].strip() + kill_request = KillRequest.objects.filter(kill_house__name=name, + recive_date__date=queryset.send_date.date(), + trash=False, poultry__isnull=True, + province_state='accepted').first() + if kill_request: + kill_request.remain_quantity_for_poultry -= queryset.quantity + kill_request.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +# ویوست مربوط به ریزجزییات پرونده مرغدار برای پنل مرغدار و شهرستان و کشتارگاه +class ProcessViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به نمایش ریزجزییات پرونده مرغدار برای پنل مرغدار و شهرستان و کشتارگاه + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + process = {} + process1 = {} + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_request = PoultryRequest.objects.get(id=int(request.GET['id']), trash=False) + # date = str(poultry_request.poultry.incubation_date) + # new_date = date[:19] + # chicken_date = datetime.datetime.strptime(new_date, '%Y-%m-%d %H:%M:%S') + kill_date = datetime.datetime.strptime(str(poultry_request.send_date), '%Y-%m-%d %H:%M:%S') + # age = (kill_date - chicken_date).days + if ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, state='accepted').exists(): + age2 = (poultry_request.send_date - poultry_request.hatching.date).days + 1 + else: + age2 = (datetime.datetime.now() - poultry_request.hatching.date).days + 1 + + file_state = 'pending' + if poultry_request.province_state == 'pending': + file_state = 'province_state_pending' + + if ProvinceKillRequest.objects.filter(province_request__poultry_request__id=poultry_request.id).exists(): + if poultry_request.remain_quantity == 0: + file_state = 'allocated_completed' + + + else: + file_state = 'allocated_pending' + + process.update({"file_state": file_state}) + process.update({"poultry": { + "poultry_unit_name": poultry_request.poultry.unit_name, + "breeding_unique_id": poultry_request.poultry.breeding_unique_id, + "general_order_code": poultry_request.general_order_code, + "halls": poultry_request.poultry.number_of_halls, + "tenant": poultry_request.poultry.tenant, + "has_tenant": poultry_request.poultry.has_tenant, + "poultry_request_id": poultry_request.id, + "base_order": poultry_request.poultry.user.base_order, + "awaiting_payment": poultry_request.awaiting_payment, + "poultry_request_final_state": poultry_request.final_state, + "poultry_request_key": poultry_request.key, + "kill_house_list": poultry_request.kill_house_list, + "poultry_order_code": poultry_request.order_code, + "poultry_send_date": poultry_request.send_date, + "poultry_name": poultry_request.poultry.user.fullname, + "poultry_mobile": poultry_request.poultry.user.mobile, + "poultry_city": poultry_request.poultry.address.city.name, + "poultry_province": poultry_request.poultry.address.province.name, + "poultry_gis_code": poultry_request.poultry.gis_code, + 'age': age2, + 'chicken_date': None, + "poultry_quantity": poultry_request.quantity, + "poultry_first_quantity": poultry_request.first_quantity, + "poultry_previous_quantity": poultry_request.previous_quantity, + "poultry_remain_quantity": poultry_request.remain_quantity, + "poultry_chicken_breed": poultry_request.chicken_breed, + "poultry_request_losses": poultry_request.losses, + "poultry_Index_weight": "{} کیلوگرم".format(poultry_request.Index_weight), + "Index_weight": poultry_request.Index_weight, + "poultry_register_date": poultry_request.create_date, + "poultry_auction": poultry_request.auction, + "sell_type": poultry_request.cell_type, + "buyer": poultry_request.buyer, + "clearance_code": poultry_request.clearance_code, + + } + }) + poultry_hatching = PoultryHatching.objects.filter(key=poultry_request.hatching.key, trash=False) + if poultry_hatching.count() > 0: + poultry_hatching = poultry_hatching.last() + inspections = VetFarmInspection.objects.filter(poultry_hatching=poultry_hatching) + losses = 0 + if inspections.count() > 0: + for ins in inspections: + if ins.Losses > 0: + losses += ins.Losses + else: + pass + + if losses > 0: + process.update({"inspection_losses": losses + }) + process.update({ + "inspection_losses_percent": (losses * 100) / poultry_request.hatching.quantity + }) + + else: + process.update({"inspection_losses": losses + }) + process.update({ + "inspection_losses_percent": losses + }) + + process.update({"poultry_hatching": { + "poultry_key": poultry_request.hatching.poultry.key, + "poultry_hatching_key": poultry_request.hatching.key, + "poultry_name": poultry_request.hatching.poultry.unit_name, + "quantity": poultry_request.hatching.quantity, + "losses": poultry_request.hatching.losses, + "total_losses_percent": (poultry_request.hatching.losses * 100) / poultry_request.hatching.quantity, + "poultry_losses_percent": (poultry_request.losses * 100) / poultry_request.hatching.quantity, + "left_over": poultry_request.hatching.left_over, + "hall": poultry_request.hatching.hall, + "date": poultry_request.hatching.date, + "allow_hatching": poultry_request.hatching.allow_hatching, + "period": poultry_request.hatching.period, + "state": poultry_request.hatching.state, + } + }) + else: + process.update({"poultry_hatching": None + }) + + vetfarm_inspection = VetFarmInspection.objects.filter(vet_farm__poultry=poultry_request.poultry, + trash=False) + if vetfarm_inspection.count() > 0: + vetfarm_inspection = vetfarm_inspection.last() + process.update({"vetfarm_inspection": { + "vet_name": vetfarm_inspection.vet_farm.vet.user.fullname, + "hall": vetfarm_inspection.hall, + "topic": vetfarm_inspection.topic, + "description": vetfarm_inspection.description, + "image": vetfarm_inspection.image, + "losses": vetfarm_inspection.Losses, + "longitude": vetfarm_inspection.longitude, + "latitude": vetfarm_inspection.latitude, + } + }) + else: + process.update({"vetfarm_inspection": None + }) + auctions = PoultryRequestAuction.objects.filter(poultry_request=poultry_request, + state__in=('active', 'inactive'), trash=False).order_by( + 'auction_date') + if auctions.count() > 0: + auctions_list = [] + for auction in auctions: + if auction.state == 'active': + index = list(auctions).index(auction) + 1 + pricing = Pricing.objects.get(id=auction.pricing.id) + internal_dict_auction = { + "ceiling_price": pricing.ceiling_price, + "floor_price": pricing.floor_price, + "fee": auction.fee, + "hour": auction.hour, + "date": auction.auction_date, + "index": index, + "total_index": auctions.count() + } + auctions_list.append(internal_dict_auction) + process.update({"auctions_list": auctions_list}) + # else: + # break + + + else: + process.update({"auctions_list": None}) + kill_house_auctions = KillHouseRequestAction.objects.filter(poultry_request=poultry_request, + state='pending', + trash=False) + if kill_house_auctions.count() > 0: + kill_house_auctions_list = [] + for kill_house_auction in kill_house_auctions: + internal_dict_kill_house_auction = { + "kill_house_name": kill_house_auction.kill_house.name, + "fullname": kill_house_auction.kill_house.kill_house_operator.user.fullname, + "mobile": kill_house_auction.kill_house.kill_house_operator.user.mobile, + "city": kill_house_auction.kill_house.system_address.city.name, + "province": kill_house_auction.kill_house.system_address.province.name, + "fee": kill_house_auction.fee, + } + kill_house_auctions_list.append(internal_dict_kill_house_auction) + process.update({"kill_house_auctions_list": kill_house_auctions_list}) + else: + process.update({"kill_house_auctions_list": None}) + + kill_house_auction_winner = KillHouseRequestActionWinner.objects.filter( + kill_house_request_auction__poultry_request=poultry_request, trash=False) + if kill_house_auction_winner.count() > 0: + kill_house_auction_winner = kill_house_auction_winner.last() + process.update({"kill_house_winner": { + "kill_house_winner_key": kill_house_auction_winner.key, + "kill_house_name": kill_house_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_user_name": kill_house_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.fullname, + "kill_house_user_mobile": kill_house_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "kill_house_city": kill_house_auction_winner.kill_house_request_auction.kill_house.system_address.city.name, + "kill_house_province": kill_house_auction_winner.kill_house_request_auction.kill_house.system_address.province.name, + "fee": kill_house_auction_winner.fee, + "quantity": kill_house_auction_winner.quantity + } + }) + else: + process.update({"kill_house_winner": None + }) + + province_request_auctions = ProvinceRequestAction.objects.filter(poultry_request=poultry_request, + state='active', trash=False) + if province_request_auctions.count() > 0: + province_request_auction_list = [] + for province_request_auction in province_request_auctions: + internal_dict_province_request_auction_list = { + "fullname": province_request_auction.province_operator_system.user.fullname, + "mobile": province_request_auction.province_operator_system.user.mobile, + "city": province_request_auction.province_operator_system.user.city.name, + "province": province_request_auction.province_operator_system.user.province.name, + } + province_request_auction_list.append(internal_dict_province_request_auction_list) + process.update({"province_request_auction_list": province_request_auction_list}) + else: + process.update({"province_request_auction_list": None}) + poultry_assignment = PoultryAssignmentInformation.objects.filter(poultry_request=poultry_request, + trash=False) + + if poultry_assignment: + poultry_bar_list = [] + for bar in poultry_assignment: + internal_poultry_bar = { + "poultry_bar_info_key": bar.key, + "car_weight_without_load": bar.car_weight_without_load, + "car_weight_without_load_image": bar.car_weight_without_load_image, + "car_weight_with_load": bar.car_weight_with_load, + "car_weight_with_load_image": bar.car_weight_with_load_image, + "net_weight": bar.net_weight, + } + poultry_bar_list.append(internal_poultry_bar) + + process.update({"poultry_bar_info": poultry_bar_list}) + if not poultry_assignment: + process.update({"poultry_bar_info": None}) + + city = CityOperatorCheckRequest.objects.filter(poultry_request=poultry_request, trash=False) + if city: + process.update({"city": { + "city_operator_name": city[0].city_operator_system.user.fullname, + "city_operator_mobile": city[0].city_operator_system.user.mobile, + "city_operator_province": city[0].city_operator_system.address.province.name, + "city_operator_city": city[0].city_operator_system.address.city.name, + "city_operator_address": city[0].city_operator_system.address.address, + "city_operator_national_id": city[0].city_operator_system.user.national_id, + "city_state": city[0].state, + "province_accept": city[0].province_accept, + "accepted_rejected_date": city[0].create_date, + "city_operator_message": city[0].message, + "unit_name": city[0].city_operator_system.unit_name, + }}) + if not city: + process.update({"city": None}) + # cit = CityUnit.objects.filter(name=poultry_request.poultry.address.city.name, trash=False) + # if cit.count() > 0: + # city_operator = CityOperator.objects.get(address__city=cit[0].city, trash=False) + city_operator = CityOperator.objects.get(key=poultry_request.city_operator.key, trash=False) + process.update({"city_operator": { + "city_operator_name": city_operator.user.fullname, + "city_operator_mobile": city_operator.user.mobile, + "city_operator_province": city_operator.address.province.name, + "city_operator_city": city_operator.address.city.name, + "city_operator_address": city_operator.address.address, + "city_operator_national_id": city_operator.user.national_id, + "unit_name": city_operator.unit_name, + }}) + + province = ProvinceCheckOperatorRequest.objects.filter(poultry_request=poultry_request, + trash=False) + + if province.count() > 0: + if 'role' in request.GET: + if request.GET['role'] == 'Poultry': + process.update({"province": { + "province_check_request_key": province[0].key, + "province_operator_name": province[0].province_operator_system.user.fullname, + "province_operator_mobile": province[0].province_operator_system.user.mobile, + "province_operator_provinc": province[0].province_operator_system.address.province.name, + "province_operator_city": province[0].province_operator_system.address.city.name, + "province_operator_address": province[0].province_operator_system.address.address, + "province_operator_national_id": province[0].province_operator_system.user.national_id, + "province_state": province[0].state, + "province_message": province[0].message, + "chicken_price": province[0].fee, + "accepted_rejected_date": province[0].create_date, + }}) + else: + + process.update({"province": { + "province_check_request_key": province[0].key, + "province_operator_name": province[0].province_operator_system.user.fullname, + "province_operator_mobile": province[0].province_operator_system.user.mobile, + "province_operator_provinc": province[0].province_operator_system.address.province.name, + "province_operator_city": province[0].province_operator_system.address.city.name, + "province_operator_address": province[0].province_operator_system.address.address, + "province_operator_national_id": province[0].province_operator_system.user.national_id, + "province_state": province[0].state, + "province_message": province[0].message, + "chicken_price": province[0].fee, + "accepted_rejected_date": province[0].create_date, + }}) + + if not province: + process.update({"province": None}) + + role = Group.objects.get(name='ProvinceOperator') + province_operator = ProvinceOperator.objects.get( + address__province__name=poultry_request.poultry.address.province.name, + user__role=role, trash=False) + process.update({"province_operator": { + "province_operator_name": province_operator.user.fullname, + "province_operator_mobile": province_operator.user.mobile, + "province_operator_provinc": province_operator.address.province.name, + "province_operator_city": province_operator.address.city.name, + "province_operator_address": province_operator.address.address, + "province_operator_national_id": province_operator.user.national_id, + }}) + if ProvinceFactorToKillHouseForPoultry.objects.filter(province_check_req=province.last()).exists(): + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_req=province.last()).last() + if poultry_factor.bank != None: + name_of_bank_user_poultry = poultry_factor.bank.name_of_bank_user + bank_name_poultry = poultry_factor.bank.bank_name + card_poultry = poultry_factor.bank.card + shaba_poultry = poultry_factor.bank.shaba + account_poultry = poultry_factor.bank.account + else: + name_of_bank_user_poultry = None + bank_name_poultry = None + card_poultry = None + shaba_poultry = None + account_poultry = None + process.update({"poultry_factor": { + "poultry_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_req.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_req.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares, + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "name_of_bank_user": name_of_bank_user_poultry, + "bank_name": bank_name_poultry, + "card": card_poultry, + "shaba": shaba_poultry, + "account": account_poultry, + }}) + else: + process.update({"poultry_factor": None}) + + if ProvinceFactorToKillHouse.objects.filter(province_check_req=province.last()).exists(): + province_factor = ProvinceFactorToKillHouse.objects.filter(province_check_req=province.last()).last() + + if province_factor.bank != None: + name_of_bank_user_province_factor = province_factor.bank.name_of_bank_user + bank_name_province_factor = province_factor.bank.bank_name + card_province_factor = province_factor.bank.card + shaba_province_factor = province_factor.bank.shaba + account_province_factor = province_factor.bank.account + else: + name_of_bank_user_province_factor = None + bank_name_province_factor = None + card_province_factor = None + shaba_province_factor = None + account_province_factor = None + + process.update({"province_factor": { + "province_factor_key": province_factor.key, + "province_factor_fee": province_factor.factor_fee, + "province_operator": province_factor.province_check_req.province_operator_system.user.fullname, + "province_mobile": province_factor.province_check_req.province_operator_system.user.mobile, + "weight": province_factor.total_weight, + "cost": province_factor.total_price, + "union_share_with_profit": province_factor.shares, + "total_amount_char": words(province_factor.total_price) + " " + "ریال", + "name_of_bank_user": name_of_bank_user_province_factor, + "bank_name": bank_name_province_factor, + "card": card_province_factor, + "shaba": shaba_province_factor, + "account": account_province_factor, + }}) + else: + process.update({"province_factor": None}) + + if ProvinceImportKillHouseOutFactors.objects.filter(province_check=province.last()).exists(): + payment_out_factors = ProvinceImportKillHouseOutFactors.objects.filter(province_check=province.last()) + interal_factor_list = [] + for payment_out_factor in payment_out_factors: + internal_dict = { + "key": payment_out_factor.key, + "amount": payment_out_factor.amount, + "image": payment_out_factor.image, + } + interal_factor_list.append(internal_dict) + process.update({"out_factors": interal_factor_list}) + else: + process.update({"out_factors": None}) + + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.filter(user=user, trash=False) + if kill_house_operator.count() > 0: + kill_house_operator = kill_house_operator.last() + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + killhouse_user__in=kill_house, trash=False) + elif request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.filter(user=user, trash=False) + if vet.count() > 0: + vet = vet.last() + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + kill_house_vet = kill_house_vet.last() + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + killhouse_user=kill_house_vet.kill_house, trash=False) + else: + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, trash=False) + + if province_kill_reqs.count() > 0: + state_list = [] + for province_kill_req in province_kill_reqs: + state_list.append(province_kill_req.payment_type) + l1 = set(state_list) + if len(l1) > 1: + process.update({"file_payment_type": "cash_credit"}) + else: + process.update({"file_payment_type": state_list[0]}) + province_kill_reqs_list = [] + for province_kill_req in province_kill_reqs: + check = KillHouseCheckRequest.objects.filter(province_kill_request=province_kill_req, + trash=False) + internal_province_kill_dict_infos = { + "province_kill_req_key": province_kill_req.key, + "payment_type": province_kill_req.payment_type, + "payment_dead_line": province_kill_req.payment_dead_line, + "kill_req_key": province_kill_req.kill_request.key, + "province_kill_req_state": province_kill_req.state, + "kill_house_name": province_kill_req.kill_request.kill_house.name, + "kill_house_user_name": province_kill_req.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_city": province_kill_req.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_user_province": province_kill_req.kill_request.kill_house.kill_house_operator.user.province.name, + "kill_house_user_national_id": province_kill_req.kill_request.kill_house.kill_house_operator.user.national_id, + "kill_house_mobile": province_kill_req.kill_request.kill_house.kill_house_operator.user.mobile, + "quantity": province_kill_req.quantity, + "time": province_kill_req.kill_request.recive_time, + "date": province_kill_req.kill_request.recive_date, + "automatic_state": province_kill_req.automatic, + "fee": province_kill_req.fee, + "province_kill_req_message": province_kill_req.message + } + + kill_house_requests = KillHouseRequest.objects.filter( + province_request__city_request_Poultry__poultry_request=poultry_request, + province_kill_request=province_kill_req, trash=False) + if kill_house_requests.count() > 0: + reqs = [] + for kill_house_request in kill_house_requests: + province_req = kill_house_request.province_request + internal_dict_infos = { + "kill_house_req_key": kill_house_request.key, + "payment_type": province_kill_req.payment_type, + "province_fee": province_kill_req.fee, + "payment_dead_line": province_kill_req.payment_dead_line, + "kill_house_vet_state": kill_house_request.vet_state, + "kill_req_key": kill_house_request.kill_request.key, + "kill_house_check_key": check[0].key, + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_request.kill_house.name, + "kill_house_user_name": kill_house_request.kill_request.kill_house.kill_house_operator.user.fullname, + "kill_house_user_province": kill_house_request.kill_request.kill_house.kill_house_operator.user.province.name, + "kill_house_user_city": kill_house_request.kill_request.kill_house.kill_house_operator.user.city.name, + "kill_house_user_address": kill_house_request.kill_request.kill_house.system_address.address, + "kill_house_mobile": kill_house_request.kill_request.kill_house.kill_house_operator.user.mobile, + "kill_house_national_id": kill_house_request.kill_request.kill_house.kill_house_operator.user.national_id, + "quantity": kill_house_request.quantity, + "fee": kill_house_request.province_kill_request.fee, + "time": kill_house_request.kill_request.recive_time, + "date": kill_house_request.kill_request.recive_date, + "cars": kill_house_request.car, + "driver_name": kill_house_request.add_car.driver.driver_name, + "type_car": kill_house_request.add_car.driver.type_car, + "pelak": kill_house_request.add_car.driver.pelak, + "clearance_code": kill_house_request.clearance_code, + "traffic_code": kill_house_request.traffic_code, + "show_kill_house": kill_house_request.show_kill_house, + "kill_house_message": kill_house_request.kill_house_message + } + + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request, + trash=False) + if vet_check: + internal_dict_infos.update({ + "vet_check_info": { + "vet_user": vet_check[0].kill_house_vet.vet.user.fullname, + "vet_user_mobile": vet_check[0].kill_house_vet.vet.user.mobile, + "vet_check_state": vet_check[0].state, + "vet_check_accept_date": vet_check[0].create_date, + } + }) + if not vet_check: + internal_dict_infos.update({ + "vet_check_info": None + }) + kill_house_assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_check__province_kill_request__province_request=province_req, + kill_house_request=kill_house_request, trash=False) + if kill_house_assignment: + internal_dict_infos.update({ + "bar_info": { + "kill_house_assignment_key": kill_house_assignment[0].key, + "real_quantity": kill_house_assignment[0].real_quantity, + "kill_house_weight_without_load": kill_house_assignment[ + 0].car_weight_without_load, + "kill_house_weight_with_load": kill_house_assignment[ + 0].car_weight_with_load, + "kill_house_image_without_load": kill_house_assignment[ + 0].car_weight_without_load_image, + "kill_house_image_with_load": kill_house_assignment[ + 0].car_weight_with_load_image, + "kill_house_net_weight": kill_house_assignment[0].net_weight, + "kill_house_assignment_state": kill_house_assignment[0].state, + "expire_time": kill_house_assignment[0].protest_time, + "kill_house_assignment_message": kill_house_assignment[0].message, + "accept_reject_date": kill_house_assignment[0].modify_date, + "unusual_casualties": kill_house_assignment[0].unusual_casualties, + + } + }) + + complaint = KillHouseComplaint.objects.filter(bar=kill_house_assignment[0], + trash=False) + percentage_losses = PercentageOfLosses.objects.all() + if percentage_losses.count() > 0: + percentage_losses = percentage_losses.last().percent + else: + percentage_losses = None + if complaint.count() > 0: + complaint = complaint.last() + check_complaint = CheckUnusualCasualties.objects.filter(complaint=complaint) + if check_complaint.count() > 0: + reviewer = check_complaint.last().role + else: + reviewer = None + internal_dict_infos.update({ + "complaint": { + "complaint_key": complaint.key, + "create_date": complaint.create_date, + "title": complaint.title, + "description": complaint.description, + "percent": complaint.percent, + "image": complaint.image, + "state": complaint.state, + "message": complaint.message, + "registrar": complaint.registrar, + "reviewer": reviewer, + "real_weight": kill_house_assignment[0].net_weight, + "losses_weight": kill_house_assignment[0].weight_withs_losses, + "percentage_losses": percentage_losses, + } + }) + else: + internal_dict_infos.update({ + "complaint": None + }) + + if not kill_house_assignment: + internal_dict_infos.update({ + "bar_info": None + }) + internal_dict_infos.update({ + "complaint": None + }) + + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if poultry_factor.count() > 0: + poultry_factor = poultry_factor.last() + if poultry_factor.bank != None: + name_of_bank_user = poultry_factor.bank.name_of_bank_user + bank_name = poultry_factor.bank.bank_name + card = poultry_factor.bank.card, + shaba = poultry_factor.bank.shaba, + account = poultry_factor.bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": { + "province_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "bar_code": poultry_factor.factor_bar_code, + "kill_house_name": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares[ + 'poultryShareWithProfit'], + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "total_share_allocation": poultry_factor.total_weight * total, + "total_share_allocation_char": words( + poultry_factor.total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not poultry_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": None + }) + + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if province_factor: + if province_factor[0].bank != None: + name_of_bank_user = province_factor[0].bank.name_of_bank_user + bank_name = province_factor[0].bank.bank_name + card = province_factor[0].bank.card, + shaba = province_factor[0].bank.shaba, + account = province_factor[0].bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + + if province_factor[0].poultry_factor == None: + poultry_share_with_profit = province_factor[0].shares['poultryShareWithProfit'] + else: + poultry_share_with_profit = province_factor[0].poultry_factor.total_price + + internal_dict_infos.update({ + "province_factor_to_kill_house": { + "province_factor_key": province_factor[0].key, + "province_factor_fee": province_factor[0].factor_fee, + "province_operator": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": province_factor[0].total_weight, + "bar_code": province_factor[0].factor_bar_code, + "kill_house_name": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": province_factor[0].total_price, + "poultry_share_with_profit": poultry_share_with_profit, + "union_share_with_profit": province_factor[0].shares[ + 'unionShareWithProfit'], + "total_amount_char": words(province_factor[0].total_price) + " " + "ریال", + "total_share_allocation": province_factor[0].total_weight * total, + "total_share_allocation_char": words( + province_factor[0].total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not province_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house": None + }) + + kill_house_factor_poultry = KillHouseFactorToPoultry.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor_poultry.count(): + kill_house_factor_poultry = kill_house_factor_poultry.last() + internal_dict_infos.update({ + "kill_house_factor_to_poultry": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor_poultry.create_date, + "payment_code": kill_house_factor_poultry.payment_code, + "factor_image": kill_house_factor_poultry.factor_image, + "factor_key": kill_house_factor_poultry.key, + "factor_state": kill_house_factor_poultry.state, + "total_money": kill_house_factor_poultry.province_factor.total_price, + "factor_message": kill_house_factor_poultry.message + } + }) + if not kill_house_factor_poultry: + internal_dict_infos.update({ + "kill_house_factor_to_poultry": None + }) + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor[0].create_date, + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "factor_key": kill_house_factor[0].key, + "factor_state": kill_house_factor[0].state, + "total_money": kill_house_factor[0].province_factor.total_price, + "factor_message": kill_house_factor[0].message + } + }) + if not kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": None + }) + + reqs.append(internal_dict_infos) + internal_province_kill_dict_infos.update({"kill_house_requests": reqs + + }) + if not kill_house_requests: + internal_province_kill_dict_infos.update({"kill_house_requests": None + + }) + + province_kill_reqs_list.append(internal_province_kill_dict_infos) + process.update({"province_kill_requests": province_kill_reqs_list}) + + elif province_kill_reqs.count() == 0: + process.update({"province_kill_requests": None + + }) + if 'role' in request.GET: + if request.GET['role'] == 'KillHouse': + kill_house_operator = KillHouseOperator.objects.filter(user=user, trash=False) + if kill_house_operator.count() > 0: + kill_house_operator = kill_house_operator.last() + kill_house = KillHouse.objects.filter(kill_house_operator=kill_house_operator, trash=False) + kill_house_reqs = KillHouseRequest.objects.filter( + kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + killhouse_user__in=kill_house, trash=False) + elif request.GET['role'] == 'KillHouseVet': + vet = Vet.objects.filter(user=user, trash=False) + if vet.count() > 0: + vet = vet.last() + kill_house_vet = KillHouseVet.objects.filter(vet=vet) + kill_house_vet = kill_house_vet.last() + kill_house_reqs = KillHouseRequest.objects.filter( + kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + killhouse_user=kill_house_vet.kill_house, trash=False) + else: + kill_house_reqs = KillHouseRequest.objects.filter( + kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + trash=False) + + if kill_house_reqs.count() > 0: + + reqs = [] + for kill_house_request in kill_house_reqs: + # province_req = kill_house_request.province_request + internal_dict_infos = { + "kill_house_req_key": kill_house_request.key, + "kill_house_vet_state": kill_house_request.vet_state, + "order_code": poultry_request.order_code, + "barcod": kill_house_request.bar_code, + "kill_house_state": kill_house_request.state, + "kill_house_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_user_name": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.fullname, + "kill_house_user_province": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.province.name, + "kill_house_user_city": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.city.name, + "kill_house_user_address": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.system_address.address, + "kill_house_mobile": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "kill_house_national_id": kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.national_id, + "quantity": kill_house_request.quantity, + # "time": kill_house_request.kill_request.recive_time, + # "date": kill_house_request.kill_request.recive_date, + "cars": kill_house_request.car, + "driver_name": kill_house_request.add_car.driver.driver_name, + "type_car": kill_house_request.add_car.driver.type_car, + "pelak": kill_house_request.add_car.driver.pelak, + "clearance_code": kill_house_request.clearance_code, + "traffic_code": kill_house_request.traffic_code, + "show_kill_house": kill_house_request.show_kill_house, + "kill_house_message": kill_house_request.kill_house_message + } + + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request, trash=False) + if vet_check: + internal_dict_infos.update({ + "vet_check_info": { + "vet_user": vet_check[0].kill_house_vet.vet.user.fullname, + "vet_user_mobile": vet_check[0].kill_house_vet.vet.user.mobile, + "vet_check_state": vet_check[0].state, + "vet_check_accept_date": vet_check[0].create_date, + } + }) + if not vet_check: + internal_dict_infos.update({ + "vet_check_info": None + }) + kill_house_assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False) + if kill_house_assignment: + internal_dict_infos.update({ + "bar_info": { + "kill_house_assignment_key": kill_house_assignment[0].key, + "real_quantity": kill_house_assignment[0].real_quantity, + "kill_house_weight_without_load": kill_house_assignment[0].car_weight_without_load, + "kill_house_weight_with_load": kill_house_assignment[0].car_weight_with_load, + "kill_house_image_without_load": kill_house_assignment[ + 0].car_weight_without_load_image, + "kill_house_image_with_load": kill_house_assignment[0].car_weight_with_load_image, + "kill_house_net_weight": kill_house_assignment[0].net_weight, + "expire_time": kill_house_assignment[0].protest_time, + "kill_house_assignment_state": kill_house_assignment[0].state, + "kill_house_assignment_message": kill_house_assignment[0].message, + "accept_reject_date": kill_house_assignment[0].modify_date + + } + }) + complaint = KillHouseComplaint.objects.filter(bar=kill_house_assignment[0], trash=False) + if complaint.count() > 0: + complaint = complaint.last() + internal_dict_infos.update({ + "complaint": { + "complaint_key": complaint.key, + "title": complaint.title, + "description": complaint.description, + "percent": complaint.percent, + "image": complaint.image, + "state": complaint.state, + "message": complaint.message, + } + }) + else: + internal_dict_infos.update({ + "complaint": None + }) + + if not kill_house_assignment: + internal_dict_infos.update({ + "bar_info": None + }) + internal_dict_infos.update({ + "complaint": None + }) + poultry_factor = ProvinceFactorToKillHouseForPoultry.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if poultry_factor.count() > 0: + poultry_factor = poultry_factor.last() + if poultry_factor.bank != None: + name_of_bank_user = poultry_factor.bank.name_of_bank_user + bank_name = poultry_factor.bank.bank_name + card = poultry_factor.bank.card, + shaba = poultry_factor.bank.shaba, + account = poultry_factor.bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": { + "province_factor_key": poultry_factor.key, + "province_factor_fee": poultry_factor.factor_fee, + "province_operator": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.fullname, + "province_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.province_request.province_operator_system.user.mobile, + "weight": poultry_factor.total_weight, + "bar_code": poultry_factor.factor_bar_code, + "kill_house_name": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.name, + "kill_house_mobile": poultry_factor.province_check_info.kill_house_assignment.kill_house_check.province_kill_request.kill_request.kill_house.kill_house_operator.user.mobile, + "cost": poultry_factor.total_price, + "poultry_share_with_profit": poultry_factor.shares[ + 'poultryShareWithProfit'], + "total_amount_char": words(poultry_factor.total_price) + " " + "ریال", + "total_share_allocation": poultry_factor.total_weight * total, + "total_share_allocation_char": words( + poultry_factor.total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + } + }) + if not poultry_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house_for_poultry": None + }) + province_factor = ProvinceFactorToKillHouse.objects.filter( + province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if province_factor: + if province_factor[0].bank != None: + name_of_bank_user = province_factor[0].bank.name_of_bank_user + bank_name = province_factor[0].bank.bank_name + card = province_factor[0].bank.card, + shaba = province_factor[0].bank.shaba, + account = province_factor[0].bank.account, + else: + name_of_bank_user = None + bank_name = None + card = None + shaba = None + account = None + share_allocation = ShareOfAllocation.objects.all() + if share_allocation.count() > 0: + share_allocation = share_allocation.last() + total = share_allocation.total + else: + total = 0 + if province_factor[0].poultry_factor == None: + poultry_share_with_profit = province_factor[0].shares['poultryShareWithProfit'] + else: + poultry_share_with_profit = province_factor[0].poultry_factor.total_price + province_operator = province_factor[0].province_check_info.province_operator + internal_dict_infos.update({ + "province_factor_to_kill_house": { + "province_factor_key": province_factor[0].key, + "province_factor_fee": province_factor[0].factor_fee, + "province_operator": province_operator.user.fullname, + "province_mobile": province_operator.user.mobile, + "weight": province_factor[0].total_weight, + "bar_code": province_factor[0].factor_bar_code, + "kill_house_name": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.name, + "kill_house_mobile": province_factor[ + 0].province_check_info.kill_house_assignment.kill_house_request.kill_house_request_auction_winner.kill_house_request_auction.kill_house.kill_house_operator.user.mobile, + "cost": province_factor[0].total_price, + "poultry_share_with_profit": poultry_share_with_profit, + "union_share_with_profit": province_factor[0].shares['unionShareWithProfit'], + "total_amount_char": words(province_factor[0].total_price) + " " + "ریال", + "total_share_allocation": province_factor[0].total_weight * total, + "total_share_allocation_char": words( + province_factor[0].total_weight * total) + " " + "ریال", + "name_of_bank_user": name_of_bank_user, + "bank_name": bank_name, + "card": card, + "shaba": shaba, + "account": account, + + } + }) + if not province_factor: + internal_dict_infos.update({ + "province_factor_to_kill_house": None + }) + + kill_house_factor_poultry = KillHouseFactorToPoultry.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor_poultry.count(): + kill_house_factor_poultry = kill_house_factor_poultry.last() + internal_dict_infos.update({ + "kill_house_factor_to_poultry": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor_poultry.create_date, + "payment_code": kill_house_factor_poultry.payment_code, + "factor_image": kill_house_factor_poultry.factor_image, + "factor_key": kill_house_factor_poultry.key, + "factor_state": kill_house_factor_poultry.state, + "total_money": kill_house_factor_poultry.province_factor.total_price, + "factor_message": kill_house_factor_poultry.message + } + }) + if not kill_house_factor_poultry: + internal_dict_infos.update({ + "kill_house_factor_to_poultry": None + }) + kill_house_factor = KillHouseFactorToProvince.objects.filter( + province_factor__province_check_info__kill_house_assignment__kill_house_request__kill_house_request_auction_winner__kill_house_request_auction__poultry_request=poultry_request, + province_factor__province_check_info__kill_house_assignment__kill_house_request=kill_house_request, + trash=False) + if kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": { + "kill_house_name": kill_house_request.killhouse_user.name, + "kill_house_user_city": kill_house_request.killhouse_user.system_address.city.name, + "kill_house_user_province": kill_house_request.killhouse_user.system_address.province.name, + "time": kill_house_factor[0].create_date, + "payment_code": kill_house_factor[0].payment_code, + "factor_image": kill_house_factor[0].factor_image, + "factor_key": kill_house_factor[0].key, + "total_money": kill_house_factor[0].province_factor.total_price, + "factor_state": kill_house_factor[0].state, + "factor_message": kill_house_factor[0].message + } + }) + if not kill_house_factor: + internal_dict_infos.update({ + "kill_house_factor_to_province": None + }) + + reqs.append(internal_dict_infos) + process.update({"auction": reqs}) + + elif kill_house_reqs.count() > 0: + process.update({"auction": None}) + + allocation = DepositAllocation.objects.filter(poultry=poultry_request, trash=False) + if allocation.count() > 0: + if request.GET['role'] == 'Poultry': + if poultry_request.poultry.user_bank_info != None: + poultry_bank_info = poultry_request.poultry.user_bank_info.name_of_bank_user + poultry_bank_name = poultry_request.poultry.user_bank_info.bank_name + poultry_card_number = poultry_request.poultry.user_bank_info.card + poultry_shaba = poultry_request.poultry.user_bank_info.shaba + + else: + poultry_bank_info = None + poultry_bank_name = None + poultry_card_number = None + poultry_shaba = None + + process.update({"allocation": {"allocation_key": allocation[0].key, + "poultry_share_digit": allocation[0].poultry_share, + "poultry_share_char": words( + allocation[0].poultry_share) + " " + 'ریال', + "poultry_share_payment": allocation[0].poultry_share_payment, + "poultry_remaining": (allocation[0].poultry_share - allocation[ + 0].poultry_share_payment), + "poultry_payment_documents": allocation[ + 0].poultry_share_payment_info, + "poultry_bank_info": poultry_bank_info, + "poultry_bank_name": poultry_bank_name, + "poultry_card_number": poultry_card_number, + "poultry_shaba": poultry_shaba, + "poultry_image": allocation[0].poultry_image, + + }}) + elif request.GET['role'] == 'CityOperator': + if city_operator.user_bank_info != None: + city_bank_info = city_operator.user_bank_info.name_of_bank_user + city_bank_name = city_operator.user_bank_info.bank_name + city_card_number = city_operator.user_bank_info.card + city_shaba = city_operator.user_bank_info.shaba + else: + city_bank_info = None + city_bank_name = None + city_card_number = None + city_shaba = None + process.update({"allocation": {"allocation_key": allocation[0].key, + "city_share_digit": allocation[0].city_share, + "city_share_char": words( + allocation[0].city_share) + " " + 'ریال', + "city_share_payment": allocation[0].city_share_payment, + "city_share_remaining": ( + allocation[0].city_share - allocation[0].city_share_payment), + "city_payment_documents": allocation[0].city_share_payment_info, + "city_image": allocation[0].city_image, + "city_bank_info": city_bank_info, + "city_bank_name": city_bank_name, + "city_card_number": city_card_number, + "city_shaba": city_shaba, + }}) + else: + process.update({"allocation": None}) + + if not allocation: + process.update({"allocation": None}) + + province_incpector = PovinceInspector.objects.filter(poultry_request=poultry_request, trash=False) + if province_incpector: + process.update( + {"province_incpector": {"inspector_name": province_incpector[0].inspector_operator.user.fullname, + "state": province_incpector[0].state, + "message": province_incpector[0].message, + "accept-reject-date": province_incpector[0].create_date, }}) + if not province_incpector: + province_name = poultry_request.poultry.address.province.name + inspector = InspectorOperator.objects.get(address__province__name=province_name, trash=False) + process.update({"province_incpector": {"province_incpector": None, + "state": 'pending', + "inspector_name": inspector.user.fullname, + "inspector_mobile": inspector.user.mobile, + "inspector_address": inspector.address.province.name}}) + process1.update({"process": process}) + + return Response(process1, status=status.HTTP_200_OK) + + +# ویوست مربوط به ثبت و نمایش و ... مستاجر مرغداری +class PoultryRequestAuctionViewSet(viewsets.ModelViewSet): + queryset = PoultryRequestAuction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryRequestAuction + + +# ویوست مربوط به وارد کردن اطلاعات بار توسط مرغدار +class PoultryAssignmentInformationViewSet(viewsets.ModelViewSet): + queryset = PoultryAssignmentInformation.objects.all() + serializer_class = PoultryAssignmentInformationSerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به وارد کردن اطلاعات بار توسط مرغدار + def create(self, request, *args, **kwargs): + # refresh(request.user.id) + poultry = PoultryRequest.objects.get(key=request.data['key'], trash=False) + car_without_load_image = request.data['car_without_load_image'] + car_with_load_image = request.data['car_with_load_image'] + request.data.pop('key') + request.data.pop('car_without_load_image') + request.data.pop('car_with_load_image') + pic = [] + pic.append(car_without_load_image) + pic.append(car_with_load_image) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + poultry_assignment_info = serializer.create(validated_data=request.data) + poultry_assignment_info.poultry_request = poultry + for p in pic: + if p == car_without_load_image: + poultry_assignment_info.car_weight_without_load_image = send_image_to_server(p) + else: + poultry_assignment_info.car_weight_with_load_image = send_image_to_server(p) + poultry_assignment_info.save() + assignment_info_serializer = self.serializer_class(poultry_assignment_info) + return Response(assignment_info_serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status=status.HTTP_403_FORBIDDEN) + + # تابع مربوط به ویرایش اطلاعات بار وارد شده توسط مرغدار + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + poultry_assignment = PoultryAssignmentInformation.objects.get(key__exact=request.data["key"], trash=False) + request.data.pop('key') + try: + if request.data['car_without_load_image'] == "": + car_without_load_image = None + + else: + car_without_load_image = request.data['car_without_load_image'] + request.data.pop('car_without_load_image') + + except: + car_without_load_image = None + + try: + if request.data['car_with_load_image'] == "": + car_with_load_image = None + + else: + car_with_load_image = request.data['car_with_load_image'] + request.data.pop('car_with_load_image') + + except: + car_with_load_image = None + + if car_without_load_image: + poultry_assignment.car_weight_without_load_image = send_image_to_server(car_without_load_image) + + if car_with_load_image: + poultry_assignment.car_weight_with_load_image = send_image_to_server(car_with_load_image) + + poultry_assignment.save() + serializer = self.serializer_class(poultry_assignment) + serializer.update(instance=poultry_assignment, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + +# ویوست مربوط به سرچ درخواست مرغدار +class PoultryRequestSearchViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + if 'type' in request.GET: + if request.GET['type'] == 'fullname': + queryset = PoultryRequest.objects.filter(user__fullname=request.GET['value'], trash=False) + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'mobile': + queryset = PoultryRequest.objects.filter(user__mobile=request.GET['value'], trash=False) + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'gis_code': + queryset = PoultryRequest.objects.filter(user__gis_code=request.GET['value'], trash=False) + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'order_code': + queryset = PoultryRequest.objects.get(order_code=int(request.GET['value']), trash=False) + serializer = PoultryRequestSerializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'bar_code': + poultry = KillHouseRequest.objects.get( + bar_code=int(request.GET['value'])).province_request.city_request_Poultry.poultry_request + queryset = PoultryRequest.objects.get(key=poultry.key, trash=False) + serializer = PoultryRequestSerializer(queryset) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'city': + queryset = PoultryRequest.objects.filter(user__address__city=request.GET['value'], trash=False) + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + elif request.GET['type'] == 'province': + queryset = PoultryRequest.objects.filter(user__address__province=request.GET['value'], trash=False) + serializer = PoultryRequestSerializer(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + return Response({"msg": "Enter 'Type' In Get Parameters"}, status=status.HTTP_403_FORBIDDEN) + + +# تابع برای کنسل کردن اتوماتیک درخواست بورسی مرغدار طبق شرایط خاص +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def Cancel_Poultry_Exchange_request(request): + for req in PoultryRequestExchange.objects.all(): + if (req.send_date - req.hatching_date).days > 65: + req.trash = True + req.save() + return Response("ok") + + +def Check_Poultry_Auction_request(): + reqs = PoultryRequest.objects.filter(auction=True, final_state='pending', trash=False).order_by('send_date') + for req in reqs: + now = datetime.datetime.now() + kill_house_auction = KillHouseRequestAction.objects.filter(poultry_request=req, trash=False).order_by('fee') + auction = PoultryRequestAuction.objects.filter(poultry_request=req, state='active', trash=False) + if auction.count() > 0: + auction = auction.last() + if now.year >= auction.auction_date.year and now.month >= auction.auction_date.month and now.day >= auction.auction_date.day and now.hour >= auction.auction_date.hour and now.minute >= auction.auction_date.minute: + if kill_house_auction.count() > 0: + kill_house_auction = kill_house_auction.last() + kill_house_auction_win = KillHouseRequestActionWinner( + kill_house_request_auction=kill_house_auction, + fee=kill_house_auction.fee, + quantity=req.quantity + ) + kill_house_auction_win.save() + req.auction = False + req.save() + auction.state = 'complete' + auction.save() + kill_house_auction.state = 'accepted' + kill_house_auction.save() + kill_house_aucs = KillHouseRequestAction.objects.filter(poultry_request=req, state='pending', + trash=False) + for kill_house_auc in kill_house_aucs: + kill_house_auc.state = 'unaccepted' + kill_house_auc.save() + auctions = PoultryRequestAuction.objects.filter(poultry_request=req, state='inactive', + trash=False) + for auc in auctions: + auc.state = 'complete' + auc.save() + + else: + + auction.state = 'complete' + auction.save() + auctions = PoultryRequestAuction.objects.filter(poultry_request=req, state='inactive', + trash=False).order_by( + 'auction_date') + if auctions.count() > 0: + for auction in auctions: + auction.state = 'active' + auction.save() + break + else: + if req.union == True: + req.auction = False + req.save() + city_operator_check_request = CityOperatorCheckRequest.objects.get(poultry_request=req, + trash=False) + city_operator_check_request.show_province = True + city_operator_check_request.save() + + return Response({"result": "system checked"}, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@csrf_exempt +@permission_classes([AllowAny]) +def Check_Poultry_Auction_request_front(request): + reqs = PoultryRequest.objects.filter(auction=True, final_state='pending', trash=False).order_by('send_date') + for req in reqs: + now = datetime.datetime.now() + kill_house_auction = KillHouseRequestAction.objects.filter(poultry_request=req, trash=False).order_by('fee') + auction = PoultryRequestAuction.objects.filter(poultry_request=req, state='active', trash=False) + if auction.count() > 0: + auction = auction.last() + if now.year >= auction.auction_date.year and now.month >= auction.auction_date.month and now.day >= auction.auction_date.day and now.hour >= auction.auction_date.hour and now.minute >= auction.auction_date.minute: + if kill_house_auction.count() > 0: + kill_house_auction = kill_house_auction.last() + kill_house_auction_win = KillHouseRequestActionWinner( + kill_house_request_auction=kill_house_auction, + fee=kill_house_auction.fee, + quantity=req.quantity + ) + kill_house_auction_win.save() + req.auction = False + req.save() + auction.state = 'complete' + auction.save() + kill_house_auction.state = 'accepted' + kill_house_auction.save() + kill_house_aucs = KillHouseRequestAction.objects.filter(poultry_request=req, state='pending', + trash=False) + for kill_house_auc in kill_house_aucs: + kill_house_auc.state = 'unaccepted' + kill_house_auc.save() + auctions = PoultryRequestAuction.objects.filter(poultry_request=req, state='inactive', + trash=False) + for auc in auctions: + auc.state = 'complete' + auc.save() + else: + + auction.state = 'complete' + auction.save() + auctions = PoultryRequestAuction.objects.filter(poultry_request=req, state='inactive', + trash=False).order_by( + 'auction_date') + if auctions.count() > 0: + for auction in auctions: + auction.state = 'active' + auction.save() + break + else: + if req.union == True: + req.auction = False + req.save() + city_operator_check_request = CityOperatorCheckRequest.objects.get(poultry_request=req, + trash=False) + city_operator_check_request.show_province = True + city_operator_check_request.save() + + return Response({"result": "system checked"}, status=status.HTTP_200_OK) + + +class Chicken_informationViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + serializer_class = PoultryHatchingSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + + poultry_list = [] + quantity_list = [] + + now = datetime.datetime.now().date() + + poultryhatchings = PoultryHatching.objects.filter(state='pending', trash=False) + if poultryhatchings.count() > 0: + if 'age1' in request.GET: + if 'age2' in request.GET: + for poultryhatching in poultryhatchings: + if int(request.GET['age1']) <= (now - poultryhatching.date.date()).days + 1 and ( + now - poultryhatching.date.date()).days + 1 <= int(request.GET['age2']): + quantity_list.append(poultryhatching.quantity) + + internal_dict = { + "full_name": poultryhatching.poultry.user.fullname, + "mobile": poultryhatching.poultry.user.mobile, + "city": poultryhatching.poultry.user.city.name, + "province": poultryhatching.poultry.user.province.name, + "unit_name": poultryhatching.poultry.unit_name, + "breeding_unique_id": poultryhatching.poultry.breeding_unique_id, + "quantity": quantity_list, + } + poultry_list.append(internal_dict) + else: + for poultryhatching in poultryhatchings: + if (now - poultryhatching.date.date()).days + 1 == int(request.GET['age1']): + internal_dict = { + "full_name": poultryhatching.poultry.user.fullname, + "mobile": poultryhatching.poultry.user.mobile, + "city": poultryhatching.poultry.user.city.name, + "province": poultryhatching.poultry.user.province.name, + "unit_name": poultryhatching.poultry.unit_name, + "breeding_unique_id": poultryhatching.poultry.breeding_unique_id, + "quantity": poultryhatching.quantity, + } + poultry_list.append(internal_dict) + + return Response(poultry_list, status=status.HTTP_200_OK) + + +class SingleAgeHatchingStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + + now = timezone.now().date() + ages_list = [] + hatching_list = [] + hatches = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', archive=False + , trash=False).order_by( + '-date') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchs = hatches.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatchs = hatches.filter(poultry__address__city=user.city) + else: + hatchs = hatches + else: + hatchs = hatches + for hatch in hatchs: + if (now - hatch.date.date()).days + 1 not in ages_list: + ages_list.append((now - hatch.date.date()).days + 1) + + # age_difference = ExpressionWrapper(now - F('date'), output_field=DurationField()) + # hatchs = hatchs.annotate(age_difference=age_difference) + for age_list in ages_list: + quantity = 0 + losses = 0 + for hatch in hatchs: + age = (now - hatch.date.date()).days + 1 + if age == age_list: + quantity += hatch.left_over + losses += hatch.losses + hatching_list.append({ + "type": age_list, + "quantity": quantity, + "losses": losses, + }) + return Response(hatching_list, status=status.HTTP_200_OK) + + +class DoughnutHatchingStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + + year = datetime.datetime.now().year + total = 0 + city_list = [] + hatching_list = [] + hatchings_list = [] + hatchingss_lists = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', + archive=False).order_by( + '-date') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchingss_list = hatchingss_lists.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatchingss_list = hatchingss_lists.filter(poultry__address__city=user.city) + else: + hatchingss_list = hatchingss_lists + else: + hatchingss_list = hatchingss_lists + for hatchingss in hatchingss_list: + if (jdatetime.datetime.fromgregorian(year=hatchingss.date.year, month=hatchingss.date.month, + day=hatchingss.date.day)).month == int(request.GET['month']): + hatchings_list.append(hatchingss) + total += hatchingss.quantity + if hatchingss.poultry.address.city not in city_list: + city_list.append(hatchingss.poultry.address.city) + + for city in city_list: + quantity = 0 + for hatch in hatchings_list: + if hatch.poultry.address.city == city: + quantity += hatch.quantity + hatching_list.append({ + "city": city.name, + "percent": round((quantity / total) * 100, 2), + "quantity": quantity, + }) + + return Response(hatching_list, status=status.HTTP_200_OK) + + +class DoughnutHatchingLeftOverStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + + year = datetime.datetime.now().year + total = 0 + city_list = [] + hatching_list = [] + hatchings_list = [] + hatchingss_lists = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', + archive=False).order_by( + '-date') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchingss_list = hatchingss_lists.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatchingss_list = hatchingss_lists.filter(poultry__address__city=user.city) + else: + hatchingss_list = hatchingss_lists + else: + hatchingss_list = hatchingss_lists + for hatchingss in hatchingss_list: + if (jdatetime.datetime.fromgregorian(year=hatchingss.date.year, month=hatchingss.date.month, + day=hatchingss.date.day)).month == int(request.GET['month']): + hatchings_list.append(hatchingss) + total += hatchingss.left_over + if hatchingss.poultry.address.city not in city_list: + city_list.append(hatchingss.poultry.address.city) + + for city in city_list: + quantity = 0 + for hatch in hatchings_list: + if hatch.poultry.address.city == city: + quantity += hatch.left_over + hatching_list.append({ + "city": city.name, + "percent": round((quantity / total) * 100, 2), + "quantity": quantity, + }) + + return Response(hatching_list, status=status.HTTP_200_OK) + + +class HatchingStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user) + now = timezone.now().date() + age_ranges = [ + (1, 5), (6, 10), (11, 15), (16, 20), (21, 25), (26, 30), + (31, 35), (36, 40), (41, 45), (46, 50), (51, 55), (56, 60), (61, 65), (66, 70), (71, 75), (76, 80), + (81, 85), (86, 90), (91, 95), (96, 100) + ] + + age_ranges_dict = {f"{start}_{end}": {"quantity": 0, "losses": 0} for start, end in age_ranges} + + hatches = PoultryHatching.objects.filter(state='pending', allow_hatching='pending', archive=False, + trash=False).order_by( + 'date') + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + hatchs = hatches.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + hatchs = hatches.filter(poultry__address__city=user.city) + else: + hatchs = hatches + else: + hatchs = hatches + for hatch in hatchs: + age = (now - hatch.date.date()).days + 1 + for age_range, range_data in age_ranges_dict.items(): + start_age, end_age = map(int, age_range.split('_')) + if start_age <= age <= end_age: + range_data["quantity"] += hatch.left_over + range_data["losses"] += hatch.losses + + information_list = [{"type": age_range, **data} for age_range, data in age_ranges_dict.items()] + + return Response(information_list) + + +class PoultryRequestProcessDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + + poultry_request_quantity = 0 + poultry_request_index_weight = 0 + poultry_quantity = 0 + poultry_list = [] + now = datetime.datetime.now().date() + poultry_reqs = PoultryRequest.objects.filter(state_process='accepted', province_state='accepted', + archive=False, send_date__year=now.year, + send_date__month=now.month, send_date__day=now.day, + trash=False).select_related( + 'poultry').only('poultry', 'quantity', 'Index_weight') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + poultry_requests = poultry_reqs.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + poultry_requests = poultry_reqs.filter(poultry__address__city=user.city) + else: + poultry_requests = poultry_reqs + else: + poultry_requests = poultry_reqs + for poultry_request in poultry_requests: + if poultry_request.poultry not in poultry_list: + poultry_list.append(poultry_request.poultry) + + poultry_request_quantity += poultry_request.quantity + poultry_request_index_weight += round(poultry_request.quantity * poultry_request.Index_weight) + poultry_quantity = len(poultry_list) + + # province_kill_requests_list = ProvinceKillRequest.objects.filter(state='accepted', trash=False).select_related( + # 'province_request__poultry_request', 'kill_request__kill_house').only( + # 'province_request__poultry_request__Index_weight', 'quantity', 'kill_request__kill_house') + # + # province_kill_requests = [ + # province_kill_request_list for province_kill_request_list in province_kill_requests_list + # if date1 <= province_kill_request_list.kill_request.recive_date.date() <= date2 + # ] + # for province_kill_request in province_kill_requests: + # if province_kill_request.kill_request.kill_house not in kill_house_list: + # kill_house_list.append(province_kill_request.kill_request.kill_house) + # province_kill_request_index_weight += province_kill_request.quantity * province_kill_request.province_request.poultry_request.Index_weight + # province_kill_request_quantity += province_kill_request.quantity + # kill_house_quantity = len(kill_house_list) + # + # kill_house_requests_list = KillHouseRequest.objects.filter(trash=False).select_related( + # 'province_kill_request__province_request__poultry_request', 'kill_request').only( + # 'province_kill_request__province_request__poultry_request__Index_weight', 'kill_request', 'quantity', + # 'vet_state') + # + # kill_house_requests = [ + # kill_house_request_list for kill_house_request_list in kill_house_requests_list + # if date1 <= kill_house_request_list.kill_request.recive_date.date() <= date2 + # ] + # for kill_house_request in kill_house_requests: + # kill_house_assignment_information = KillHouseAssignmentInformation.objects.filter( + # kill_house_request=kill_house_request, trash=False).only('net_weight').last() + # if kill_house_assignment_information: + # kill_house_request_weight += kill_house_assignment_information.net_weight + # else: + # + # kill_house_request_weight += kill_house_request.quantity * kill_house_request.province_kill_request.province_request.poultry_request.Index_weight + # if kill_house_request.clearance_code != None: + # clearance_code_counter += 1 + # if kill_house_request.vet_state == 'accepted': + # vet_state_counter += 1 + # kill_house_request_quantity += kill_house_request.quantity + return Response({ + "poultry_quantity": poultry_quantity, + "poultry_request_quantity": poultry_request_quantity, + "poultry_request_index_weight": poultry_request_index_weight, + # "province_kill_request_quantity": province_kill_request_quantity, + # "province_kill_request_index_weight": province_kill_request_index_weight, + # "kill_house_quantity": kill_house_quantity, + # "clearance_code_counter": clearance_code_counter, + # "kill_house_request_quantity": kill_house_request_quantity, + # "kill_house_request_weight": kill_house_request_weight, + # "vet_state_counter": vet_state_counter, + }) + + +class ProvinceKillRequestProcessDashboardViewSet(viewsets.ModelViewSet): + queryset = ProvinceKillRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = ProvinceKillRequestSerializer + + def list(self, request, *args, **kwargs): + + province_kill_request_quantity = 0 + province_kill_request_index_weight = 0 + kill_house_quantity = 0 + kill_house_list = [] + now = datetime.datetime.now().date() + + province_kill_reqs = ProvinceKillRequest.objects.filter(state__in=('accepted', 'pending'), + kill_request__recive_date__year=now.year, + kill_request__recive_date__month=now.month, + kill_request__recive_date__day=now.day, + trash=False).select_related( + 'province_request__poultry_request', 'kill_request__kill_house').only( + 'province_request__poultry_request__Index_weight', 'quantity', 'kill_request__kill_house') + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + province_kill_requests = province_kill_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + province_kill_requests = province_kill_reqs.filter( + province_request__poultry_request__poultry__address__city=user.city) + else: + province_kill_requests = province_kill_reqs + else: + province_kill_requests = province_kill_reqs + + for province_kill_request in province_kill_requests: + if province_kill_request.kill_request.kill_house not in kill_house_list: + kill_house_list.append(province_kill_request.kill_request.kill_house) + province_kill_request_index_weight += province_kill_request.main_quantity * province_kill_request.province_request.poultry_request.Index_weight + province_kill_request_quantity += province_kill_request.main_quantity + kill_house_quantity = len(kill_house_list) + return Response({ + "province_kill_request_quantity": province_kill_request_quantity, + "province_kill_request_index_weight": province_kill_request_index_weight, + "kill_house_quantity": kill_house_quantity, + }) + + +class KillHouseRequestVetFarmProcessDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = KillHouseRequestSerializer + + def list(self, request, *args, **kwargs): + + kill_house_request_quantity = 0 + kill_house_request_weight = 0 + clearance_code_counter = 0 + now = datetime.datetime.now().date() + + kill_house_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__year=now.year, + kill_request__recive_date__month=now.month, + kill_request__recive_date__day=now.day, + trash=False).select_related( + 'province_kill_request__province_request__poultry_request', 'kill_request').only( + 'province_kill_request__province_request__poultry_request__Index_weight', 'kill_request', 'quantity', + 'vet_state', 'clearance_code') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__address__city=user.city) + else: + kill_house_requests = kill_house_reqs + else: + kill_house_requests = kill_house_reqs + + for kill_house_request in kill_house_requests: + kill_house_assignment_information = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False).only('net_weight').last() + if kill_house_assignment_information: + kill_house_request_weight += kill_house_assignment_information.net_weight + else: + + kill_house_request_weight += kill_house_request.quantity * kill_house_request.province_kill_request.province_request.poultry_request.Index_weight + if kill_house_request.clearance_code != None: + clearance_code_counter += 1 + kill_house_request_quantity += kill_house_request.quantity + return Response({ + "kill_house_quantity": kill_house_request_quantity, + "clearance_code_counter": clearance_code_counter, + "kill_house_request_weight": kill_house_request_weight, + }) + + +class KillHouseRequestVetProcessDashboardViewSet(viewsets.ModelViewSet): + queryset = KillHouseRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = KillHouseRequestSerializer + + def list(self, request, *args, **kwargs): + + kill_house_request_quantity = 0 + kill_house_request_weight = 0 + vet_check_counter = 0 + now = datetime.datetime.now().date() + + kill_house_reqs = KillHouseRequest.objects.filter(kill_request__recive_date__year=now.year, + kill_request__recive_date__month=now.month, + kill_request__recive_date__day=now.day, + trash=False, vet_state='accepted').select_related( + 'province_kill_request__province_request__poultry_request', 'kill_request').only( + 'province_kill_request__province_request__poultry_request__Index_weight', 'kill_request', 'quantity', + 'vet_state') + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + user = SystemUserProfile.objects.get(user=request.user) + city_operator = CityOperator.objects.get(trash=False, user=user) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + user = SystemUserProfile.objects.get(user=request.user) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__address__city=user.city) + else: + kill_house_requests = kill_house_reqs + else: + kill_house_requests = kill_house_reqs + + for kill_house_request in kill_house_requests: + kill_house_assignment_information = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request, trash=False).only('net_weight').last() + if kill_house_assignment_information: + kill_house_request_weight += kill_house_assignment_information.net_weight + else: + + kill_house_request_weight += kill_house_request.quantity * kill_house_request.province_kill_request.province_request.poultry_request.Index_weight + if kill_house_request.vet_state == 'accepted': + vet_check_counter += 1 + kill_house_request_quantity += kill_house_request.quantity + return Response({ + "kill_house_quantity": kill_house_request_quantity, + "vet_check_counter": vet_check_counter, + "kill_house_request_weight": kill_house_request_weight, + }) + + +class TotalPoultryRequestStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryRequestSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + accepted_poultry_request_quantity = 0 + accepted_kill_house_request_quantity = 0 + poultry_reqs = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False).only( + 'quantity', 'province_state', + 'state_process') + kill_house_reqs = KillHouseRequest.objects.filter(trash=False).only('quantity', 'vet_state') + + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultry_requests = poultry_reqs.filter(poultry__city_operator=city_operator.unit_name) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = poultry_reqs.filter(poultry__address__city=user.city) + kill_house_requests = kill_house_reqs.filter( + province_request__poultry_request__poultry__address__city=user.city) + + else: + poultry_requests = poultry_reqs + kill_house_requests = kill_house_reqs + else: + poultry_requests = poultry_reqs + kill_house_requests = kill_house_reqs + total_poultry_request_quantity = poultry_requests.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + for poultry_request in poultry_requests: + if poultry_request.state_process == 'accepted' and poultry_request.province_state == 'accepted' and poultry_request.archive == False: + accepted_poultry_request_quantity += poultry_request.quantity + total_kill_house_request_quantity = kill_house_requests.aggregate(total_quantity=Sum('quantity')).get( + 'total_quantity', 0) + for kill_house_request in kill_house_requests: + if kill_house_request.vet_state == 'accepted': + accepted_kill_house_request_quantity += kill_house_request.quantity + return Response({ + "total_poultry_request_quantity": total_poultry_request_quantity, + "accepted_poultry_request_quantity": accepted_poultry_request_quantity, + "total_kill_house_request_quantity": total_kill_house_request_quantity, + "accepted_kill_house_request_quantity": accepted_kill_house_request_quantity, + }) + + +class TotalFilePoultryRequestStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + permission_classes = [AllowAny] + serializer_class = PoultryRequestSerializer + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + accepted_poultry_request_quantity = 0 + rejected_poultry_request_quantity = 0 + archive_poultry_request_quantity = 0 + poultry_reqs = PoultryRequest.objects.filter(trash=False).only('quantity', 'province_state', + 'state_process', 'archive', + 'final_state') + if 'role' in request.GET: + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultry_requests = poultry_reqs.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultry_requests = poultry_reqs.filter(poultry__address__city=user.city) + else: + poultry_requests = poultry_reqs + else: + poultry_requests = poultry_reqs + for poultry_request in poultry_requests: + if poultry_request.state_process == 'accepted' and poultry_request.province_state == 'accepted' and poultry_request.archive == False: + accepted_poultry_request_quantity += 1 + if poultry_request.province_state == 'rejected' or poultry_request.state_process == 'rejected': + rejected_poultry_request_quantity += 1 + if poultry_request.archive == True: + archive_poultry_request_quantity += 1 + + return Response({ + "total_poultry_request_quantity": poultry_requests.count(), + "accepted_poultry_request_quantity": accepted_poultry_request_quantity, + "rejected_poultry_request_quantity": rejected_poultry_request_quantity, + "archive_poultry_request_quantity": archive_poultry_request_quantity, + }) + + +class TotalPoultryHatchingStatisticsDashboardViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + filterset_class = PoultryManageFilterSet + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + poultreis = Poultry.objects.filter(trash=False).select_related('user', 'address__province', 'address__city') + if 'role' in request.GET: + user = SystemUserProfile.objects.get(user=request.user) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultrys = poultreis.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultrys = poultreis.filter(poultry__user__city=user.city) + else: + poultrys = poultreis + else: + poultrys = poultreis + if value and search == 'filter': + if value != 'undefined' and value.strip(): + poultrys = poultreis.filter( + build_query(self.filterset_class, value) + ) + all_period = 0 + all_total_quantity = 0 + all_hatching_pending = 0 + all_total_quantity_poultry_hatching_pending = 0 + all_total_left_over_poultry_hatching_pending = 0 + all_kill_request = 0 + all_kill_request_quantity = 0 + all_all_weight_loss = 0 + len_werhouse_enter = 0 + for poultry in poultrys: + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, trash=False).only('quantity', 'left_over' + ) + if poultry_hatching: + + poultry_hatching_pending = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False).last() + if poultry_hatching_pending: + all_hatching_pending += 1 + if poultry_hatching_pending: + period = poultry_hatching_pending.period + else: + period = poultry_hatching.last().period + all_period += period + poultry_hatching_pending1 = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False) + total_quantity = \ + poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_quantity_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_left_over_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + all_total_quantity += total_quantity + all_total_quantity_poultry_hatching_pending += total_quantity_poultry_hatching_pending + all_total_left_over_poultry_hatching_pending += total_left_over_poultry_hatching_pending + poultry_request = PoultryRequest.objects.filter(trash=False, poultry=poultry, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only( + 'quantity', 'Index_weight') + kill_request = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_request).only( + 'accepted_real_quantity', 'accepted_real_weight') + + all_kill_request += len(kill_request) + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_kill_request_quantity += kill_request_quantity + + werhouse_enter = kill_request.filter(ware_house_confirmation=True).only( + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss') + + all_weight_loss = werhouse_enter.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_all_weight_loss += all_weight_loss + len_werhouse_enter += len(werhouse_enter) + + return Response({ + "poultryCounts": len(poultrys), + "allPeriod": all_period, + "allTotalQuantity": all_total_quantity, + "hatchingPending": all_hatching_pending, + "totalQuantityPoultryHatchingPending": all_total_quantity_poultry_hatching_pending, + "totalLeftOverPoultryHatchingPending": all_total_left_over_poultry_hatching_pending, + "allKillRequest": all_kill_request, + "allKillRequestQuantity": all_kill_request_quantity, + "percentLoss": round(int(all_all_weight_loss) / len_werhouse_enter, 2) if len_werhouse_enter > 0 else 0, + }) + + +# test +class Chart_DashbourdViewSet(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryHatchingSerializer + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + poultry_hatching = {} + price_dict = {} + price_list = [] + poultry_requests = {} + kill_house_requests = {} + operators = {} + prices = {} + file = {} + box = {} + total_users = 0 + number_of_users = 0 + number_of_operators = 0 + chicken_price = 0 + celling_chicken_price = 0 + floor_chicken_price = 0 + total_users = 0 + total_hatching = 0 + total_lossess = 0 + real_hatching = 0 + total_list = [] + killcapacity = 0 + poultryquentity = 0 + + now = datetime.datetime.now().date() + quantity_1_5 = 0 + quantity_1_5_losses = 0 + quantity_5_10 = 0 + quantity_5_10_losses = 0 + quantity_10_15 = 0 + quantity_10_15_losses = 0 + quantity_15_20 = 0 + quantity_15_20_losses = 0 + + quantity_20_25 = 0 + quantity_20_25_losses = 0 + quantity_25_30 = 0 + quantity_25_30_losses = 0 + quantity_30_35 = 0 + quantity_30_35_losses = 0 + quantity_35_40 = 0 + quantity_35_40_losses = 0 + quantity_40_45 = 0 + quantity_40_45_losses = 0 + quantity_45_50 = 0 + quantity_45_50_losses = 0 + quantity_50_55 = 0 + quantity_50_55_losses = 0 + quantity_55_60 = 0 + quantity_55_60_losses = 0 + + killreques_10 = 0 + killreques_20 = 0 + killreques_30 = 0 + killreques_40 = 0 + killreques_50 = 0 + killreques_60 = 0 + + if 'city' in request.GET: + hatchs = PoultryHatching.objects.filter(state='pending', + poultry__address__city__name=request.GET['city'], + poultry__address__province=user.province) + + elif 'breed' in request.GET: + hatchs = PoultryHatching.objects.filter(state='pending', chicken_breed=request.GET['breed'], + poultry__address__province=user.province) + else: + hatchs = PoultryHatching.objects.filter(state='pending', poultry__address__province=user.province) + + if hatchs.count() > 0: + + for hatch in hatchs: + age = (now - hatch.date.date()).days + 1 + if age >= 1 and age <= 5: + quantity_1_5 += hatch.quantity + quantity_1_5_losses += hatch.losses + + elif age >= 5 and age <= 10: + quantity_5_10 += hatch.quantity + quantity_5_10_losses += hatch.losses + + elif age >= 10 and age <= 15: + quantity_10_15 += hatch.quantity + quantity_10_15_losses += hatch.losses + + elif age >= 15 and age <= 20: + quantity_15_20 += hatch.quantity + quantity_15_20_losses += hatch.losses + + elif age >= 20 and age <= 25: + quantity_20_25 += hatch.quantity + quantity_20_25_losses += hatch.losses + + + elif age >= 25 and age <= 30: + quantity_25_30 += hatch.quantity + quantity_25_30_losses += hatch.losses + + elif age >= 30 and age <= 35: + quantity_30_35 += hatch.quantity + quantity_30_35_losses += hatch.losses + + elif age >= 35 and age <= 40: + quantity_35_40 += hatch.quantity + quantity_35_40_losses += hatch.losses + + elif age >= 40 and age <= 45: + quantity_40_45 += hatch.quantity + quantity_40_45_losses += hatch.losses + + elif age >= 45 and age <= 50: + quantity_45_50 += hatch.quantity + quantity_45_50_losses += hatch.losses + + elif age >= 50 and age <= 55: + quantity_50_55 += hatch.quantity + quantity_50_55_losses += hatch.losses + + elif age >= 55 and age <= 60: + quantity_55_60 += hatch.quantity + quantity_55_60_losses += hatch.losses + information_list = [ + {"type": "1_5", "quantity": quantity_1_5, "losses": quantity_1_5_losses}, + {"type": "5_10", "quantity": quantity_5_10, "losses": quantity_5_10_losses}, + {"type": "10_15", "quantity": quantity_10_15, "losses": quantity_10_15_losses}, + {"type": "15_20", "quantity": quantity_15_20, "losses": quantity_15_20_losses}, + {"type": "20_25", "quantity": quantity_20_25, "losses": quantity_20_25_losses}, + {"type": "25_30", "quantity": quantity_25_30, "losses": quantity_25_30_losses}, + {"type": "30_35", "quantity": quantity_30_35, "losses": quantity_30_35_losses}, + {"type": "35_40", "quantity": quantity_35_40, "losses": quantity_35_40_losses}, + {"type": "40_45", "quantity": quantity_40_45, "losses": quantity_40_45_losses}, + {"type": "45_50", "quantity": quantity_45_50, "losses": quantity_45_50_losses}, + {"type": "50_55", "quantity": quantity_50_55, "losses": quantity_5_10_losses}, + {"type": "55_60", "quantity": quantity_55_60, "losses": quantity_55_60_losses}, + + ] + else: + information_list = [] + + poultry_hatching.update({"poultry_hatching": information_list}) + + total_list.append(poultry_hatching) + + pricing = Pricing.objects.all() + price_internal_dict = {} + for price in pricing: + inter_dict = { + "price": price.live_chicken_price, + "date": price.date + } + price_list.append(inter_dict) + inter_dict = {} + price_internal_dict.update({"price_list": price_list}) + total_list.append(price_internal_dict) + + poultry = Poultry.objects.filter(user__province=user.province) + city_operator = CityOperator.objects.filter(user__province=user.province) + province_operator = ProvinceOperator.objects.filter(user__province=user.province, + user__role__name='ProvinceOperator') + financial_operator = Poultry.objects.filter(user__province=user.province, + user__role__name='ProvinceFinancial') + inspector_operator = InspectorOperator.objects.filter(user__province=user.province) + killhouse_operator = KillHouseOperator.objects.filter(user__province=user.province) + driver = KillHouseDriver.objects.filter(user__province=user.province) + vet = Vet.objects.filter(user__province=user.province) + killhouse_vet = KillHouseVet.objects.filter(vet__user__province=user.province) + total_users = poultry.count() + city_operator.count() + province_operator.count() + financial_operator.count() + inspector_operator.count() + killhouse_operator.count() + vet.count() + driver.count() + number_of_users = poultry.count() + killhouse_operator.count() + vet.count() + driver.count() + number_of_operators = city_operator.count() + province_operator.count() + financial_operator.count() + inspector_operator.count() + + poultry_reqs = PoultryRequest.objects.filter(poultry__address__province=user.province) + files_count = [] + active = 0 + archive = 0 + rejected = 0 + if poultry_reqs.count() > 0: + + for poultry_req in poultry_reqs: + if poultry_req.final_state == 'pending': + active += 1 + if poultry_req.final_state == 'archive': + archive += 1 + if poultry_req.state_process == 'rejected' or poultry_req.province_state == 'rejected': + rejected += 1 + poultyry_hachting = PoultryHatching.objects.filter(state='pending', + poultry__address__province=user.province) + if poultyry_hachting.count() > 0: + for hatching in poultyry_hachting: + total_hatching += hatching.quantity + total_lossess += hatching.losses + real_hatching = total_hatching - total_lossess + + pricies = Pricing.objects.all() + + if pricies.count() > 0: + price = pricies.last() + chicken_price = price.live_chicken_price + celling_chicken_price = price.ceiling_price + floor_chicken_price = price.floor_price + + poultryrequests = PoultryRequest.objects.filter(state_process='accepted') + + if poultryrequests.count() > 0: + for poultryrequest in poultryrequests: + poultryquentity += poultryrequest.quantity + + box.update({"box": {"total_users": total_users, "number_of_users": number_of_users, + "number_of_operators": number_of_operators, "number_of_active_files": active, + "number_of_archive_files": archive, "number_of_rejected_files": rejected, + "total_hatching": total_hatching, "total_lossess": total_lossess, + "real_hatching": real_hatching, "price": chicken_price, + "floor_price": floor_chicken_price, "celling_price": celling_chicken_price, + "killcapacity": killcapacity, "poultryquentity": poultryquentity}}) + total_list.append(box) + + return Response(total_list, status=status.HTTP_200_OK) + + +class PoultryRequestInformation(viewsets.ModelViewSet): + queryset = PoultryHatching.objects.all() + serializer_class = PoultryHatchingSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # refresh(request.user.id) + poultry_hatchings = PoultryHatching.objects.filter(state='pending', trash=False) + l = [] + + for hatch in poultry_hatchings: + if PoultryRequest.objects.filter(hatching_id=hatch.id).exists(): + inter_dict = { + "period": hatch.period, + "breed": hatch.chicken_breed, + "hatching_date": hatch.create_date, + "losses": hatch.losses + } + l.append(inter_dict) + return Response(l, status=status.HTTP_200_OK) + + +class TotalPoultryRequestQuantityForCitryViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + city_operator = CityOperator.objects.get(user=SystemUserProfile.objects.get(user=request.user)) + poultry_list = [] + total_quantity = 0 + first_quantity = 0 + accepted_quantity = 0 + city_accepted_quantity = 0 + allocated_quantity = 0 + kill_request_quantity = 0 + rejected_quantity = 0 + waiting_quantity = 0 + assignableQuantity = 0 + quantity_of_45 = 0 + now = datetime.datetime.strptime(request.GET['date'], + '%Y-%m-%d').date() if 'date' in request.GET else datetime.datetime.now().date() + + hatchings = PoultryHatching.objects.filter(trash=False, allow_hatching='pending', archive=False) + if hatchings.count() > 0: + + for hatcing in hatchings: + if (now - hatcing.date.date()).days + 1 <= 65 and (now - hatcing.date.date()).days + 1 >= 45: + quantity_of_45 += hatcing.left_over + + poultry_requests = PoultryRequest.objects.filter(final_state='pending', city_operator=city_operator, + trash=False, + out=False, send_date__year=now.year, + send_date__month=now.month, send_date__day=now.day + ) + + for poultry_request in poultry_requests: + if poultry_request.province_state == 'accepted' or poultry_request.province_state == 'pending': + total_quantity += poultry_request.quantity + first_quantity += poultry_request.first_quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + if poultry_request.state_process == 'accepted': + city_accepted_quantity += poultry_request.quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + + if poultry_request.province_state == 'accepted': + accepted_quantity += poultry_request.quantity + assignableQuantity += poultry_request.remain_quantity + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request=poultry_request, + trash=False, state__in=('pending', 'accepted')) + if province_kill_reqs.count() > 0: + for province_kill_req in province_kill_reqs: + allocated_quantity += province_kill_req.main_quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + + if poultry_request.province_state == 'rejected' or poultry_request.state_process == 'rejected': + rejected_quantity += poultry_request.quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + + if poultry_request.province_state == 'pending': + if poultry_request.state_process == 'rejected': + continue + else: + waiting_quantity += poultry_request.quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + + dict1 = { + "total_quantity": total_quantity, + "first_quantity": first_quantity, + "accepted_quantity": accepted_quantity, + "city_accepted_quantity": city_accepted_quantity, + "allocated_quantity": allocated_quantity, + "kill_request_quantity": kill_request_quantity, + "rejected_quantity": rejected_quantity, + "waiting_quantity": waiting_quantity, + "assignableQuantity": assignableQuantity, + "quantity_of_45": quantity_of_45 + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class TotalPoultryRequestQuantityViewSet(viewsets.ModelViewSet): + queryset = TotalPoultryRequestQuantity.objects.all() + serializer_class = TotalPoultryRequestQuantitySerializer + permission_classes = [TokenHasReadWriteScope] + + # تابع مربوط به ویرایش مرغداری + def update(self, request, pk=None, *args, **kwargs): + # refresh(request.user.id) + user = SystemUserProfile.objects.get(user=request.user) + now = datetime.datetime.now().date() + total_poultry_request_quantity = TotalPoultryRequestQuantity.objects.get(key=request.data["key"], + trash=False) + request.data.pop('key') + for kill_house in KillHouse.objects.filter(system_address__province=user.province): + percentage = KillHousePercentage.objects.get(kill_house=kill_house) + percentage.quantity = percentage.percent / 100 * int(request.data['input_quantity']) + percentage.save() + kill_req = KillRequest.objects.filter(recive_date__year=now.year, recive_date__month=now.month, + recive_date__day=now.day, kill_house=kill_house) + if kill_req.count() > 0: + kill_req = kill_req.last() + kill_req.kill_capacity = percentage.quantity + kill_req.remain_quantity += percentage.quantity - kill_req.remain_quantity + kill_req.save() + serializer = self.serializer_class(total_poultry_request_quantity) + serializer.update(instance=total_poultry_request_quantity, validated_data=request.data) + return Response(serializer.data, status=status.HTTP_200_OK) + + # تابع مربوط به نمایش مرغداری + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + poultry_list = [] + total_quantity = 0 + first_quantity = 0 + accepted_quantity = 0 + city_accepted_quantity = 0 + allocated_quantity = 0 + returned_quantity = 0 + direct_buying_quantity = 0 + kill_request_quantity = 0 + rejected_quantity = 0 + waiting_quantity = 0 + assignableQuantity = 0 + quantity_of_45 = 0 + if 'date' in request.GET: + now = datetime.datetime.strptime(request.GET['date'], '%Y-%m-%d').date() + else: + now = datetime.datetime.now().date() + + hatchings = PoultryHatching.objects.filter(trash=False, allow_hatching='pending', + archive=False) + + if hatchings: + for hatcing in hatchings: + if (now - hatcing.date.date()).days + 1 <= 80: + if (now - hatcing.date.date()).days + 1 >= 45: + quantity_of_45 += hatcing.left_over + + poultry_requests = PoultryRequest.objects.filter( + # final_state='pending', + # province_state__in=('accepted', 'pending'), + poultry__address__province=user.province, trash=False, + out=False, + # direct_buying=False, + send_date__year=now.year, send_date__month=now.month, + send_date__day=now.day) + for poultry_request in poultry_requests: + total_quantity += poultry_request.quantity + first_quantity += poultry_request.first_quantity + if poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(poultry_request.poultry) + city_accepted_poultry_requests = PoultryRequest.objects.filter(final_state='pending', + state_process='accepted', + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=False, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + + if city_accepted_poultry_requests.count() > 0: + for city_accepted_poultry_request in city_accepted_poultry_requests: + city_accepted_quantity += city_accepted_poultry_request.quantity + if city_accepted_poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(city_accepted_poultry_request.poultry) + + accepted_poultry_requests = PoultryRequest.objects.filter(final_state='pending', + province_state='accepted', + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=False, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + + if accepted_poultry_requests.count() > 0: + for accepted_poultry_request in accepted_poultry_requests: + accepted_quantity += accepted_poultry_request.quantity + assignableQuantity += accepted_poultry_request.remain_quantity + if accepted_poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(accepted_poultry_request.poultry) + + rejected_requests = PoultryRequest.objects.filter( + Q(province_state='rejected') | Q(state_process='rejected'), + final_state='pending', + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=False, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + + if rejected_requests.count() > 0: + for rejected_request in rejected_requests: + rejected_quantity += rejected_request.quantity + if rejected_request.poultry in poultry_list: + pass + else: + poultry_list.append(rejected_request.poultry) + waiting_requests = PoultryRequest.objects.filter(final_state='pending', + province_state='pending', + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=False, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + + if waiting_requests.count() > 0: + for waiting_request in waiting_requests: + if waiting_request.state_process == 'rejected': + continue + else: + waiting_quantity += waiting_request.quantity + if waiting_request.poultry in poultry_list: + pass + else: + poultry_list.append(waiting_request.poultry) + + allocated_poultry_requests = PoultryRequest.objects.filter(final_state='pending', + province_state='accepted', + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=False, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + if allocated_poultry_requests.count() > 0: + for allocated_poultry_request in allocated_poultry_requests: + if allocated_poultry_request.poultry in poultry_list: + pass + else: + poultry_list.append(allocated_poultry_request.poultry) + province_kill_reqs = ProvinceKillRequest.objects.filter( + province_request__poultry_request=allocated_poultry_request, + trash=False, state__in=('pending', 'accepted')) + if province_kill_reqs.count() > 0: + for province_kill_req in province_kill_reqs: + if province_kill_req.return_to_province == False: + allocated_quantity += province_kill_req.main_quantity + else: + returned_quantity += province_kill_req.main_quantity + + direct_buying_poultry_requests = PoultryRequest.objects.filter( + + poultry__address__province=user.province, + trash=False, + out=False, + direct_buying=True, + send_date__year=now.year, + send_date__month=now.month, + send_date__day=now.day) + if direct_buying_poultry_requests.count() > 0: + for direct in direct_buying_poultry_requests: + direct_buying_quantity += direct.quantity + + total_poultry_request_quantity = TotalPoultryRequestQuantity.objects.filter(create_date__year=now.year, + create_date__month=now.month, + create_date__day=now.day) + if total_poultry_request_quantity.count() > 0: + total_poultry_request_quantity = total_poultry_request_quantity.last() + total_poultry_request_quantity.quantity = total_quantity + total_poultry_request_quantity.accepted_quantity = accepted_quantity + total_poultry_request_quantity.allocated_quantity = allocated_quantity + total_poultry_request_quantity.returned_quantity = returned_quantity + total_poultry_request_quantity.city_accepted_quantity = city_accepted_quantity + total_poultry_request_quantity.first_quantity = first_quantity + total_poultry_request_quantity.rejected_quantity = rejected_quantity + total_poultry_request_quantity.waiting_quantity = waiting_quantity + total_poultry_request_quantity.direct_buying_quantity = direct_buying_quantity + total_poultry_request_quantity.age_up_45 = quantity_of_45 + total_poultry_request_quantity.save() + else: + total_poultry_request_quantity = TotalPoultryRequestQuantity( + quantity=total_quantity, + accepted_quantity=accepted_quantity, + allocated_quantity=allocated_quantity, + returned_quantity=returned_quantity, + city_accepted_quantity=city_accepted_quantity, + first_quantity=first_quantity, + rejected_quantity=rejected_quantity, + waiting_quantity=waiting_quantity, + direct_buying_quantity=direct_buying_quantity, + age_up_45=quantity_of_45, + ) + total_poultry_request_quantity.save() + percentage = KillHousePercentage.objects.filter(percent__gt=0) + kill_reqs = KillRequest.objects.filter(recive_date__year=now.year, recive_date__month=now.month, + recive_date__day=now.day, trash=False) + if kill_reqs.count() > 0: + for kill_req in kill_reqs: + kill_request_quantity += kill_req.kill_capacity + + total_poultry_request_quantity.kill_requests_quantity = kill_request_quantity + total_poultry_request_quantity.number_of_kill_house = percentage.count() + total_poultry_request_quantity.number_of_poultry = len(poultry_list) + total_poultry_request_quantity.assignableQuantity = assignableQuantity + total_poultry_request_quantity.save() + serializer = self.serializer_class(total_poultry_request_quantity) + return Response(serializer.data) + + +class PoultryRequestWeightViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + # user = SystemUserProfile.objects.get(user=request.user) + # # refresh(request.user.id) + # weight_list = [] + # average = 0 + # now = datetime.datetime.now().date() + # poultry_requests = PoultryRequest.objects.filter(final_state='pending', + # province_state__in=('accepted', 'pending'), + # poultry__address__province=user.province) + # # poultry_requests = PoultryRequest.objects.filter(final_state='pending', + # # province_state__in=('accepted', 'pending'), + # # send_date__year=now.year, send_date__month=now.month, + # # send_date__day=now.day, + # # poultry__address__province=user.province) + # if poultry_requests.count() > 0: + # + # for poultry_request in poultry_requests: + # total_quantity = poultry_request.quantity + # + # province_kill_reqs = ProvinceKillRequest.objects.filter( + # province_request__poultry_request=poultry_request) + # if province_kill_reqs.count() > 0: + # for province_kill_req in province_kill_reqs: + # total_quantity -= province_kill_req.main_quantity + # if total_quantity > 0: + # weight_list.append(poultry_request.Index_weight) + # for weight in weight_list: + # average += weight + # average = average / 1 + weight_list = [3.2, 3.2, 2.5, 2.9, 3.1] + return Response({'list': weight_list, 'ave': 3613.2}) + # return Response({'list': weight_list, 'ave': round(average, 2)}) + + +class BarsForKillHouseViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.all() + serializer_class = PoultryRequestSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + kill_house = KillHouse.objects.filter(kill_house_operator__user=user, trash=False).select_related( + 'system_address__province').first() + if kill_house.killer == True: + percentage = KillHousePercentage.objects.get(kill_house=kill_house, trash=False) + kill_house_vet = KillHouseVet.objects.filter(kill_house=percentage.kill_house_for_killer, + trash=False).select_related( + 'vet__user').last() + else: + kill_house_vet = KillHouseVet.objects.filter(kill_house=kill_house, trash=False).select_related( + 'vet__user').last() + kill_house_req_dict = {} + kill_house_req_list = [] + + now = datetime.datetime.now().date() + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + # date = date - timedelta(days=1) + # if 'freezing' in request.GET: + # freezing = True + # # freezing = False if user.province.name == 'مركزی' else True + # + # queryset = PoultryRequest.objects.filter( + # poultry__address__province=kill_house.system_address.province, + # final_state__in=('pending', 'archive'), + # trash=False, out=False, + # send_date__date=date, + # freezing=freezing + # + # ).select_related('poultry', 'poultry__user', 'poultry__address__city').order_by('-send_date') + # else: + queryset = PoultryRequest.objects.filter( + poultry__address__province=kill_house.system_address.province, + final_state__in=('pending', 'archive'), + trash=False, out=False, + send_date__date__gte=date1, send_date__date__lte=date2, + + ).select_related('poultry', 'poultry__user', 'poultry__address__city').order_by('-send_date') + + if len(queryset) > 0: + for poultry_req in queryset: + vet_farm = VetFarm.objects.filter(poultry=poultry_req.poultry).select_related('vet__user').last() + if vet_farm: + vet_name = vet_farm.vet.user.fullname + vet_mobile = vet_farm.vet.user.mobile + else: + vet_name = None + vet_mobile = None + if request.GET['type'] == 'entered': + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + province_kill_request__province_request__poultry_request=poultry_req, + ware_house_confirmation=True, trash=False).select_related( + 'kill_request__kill_house__kill_house_operator__user', 'add_car__driver', + 'kill_request__kill_house') + else: + + kill_house_requests = KillHouseRequest.objects.filter( + Q(killhouse_user=kill_house) | Q(killer=kill_house), + province_kill_request__province_request__poultry_request=poultry_req, + ware_house_confirmation=False).select_related( + 'kill_request__kill_house__kill_house_operator__user', 'add_car__driver', + 'kill_request__kill_house') + if kill_house_requests: + for kill_house_request in kill_house_requests: + weight_loss = kill_house_request.accepted_real_weight - kill_house_request.ware_house_accepted_real_weight if kill_house_request.ware_house_accepted_real_weight > 0 else 0 + if weight_loss < 0: + weight_loss = weight_loss * -1 + total_weight_loss = ( + weight_loss / kill_house_request.accepted_real_weight) * 100 if weight_loss != 0 else 0 + # kill_house_request.weight_loss = total_weight_loss + # kill_house_request.save() + vet_check = VetCheckRequest.objects.filter(kill_house_request=kill_house_request) + if vet_check.count() > 0: + vet_check_state = vet_check.last().state + else: + vet_check_state = 'pending' + assignment = KillHouseAssignmentInformation.objects.filter( + kill_house_request=kill_house_request).last() + if assignment: + assignment_state = 'accepted' + assignment_real_quantity = kill_house_request.accepted_real_quantity + assignment_net_weight = kill_house_request.accepted_real_weight + + else: + if kill_house_request.vet_state == 'pending': + assignment_state = 'pending' + else: + assignment_state = 'no_state' + assignment_real_quantity = kill_house_request.accepted_real_quantity + assignment_net_weight = kill_house_request.accepted_real_weight + exclusive_killer = None + if kill_house_request.killer != None: + exclusive_killer = { + "killer_name": kill_house_request.killer.name, + "killer_mobile": kill_house_request.killer.kill_house_operator.user.mobile, + "killer_fullname": kill_house_request.killer.kill_house_operator.user.fullname, + } + + kill_house_req_dict.update({ + "poultry_req_order_code": poultry_req.order_code, + "poultry_name": poultry_req.poultry.unit_name, + "poultry_user_name": poultry_req.poultry.user.fullname, + "poultry_mobile": poultry_req.poultry.user.mobile, + "poultry_city": poultry_req.poultry.address.city.name, + "chicken_breed": poultry_req.chicken_breed, + "date": poultry_req.send_date, + "freezing": poultry_req.freezing, + "clearance_code": kill_house_request.clearance_code, + "traffic_code": kill_house_request.traffic_code, + "kill_house_request_key": kill_house_request.key, + "ware_house_accepted_real_quantity": kill_house_request.ware_house_accepted_real_quantity, + "ware_house_accepted_real_weight": kill_house_request.ware_house_accepted_real_weight, + "bar_code": kill_house_request.bar_code, + "health_code": kill_house_request.add_car.driver.health_code, + "vet_name": vet_name, + "vet_mobile": vet_mobile, + "kill_house_vet_name": kill_house_vet.vet.user.fullname, + "kill_house_vet_mobile": kill_house_vet.vet.user.mobile, + "driver_name": kill_house_request.add_car.driver.driver_name, + "driver_mobile": kill_house_request.add_car.driver.driver_mobile, + "kill_house_name": kill_house_request.killhouse_user.name, + "type_car": kill_house_request.add_car.driver.type_car, + "killer": exclusive_killer, + "vet_check_state": vet_check_state, + "assignment_state": assignment_state, + "kill_house_request_quantity": kill_house_request.quantity, + "assignment_real_quantity": assignment_real_quantity, + "assignment_net_weight": assignment_net_weight, + "weight_loss": round(total_weight_loss, 1), + "input_loss": kill_house_request.weight_loss, + + }) + kill_house_req_list.append(kill_house_req_dict) + kill_house_req_dict = {} + + return Response(kill_house_req_list, status=status.HTTP_200_OK) + + +@api_view(["POST"]) +@permission_classes([AllowAny]) +@csrf_exempt +def city_operator_for_poultry(request): + file = request.FILES['file'].read() + wb_obj = openpyxl.load_workbook(filename=BytesIO(file)) + sheet = wb_obj.active + list1 = [] + + for i, row in enumerate(sheet.iter_rows(values_only=True)): + if i == 0: + continue + try: + poultry = Poultry.objects.get(breeding_unique_id=row[3], trash=False) + poultry.city_operator = row[5] + poultry.save() + except: + dict1 = { + "name": row[4], + "breeding": row[3] + } + list1.append(dict1) + continue + return Response(list1) + + +@api_view(["POST"]) +@permission_classes([TokenHasReadWriteScope]) +@csrf_exempt +def archive_hatching(request): + user = SystemUserProfile.objects.get(user=request.user) + if request.data['role'] == 'ProvinceOperator': + return Response({'result': 'شما دسترسی لازم را ندارید!'}, + status=status.HTTP_403_FORBIDDEN) + now = datetime.datetime.now().date() + date = (datetime.datetime(year=now.year, month=now.month, day=now.day, hour=23, minute=59, + second=59) - timedelta( + days=int(request.data['age']))) + poultry_hatching = PoultryHatching.objects.filter(date__lte=date, trash=False, allow_hatching='pending', + archive=False) + for hatching in poultry_hatching: + if hatching.left_over > (hatching.quantity * percent_of_losses): + hatching.violation = True + hatching.allow_hatching = 'True' + hatching.state = 'complete' + hatching.archive = True + hatching.archive_date = datetime.datetime.now() + if hatching.first_date_input_archive is None: + hatching.first_date_input_archive = datetime.datetime.now() + else: + hatching.second_date_input_archive = datetime.datetime.now() + hatching.input_archiver = user.fullname + hatching.last_change = { + "date": str(datetime.datetime.now()), + "full_name": user.fullname, + "role": request.data['role'], + "type": "automatic-archive" + } + hatching.save() + return Response({"msg": f"تعداد {poultry_hatching.count()} جوجه ریزی بایگانی شد."}, status=status.HTTP_200_OK) + + +class LastUpdateViewSet(viewsets.ModelViewSet): + queryset = LastUpdate.objects.first() + serializer_class = LastUpdateSerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + if 'type' in request.GET: + if request.GET['type'] == 'poultry_hatching': + update = LastUpdate.objects.first().update_date + # ser_deta=self.serializer_class(update).data + return Response(update) + + return Response({"result": "you havnt type in url params"}, status=status.HTTP_403_FORBIDDEN) + + +class UpdatePoultryTenantViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.all() + serializer_class = PoultrySerializer + permission_classes = [AllowAny] + + def update(self, request, *args, **kwargs): + poultry_tenant = self.queryset.get(trash=False, key=request.data['tenant_key']) + system_user_profile = SystemUserProfile.objects.get(trash=False, key=poultry_tenant.user.key) + first_mobile_number = system_user_profile.mobile + second_mobile_number = request.data['mobile'] + poultry_tenant.breeding_unique_id = request.data['breeding_unique_id'] + system_user_profile.last_name = request.data['last_name'] + system_user_profile.first_name = request.data['first_name'] + system_user_profile.fullname = request.data['first_name'] + ' ' + request.data['last_name'] + system_user_profile.national_id = request.data['national_id'] + if first_mobile_number != second_mobile_number: + if SystemUserProfile.objects.filter(mobile=second_mobile_number).exists(): + return Response({"result": "این شماره در سامانه به نام شخص دیگری است"}, + status=status.HTTP_403_FORBIDDEN) + data = { + "first_mobile_number": first_mobile_number, + "second_mobile_number": second_mobile_number, + } + req = requests.post( + url=ARTA_URL_CHANGE_MOBILE_NUMBER, + data=data, + verify=False + ) + if req.status_code == 200: + second_mobile_number = second_mobile_number + user = User.objects.get(id=system_user_profile.user.id) + user.username = second_mobile_number + user.save() + system_user_profile.mobile = second_mobile_number + poultry_tenant.save() + system_user_profile.save() + return Response('poultry tenant successfully update!', status=status.HTTP_201_CREATED) + + +class GeneralStatisticsdashboardForCasesViewSet(viewsets.ViewSet): + permission_classes = [TokenHasReadWriteScope] + + def list(self, request): + date1 = datetime.datetime.strptime(request.GET['date1'], + '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(request.GET['date2'], + '%Y-%m-%d').date() + user = SystemUserProfile.objects.get(user=request.user, trash=False) + poultry_requests = PoultryRequest.objects.filter(trash=False, + send_date__date__gte=date1, + send_date__date__lte=date2).order_by('send_date') + + if request.GET['role'] in ['CityCommerce', 'CityVet', 'CityPoultry', 'CityJahad']: + poultry_requests = poultry_requests.filter(poultry__address__city=user.city) + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + poultry_requests = poultry_requests.filter(poultry__city_operator=city_operator.unit_name) + else: + poultry_requests = poultry_requests + poultry = poultry_requests.values('poultry').distinct().count() + poultry_requests_quantity = poultry_requests.aggregate(total=Sum('quantity'))['total'] or 0 + poultry_requests_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))['total'] or 0 + out_poultry_request = poultry_requests.filter(out=True) + out_poultry_request_quantity = poultry_requests.aggregate(total=Sum('quantity'))['total'] or 0 + out_poultry_request_weight = poultry_requests.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + province_kill_requests = ProvinceKillRequest.objects.filter(trash=False, state__in=('pending', 'accepted'), + return_to_province=False, + province_request__poultry_request__in=poultry_requests) + province_kill_requests_quantity = province_kill_requests.aggregate(total=Sum('main_quantity'))['total'] or 0 + province_kill_requests_weight = province_kill_requests.aggregate( + total=Sum(F('main_quantity') * F('province_request__poultry_request__Index_weight')))['total'] or 0 + province_kill_requests_buyers = province_kill_requests.values('killhouse_user').distinct().count() + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_kill_request__in=province_kill_requests) + kill_house_request_quantity = kill_house_requests.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house_request_weight = kill_house_requests.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + kill_house_requests_with_quarantine_code = kill_house_requests.filter(clearance_code__isnull=False) + kill_house_requests_with_quarantine_code_quantity = \ + kill_house_requests_with_quarantine_code.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house_requests_with_quarantine_code_weight = \ + kill_house_requests_with_quarantine_code.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + kill_house_requests_without_quarantine_code = kill_house_requests.filter(clearance_code__isnull=True) + kill_house_requests_without_quarantine_code_quantity = \ + kill_house_requests_without_quarantine_code.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house_requests_without_quarantine_code_weight = \ + kill_house_requests_without_quarantine_code.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + kill_house_requests_with_kill_house_vet_accepted = kill_house_requests.filter(vet_state='accepted') + kill_house_requests_with_kill_house_vet_accepted_quantity = \ + kill_house_requests_with_kill_house_vet_accepted.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_house_requests_with_kill_house_vet_accepted_weight = \ + kill_house_requests_with_kill_house_vet_accepted.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + kill_house_requests_without_kill_house_vet_accepted = kill_house_requests.filter(vet_state='pending') + kill_house_requests_without_kill_house_vet_accepted_quantity = \ + kill_house_requests_without_kill_house_vet_accepted.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_house_requests_without_kill_house_vet_accepted_weight = \ + kill_house_requests_without_kill_house_vet_accepted.aggregate(total=Sum('accepted_real_weight'))[ + 'total'] or 0 + kill_house_requests_with_kill_house_assignment = kill_house_requests.filter( + assignment_state_archive='True') + kill_house_requests_with_kill_house_assignment_quantity = \ + kill_house_requests_with_kill_house_assignment.aggregate(total=Sum('accepted_real_quantity'))['total'] or 0 + kill_house_requests_with_kill_house_assignment_weight = \ + kill_house_requests_with_kill_house_assignment.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + kill_house_requests_without_kill_house_assignment = kill_house_requests.filter( + assignment_state_archive='True') + kill_house_requests_without_kill_house_assignment_quantity = \ + kill_house_requests_without_kill_house_assignment.aggregate(total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + kill_house_requests_without_kill_house_assignment_weight = \ + kill_house_requests_without_kill_house_assignment.aggregate(total=Sum('accepted_real_weight'))['total'] or 0 + + return Response( + { + "poultry_requests": len(poultry_requests), + "poultry": poultry, + "poultry_requests_quantity": poultry_requests_quantity, + "poultry_requests_weight": poultry_requests_weight, + "out_poultry_request": len(out_poultry_request), + "out_poultry_request_quantity": out_poultry_request_quantity, + "out_poultry_request_weight": out_poultry_request_weight, + "province_kill_requests": len(province_kill_requests), + "province_kill_requests_quantity": province_kill_requests_quantity, + "province_kill_requests_weight": province_kill_requests_weight, + "province_kill_requests_buyers": province_kill_requests_buyers, + "kill_house_requests": len(kill_house_requests), + "kill_house_request_quantity": kill_house_request_quantity, + "kill_house_request_weight": kill_house_request_weight, + "kill_house_requests_with_quarantine_code": len(kill_house_requests_with_quarantine_code), + "kill_house_requests_with_quarantine_code_quantity": kill_house_requests_with_quarantine_code_quantity, + "kill_house_requests_with_quarantine_code_weight": kill_house_requests_with_quarantine_code_weight, + "kill_house_requests_without_quarantine_code": len(kill_house_requests_without_quarantine_code), + "kill_house_requests_without_quarantine_code_quantity": kill_house_requests_without_quarantine_code_quantity, + "kill_house_requests_without_quarantine_code_weight": kill_house_requests_without_quarantine_code_weight, + "kill_house_requests_with_kill_house_vet_accepted": len( + kill_house_requests_with_kill_house_vet_accepted), + "kill_house_requests_with_kill_house_vet_accepted_quantity": kill_house_requests_with_kill_house_vet_accepted_quantity, + "kill_house_requests_with_kill_house_vet_accepted_weight": kill_house_requests_with_kill_house_vet_accepted_weight, + "kill_house_requests_without_kill_house_vet_accepted": len( + kill_house_requests_without_kill_house_vet_accepted), + "kill_house_requests_without_kill_house_vet_accepted_quantity": kill_house_requests_without_kill_house_vet_accepted_quantity, + "kill_house_requests_without_kill_house_vet_accepted_weight": kill_house_requests_without_kill_house_vet_accepted_weight, + "kill_house_requests_with_kill_house_assignment": len(kill_house_requests_with_kill_house_assignment), + "kill_house_requests_with_kill_house_assignment_quantity": kill_house_requests_with_kill_house_assignment_quantity, + "kill_house_requests_with_kill_house_assignment_weight": kill_house_requests_with_kill_house_assignment_weight, + "kill_house_requests_without_kill_house_assignment": len( + kill_house_requests_without_kill_house_assignment), + "kill_house_requests_without_kill_house_assignment_quantity": kill_house_requests_without_kill_house_assignment_quantity, + "kill_house_requests_without_kill_house_assignment_weight": kill_house_requests_without_kill_house_assignment_weight, + }) + + +def archive_poultry_hatching_with_cron_job(): + hatching = PoultryHatching.objects.filter(Q(left_over=0) | Q(chicken_age__gt=80), trash=False, + allow_hatching='pending', + state='pending', archive=False).only('allow_hatching', + 'left_over', 'quantity', 'state', + 'archive') + now_date = datetime.datetime.now() + for hatch in hatching: + if hatch.left_over > (hatch.quantity * percent_of_losses): + hatch.violation = True + hatch.allow_hatching = 'True' + hatch.state = 'complete' + hatch.archive = True + hatch.archive_date = datetime.datetime.now() + if hatch.first_date_input_archive is None: + hatch.first_date_input_archive = now_date + else: + hatch.second_date_input_archive = now_date + hatch.input_archiver = 'automatic-archive' + hatch.last_change = { + "date": str(now_date), + "full_name": 'automatic-archive', + "role": 'automatic-archive1', + "type": "automatic-archive" + } + hatch.save() + + +def archive_poultry_hatching_with_archive_percent_cron_job(): + now_date = datetime.datetime.now() + archive_percent = HatchingArchivePercent.objects.filter(trash=False, active=True).first() + if archive_percent: + hatchings = PoultryHatching.objects.filter( + state='pending', + archive=False, + allow_hatching='pending', + trash=False, + ).annotate( + allowed_left_over=ExpressionWrapper( + F('quantity') * (archive_percent.percent / 100), + output_field=FloatField() + ) + ).filter( + left_over__lte=F('allowed_left_over') + ) + + Poultry.objects.filter( + id__in=hatchings.values_list('poultry__id', flat=True), order_limit=True + ).update(order_limit=False) + for hatching in hatchings: + if hatching.left_over > (hatching.quantity * percent_of_losses): + hatching.violation = True + hatching.allow_hatching = 'True' + hatching.state = 'complete' + hatching.archive = True + hatching.unknown = False + hatching.archive_date = datetime.datetime.now() + if hatching.first_date_input_archive is None: + hatching.first_date_input_archive = now_date + else: + hatching.second_date_input_archive = now_date + hatching.input_archiver = 'automatic-archive' + hatching.last_change = { + "date": str(now_date), + "full_name": 'automatic-archive', + "role": 'automatic-archive1', + "type": "automatic-archive" + } + hatching.save() + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def archive_poultry_hatching_with_archive_percent(request): + now_date = datetime.datetime.now() + archive_percent = HatchingArchivePercent.objects.filter(trash=False, active=True).first() + if archive_percent: + hatchings = PoultryHatching.objects.filter( + state='pending', + archive=False, + allow_hatching='pending', + trash=False, + ).annotate( + allowed_left_over=ExpressionWrapper( + F('quantity') * (archive_percent.percent / 100), + output_field=FloatField() + ) + ).filter( + left_over__lte=F('allowed_left_over') + ) + + Poultry.objects.filter( + id__in=hatchings.values_list('poultry__id', flat=True), order_limit=True + ).update(order_limit=False) + for hatching in hatchings: + hatching.allow_hatching = 'True' + hatching.state = 'complete' + hatching.archive = True + hatching.unknown = False + hatching.archive_date = datetime.datetime.now() + if hatching.first_date_input_archive is None: + hatching.first_date_input_archive = now_date + else: + hatching.second_date_input_archive = now_date + hatching.input_archiver = 'automatic-archive' + hatching.last_change = { + "date": str(now_date), + "full_name": 'automatic-archive', + "role": 'automatic-archive1', + "type": "automatic-archive" + } + hatching.save() + + +class PoultryLocationViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.filter( + trash=False, + Long__isnull=False + ).select_related( + 'user', 'address', 'address__city' + ).only( + 'id', 'unit_name', 'Lat', 'Long', + 'user__fullname', 'user__mobile', + 'address__address', 'address__city__name', 'breeding_unique_id' + ).prefetch_related( + Prefetch('poultry_hatching_user', + queryset=PoultryHatching.objects.filter( + state__in=('pending', 'complete'), + archive=False, + allow_hatching='pending', + trash=False + ).only( + 'left_over', 'chicken_age', 'date', + 'licence_number', + 'poultry_id', 'killed_quantity', 'total_losses' + ) + ) + ) + serializer_class = PoultryLocationSerializer + permission_classes = [AllowAny] + filter_backends = [DjangoFilterBackend] + filterset_class = PoultryManageFilterSet + + @staticmethod + def haversine_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + radius = 6378137.0 + + dlat = math.radians(lat2 - lat1) + dlon = math.radians(lon2 - lon1) + lat1_rad = math.radians(lat1) + lat2_rad = math.radians(lat2) + + a = math.sin(dlat / 2) ** 2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2) ** 2 + c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) + return radius * c + + def filter_nearby_poultries(self, poultries: List[Dict], center_lat: float, center_lon: float, radius: float) -> \ + List[Dict]: + nearby_poultries = [ + poultry for poultry in poultries + if self.haversine_distance(center_lat, center_lon, poultry['Lat'], poultry['Long']) <= radius + ] + return nearby_poultries + + def list(self, request, *args, **kwargs): + queryset = self.filter_queryset(self.get_queryset()) + value = request.GET.get('value') + if value: + if value != 'undefined' and value.strip(): + queryset = queryset.filter( + build_query(self.filterset_class, value) + ) + serializer = self.get_serializer(queryset, many=True) + data = serializer.data + + center_lat = request.query_params.get('center_lat') + center_lon = request.query_params.get('center_lon') + radius = request.query_params.get('radius') + + if center_lat and center_lon and radius: + try: + center_lat = float(center_lat) + center_lon = float(center_lon) + radius = float(radius) + + if radius > 100: + radius_meters = radius + else: + radius_meters = radius * 1000 + + data = self.filter_nearby_poultries(data, center_lat, center_lon, radius_meters) + except (ValueError, TypeError): + pass + + return Response(data) + + +class DashboardOutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardPoultryRequestFilterSet + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + user = SystemUserProfile.objects.get(user=request.user, trash=False) + state = request.GET.get('state') + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + if request.GET['role'] == 'VetFarm': + vet_farms = VetFarm.objects.filter(vet__user=user, trash=False) + poultries = Poultry.objects.filter( + pk__in=vet_farms.values('poultry') + ) + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__in=poultries, send_date__date__gte=date1, + send_date__date__lte=date2, + trash=False).order_by('-send_date') + + elif request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + if state == 'pending': + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__city_operator=city_operator.unit_name, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if state == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True), + poultry__address__city=user.city, + send_date__date__gte=date1, + send_date__date__lte=date2, + out=True, + trash=False).order_by('-send_date') + + else: + if request.GET['state'] == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=True, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=True, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + poultry_requests = poultry_requests.filter( + build_query(self.filterset_class, value) + ) + + index_weight = poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + has_code = len(poultry_requests.filter(quarantine_code__isnull=False)) + hasnt_code = len(poultry_requests.filter(quarantine_code__isnull=True)) + hatching = poultry_requests.values_list('hatching__id', flat=True).distinct() + hatchings = PoultryHatching.objects.filter(trash=False, id__in=hatching) + left_over = hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + quantity_hatching = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + poultry_request_aggregates = poultry_requests.aggregate( + total_weight=Sum(F('quantity') * F('Index_weight')), + ) + dict1 = { + 'lenBar': len(poultry_requests), + 'indexWeight': round(index_weight / len(poultry_requests) if len(poultry_requests) > 0 else 0), + 'quantity': quantity, + # 'weight': int(quantity * index_weight), + 'weight': poultry_request_aggregates['total_weight'] or 0, + 'hasCode': has_code, + 'hasntCode': hasnt_code, + 'leftOver': left_over, + 'hatchingQuantity': quantity_hatching, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class ParentCompanyDashboardOutProvincePoultryRequestViewSet(viewsets.ModelViewSet): + queryset = PoultryRequest.objects.filter(out=True, trash=False) + serializer_class = PoultryRequestoutProvinceSerializer + permission_classes = [AllowAny] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = DashboardPoultryRequestFilterSet + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + state = request.GET.get('state') + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['state'] == 'pending': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=False) | Q(state_process='pending', province_state='pending', final_state='pending', + wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + + elif state == 'accepted': + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='accepted', province_state='accepted', final_state='archive', has_wage=True, + wage_pay=True) | Q(state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + out_province_request_cancel=False, + trash=False).order_by('-send_date') + else: + poultry_requests = PoultryRequest.objects.filter( + Q(state_process='rejected', province_state='rejected', final_state='archive', has_wage=True, + wage_pay=False, out_province_request_cancel=False) | Q(state_process='rejected', + province_state='rejected', + final_state='archive', + has_wage=False, wage_pay=False, + out_province_request_cancel=False) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='pending', province_state='pending', final_state='pending', + has_wage=True, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=False, wage_pay=False, out_province_request_cancel=True) | Q( + state_process='accepted', province_state='accepted', final_state='archive', + has_wage=True, wage_pay=False, out_province_request_cancel=True), + send_date__date__gte=date1, + send_date__date__lte=date2, out=True, + trash=False).order_by('-send_date') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + poultry_requests = poultry_requests.filter( + build_query(self.filterset_class, value) + ) + + index_weight = poultry_requests.aggregate(total=Sum('Index_weight'))[ + 'total'] or 0 + quantity = poultry_requests.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + has_code = len(poultry_requests.filter(quarantine_code__isnull=False)) + hasnt_code = len(poultry_requests.filter(quarantine_code__isnull=True)) + hatching = poultry_requests.values_list('hatching__id', flat=True).distinct() + hatchings = PoultryHatching.objects.filter(trash=False, id__in=hatching) + left_over = hatchings.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + quantity_hatching = hatchings.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + dict1 = { + 'lenBar': len(poultry_requests), + 'indexWeight': round(index_weight / len(poultry_requests) if len(poultry_requests) > 0 else 0), + 'quantity': quantity, + 'weight': int(quantity * index_weight), + 'hasCode': has_code, + 'hasntCode': hasnt_code, + 'leftOver': left_over, + 'hatchingQuantity': quantity_hatching, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class DashboardChainAllocationViewSet(viewsets.ModelViewSet): + queryset = ChainAllocation.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = ChainAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + + def list(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if request.GET['role'] == "ChainCompany": + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(chain_company__user=user, date__date__gte=date1, + date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(chain_company__user=user, date__date__gte=date1, + date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(poultry_hatching__poultry__address__city=user.city, + date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + + chain_allocations = ChainAllocation.objects.filter(poultry_hatching__poultry__address__city=user.city, + date__date__gte=date1, date__date__lte=date2, + state='accepted', + trash=False).order_by('-id') + elif request.GET['role'] == "CityOperator": + city_operator = CityOperator.objects.get(user=user, trash=False) + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, date__date__gte=date1, + date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter( + poultry_hatching__poultry__city_operator=city_operator.unit_name, date__date__gte=date1, + date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + elif request.GET['role'] == "VetFarm": + vet = Vet.objects.get(user=user, trash=False) + poultry_ids = VetFarm.objects.filter(vet=vet, trash=False).select_related('poultry').only( + 'poultry').values_list('poultry', flat=True).distinct() + poultry = Poultry.objects.filter(id__in=poultry_ids) + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + poultry_hatching__poultry__in=poultry, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + poultry_hatching__poultry__in=poultry, + state='accepted', + trash=False).order_by('-id') + else: + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + index_weight = chain_allocations.aggregate(total=Sum('index_weight'))[ + 'total'] or 0 + weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + quantity = chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + has_code = len(chain_allocations.filter(quarantine_code__isnull=False)) + hasnt_code = len(chain_allocations.filter(quarantine_code__isnull=True)) + + dict1 = { + 'lenBar': len(chain_allocations), + 'indexWeight': round(index_weight / len(chain_allocations) if len(chain_allocations) > 0 else 0), + 'quantity': quantity, + 'weight': int(weight), + 'hasCode': has_code, + 'hasntCode': hasnt_code, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class ParentCompanyDashboardChainAllocationViewSet(viewsets.ModelViewSet): + queryset = ChainAllocation.objects.all() + permission_classes = [AllowAny] + serializer_class = ChainAllocationSerializer + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = ChainAllocationFilterSet + filterset_fields = [ + 'poultry_hatching__poultry__breeding_unique_id', + 'poultry_hatching__poultry__user__mobile', + 'poultry_hatching__poultry__user__fullname', + 'poultry_hatching__poultry__user__first_name', + 'poultry_hatching__poultry__user__last_name', + 'poultry_hatching__poultry__unit_name', + 'chain_company__name', + + ] + + def list(self, request, *args, **kwargs): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + + if 'state' in request.GET: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('rejected', 'deleted'), + trash__in=(False, True)).order_by('-id') + else: + chain_allocations = ChainAllocation.objects.filter(date__date__gte=date1, date__date__lte=date2, + state__in=('accepted', 'pending'), + trash=False).order_by('-id') + + index_weight = chain_allocations.aggregate(total=Sum('index_weight'))[ + 'total'] or 0 + weight = chain_allocations.aggregate(total=Sum('weight'))[ + 'total'] or 0 + quantity = chain_allocations.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + has_code = len(chain_allocations.filter(quarantine_code__isnull=False)) + hasnt_code = len(chain_allocations.filter(quarantine_code__isnull=True)) + + dict1 = { + 'lenBar': len(chain_allocations), + 'indexWeight': round(index_weight / len(chain_allocations) if len(chain_allocations) > 0 else 0), + 'quantity': quantity, + 'weight': int(weight), + 'hasCode': has_code, + 'hasntCode': hasnt_code, + + } + return Response(dict1, status=status.HTTP_200_OK) + + +class DashboardTotalPoultryViewSet(viewsets.ModelViewSet): + queryset = Poultry.objects.all() + serializer_class = PoultrySerializer + permission_classes = [AllowAny] + + def list(self, request, *args, **kwargs): + poultreis = Poultry.objects.filter(trash=False).select_related('user', 'address__province', 'address__city') + if 'role' in request.GET: + user = SystemUserProfile.objects.get(key=request.GET['key']) + if request.GET['role'] == 'CityOperator': + city_operator = CityOperator.objects.get(trash=False, user=user) + poultrys = poultreis.filter(poultry__city_operator=city_operator.unit_name) + elif request.GET['role'] in ['CityJahad', 'CityPoultry']: + poultrys = poultreis.filter(poultry__user__city=user.city) + else: + poultrys = poultreis + else: + poultrys = poultreis + all_hatching_pending = 0 + all_total_quantity = 0 + all_poultry_request = 0 + all_kill_request = 0 + all_kill_request_quantity = 0 + all_kill_request_weight = 0 + all_kill_request_has_assigment = 0 + all_kill_request_quantity_assigment = 0 + all_kill_request_weight_assigment = 0 + all_total_quantity_poultry_hatching_pending = 0 + all_total_left_over_poultry_hatching_pending = 0 + all_total_quantity_poultry_request = 0 + all_len_out_poultry_request = 0 + all_total_out_quantity_poultry_request = 0 + all_total_out_weight_poultry_request = 0 + all_period = 0 + len_werhouse_enter = 0 + all_werhouse_enter_quantity = 0 + all_werhouse_enter_weight = 0 + all_all_weight_loss = 0 + for poultry in poultrys: + user_mobile = poultry.user.mobile if poultry.user else '-' + user_name = poultry.user.fullname if poultry.user else '-' + city_operator = poultry.city_operator if poultry.city_operator else '-' + health_certificate_number = poultry.health_certificate_number if poultry.health_certificate_number else '-' + epidemiological_code = poultry.epidemiological_code if poultry.epidemiological_code else '-' + vet_farm = VetFarm.objects.filter(poultry=poultry, trash=False).select_related('vet__user').last() + vet_name = '-' + mobile_vet = '-' + if vet_farm: + vet_name = vet_farm.vet.user.fullname + mobile_vet = vet_farm.vet.user.mobile + poultry_hatching = PoultryHatching.objects.filter(poultry=poultry, trash=False).only('quantity', 'left_over' + ) + + if poultry_hatching: + + poultry_hatching_pending = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False).last() + if poultry_hatching_pending: + all_hatching_pending += 1 + hatching = 'ندارد' if not poultry_hatching_pending else f'دارد' + + if poultry_hatching_pending: + period = poultry_hatching_pending.period + else: + period = poultry_hatching.last().period + all_period += period + poultry_hatching_pending1 = poultry_hatching.filter(state='pending', allow_hatching='pending', + archive=False) + total_quantity = \ + poultry_hatching.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_quantity_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_left_over_poultry_hatching_pending = \ + poultry_hatching_pending1.aggregate(total=Sum('left_over'))[ + 'total'] or 0 + all_total_quantity += total_quantity + all_total_quantity_poultry_hatching_pending += total_quantity_poultry_hatching_pending + all_total_left_over_poultry_hatching_pending += total_left_over_poultry_hatching_pending + poultry_request = PoultryRequest.objects.filter(trash=False, poultry=poultry, + state_process__in=('accepted', 'pending'), + province_state__in=('accepted', 'pending')).only( + 'quantity', 'Index_weight') + kill_request = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_request).only( + 'accepted_real_quantity', 'accepted_real_weight') + + out_poultry_request = poultry_request.filter(out=True, out_province_request_cancel=False).only( + 'quantity', 'Index_weight' + ) + total_out_quantity_poultry_request = \ + out_poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + total_out_weight_poultry_request = \ + out_poultry_request.aggregate(total=Sum(F('quantity') * F('Index_weight')))[ + 'total'] or 0 + + all_total_out_quantity_poultry_request += total_out_quantity_poultry_request + all_total_out_weight_poultry_request += total_out_weight_poultry_request + all_len_out_poultry_request += len(out_poultry_request) + total_quantity_poultry_request = \ + poultry_request.aggregate(total=Sum('quantity'))[ + 'total'] or 0 + all_total_quantity_poultry_request += total_quantity_poultry_request + all_poultry_request += len(poultry_request) + all_kill_request += len(kill_request) + kill_request_quantity = kill_request.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_kill_request_quantity += kill_request_quantity + kill_request_weight = kill_request.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_kill_request_weight += int(kill_request_weight) + kill_request_has_assigment = kill_request.filter(assignment_state_archive='True').only( + 'accepted_real_quantity', 'accepted_real_weight') + + all_kill_request_has_assigment += len(kill_request_has_assigment) + + kill_request_quantity_assigment = kill_request_has_assigment.aggregate( + total=Sum('accepted_real_quantity'))[ + 'total'] or 0 + all_kill_request_quantity_assigment += kill_request_quantity_assigment + kill_request_weight_assigment = kill_request_has_assigment.aggregate( + total=Sum('accepted_real_weight'))[ + 'total'] or 0 + all_kill_request_weight_assigment += int(kill_request_weight_assigment) + + werhouse_enter = kill_request.filter(ware_house_confirmation=True).only( + 'ware_house_accepted_real_quantity', + 'ware_house_accepted_real_weight', + 'weight_loss') + werhouse_enter_quantity = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_quantity'))[ + 'total'] or 0 + werhouse_enter_weight = werhouse_enter.aggregate( + total=Sum('ware_house_accepted_real_weight'))[ + 'total'] or 0 + all_weight_loss = werhouse_enter.aggregate( + total_quantity=Sum('weight_loss')).get( + 'total_quantity', 0) or 0 + all_all_weight_loss += all_weight_loss + + all_weight_loss = round(int(all_weight_loss) / len(werhouse_enter), 2) if len(werhouse_enter) > 0 else 0 + + len_werhouse_enter += len(werhouse_enter) + all_werhouse_enter_quantity += werhouse_enter_quantity + all_werhouse_enter_weight += int(werhouse_enter_weight) + list1 = [ + poultry.unit_name, + user_name, + user_mobile, + poultry.breeding_unique_id, + epidemiological_code, + health_certificate_number, + poultry.number_of_halls, + poultry.total_capacity, + poultry.user.province.name + '/' + poultry.user.city.name if poultry.user.city and poultry.user.province is not None else '-', + city_operator, + vet_name + '/' + mobile_vet, + hatching, + period, + total_quantity, + round(total_quantity / period) if period > 0 else 0, + len(poultry_request), + total_quantity_poultry_request, + len(kill_request), + kill_request_quantity, + int(kill_request_weight), + round(kill_request_weight / kill_request_quantity, 1) if kill_request_weight > 0 else 0, + len(kill_request_has_assigment), + kill_request_quantity_assigment, + int(kill_request_weight_assigment), + round(kill_request_weight_assigment / kill_request_quantity_assigment, + 1) if kill_request_weight_assigment > 0 else 0, + len(out_poultry_request), + total_out_quantity_poultry_request, + int(total_out_weight_poultry_request), + str(round(total_out_weight_poultry_request / total_out_quantity_poultry_request, + 1)) if total_out_quantity_poultry_request > 0 else 0, + + len(werhouse_enter), + werhouse_enter_quantity, + int(werhouse_enter_weight), + f'%{all_weight_loss}', + + ] + + value_header_list = [ + all_period, + all_total_quantity, + all_hatching_pending, + all_total_quantity_poultry_hatching_pending, + all_total_left_over_poultry_hatching_pending, + all_poultry_request, + all_total_quantity_poultry_request, + all_kill_request, + all_kill_request_quantity, + all_kill_request_weight, + (round(all_kill_request_weight / all_kill_request_quantity, 1)) if all_kill_request_quantity > 0 else 0, + + all_kill_request_has_assigment, + all_kill_request_quantity_assigment, + all_kill_request_weight_assigment, + str(round(all_kill_request_weight_assigment / all_kill_request_quantity_assigment, + 1)) if all_kill_request_quantity_assigment > 0 else 0, + + all_len_out_poultry_request, + all_total_out_quantity_poultry_request, + int(all_total_out_weight_poultry_request), + str(round(all_total_out_weight_poultry_request / all_total_out_quantity_poultry_request, + 1)) if all_total_out_quantity_poultry_request > 0 else 0, + len_werhouse_enter, + all_werhouse_enter_quantity, + all_werhouse_enter_weight, + f'%{round(int(all_all_weight_loss) / len_werhouse_enter, 2) if len_werhouse_enter > 0 else 0}', + + ] + + +class GetAllPoultryViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + min_age = int(request.GET.get('min_age', 0)) + max_age = int(request.GET.get('max_age', min_age)) + + filters = { + 'allow_hatching': 'pending', + 'left_over__gt': 0, + 'state': 'pending', + 'archive': False, + 'trash': False + } + + if role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filters['poultry__city_operator'] = city_operator.unit_name + elif role == 'Poultry': + filters['poultry__user'] = user + elif role == 'PoultryScience': + poultry_science = PoultryScience.objects.filter(user=user).values_list('poultry__id', flat=True).distinct() + filters['poultry__id__in'] = poultry_science + + if 'chain' in request.GET: + if request.GET['chain'] == 'true' or request.GET['chain']: + filters['InteractTypeName'] = 'در مشارکت با زنجیره' + poultry_hatchings = PoultryHatching.objects.filter(**filters).values( + 'poultry', 'has_chain_company', 'key' + ).annotate( + last_hatching_remain_quantity=Max('left_over') + ) + + age_range = ChickenAgeRange.objects.filter(trash=False).first() + if 'min_age' in request.GET or 'direct_buying' in request.GET: + if age_range and age_range.active: + poultry_hatchings = poultry_hatchings.filter(chicken_age__range=(age_range.minimum, age_range.maximum)) + elif min_age: + poultry_hatchings = poultry_hatchings.filter(chicken_age__range=(min_age, max_age)) + + poultry_remain_dict = { + poultry_hatching['poultry']: { + 'last_hatching_remain_quantity': poultry_hatching['last_hatching_remain_quantity'], + 'chain_company': { + "chain_company": poultry_hatching['has_chain_company'], + "hatching_key": poultry_hatching['key'], + }, + 'allow_sell_free': ProvinceAllowPoultrySellFree.objects.filter( + poultry_id=poultry_hatching['poultry'] + ).values_list('allow', flat=True).first() or False + } + for poultry_hatching in poultry_hatchings + } + + poultry = Poultry.objects.filter(id__in=poultry_remain_dict.keys()).select_related('user', 'address').order_by( + 'id') + serializer = GetAllPoultrySerializer(poultry, many=True, context={'poultry_remain_dict': poultry_remain_dict}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryPredictionViewSet(viewsets.ModelViewSet): + queryset = PoultryPrediction.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryPredictionSerializer + + +class HatchingIncreaseRequestViewSet(viewsets.ModelViewSet): + queryset = HatchingIncreaseRequest.objects.all() + serializer_class = HatchingIncreaseRequestSerializer + permission_classes = [TokenHasReadWriteScope] + filterset_class = HatchingIncreaseRequestFilterSet + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + value = request.GET.get('value') + search = request.GET.get('search') + query = HatchingIncreaseRequest.objects.filter(trash=False).order_by('-date') + if value and search == 'filter': + if value != 'undefined' and value.strip(): + query = query.filter( + build_query(self.filterset_class, value) + ) + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(query) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = self.serializer_class(query, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + hatching_key = request.data["hatching_key"] + hatching = PoultryHatching.objects.get(trash=False, key=hatching_key) + request.data.pop('hatching_key') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + hatching_increase = serializer.create(validated_data=request.data) + hatching_increase.hatching = hatching + hatching_increase.registerer_name = user.fullname + hatching_increase.registerer_mobile = user.mobile + hatching_increase.hatching_left_over = hatching.left_over + hatching_increase.hatching_quantity = hatching.quantity + hatching_increase.hatching_losses = hatching.total_losses + hatching_increase.hatching_kill_quantity = hatching.killed_quantity + hatching_increase.save() + calculate_hatching_increase(hatching) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + + return Response(serializer.errors, status.HTTP_403_FORBIDDEN) + + def update(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(trash=False, user=request.user) + + data = request.data + query = HatchingIncreaseRequest.objects.get(trash=False, key=data['key']) + query.quantity = data['quantity'] + query.message = data['message'] + query.registerer_name = user.fullname + query.registerer_mobile = user.mobile + query.registerer_role = data['role'] + query.date = datetime.datetime.now() + query.save() + calculate_hatching_increase(query.hatching) + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + query = HatchingIncreaseRequest.objects.get(trash=False, key=request.GET['key']) + hatching = query.hatching + if hatching.left_over < query.quantity: + return Response({'result': 'به علت کم بودن حجم مانده در سالن اجازه حذف ندارید!'}, + status=status.HTTP_403_FORBIDDEN) + query.trash = True + query.save() + calculate_hatching_increase(hatching) + return Response({"result": "با موفقیت انجام شد."}, status=status.HTTP_200_OK) + + +class ChickenCommissionPricesViewSet(viewsets.ModelViewSet): + queryset = ChickenCommissionPrices.objects.all() + serializer_class = ChickenCommissionPricesSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + + def list(self, request, *args, **kwargs): + ChickenCommissionPrices.objects.get_or_create(date__date=datetime.date.today(), + defaults={'date': datetime.datetime.now(), + 'kill_house_price': kill_house_price}) + create_update_chicken_commission_prices() + query = ChickenCommissionPrices.objects.filter(trash=False).order_by('-date') + page_size = request.query_params.get('page_size', None) + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(query) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + ser_data = self.serializer_class(query, many=True) + return Response(ser_data.data, status=status.HTTP_200_OK) + + +class GetAllPoultryFoIncreaseHatchingViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=request.user, trash=False) + role = request.GET.get('role') + min_age = int(request.GET.get('min_age', 0)) + max_age = int(request.GET.get('max_age', min_age)) + + filters = { + 'allow_hatching': 'pending', + 'state': 'pending', + 'archive': False, + 'trash': False + } + + if role == 'CityOperator': + city_operator = CityOperator.objects.get(user=user) + filters['poultry__city_operator'] = city_operator.unit_name + elif role == 'Poultry': + filters['poultry__user'] = user + if 'chain' in request.GET: + if request.GET['chain'] == 'true' or request.GET['chain']: + filters['InteractTypeName'] = 'در مشارکت با زنجیره' + poultry_hatchings = PoultryHatching.objects.filter(**filters).values( + 'poultry', 'has_chain_company', 'key' + ).annotate( + last_hatching_remain_quantity=Max('left_over') + ) + + age_range = ChickenAgeRange.objects.filter(trash=False).first() + if 'min_age' in request.GET or 'direct_buying' in request.GET: + if age_range and age_range.active: + poultry_hatchings = poultry_hatchings.filter(chicken_age__range=(age_range.minimum, age_range.maximum)) + elif min_age: + poultry_hatchings = poultry_hatchings.filter(chicken_age__range=(min_age, max_age)) + + poultry_remain_dict = { + poultry_hatching['poultry']: { + 'last_hatching_remain_quantity': poultry_hatching['last_hatching_remain_quantity'], + 'chain_company': { + "chain_company": poultry_hatching['has_chain_company'], + "hatching_key": poultry_hatching['key'], + }, + 'allow_sell_free': ProvinceAllowPoultrySellFree.objects.filter( + poultry_id=poultry_hatching['poultry'] + ).values_list('allow', flat=True).first() or False + } + for poultry_hatching in poultry_hatchings + } + + poultry = Poultry.objects.filter(id__in=poultry_remain_dict.keys()).select_related('user', 'address').order_by( + 'id') + serializer = GetAllPoultrySerializer(poultry, many=True, context={'poultry_remain_dict': poultry_remain_dict}) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryRequestQuarantineCodeViewSet(viewsets.ModelViewSet): + queryset = PoultryRequestQuarantineCode.objects.all() + serializer_class = PoultryRequestQuarantineCodeSerializer + permission_classes = [TokenHasReadWriteScope] + + def list(self, request, *args, **kwargs): + poultry_request_key = request.GET.get('poultry_request_key') + codes = PoultryRequestQuarantineCode.objects.filter(poultry_request__key=poultry_request_key, + trash=False).order_by('id') + serializer = self.serializer_class(codes, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + def create(self, request, *args, **kwargs): + user = SystemUserProfile.objects.get(user=request.user) + poultry_request = PoultryRequest.objects.get(key=request.data['poultry_request_key']) + request.data.pop('poultry_request_key') + + if PoultryRequestQuarantineCode.objects.filter(quarantine_code=request.data['quarantine_code'], + trash=False).exists(): + return Response({"result": "این کد قبلا وارد شده است!"}, status=status.HTTP_403_FORBIDDEN) + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + code = serializer.create(validated_data=request.data) + code.registrar = user.fullname + code.register_date = datetime.datetime.now() + code.poultry_request = poultry_request + code.save() + get_gid_poultry_request_quarantine_code(code.id) + + return Response(serializer.data, status=status.HTTP_201_CREATED) + return Response(serializer.errors) + + def update(self, request, pk=None, *args, **kwargs): + code_key = request.data.pop('request_code_key') + + code = PoultryRequestQuarantineCode.objects.get(key=code_key) + + if 'quarantine_code' in request.data.keys(): + if code.quarantine_code != request.data['quarantine_code']: + if PoultryRequestQuarantineCode.objects.filter( + quarantine_code=request.data['quarantine_code'], trash=False).exists(): + return Response({"result": "این کد قبلا وارد شده است!"}, status=status.HTTP_403_FORBIDDEN) + + serializer = self.serializer_class(code) + serializer.update(instance=code, validated_data=request.data) + get_gid_poultry_request_quarantine_code(code.id) + + return Response(serializer.data, status=status.HTTP_200_OK) + + def destroy(self, request, *args, **kwargs): + code_key = request.GET.get('request_code_key') + code = PoultryRequestQuarantineCode.objects.get(key=code_key) + code.trash = True + code.save() + return Response({"result": "با موفقیت حذف شد"}, status=status.HTTP_200_OK) + + +class EvacuationHatchingDetailViewSet(viewsets.ModelViewSet): + queryset = EvacuationHatchingDetail.objects.filter(trash=False) + serializer_class = EvacuationHatchingDetailSerializer + permission_classes = [TokenHasReadWriteScope] + pagination_class = CustomPagination + filter_backends = [DjangoFilterBackend] + filterset_class = EvacuationHatchingDetailFilterSet + filterset_fields = [ + 'hatching__key', + 'hatching__poultry__breeding_unique_id', + 'PartIdCode', + 'RequestId', + 'MoReportId', + 'ReportType', + 'ReportStatus', + 'GoodCount', + 'IsDeleted', + 'IsPersisted', + 'AllowInsert', + 'AllowUpdate', + 'ExternalId', + 'StringId', + ] + + +class HatchingDetailView(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + hatching = PoultryHatching.objects.filter( + trash=False, + key=request.GET['key'] + ).select_related('poultry').first() + ser_data = PoultryHatchingForDetailsSerializer(hatching).data + kill_requests = KillHouseRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=hatching, + ware_house_confirmation=True + ).select_related( + 'killhouse_user', + 'killer', + 'province_request', + 'province_request__poultry_request', + 'kill_request' + ).order_by('-create_date') + ser_data_kill_request = KillHouseRequestForHatchingDetailSerializer(kill_requests, many=True).data + + poultry_requests = PoultryRequest.objects.filter(hatching=hatching, trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, + temporary_deleted=False) + + ser_data_poultry_request = PoultryRequestForHatchingDetailSerializer(poultry_requests, many=True).data + + chain_allocation = ChainAllocation.objects.filter(trash=False, state='accepted', poultry_hatching=hatching) + ser_data_chain_allocation = ChainAllocationForHatchingDetailSerializer(chain_allocation, many=True).data + + bar_diffrent_requests = BarDifferenceRequest.objects.filter(trash=False, hatching=hatching, + state='accepted').order_by('-id') + bar_diffrent_requests_serializer_data = BarDifferenceRequestSerializer(bar_diffrent_requests, many=True).data + + evacuation_reports = [] + if hatching: + details_qs = hatching.evacuation_details.filter(trash=False).order_by('-ReportDate', '-create_date') + evacuation_reports = EvacuationHatchingDetailSerializer(details_qs, many=True).data + + date1 = datetime.datetime.strptime(str(request.GET['date1']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + date2 = datetime.datetime.strptime(str(request.GET['date2']), + '%Y-%m-%d').date() if 'date1' in request.GET else None + + poultry_hatching_licence_number = hatching.licence_number + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar_with_licence_number/?' + f'licence_number={poultry_hatching_licence_number}' + f'&date1={date1}&date2={date2}', + headers={'Content-Type': 'application/json'} + ) + + kill_requests_non_receipt = KillHouseRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=hatching, + non_receipt=True, main_non_receipt=True + ).select_related( + 'killhouse_user', + 'killer', + 'province_request', + 'province_request__poultry_request', + 'kill_request' + ).order_by('-create_date') + ser_data_non_receipt_kill_request = KillHouseRequestForHatchingDetailSerializer(kill_requests_non_receipt, + many=True).data + filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0, + 'return_to_province': False + } + return_province_kill_requests = ProvinceKillRequest.objects.filter( + trash=True, return_trash=True, **filters, + province_request__poultry_request__hatching=hatching).order_by('id') + return_province_kill_requests_serializer = ReturnProvinceKillRequestSerializer(return_province_kill_requests, + many=True).data + + kill_house_requests_return = KillHouseRequest.objects.filter( + trash=True, return_trash=True, + province_request__poultry_request__hatching=hatching) + kill_house_requests_return_serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests_return, + many=True).data + + bar_requests = BarDifferenceRequest.objects.filter(trash=False, + state='accepted').order_by('id') + bar_request_serilizer = BarDifferenceRequestSerializer(bar_requests, many=True).data + + hatching_increase = HatchingIncreaseRequest.objects.filter(trash=False).order_by('-date') + hatching_increase_serilizer = HatchingIncreaseRequestSerializer(hatching_increase, many=True).data + result = { + **ser_data, + "bars": ser_data_kill_request, + 'outBars': ser_data_poultry_request, + 'chainAllocation': ser_data_chain_allocation, + "differentBars": response.json(), + "nonReceipt": ser_data_non_receipt_kill_request, + "returnProvinceRequest": return_province_kill_requests_serializer, + "returnKillHouseRequest": kill_house_requests_return_serializer, + "killingDifference": bar_request_serilizer, + "hatchingIncrease": hatching_increase_serilizer, + "bar_diffrent_requets": bar_diffrent_requests_serializer_data, + "evacuation_reports": evacuation_reports, + } + return Response(result) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def bulk_test_data(request): + count = int(request.query_params.get('count', 1000000)) # پیش‌فرض 1 میلیون + + result = [] + for i in range(count): + data = { + "id": i + 1, + "unit_name": 'nn', + "Lat": 34.88681445023634 + random.uniform(-0.1, 0.1), + "Long": 48.32817003380081 + random.uniform(-0.1, 0.1), + "user": { + "fullname": 'sdfsd', + "mobile": 'sdfsd' + }, + "hatching": [ + { + "quantity": random.randint(10000, 50000), + "left_over": random.randint(10000, 50000), + "period": random.randint(1, 30), + "chicken_age": random.randint(1, 100), + "date": (datetime.datetime.now() - timedelta(days=random.randint(1, 365))).isoformat(), + "violation": random.choice([True, False]), + "archive": False, + "licence_number": str(random.randint(1000000000, 9999999999)), + "samasat_discharge_percentage": random.randint(0, 100), + "chicken_breed": random.choice(["آربراکرز (آپلاس)", "راس", "کاب", "هوبارد"]), + "total_killed_weight": round(random.uniform(0, 1000), 2), + "killed_quantity": random.randint(0, 1000), + "PersonTypeName": random.choice(["حقیقی", "حقوقی"]), + "InteractTypeName": random.choice(["مالک", "مستأجر"]), + "UnionTypeName": random.choice(["تعاونی", "خصوصی", "دولتی"]), + "CertId": str(random.randint(100000000000, 999999999999)) + } + ], + "address": { + "city": { + "name": 'همدان' + }, + "address": 'sdasdasdasd' + }, + "breeding_unique_id": str(random.randint(100000000000, 999999999999)) + } + result.append(data) + + return Response(result) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_hatching_for_bazrasi(request): + active = request.GET['active'] + poultry = Poultry.objects.filter(trash=False, breeding_unique_id=request.GET['code']).first() + if poultry: + poultry_hatching = PoultryHatching.objects.filter(trash=False, poultry=poultry).order_by('id') + if active == 'true': + poultry_hatching = poultry_hatching.filter(state='pending', allow_hatching='pending', archive=False) + else: + poultry_hatching = poultry_hatching.filter(archive=True).last() + poultry_hatching = [poultry_hatching] if poultry_hatching else [] + ser_data = PoultryHatchingForBazrasiSerializer(poultry_hatching, many=True).data + return Response(ser_data, status.HTTP_200_OK) + return Response({'result': "مرغدار وجود ندارد!"}, status.HTTP_403_FORBIDDEN) + + +@api_view(["GET"]) +@permission_classes([AllowAny]) +@csrf_exempt +def get_poultry_for_bazrasi(request): + breeding_unique_id = request.GET.get('code') or request.GET.get('breeding_unique_id') + + if not breeding_unique_id: + return Response({'result': "شناسه یکتا مرغدار ارسال نشده است!"}, status=status.HTTP_400_BAD_REQUEST) + + poultry = Poultry.objects.filter( + trash=False, + breeding_unique_id=breeding_unique_id + ).select_related( + 'user', 'address', 'address__city', 'address__province' + ).first() + + if not poultry: + return Response({'result': "مرغدار وجود ندارد!"}, status=status.HTTP_404_NOT_FOUND) + + active_hatchings = PoultryHatching.objects.filter( + trash=False, + poultry=poultry, + state='pending', + allow_hatching='pending', + archive=False + ).select_related( + 'chain_company', 'poultry' + ).order_by('id') + + poultry_serializer = PoultryDetailForPoultryAndHatchingForPoultryScienceSerializer(poultry) + hatchings_serializer = PoultryHatchingForPoultryAndHatchingForPoultryScienceSerializer(active_hatchings, many=True) + + result = { + 'poultry': poultry_serializer.data, + 'active_hatchings': hatchings_serializer.data + } + + return Response(result, status=status.HTTP_200_OK) + + +class PoultryRequestForDirectBuyingViewSet(GenericAPIView): + permission_classes = [TokenHasReadWriteScope] + serializer_class = PoultryRequestForDirectBuyingSerializer + filterset_class = PoultryRequestDirectBuyingFilterSet + pagination_class = CustomPagination + + def get_queryset(self): + user = SystemUserProfile.objects.select_related("user").get(user=self.request.user, trash=False) + role = self.request.GET.get('role') + date1, date2 = self.request.GET.get('date1'), self.request.GET.get('date2') + now = datetime.datetime.now() + + categories = {c.name: c for c in IndexWeightCategory.objects.filter(trash=False).only('name')} + light, average, heavy = categories.get("سبک"), categories.get("متوسط"), categories.get("سنگین") + + show_market = ShowMarketRequest.objects.filter(trash=False, allow=True).first() + now_time = now.time().replace(second=0, microsecond=0) + + filters = Q( + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state='pending', + market=True + ) + + if date1 and date2: + filters &= Q(send_date__date__gte=date1, send_date__date__lte=date2) + else: + filters &= Q(send_date__date=now.date()) + + queryset = PoultryRequest.objects.select_related( + "poultry__user__city", + "hatching" + ).filter(filters) + + if role == "KillHouse" and show_market: + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user).first() + if not ( + kill_house and kill_house.market_buying and show_market.start_time < now_time < show_market.end_time): + return PoultryRequest.objects.none() + + breed = self.request.GET.get('breed') + city = self.request.GET.get('city') + remain = self.request.GET.get('remain') + min_amount = self.request.GET.get('min_amount') + max_amount = self.request.GET.get('max_amount') + weight = self.request.GET.get('weight') + min_age = self.request.GET.get('min_age') + max_age = self.request.GET.get('max_age') + value = self.request.GET.get('value') + search = self.request.GET.get('search') + + if breed: + queryset = queryset.filter(chicken_breed__in=breed.split(',')) + if city: + queryset = queryset.filter(poultry__user__city__name__in=city.split(',')) + if remain == 'true': + queryset = queryset.filter(remain_quantity__gt=0) + if min_amount: + queryset = queryset.filter(amount__gte=min_amount) + if max_amount: + queryset = queryset.filter(amount__lte=max_amount) + + if weight and (light and average and heavy): + if weight == 'سبک': + queryset = queryset.filter(Index_weight__gte=light.min_value, Index_weight__lt=light.max_value) + elif weight == 'متوسط': + queryset = queryset.filter(Index_weight__gte=average.min_value, Index_weight__lt=average.max_value) + elif weight == 'سنگین': + queryset = queryset.filter(Index_weight__gte=heavy.min_value, Index_weight__lte=heavy.max_value) + + if min_age: + queryset = queryset.filter(hatching__chicken_age__gte=min_age) + if max_age: + queryset = queryset.filter(hatching__chicken_age__lte=max_age) + + if value and search == 'filter' and value.strip() and value != 'undefined': + queryset = queryset.filter(build_query(self.filterset_class, value)) + + return queryset + + def get(self, request): + queryset = self.get_queryset() + + page_size = request.query_params.get('page_size') + if page_size: + self.pagination_class.page_size = int(page_size) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.serializer_class(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.serializer_class(queryset, many=True) + return Response(serializer.data, status=status.HTTP_200_OK) + + +class PoultryHatchingForDirectBuyingViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + result = None + hatching = PoultryHatching.objects.get(key=request.GET['hatching_key']) + poultry_requests = PoultryRequest.objects.filter(hatching=hatching, state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), trash=False, + temporary_trash=False, + out=False).order_by('send_date') + poultry_requests_info = poultry_requests.aggregate( + avg_weight=Avg('Index_weight'), + min_age=Min('killing_age'), + max_age=Max('killing_age') + ) + + kill_house_requests = KillHouseRequest.objects.filter(trash=False, + province_request__poultry_request__in=poultry_requests) + kill_house_requests_info = kill_house_requests.aggregate( + avg_weight_losse=Avg('weight_loss') + ) + completed_bars = kill_house_requests.filter(assignment_state_archive='True') + receive_bars_percent = ( + completed_bars.count() / kill_house_requests.count()) * 100 if kill_house_requests else 0 + + if poultry_requests: + result = { + 'min_age': poultry_requests_info['min_age'] or 1, + 'max_age': poultry_requests_info['max_age'] or 1, + 'now_age': hatching.chicken_age, + 'avg_weight': round(poultry_requests_info['avg_weight'] or 0, 2) or 0, + 'avg_weight_losse': round(kill_house_requests_info['avg_weight_losse'] or 0, 2) or 0, + 'receive_bars_percent': round(receive_bars_percent, 2), + } + + return Response(result, status=status.HTTP_200_OK) + + +class PoultryHatchingChartForDirectBuyingViewSet(APIView): + permission_classes = [TokenHasReadWriteScope] + + def get(self, request): + user = SystemUserProfile.objects.get(user=self.request.user, trash=False) + today = datetime.date.today() + now = datetime.datetime.now() + role = request.GET.get('role') + show_market = ShowMarketRequest.objects.filter(trash=False, allow=True).first() + now_time = now.time().replace(second=0, microsecond=0) + index_weight_category = IndexWeightCategory.objects.filter(trash=False).order_by('id') + light = index_weight_category.filter(name='سبک').first() + average = index_weight_category.filter(name='متوسط').first() + heavy = index_weight_category.filter(name='سنگین').first() + light_min_value = light.min_value + light_max_value = light.max_value + average_min_value = average.min_value + average_max_value = average.max_value + heavy_min_value = heavy.min_value + heavy_max_value = heavy.max_value + if show_market and role == 'KillHouse': + kill_house = KillHouse.objects.filter(trash=False, kill_house_operator__user=user).first() + + if show_market.start_time < \ + now_time < show_market.end_time: + if kill_house.market_buying: + + queryset = ( + PoultryRequest.objects.filter( + send_date__date=today, + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state='pending', + market=True, + ) + .values("poultry__user__city__name") + .annotate( + total_quantity=Sum('quantity'), + light_quantity=Sum( + Case( + When(Q(Index_weight__gte=light_min_value, Index_weight__lt=light_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + average_quantity=Sum( + Case( + When(Q(Index_weight__gte=average_min_value, Index_weight__lt=average_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + heavy_quantity=Sum( + Case( + When(Q(Index_weight__gte=heavy_min_value, Index_weight__lt=heavy_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + ) + ) + + result = [ + { + "city": row["poultry__user__city__name"], + "total_quantity": row["total_quantity"] or 0, + "category": [ + { + "name": light.name, + "min_value": light.min_value, + "max_value": light.max_value, + "quantity": row['light_quantity'] or 0, + }, + { + "name": average.name, + "min_value": average.min_value, + "max_value": average.max_value, + "quantity": row['average_quantity'] or 0, + }, + { + "name": heavy.name, + "min_value": heavy.min_value, + "max_value": heavy.max_value, + "quantity": row['heavy_quantity'] or 0, + } + ] + } + for row in queryset + ] + + else: + result = [] + + else: + result = [] + else: + queryset = ( + PoultryRequest.objects.filter( + send_date__date=today, + state_process='accepted', + province_state='accepted', + temporary_trash=False, + trash=False, + out=False, + final_state='pending', + market=True, + ) + .values("poultry__user__city__name") + .annotate( + total_quantity=Sum('quantity'), + light_quantity=Sum( + Case( + When(Q(Index_weight__gte=light_min_value, Index_weight__lt=light_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + average_quantity=Sum( + Case( + When(Q(Index_weight__gte=average_min_value, Index_weight__lt=average_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + heavy_quantity=Sum( + Case( + When(Q(Index_weight__gte=heavy_min_value, Index_weight__lt=heavy_max_value), + then="quantity"), + output_field=IntegerField(), + ) + ), + ) + ) + + result = [ + { + "city": row["poultry__user__city__name"], + "total_quantity": row["total_quantity"] or 0, + "category": [ + { + "name": light.name, + "min_value": light.min_value, + "max_value": light.max_value, + "quantity": row['light_quantity'] or 0, + }, + { + "name": average.name, + "min_value": average.min_value, + "max_value": average.max_value, + "quantity": row['average_quantity'] or 0, + }, + { + "name": heavy.name, + "min_value": heavy.min_value, + "max_value": heavy.max_value, + "quantity": row['heavy_quantity'] or 0, + } + ] + } + for row in queryset + ] + + return Response(result, status=status.HTTP_200_OK) + + +class ManagementHatchingAgeRangeViewSet(viewsets.ModelViewSet): + queryset = ManagementHatchingAgeRange.objects.all().order_by('from_age') + serializer_class = ManagementHatchingAgeRangeSerializer + permission_classes = [TokenHasReadWriteScope] diff --git a/panel/scripts/__init__.py b/panel/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/scripts/database_merge.py b/panel/scripts/database_merge.py new file mode 100644 index 0000000..c5837e4 --- /dev/null +++ b/panel/scripts/database_merge.py @@ -0,0 +1,6 @@ +def update_database(): + from panel.models import Poultry + poultries = Poultry.objects.all() + for poultry in poultries: + poultry.city = poultry.address.city.id + poultry.save() diff --git a/panel/temp_keys.py b/panel/temp_keys.py new file mode 100644 index 0000000..20ffa64 --- /dev/null +++ b/panel/temp_keys.py @@ -0,0 +1,430 @@ +from authentication.models import Province, City, CityUnit, SystemAddress, SystemUserProfile, BankCard +from panel.models import Poultry, PoultryHatching, CityOperator, PoultryRequest, KillHouseOperator, \ + KillHouseAllowVet, KillHousePercentage, KillHouseDriver, CityOperatorCheckRequest, KillHouseADDCAR, \ + ProvinceOperator, ProvinceCheckOperatorOutRequest, ProvinceCheckOperatorRequest, ShareOfAllocation, KillRequest, \ + KillRequestFactor, KillRequestFactorPayment, ProvinceKillRequest, KillHouseRequest, KillHouseCheckRequest, \ + KillHouseAssignmentInformation, ProvinceCheckInformation, ProvinceFactorToKillHouse, KillHouseFactorToProvince, \ + ProvinceCheckKillHouseFactor, DepositAllocation, InspectorOperator, PovinceInspector, Vet, KillHouseVet, \ + VetCheckRequest, VetFarm, VetFarmInspection, Admin, Jahad, CityJahad, ProvincialGovernment, VetSupervisor, \ + ProvinceAllowKillHouseRegisterCar, ProvinceAllowPoultryChooseKillHouse, ProvinceAllowPoultrySellFree, \ + KillHouseDailyQuota, ProvinceAutoAllocation, Pricing, PoultryAllowCityProvince, TotalPoultryRequestQuantity, \ + VetCheckAllocations, Wallet + + +def make_temp_keys(): + from panel.models import KillHouse + wallets = Wallet.objects.all() + provinces = Province.objects.all() + cities = City.objects.all() + cityunits = CityUnit.objects.all() + system_addresses = SystemAddress.objects.all() + bank_cards = BankCard.objects.all() + system_userprofiles = SystemUserProfile.objects.all() + pricings = Pricing.objects.all() + poultries = Poultry.objects.all() + poultry_allow_citys_provinces = PoultryAllowCityProvince.objects.all() + hatchings = PoultryHatching.objects.all() + city_operators = CityOperator.objects.all() + poultry_requests = PoultryRequest.objects.all() + totals_poultry_request_quantity = TotalPoultryRequestQuantity.objects.all() + kill_house_operators = KillHouseOperator.objects.all() + KillHouses = KillHouse.objects.all() + killhouseallowvets = KillHouseAllowVet.objects.all() + killhousepercentages = KillHousePercentage.objects.all() + drivers = KillHouseDriver.objects.all() + add_cars = KillHouseADDCAR.objects.all() + city_check_requests = CityOperatorCheckRequest.objects.all() + province_operators = ProvinceOperator.objects.all() + province_check_out_requests = ProvinceCheckOperatorOutRequest.objects.all() + province_check_requests = ProvinceCheckOperatorRequest.objects.all() + share_of_allocations = ShareOfAllocation.objects.all() + kill_requests = KillRequest.objects.all() + kill_request_factors = KillRequestFactor.objects.all() + kill_request_payment_factors = KillRequestFactorPayment.objects.all() + province_kill_requests = ProvinceKillRequest.objects.all() + kill_house_requests = KillHouseRequest.objects.all() + kill_house_check_requests = KillHouseCheckRequest.objects.all() + assignment_informations = KillHouseAssignmentInformation.objects.all() + province_check_informations = ProvinceCheckInformation.objects.all() + province_factors = ProvinceFactorToKillHouse.objects.all() + kill_house_factors = KillHouseFactorToProvince.objects.all() + province_check_kill_house_factors = ProvinceCheckKillHouseFactor.objects.all() + deposit_allocations = DepositAllocation.objects.all() + inspectors = InspectorOperator.objects.all() + inspector_checks = PovinceInspector.objects.all() + vets = Vet.objects.all() + kill_house_vets = KillHouseVet.objects.all() + vet_check_requests = VetCheckRequest.objects.all() + vet_farms = VetFarm.objects.all() + vet_farm_inspections = VetFarmInspection.objects.all() + admins = Admin.objects.all() + jahads = Jahad.objects.all() + city_jahads = CityJahad.objects.all() + goverments = ProvincialGovernment.objects.all() + vet_supervisers = VetSupervisor.objects.all() + vet_check_allocations = VetCheckAllocations.objects.all() + province_allow_kill_house_registers = ProvinceAllowKillHouseRegisterCar.objects.all() + province_allow_poultry_choose_kill_houses = ProvinceAllowPoultryChooseKillHouse.objects.all() + province_allow_poultry_auto_sell = ProvinceAllowPoultrySellFree.objects.all() + kill_house_daily_quotas = KillHouseDailyQuota.objects.all() + province_auto_allocations = ProvinceAutoAllocation.objects.all() + + for wallet in wallets: + wallet.province_name = 'لرستان' + wallet.save() + + for bank_card in bank_cards: + bank_card.user_bank_id_key = bank_card.id + bank_card.province_name = 'لرستان' + bank_card.save() + + + # for province in provinces: + # province.province_id_key = province.id + # province.save() + # + # for city in cities: + # city.province_id_foreign_key = city.province.id + # city.city_id_key = city.id + # city.save() + # + # for cityunit in cityunits: + # cityunit.city_id_foreign_key = cityunit.city.id + # cityunit.city_unit_id_key = cityunit.id + # cityunit.save() + # + # for system_addresse in system_addresses: + # system_addresse.province_id_foreign_key = system_addresse.province.id + # system_addresse.city_id_foreign_key = system_addresse.city.id + # system_addresse.address_id_key = system_addresse.id + # system_addresse.save() + # + # + # for system_userprofile in system_userprofiles: + # system_userprofile.city_id_foreign_key = system_userprofile.city.id + # system_userprofile.province_id_foreign_key = system_userprofile.province.id + # system_userprofile.user_django_id_foreign_key = system_userprofile.user.id + # system_userprofile.system_user_profile_id_key = system_userprofile.id + # system_userprofile.save() + # + # for pricing in pricings: + # if pricing.operator != None: + # pricing.operator_id_foreign_key = pricing.operator.id + # pricing.pricing_id_key = pricing.id + # pricing.save() + # + # for poultry in poultries: + # if poultry.owner != None: + # poultry.owner_id_foreign_key = poultry.owner.id + # poultry.user_id_foreign_key = poultry.user.id + # poultry.address_id_foreign_key = poultry.address.id + # if poultry.user_bank_info != None: + # poultry.user_bank_id_foreign_key = poultry.user_bank_info.id + # poultry.wallet_id_foreign_key = poultry.wallet.id + # poultry.poultry_id_key = poultry.id + # poultry.save() + # + # for poultry_allow_city_province in poultry_allow_citys_provinces: + # poultry_allow_city_province.poultry_id_foreign_key = poultry_allow_city_province.poultry.id + # poultry_allow_city_province.poultry_allow_city_province_id_key = poultry_allow_city_province.id + # poultry_allow_city_province.save() + # + # for hatching in hatchings: + # hatching.poultry_id_foreign_key = hatching.poultry.id + # hatching.poultry_hatching_id_key = hatching.id + # hatching.save() + # + # for city_operator in city_operators: + # city_operator.user_id_foreign_key = city_operator.user.id + # city_operator.address_id_foreign_key = city_operator.address.id + # if city_operator.user_bank_info != None: + # city_operator.user_bank_id_foreign_key = city_operator.user_bank_info.id + # city_operator.wallet_id_foreign_key = city_operator.wallet.id + # city_operator.city_operator_id_key = city_operator.id + # city_operator.save() + # + # for poultry_request in poultry_requests: + # poultry_request.city_operator_id_foreign_key = poultry_request.city_operator.id + # poultry_request.poultry_id_foreign_key = poultry_request.poultry.id + # poultry_request.poultry_hatching_id_foreign_key = poultry_request.hatching.id + # poultry_request.poultry_request_id_key = poultry_request.id + # poultry_request.save() + # + # for total_poultry_request_quantity in totals_poultry_request_quantity: + # total_poultry_request_quantity.total_poultry_request_quantity_id_key = total_poultry_request_quantity.id + # total_poultry_request_quantity.save() + # + # for kill_house_operator in kill_house_operators: + # kill_house_operator.user_id_foreign_key = kill_house_operator.user.id + # kill_house_operator.address_id_foreign_key = kill_house_operator.address.id + # if kill_house_operator.user_bank_info != None: + # kill_house_operator.user_bank_id_foreign_key = kill_house_operator.user_bank_info.id + # kill_house_operator.wallet_id_foreign_key = kill_house_operator.wallet.id + # kill_house_operator.kill_house_operator_id_key = kill_house_operator.id + # kill_house_operator.save() + # + # for KillHouse in KillHouses: + # KillHouse.kill_house_operator_id_foreign_key = KillHouse.kill_house_operator.id + # KillHouse.system_address_id_foreign_key = KillHouse.system_address.id + # KillHouse.kill_house_id_key = KillHouse.id + # KillHouse.save() + # + # for killhouseallowvet in killhouseallowvets: + # killhouseallowvet.kill_house_id_foreign_key = killhouseallowvet.kill_house.id + # killhouseallowvet.kill_house_allow_vet_id_key = killhouseallowvet.id + # killhouseallowvet.save() + # + # for killhousepercentage in killhousepercentages: + # killhousepercentage.kill_house_id_foreign_key = killhousepercentage.kill_house.id + # if killhousepercentage.kill_house_for_killer != None: + # killhousepercentage.kill_house_for_killer_id_foreign_key = killhousepercentage.kill_house_for_killer.id + # killhousepercentage.kill_house_percentage_id_key = killhousepercentage.id + # killhousepercentage.save() + # + # for driver in drivers: + # driver.user_id_foreign_key = driver.user.id + # if driver.user_bank_info != None: + # driver.user_bank_id_foreign_key = driver.user_bank_info.id + # driver.wallet_id_foreign_key = driver.wallet.id + # driver.kill_house_driver_id_key = driver.id + # driver.save() + # + # for add_car in add_cars: + # add_car.kill_house_id_foreign_key = add_car.kill_house.id + # add_car.driver_id_foreign_key = add_car.driver.id + # add_car.kill_house_add_car_id_key = add_car.id + # add_car.save() + # + # for city_check_request in city_check_requests: + # city_check_request.city_operator_system_id_foreign_key = city_check_request.city_operator_system.id + # city_check_request.poultry_request_id_foreign_key = city_check_request.poultry_request.id + # city_check_request.city_operator_check_request_id_key = city_check_request.id + # city_check_request.save() + # + # for province_operator in province_operators: + # province_operator.user_id_foreign_key = province_operator.user.id + # province_operator.address_id_foreign_key = province_operator.address.id + # if province_operator.user_bank_info != None: + # province_operator.user_bank_id_foreign_key = province_operator.user_bank_info.id + # province_operator.wallet_id_foreign_key = province_operator.wallet.id + # province_operator.province_operator_id_key = province_operator.id + # province_operator.save() + # + # for province_check_out_request in province_check_out_requests: + # province_check_out_request.province_operator_system_id_foreign_key = province_check_out_request.province_operator_system.id + # province_check_out_request.poultry_request_id_foreign_key = province_check_out_request.poultry_request.id + # province_check_out_request.province_operator_check_out_request_id_key = province_check_out_request.id + # province_check_out_request.save() + # + # for province_check_request in province_check_requests: + # province_check_request.province_operator_system_id_foreign_key = province_check_request.province_operator_system.id + # province_check_request.poultry_request_id_foreign_key = province_check_request.poultry_request.id + # province_check_request.city_request_poultry_id_foreign_key = province_check_request.city_request_Poultry.id + # province_check_request.province_operator_check_request_id_key = province_check_request.id + # province_check_request.save() + # + # for share_of_allocation in share_of_allocations: + # share_of_allocation.province_id_foreign_key = share_of_allocation.province.id + # share_of_allocation.share_of_allocation_id_key = share_of_allocation.id + # share_of_allocation.save() + # + # for kill_request in kill_requests: + # kill_request.kill_house_id_foreign_key = kill_request.kill_house.id + # if kill_request.slaughter_house != None: + # kill_request.slaughter_house_id_foreign_key = kill_request.slaughter_house.id + # kill_request.kill_request_id_key = kill_request.id + # kill_request.save() + # + # for kill_request_factor in kill_request_factors: + # kill_request_factor.kill_request_id_foreign_key = kill_request_factor.kill_request.id + # kill_request_factor.kill_request_factor_id_key = kill_request_factor.id + # kill_request_factor.save() + # + # for kill_request_payment_factor in kill_request_payment_factors: + # kill_request_payment_factor.kill_request_factor_id_foreign_key = kill_request_payment_factor.kill_request_factor.id + # kill_request_payment_factor.kill_request_factor_payment_id_key = kill_request_payment_factor.id + # kill_request_payment_factor.save() + # + # for province_kill_request in province_kill_requests: + # province_kill_request.killhouse_user_id_foreign_key = province_kill_request.killhouse_user.id + # province_kill_request.kill_request_id_foreign_key = province_kill_request.kill_request.id + # province_kill_request.province_request_id_foreign_key = province_kill_request.province_request.id + # province_kill_request.province_kill_request_id_key = province_kill_request.id + # province_kill_request.save() + # + # for kill_house_request in kill_house_requests: + # kill_house_request.killhouse_user_id_foreign_key = kill_house_request.killhouse_user.id + # kill_house_request.kill_request_id_foreign_key = kill_house_request.kill_request.id + # kill_house_request.province_request_id_foreign_key = kill_house_request.province_request.id + # kill_house_request.province_kill_request_id_foreign_key = kill_house_request.province_kill_request.id + # kill_house_request.add_car_id_foreign_key = kill_house_request.add_car.id + # kill_house_request.kill_house_request_id_key = kill_house_request.id + # kill_house_request.save() + # + # for kill_house_check_request in kill_house_check_requests: + # kill_house_check_request.province_kill_request_id_foreign_key = kill_house_check_request.province_kill_request.id + # kill_house_check_request.kill_house_check_request_id_key = kill_house_check_request.id + # kill_house_check_request.save() + # + # for assignment_information in assignment_informations: + # assignment_information.kill_house_check_id_foreign_key = assignment_information.kill_house_check.id + # assignment_information.kill_house_request_id_foreign_key = assignment_information.kill_house_request.id + # assignment_information.kill_house_kill_house_assingment_information_id_key = assignment_information.id + # assignment_information.save() + # + # for province_check_information in province_check_informations: + # province_check_information.kill_house_assignment_id_foreign_key = province_check_information.kill_house_assignment.id + # if province_check_information.province_operator != None: + # province_check_information.province_operator_id_foreign_key = province_check_information.province_operator.id + # province_check_information.province_check_information_id_key = province_check_information.id + # province_check_information.save() + # + # for province_factor in province_factors: + # province_factor.province_check_info_id_foreign_key = province_factor.province_check_info.id + # province_factor.province_check_req_id_foreign_key = province_factor.province_check_req.id + # province_factor.user_bank_id_foreign_key = province_factor.bank.id + # province_factor.province_factor_to_kill_house_id_key = province_factor.id + # province_factor.save() + # + # for kill_house_factor in kill_house_factors: + # kill_house_factor.province_factor_id_foreign_key = kill_house_factor.province_factor.id + # kill_house_factor.kill_house_factor_to_province_id_key = kill_house_factor.id + # kill_house_factor.save() + # + # for province_check_kill_house_factor in province_check_kill_house_factors: + # province_check_kill_house_factor.kill_house_factor_id_foreign_key = province_check_kill_house_factor.kill_house_factor.id + # province_check_kill_house_factor.province_check_kill_house_factor_id_key = province_check_kill_house_factor.id + # province_check_kill_house_factor.save() + # + # for deposit_allocation in deposit_allocations: + # deposit_allocation.poultry_request_id_foreign_key = deposit_allocation.poultry.id + # deposit_allocation.deposit_allocation_id_key = deposit_allocation.id + # deposit_allocation.save() + # + # for inspector in inspectors: + # inspector.user_id_foreign_key = inspector.user.id + # inspector.address_id_foreign_key = inspector.address.id + # if inspector.user_bank_info != None: + # inspector.user_bank_id_foreign_key = inspector.user_bank_info.id + # inspector.wallet_id_foreign_key = inspector.wallet.id + # inspector.inspector_operator_id_key = inspector.id + # inspector.save() + # + # for inspector_check in inspector_checks: + # inspector_check.inspector_operator_id_foreign_key = inspector_check.inspector_operator.id + # inspector_check.poultry_request_id_foreign_key = inspector_check.poultry_request.id + # inspector_check.province_inspector_id_key = inspector_check.id + # inspector_check.save() + # + # for vet in vets: + # vet.user_id_foreign_key = vet.user.id + # vet.address_id_foreign_key = vet.address.id + # if vet.user_bank_info != None: + # vet.user_bank_id_foreign_key = vet.user_bank_info.id + # vet.wallet_id_foreign_key = vet.wallet.id + # vet.vet_id_key = vet.id + # vet.save() + # + # for kill_house_vet in kill_house_vets: + # kill_house_vet.vet_id_foreign_key = kill_house_vet.vet.id + # kill_house_vet.kill_house_id_foreign_key = kill_house_vet.kill_house.id + # kill_house_vet.kill_house_vet_id_key = kill_house_vet.id + # kill_house_vet.save() + # + # for vet_check_request in vet_check_requests: + # vet_check_request.kill_house_vet_id_foreign_key = vet_check_request.kill_house_vet.id + # vet_check_request.kill_house_request_id_foreign_key = vet_check_request.kill_house_request.id + # vet_check_request.vet_check_request_id_key = vet_check_request.id + # vet_check_request.save() + # + # for vet_farm in vet_farms: + # vet_farm.vet_id_foreign_key = vet_farm.vet.id + # vet_farm.poultry_id_foreign_key = vet_farm.poultry.id + # vet_farm.vet_farm_id_key = vet_farm.id + # vet_farm.save() + # + # for vet_farm_inspection in vet_farm_inspections: + # vet_farm_inspection.vet_farm_id_foreign_key = vet_farm_inspection.vet_farm.id + # vet_farm_inspection.poultry_hatching_id_foreign_key = vet_farm_inspection.poultry_hatching.id + # vet_farm_inspection.vet_farm_inspection_id_key = vet_farm_inspection.id + # vet_farm_inspection.save() + # + # for admin in admins: + # admin.user_id_foreign_key = admin.user.id + # admin.address_id_foreign_key = admin.address.id + # admin.admin_id_key = admin.id + # admin.save() + # + # for jahad in jahads: + # jahad.user_id_foreign_key = jahad.user.id + # if jahad.user_bank_info != None: + # jahad.user_bank_id_foreign_key = jahad.user_bank_info.id + # jahad.address_id_foreign_key = jahad.address.id + # jahad.wallet_id_foreign_key = jahad.wallet.id + # jahad.jahad_id_key = jahad.id + # jahad.save() + # + # for city_jahad in city_jahads: + # city_jahad.user_id_foreign_key = city_jahad.user.id + # city_jahad.address_id_foreign_key = city_jahad.address.id + # if city_jahad.user_bank_info != None: + # city_jahad.user_bank_id_foreign_key = city_jahad.user_bank_info.id + # city_jahad.wallet_id_foreign_key = city_jahad.wallet.id + # city_jahad.city_jahad_id_key = city_jahad.id + # city_jahad.save() + # + # for goverment in goverments: + # goverment.user_id_foreign_key = goverment.user.id + # goverment.address_id_foreign_key = goverment.address.id + # if goverment.user_bank_info != None: + # goverment.user_bank_id_foreign_key = goverment.user_bank_info.id + # goverment.wallet_id_foreign_key = goverment.wallet.id + # goverment.provincial_government_id_key = goverment.id + # goverment.save() + # + # for vet_superviser in vet_supervisers: + # vet_superviser.user_id_foreign_key = vet_superviser.user.id + # vet_superviser.address_id_foreign_key = vet_superviser.address.id + # if vet_superviser.user_bank_info != None: + # vet_superviser.user_bank_id_foreign_key = vet_superviser.user_bank_info.id + # vet_superviser.wallet_id_foreign_key = vet_superviser.wallet.id + # if vet_superviser.vet != None: + # vet_superviser.vet_id_foreign_key = vet_superviser.vet.id + # vet_superviser.vet_superviser_id_key = vet_superviser.id + # vet_superviser.save() + # + # for vet_check_allocation in vet_check_allocations: + # vet_check_allocation.vet_id_foreign_key = vet_check_allocation.vet.id + # vet_check_allocation.kill_house_request_id_foreign_key = vet_check_allocation.kill_house_request.id + # vet_check_allocation.vet_chick_allocations_id_key = vet_check_allocation.id + # vet_check_allocation.save() + # + # for province_allow_kill_house_register in province_allow_kill_house_registers: + # province_allow_kill_house_register.kill_house_id_foreign_key = province_allow_kill_house_register.kill_house.id + # province_allow_kill_house_register.province_allow_kill_house_register_car_id_key = province_allow_kill_house_register.id + # province_allow_kill_house_register.save() + # + # for province_allow_poultry_choose_kill_house in province_allow_poultry_choose_kill_houses: + # province_allow_poultry_choose_kill_house.poultry_id_foreign_key = province_allow_poultry_choose_kill_house.poultry.id + # province_allow_poultry_choose_kill_house.province_allow_poultry_choose_kill_house_id_key = province_allow_poultry_choose_kill_house.id + # province_allow_poultry_choose_kill_house.save() + # + # for province_allow_poultry_auto in province_allow_poultry_auto_sell: + # province_allow_poultry_auto.poultry_id_foreign_key = province_allow_poultry_auto.poultry.id + # province_allow_poultry_auto.province_allow_poultry_sell_free_id_key = province_allow_poultry_auto.id + # province_allow_poultry_auto.save() + # + # for kill_house_daily_quota in kill_house_daily_quotas: + # kill_house_daily_quota.kill_house_id_foreign_key = kill_house_daily_quota.kill_house.id + # if kill_house_daily_quota.killer_kill_house != None: + # kill_house_daily_quota.killer_kill_house_id_foreign_key = kill_house_daily_quota.killer_kill_house.id + # kill_house_daily_quota.kill_request_id_foreign_key = kill_house_daily_quota.kill_request.id + # kill_house_daily_quota.kill_house_daily_quota_id_key = kill_house_daily_quota.id + # kill_house_daily_quota.save() + # + # for province_auto_allocation in province_auto_allocations: + # province_auto_allocation.daily_quota_id_foreign_key = province_auto_allocation.daily_quota.id + # province_auto_allocation.poultry_request_id_foreign_key = province_auto_allocation.poultry_request.id + # province_auto_allocation.province_kill_request_id_foreign_key = province_auto_allocation.province_kill_request.id + # province_auto_allocation.province_auto_allocation_id_key = province_auto_allocation.id + # province_auto_allocation.save() diff --git a/panel/templatetags/__init__.py b/panel/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/panel/templatetags/jalali_filters.py b/panel/templatetags/jalali_filters.py new file mode 100644 index 0000000..5098a0c --- /dev/null +++ b/panel/templatetags/jalali_filters.py @@ -0,0 +1,47 @@ +from django import template +from datetime import datetime + +from panel.helper_excel import shamsi_date, to_locale_str + +register = template.Library() + + +@register.filter(name='jalali') +def jalali(value): + if not value: + return "" + + try: + if isinstance(value, str): + try: + value = datetime.fromisoformat(value) + except: + return '-' + + if hasattr(value, 'date'): + value = value.date() + + return shamsi_date(value,in_value=True) + except: + return '-' + + +@register.filter(name='isNone') +def is_none(value): + if value is None: + return "-" + return value + + +@register.filter(name='toLocaleStr') +def to_locale_string(value): + if value is None: + return "-" + return to_locale_str(value) + + +@register.filter(name='int') +def to_int(value): + if value is None: + return "-" + return int(value) diff --git a/panel/tests.py b/panel/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/panel/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/panel/urls.py b/panel/urls.py new file mode 100644 index 0000000..fbfddba --- /dev/null +++ b/panel/urls.py @@ -0,0 +1,1393 @@ +from authentication.register import add_zero_for_user_mobile +from authentication.sms_management import send_daily_slaughter_statistics_sms_manual, \ + send_daily_distribution_report_sms_manual +from pdf.views import kill_request_pdf, management_all_poultry_and_warehouse_pdf, summary_report_pdf, \ + hatching_detail_pdf, poultry_science_report_pdf +from .KillHouse.excel_processing import direct_purchase_archive_excel, kill_house_user_excel, \ + bar_excel, bar_excel_trash_true, kill_house_total_wage_excel, export_kill_house_excel, monitor_loads_excel, \ + kill_house_free_bar_excel, comprehensive_report_of_the_slaughterhouse_excel, \ + out_province_carcasses_buyer_kill_house_excel, kill_house_free_sale_bar_information_excel, \ + kill_house_free_sale_bar_information_for_excel_excel, notentered_bars_for_kill_house_excel, \ + entered_bars_for_kill_house_excel, kill_house_free_bar_entered_for_warehouse_excel, \ + steward_allocation_for_warehouse_excel, kill_house_free_bar_carcasses_for_warehouse_excel, \ + kill_house_inventory_data, all_kill_house_inventory_data, cold_house_excel, management_cold_house_excel, \ + direct_purchase_excel, non_receipt_request_excel, return_kill_house_request_excel, \ + warehouse_archive_combined_excel +from .KillHouse.helpers import create_kill_house_free_bar +from .KillHouse.views import make_kill_request, get_hatching_kill_ingo, dashboard_monitoring_bar_and_killing, \ + dashboarad_bar_for_kill_house, dashboard_bar_difference_request, KillHousePerformanceDashboardViewSet, \ + KillHouseMarketInfoViewSet, KillHouseMarketInfoDashboardViewSet, KillHouseSalesInformationViewSet, \ + KillHouseForColdHouseAllocationViewSet, KillHouseForSegmentationViewSet, KillHouseComparativeInformationViewSet, \ + cancel_bar_and_province_request, ReturnProvinceKillRequestViewSet, ReturnRequestDashboardViewSet, fix_wage, \ + KillHouseRemainWeightViewSet, TotalKillHouseRemainWeightViewSet, TotalKillHouseWarehouseArchiveDashboardViewSet, \ + KillHouseLock +from .ProvinceOperator.excel_processing import kill_house_total_transactions_wage_payid_excel, \ + kill_house_total_transactions_wage_payid_super_admin_excel, kill_house_total_wage_excel_new, \ + payment_transactions_province_excel, general_free_bar_excel, out_province_poultry_request_buyers_excel, \ + chain_company_buyers_excel, bar_chain_excel, general_city_operator, \ + kill_house_total_transactions_wage_payid_admin_x_excel, poultry_request_report_excel, transacion_out_request_excel, \ + from_allocation_to_distribution_excel, all_distribution_province, login_user_excel, \ + sub_section_of_cooperative_share_detail, city_operator_for_sub_sector_excel, vet_for_sub_sector_excel, \ + guild_for_sub_sector_excel, all_guilds_transaction_excel, detail_guilds_transaction_excel, GetExcel, \ + management_hatching_excel, user_without_role_excel, sub_section_of_cooperative_share_detail_with_date_excel, \ + dashboard_monitoring_bar_and_killing_excel, steward_allocation_excel, free_sale_out_province_excel, \ + sevrence_kill_house_steward_allocation_excel, steward_free_sale_out_province_excel, total_steward_dashboard_excel, \ + detail_of_killing_and_warehouse_excel, management_all_poultry_and_warehouse, market_requests_excel, \ + get_more_than_one_role, return_province_request_excel, guilds_without_allocation_excel +from .ProvinceOperator.helpers import update_role_product, update_cooperative_share +from .ProvinceOperator.views import get_gate_way_payer_info, Rolesusers, get_all_pos_company, get_all_pos_version, \ + get_all_guilds, SegmentationDashboardViewSet, GetAllPoultryForPoultryScienceViewSet, \ + PoultryAndHatchingForPoultryScience, StewardSalesInformationViewSet, PosSalesInformationViewSet, \ + PosColdHouseViewSet, PosRemainWeightViewSet, StewardRemainWeightViewSet, PosRemainWeightWithDateViewSet, \ + update_guild_by_national_id, register_legal_guild, TotalStewardRemainWeightViewSet, \ + TotalGuildStewardWarehouseArchiveDashboardViewSet, check_steward_allocation_role_mismatch, get_dispenser_user_info +from .ReportingPanel.views import check_excel, find_gid_code, fix_duplicate_guilds_steward_allocation, \ + fix_image_voilation_hatching, \ + fix_image_voilation_hatching_return, send_sms_for_poultry_from_age_notification, api_update_poultry_hatching, \ + api_update_chicken_breed, fix_bar_without_quarantine, api_update_poultry_hatching_from_rsi, \ + get_gid_out_province_manual, dashboard_monitoring_view, remove_access_token_manual, \ + find_gid_code_manual, get_all_pos_transaction, send_clearance_code_to_rsi, api_send_clearance_code_to_rsi, \ + create_steward_allocation_from_excel, send_bar_info_from_ticket, all_clearance_code_to_rsi, \ + ticket_different_clearance_code_from_rsi, management_kill_house_dashboard, periodic_performance_report_dashboard, \ + fix_killing_age, get_bar_from_rsi_with_hatching, driver_from_rsi_excel, send_again_sms_for_register_code_guild, \ + send_again_sms_steward_allocation, fix_number_from_rsi, send_again_sms_steward_free_sale_bar, \ + send_again_sms_kill_house_free_sale_bar, send_again_sms_direct_buying_code, pos_send_again_sms_steward_allocation, \ + delete_guilds_without_allocation, save_mobile_numbers, auto_warehouse_steward_allocations, hatching_unknown, \ + import_poultry_science_from_excel, sync_guilds_user_profile_from_inquiry, \ + report_guilds_without_national_or_pos_transactions, get_guilds_for_update_or_create, \ + update_all_active_guilds_from_api, find_users_with_duplicate_national_id, fix_duplicate_national_id_users, \ + get_legal_person_unit_info, upload_image_to_server_for_poultry_science, poultry_science_for_bazresi +from .VetFarm.excel_processing import technical_responsible_performance_excel, \ + totoal_technical_responsible_performance_excel +from .excel_processing import user_excel_update, user_excel, vet_check_excel, kill_house_request_excel, \ + allocated_excel, poultry_kill_request_excel, request_registration_kill_house, \ + new_load_of_kill_house_vet, request_pending_allocation, car_allocation_excel, Test, Test1, excel_for_all_user, \ + inventory, Broadcast_management, guilds_excel, commerce_report_excel, commerce_bar_excel, \ + number_of_kills_excel, \ + single_hatching_age_range_excel, total_poultry_request_dashboard_excel, \ + total_poultry_hatching_dashboard_excel, doughnut_hatching_excel, forecast_hatching_left_over_excel, \ + manager_of_farm_excel, kill_house__request_vet_killing_process_excel, kill_house_percent_excel, \ + poultry_request_out_excel, doughnut_left_hatching_excel, \ + get_all_user_excel, stewards_excel, steward_excel, \ + kill_house_total_wage_not_payid_excel, all_kill_house_total_wage_excel, slaughterhouse_fee_excel, \ + slaughterhouse_fee_not_paid_excel, car_province_excel, kill_house_wage_archive_excel, \ + kill_house_total_wage_archive_excel, process_for_each_hatching, bar_management_kill_house_excel, \ + all_inventory_excel, daily_process_excel, daily_process_klling_proccess_excel, killing_process_from_date_excel, \ + discrepancy_report_excel, bar_for_each_persion_excel, poultry_excel, \ + bar_contradiction_of_quarantine_excel, detail_of_killing_excel, pos_excel, poultry_and_bar_daily_report_excel, \ + bar_free_excel, steward_ware_house_total_report_daily_excel, steward_ware_house_total_report_daily_detail_excel, \ + hatching_by_age_range, hatching_for_detail_killing_excel, bar_live_stock_support_excel, \ + successful_transactions_excel, unsuccessful_transactions_excel, \ + poultry_hatching_between_50age_70age_excel, number_of_times_with_quarantine_code_excel, \ + the_burden_of_quarantine_excel, bar_without_quarantine_code_excel, \ + loads_that_differ_in_quarantine_and_cooperation_excel, government_burden_excel, \ + goverment_bar_state_with_a_certified_quarantine_code_excel, free_loads_excel, \ + free_cargoes_obtained_from_quarantine_excel, free_loads_with_quarantine_code_excel, \ + loads_outside_the_province_excel, loads_entering_the_slaughterhouse_excel, veterinarian_unloaded_load_excel, \ + completed_slaughterhouse_loads_excel, unloaded_cargo_without_quarantine_code_excel, unloaded_load_excel, \ + loads_unloaded_and_not_completed_by_the_slaughterhouse_excel, hatching_date_range_excel, wallete_excel, \ + number_of_kills_weight_excel, kill_house_request_suspended_load_excel, chain_excel, test_excel, \ + test_all_excel_functions +from django.urls import include, path +from rest_framework.routers import DefaultRouter +from panel.CityOperator import views as city_views +from panel.poultry import views as poultry_views +from panel.ProvinceOperator import views as province_views +from panel.KillHouse import views as killhouse_views +from panel.VetFarm import views as vet_farm_views +from panel.ReportingPanel import views as report_views +from . import views as main_views +from .helper import get_country +from .pos_helper import pos_finder, pos_get_finder, Check_server, pos_login +from .poultry.excel_processing import management_poultry, hatching_excel, archive_hatching_excel, \ + hatching_age_range_excel, poultry_monitoring_excel, hatching_report_from_age_excel, \ + poultry_hatching_prediction_chart_excel, poultry_hatching_prediction_excel, bar_difference_reques_excel, \ + direct_buying_poultry_requests, hatching_for_every_age_range +from .poultry.helpers import create_update_chicken_commission_prices, create_update_chicken_commission_prices_manual, \ + add_poultry_request_quarantine_code, update_archive_date_poultry_hatching +from .poultry.views import Cancel_Poultry_Exchange_request, Check_Poultry_Auction_request_front, \ + city_operator_for_poultry, archive_hatching, GetAllPoultryViewSet, GetAllPoultryFoIncreaseHatchingViewSet, \ + HatchingDetailView, bulk_test_data, get_hatching_for_bazrasi, PoultryRequestForDirectBuyingViewSet, \ + PoultryHatchingForDirectBuyingViewSet, PoultryHatchingChartForDirectBuyingViewSet, get_poultry_for_bazrasi, \ + archive_poultry_hatching_with_archive_percent +from bot_eata import bot_eitaa_for_bar, bot_eitaa_free_bar, bot_eitaa_for_hatching_gt_50, \ + bot_eitaa_for_province_kill_request, daily_manual_transaction_for_eata, transaction_for_eata_new, \ + daily_report_for_each_vet_farm_manual,send_all_bar_to_eitaa +from django.conf import settings +from django.conf.urls.static import static + +router = DefaultRouter() +router.register( + r'city_operator', + city_views.CityOperatorViewSet, + basename="city_operator" +) +router.register( + r'city-operator-for-sub-sector', + city_views.CityOperatorForSubSectorViewSet, + basename="city-operator-for-sub-sector" +) +router.register( + r'city_operator_check_request', + city_views.CityOperatorCheckRequestViewSet, + basename="city_operator_check_request" +) +router.register( + r'management_request', + city_views.ManagementRequestViewSet, + basename="management-request" +) +router.register( + r'city_operator_check_request_new', + city_views.CityOperatorCheckRequestNewViewSet, + basename="city_operator_check_request_new" +) +router.register(r'Poultry', poultry_views.PoultryViewSet, basename="Poultry") +router.register(r'hatching-increase-request', poultry_views.HatchingIncreaseRequestViewSet, + basename="hatching-increase-request") +router.register(r'chain-company', poultry_views.ChainCompanyViewSet, + basename="chain-company") +router.register(r'chain-company-total-allocations', poultry_views.ChainCompanyForTotalWageAllocationViewSet, + basename="chain-company-total-allocations") +router.register(r'chain-company-total-transactions', poultry_views.ChainCompanyForTotalWageTransactionViewSet, + basename="chain-company-total-transactions") +router.register(r'chain-company-transaction', poultry_views.ChainCompanyTransactionViewSet, + basename="chain-company-transaction") +router.register(r'chain-allocation', poultry_views.ChainAllocationViewSet, + basename="chain-allocation") +router.register(r'hatching-loss-management', report_views.HatchingLossManagementViewSet, + basename="hatching-loss-management") +router.register(r'parent-company-chain-allocation', poultry_views.ParentCompanyChainAllocationViewSet, + basename="parent-company-chain-allocation") +router.register(r'dashboard-chain-allocation', poultry_views.DashboardChainAllocationViewSet, + basename="dashboard-chain-allocation") +router.register(r'parent-company-dashboard-chain-allocation', + poultry_views.ParentCompanyDashboardChainAllocationViewSet, + basename="parent-company-dashboard-chain-allocation") +router.register(r'chain-allocation-total-wage', poultry_views.ChainAllocationForWageViewSet, + basename="chain-allocation-total-wage") +router.register(r'poultry-choose-chain-company', poultry_views.PoultryChooseChainCompanyViewSet, + basename="poultry-choose-chain-company") +router.register(r'total_poultry', poultry_views.TotalPoultryViewSet, basename="total_poultry"), +router.register(r'edit_poultry', city_views.PoultryEditByCityOperatorViewSet, basename="edit_poultry"), +router.register(r'show_city_operator', city_views.ShowCityOperatorViewSet, basename="show_city_operator"), +router.register(r'vet_farm', vet_farm_views.VetFarmViewSet, basename="vet_farm"), +router.register(r'management_vet_farm', vet_farm_views.ManagementVetFarmViewSet, basename="management_vet_farm"), +router.register(r'vet_farm_inspection', vet_farm_views.VetFarmInspectionViewSet, basename="vet_farm_inspection"), +router.register(r'vet_for_sub_sector', vet_farm_views.VetForSubSectorViewSet, basename="vet_for_sub_sector"), +router.register(r'vet_for_sub_sector_transaction', vet_farm_views.VetForSubSectorTransactionViewSet, + basename="vet_for_sub_sector_transaction"), +router.register(r'vet_dashboard_wage', vet_farm_views.TotalVetSubSectorWageDashboardViewSet, + basename="vet_dashboard_wage"), +router.register(r'Poultry_tenant', poultry_views.PoultryTenantViewSet, basename="Poultry_tenant"), +router.register(r'out-province-poultry-request-buyers', poultry_views.OutProvincePoultryRequestBuyerViewSet, + basename="out-province-poultry-request-buyers"), +router.register(r'Poultry_Request', poultry_views.PoultryRequestViewSet, basename="Poultry_Request"), +router.register(r'poultry-request-quarantine-code', poultry_views.PoultryRequestQuarantineCodeViewSet, basename="poultry-request-quarantine-code"), +router.register(r'evacuation-hatching-details', poultry_views.EvacuationHatchingDetailViewSet, + basename="evacuation-hatching-details"), +router.register(r'cancel-out-poultry_request', poultry_views.CancelOutProvincePoultryRequestViewSet, + basename="cancel-out-poultry_request"), +router.register(r'out-province-poultry-requests-dashboard', poultry_views.OutProvincePoultryRequestDashboardViewSet, + basename="out-province-poultry-requests-dashboard"), +router.register(r'out-province-poultry-requests', poultry_views.OutProvincePoultryRequestViewSet, + basename="out-province-poultry-requests"), \ +router.register(r'parent-company-out-province-poultry-requests', + poultry_views.ParentCompanyOutProvincePoultryRequestViewSet, + basename="parent-company-out-province-poultry-requests"), +router.register(r'dashboard-out-province-poultry-requests', poultry_views.DashboardOutProvincePoultryRequestViewSet, + basename="dashboard-out-province-poultry-requests"), +router.register(r'parent-company-dashboard-out-province-poultry-requests', + poultry_views.ParentCompanyDashboardOutProvincePoultryRequestViewSet, + basename="parent-company-dashboard-out-province-poultry-requests"), +router.register(r'temporary-out-province-poultry-requests', poultry_views.TemporaryOutProvincePoultryRequestViewSet, + basename="temporary-out-province-poultry-requests"), +router.register(r'poultry_request_letter', killhouse_views.PoultryRequestLetterForProvinceVetViewSet, + basename="poultry_request_letter"), \ +router.register(r'province_request_letter', killhouse_views.ProvinceRequestLetterForProvinceViewSet, + basename="poultry_request_letter"), +router.register(r'poultry_request_letter_order_code', poultry_views.PoultryRequestForLetterViewSet, + basename="poultry_request_letter_order_code"),\ +router.register(r'chicken-commission-prices', poultry_views.ChickenCommissionPricesViewSet, + basename="chicken-commission-prices"), +# router.register(r'bars_for_kill_house', poultry_views.BarsForKillHouseViewSet, basename="bars_for_kill_house"), +router.register(r'total_poultry_request_quantity', poultry_views.TotalPoultryRequestQuantityViewSet, + basename="total_poultry_request_quantity"), +router.register(r'forecast_hatching_left_over', poultry_views.ForecastPoultryHatchingViewSet, + basename="forecast_hatching_left_over"), +router.register(r'hatching-for-dashboard', poultry_views.PoultryHatchingForDashBoardViewSet, + basename="hatching-for-dashboard"), +router.register(r'total_poultry_request_for_city_quantity', poultry_views.TotalPoultryRequestQuantityForCitryViewSet, + basename="total_poultry_request_for_city_quantity"), +router.register(r'Poultry_auction', poultry_views.PoultryRequestAuctionViewSet, basename="Poultry_auction"), +router.register(r'poultry_hatching', poultry_views.PoultryHatchingViewSet, basename="poultry_hatching"), +router.register(r'poultry_hatching_prediction', poultry_views.PoultryHatchingForPredictionViewSet, + basename="poultry_hatching_prediction"), +router.register(r'poultry_hatching_prediction_dashboard', poultry_views.PoultryHatchingForPredictionDashboardViewSet, + basename="poultry_hatching_prediction_dashboard"), +router.register(r'poultry_hatching_prediction_chart', poultry_views.PoultryHatchingForPredictionChartViewSet, + basename="poultry_hatching_prediction_chart"), +router.register(r'poultry_prediction', poultry_views.PoultryPredictionViewSet, basename="poultry_prediction"), +router.register(r'poultry_request_exchange', poultry_views.PoultryRequestExchangeViewSet, + basename="poultry_request_exchange"), +router.register(r'Poultry_Request_exchange_accept', poultry_views.PoultryRequestExchangeAcceptViewSet, + basename="Poultry_Request_exchange_accept"), +router.register(r'process', poultry_views.ProcessViewSet, basename="process"), +router.register(r'hatching_age_range', poultry_views.HatchingStatisticsDashboardViewSet, basename="hatching_age_range"), +router.register(r'doughnut_hatching', poultry_views.DoughnutHatchingStatisticsDashboardViewSet, + basename="doughnut_hatching"), +router.register(r'doughnut_left_hatching', poultry_views.DoughnutHatchingLeftOverStatisticsDashboardViewSet, + basename="doughnut_left_hatching"), +router.register(r'single_hatching_age_range', poultry_views.SingleAgeHatchingStatisticsDashboardViewSet, + basename="single_hatching_age_range"), +router.register(r'total_poultry_request_dashboard', poultry_views.TotalPoultryRequestStatisticsDashboardViewSet, + basename="total_poultry_request_dashboard"), +router.register(r'management_hatching_age_range', poultry_views.ManagementHatchingAgeRangeViewSet, + basename="management_hatching_age_range"), +router.register(r'total_file_poultry_request_dashboard', + poultry_views.TotalFilePoultryRequestStatisticsDashboardViewSet, + basename="total_file_poultry_request_dashboard"), +router.register(r'total_poultry_hatching_dashboard', poultry_views.TotalPoultryHatchingStatisticsDashboardViewSet, + basename="total_poultry_hatching_dashboard"), +router.register(r'poultry_request_killing_process', poultry_views.PoultryRequestProcessDashboardViewSet, + basename="poultry_request_killing_process"), +router.register(r'general-statistics-dashboard-for-cases', poultry_views.GeneralStatisticsdashboardForCasesViewSet, + basename="general-statistics-dashboard-for-cases"), +router.register(r'poultry_tenant_update', poultry_views.UpdatePoultryTenantViewSet, + basename="poultry_request_killing_process"), \ +router.register(r'poultry-loc', poultry_views.PoultryLocationViewSet, + basename="poultry-loc"), +router.register(r'province_kill_request_killing_process', poultry_views.ProvinceKillRequestProcessDashboardViewSet, + basename="province_kill_request_killing_process"), +router.register(r'kill_house__request_vetfarm_killing_process', + poultry_views.KillHouseRequestVetFarmProcessDashboardViewSet, + basename="kill_house__request_vetfarm_killing_process"), + +router.register(r'kill_house__request_vet_killing_process', + poultry_views.KillHouseRequestVetProcessDashboardViewSet, + basename="kill_house__request_vet_killing_process"), +router.register(r'number_of_kills', killhouse_views.KillHouseRequestStatisticsDashboardViewSet, + basename="number_of_kills"), \ +router.register(r'number_of_kills_weight', killhouse_views.KillHouseRequestWeightStatisticsDashboardViewSet, + basename="number_of_kills_weight"), +router.register(r'Poultry_Request_search', poultry_views.PoultryRequestSearchViewSet, + basename="Poultry_Request_search"), +router.register(r'poultry_request_index_weight', poultry_views.PoultryRequestWeightViewSet, + basename="poultry_request_index_weight"), +router.register(r'poultry_assignment_information', poultry_views.PoultryAssignmentInformationViewSet, + basename="poultry_assignment_information") +router.register(r'last_update', poultry_views.LastUpdateViewSet, + basename="last_update") +router.register(r'reporting-all-poultry-requests', report_views.ReportingAllPoultryRequests, + basename='reporting-all-poultry-requests') +router.register(r'detail_general_wage', report_views.DetailsGeneralWageViewSet, + basename='detail_general_wage') +router.register(r'detail_general_killhouse_wage', report_views.DetailsGeneralKillHoseWageViewSet, + basename='detail_general_wage') +router.register(r'new_detail_general_killhouse_wage', report_views.NewDetailsGeneralKillHoseWageViewSet, + basename='new_detail_general_killhouse_wage') +router.register(r'data_report_percentages', report_views.DataReportPercentagesViewSet, + basename='data_report_percentages') + +router.register(r'reporting-all-poultry', report_views.NewReportingAllPoultryRequests, + basename='reporting-all-poultry') +router.register(r'kill_house', killhouse_views.KillHouseViewSet, basename="kill_house"), +router.register(r'pos-kill-houses', killhouse_views.PosKillHouseViewSet, basename="pos-kill-houses"), +router.register(r'kill_house_free_bar_wage_total', killhouse_views.KillHouseFreeBarInformationforWageTotalViewSet, + basename="kill_house_free_bar_wage_total"), +router.register(r'province_wage', killhouse_views.ProvinceKillRequestProvinceWageViewSet, basename="province_wage"), +router.register(r'kill_house_images', killhouse_views.KillHouseAssignmentImagesViewSet, basename="kill_house_images"), +router.register(r'kill_house_ware_house', killhouse_views.KillHouseWareHouseViewSet, basename="kill_house_ware_house"), +router.register(r'kill_house_free_bar', killhouse_views.KillHouseFreeBarInformationViewSet, + basename="kill_house_free_bar"), +router.register(r'parent_company_kill_house_free_bar', killhouse_views.ParentCompanyKillHouseFreeBarInformationViewSet, + basename="parent_company_kill_house_free_bar"), + +router.register(r'kill_house_free_sale_bar', killhouse_views.KillHouseFreeSaleBarInformationViewSet, + basename="kill_house_free_sale_bar"), +router.register(r'pos-kill-house-free-sale-bar', killhouse_views.PosKillHouseFreeSaleBarInformationViewSet, + basename="pos-kill-house-free-sale-bar"), +router.register(r'bar-difference-request', killhouse_views.BarDifferenceRequestViewSet, + basename="bar-difference-request"), +router.register(r'dashboard_kill_house_free_sale_bar', killhouse_views.KillHouseFreeSaleBarInformationDashboardViewSet, + basename="dashboard_kill_house_free_sale_bar"), +router.register(r'kill_house-buyers-dashboard', + killhouse_views.KillHousebuyersDashboarForFreeSaleBarInformationdViewSet, + basename="kill_house-buyers-dashboard"), +router.register(r'dashboard_kill_house_free_bar', killhouse_views.DashboardKillHouseFreeBarInformationViewSet, + basename="dashboard_kill_house_free_bar"), +router.register(r'parent_company_dashboard_kill_house_free_bar', + killhouse_views.ParentCopmanyDashboardKillHouseFreeBarInformationViewSet, + basename="parent_company_dashboard_kill_house_free_bar"), +router.register(r'kill_house_operator', killhouse_views.KillHouseOperatorViewSet, basename="kill_house_operator") +router.register(r'kill_house_wage_dashbord', killhouse_views.KillHouseWageForTotalDashbordViewSet, + basename="kill_house_wage_dashbord") +router.register(r'kill_house_add_car', killhouse_views.KillHouseADDCARViewSet, basename="kill_house_add_car"), +router.register(r'driver', killhouse_views.DriverViewSet, basename="driver"), +# router.register(r'make_kill_request', killhouse_views.make_kill_request, basename="make_kill_request"), +router.register(r'driver_cancel', killhouse_views.DriverRequestCancelViewSet, basename="driver_cancel"), +router.register(r'poultry_requests_for_total_information', killhouse_views.PoultryRequestForTotalInformationViewSet, + basename="poultry_requests_for_total_information"), +router.register(r'poultry_requests_for_total_information_in_table', + killhouse_views.PoultryRequestForTotalInformationInTableViewSet, + basename="poultry_requests_for_total_information_intable"), +router.register(r'province_kill_request', killhouse_views.ProvinceKillRequestViewSet, + basename="province_kill_request"), \ +router.register(r'dahsnoard_province_kill_request', killhouse_views.DahsnoardProvinceKillRequestViewSet, + basename="dahsnoard_province_kill_request"), +router.register(r'reporting_province_kill_request_wage', killhouse_views.ReportingProvinceKillRequestsWageViewSet, + basename="reporting_province_kill_request_wage"), +router.register(r'kill_house_change', killhouse_views.KillHouseRequestChangeStateViewSet, basename="kill_house_change"), +router.register(r'kill_house_Request_exchange', killhouse_views.KillHouseRequestExchangeViewSet, + basename="kill_house_Request_exchange"), +router.register(r'kill_house_Request_exchange_reserve', killhouse_views.KillHouseRequestExchangeReserveViewSet, + basename="kill_house_Request_exchange_reserve"), +router.register(r'kill_house_Request_auction', killhouse_views.KillHouseRequestActionViewSet, + basename="kill_house_Request_auction"), +router.register(r'kill_house_Request_auction_winner', killhouse_views.KillHouseRequestActionWinnerViewSet, + basename="kill_house_Request_auction_winner"), +router.register(r'kill_house_Request_exchange_reserve_add_car', + killhouse_views.KillHouseRequestExchangeAddCarViewSet, + basename="kill_house_Request_exchange_reserve_add_car"), +router.register(r'kill_house_request_bar_management_wage', + killhouse_views.KillHouseRequestForBarManagementWageViewSet, + basename="kill_house_request_bar_management_wage"), \ +router.register(r'dashboard_delete_bar', + killhouse_views.DashboardDeleteBarView, + basename="dashboard_delete_bar"), +router.register(r'kill_house_request_bar_management', killhouse_views.KillHouseRequestForBarManagementViewSet, + basename="kill_house_request_bar_management") + +router.register(r'parent_company_kill_house_request_bar_management', + killhouse_views.ParentCompanyKillHouseRequestForBarManagementViewSet, + basename="parent_company_kill_house_request_bar_management") + +router.register(r'ware-house-accept-kill-house-request', + killhouse_views.KillHouseWareHouseAcceptedKillHouseRequestViewSet, + basename="ware-house-accept-kill-house-request") +router.register(r'dashboard_enter_load_information', + killhouse_views.DashboardEnterLoadInformationView, + basename="dashboard_enter_load_information") +router.register(r'bar-documents-status', killhouse_views.BarDocumentStatusViewset, basename="bar-documents-status") +router.register(r'bars_for_kill_house', killhouse_views.InputBarsForKillHouseViewSet, basename="bars_for_kill_house"), +router.register(r'bars_for_kill_house_dashboard', killhouse_views.InputBarsForKillHouseDashboardViewSet, + basename="bars_for_kill_house_dashboard"), +router.register(r'pricing', province_views.PricingViewSet, basename="pricing") +router.register(r'kill-house-losses', province_views.KillHousePercentageOfLossesViewset, basename="kill-house-losses") +router.register(r'vet_check_province_kill_request', province_views.VetCheckAllocationsViewSet, + basename="vet_check_province_kill_request") +router.register(r'poultry_science', province_views.PoultryScienceViewSet, + basename="poultry_science") +router.register(r'poultry_science_report', province_views.PoultryScienceReportViewSet, + basename="poultry_science_report") +router.register(r'guilds-configs', province_views.GuildsGeneralConfigsViewSet, + basename="guilds-configs") +router.register(r'guilds-for-configs', province_views.GuildsForGeneralConfigsViewSet, + basename="guilds-for-configs") +router.register(r'return-deleted-allocation', province_views.ReturnStewardAllocationViewSet, + basename="return-deleted-allocation") +router.register(r'vet_check_province_kill_request', province_views.VetCheckAllocationsViewSet, + basename="vet_check_province_kill_request") +router.register(r'aggregate-vet-check-province-kill-request', province_views.AggregateVetCheckAllocationsViewSet, + basename="aggregate-vet-check-province-kill-request") +router.register(r'province_percent', province_views.ProvincePercentLeftOverViewSet, basename="province_percent") +router.register(r'product', province_views.ProductViewSet, basename="product") +router.register(r'roles-products', province_views.RolesProductsViewset, basename="roles-products") +router.register(r'pos-roles-products', province_views.PosRolesProductsViewset, basename="pos-roles-products") +router.register(r'pos-other-products', province_views.PosPosOtherProductsViewset, basename="pos-other-products") +router.register(r'pos-combine-products', province_views.CombinedPosProductsViewSet, basename="pos-combine-products") +router.register(r'pos/new-pos-combine-products', province_views.NewCombinedPosProductsViewSet, basename="new-pos-combine-products") +router.register(r'pos-machine-transactions', province_views.GuildsForPosMachineTransactionsViewSet, + basename="pos-machine-transactions") +router.register(r'details-pos-machine-transactions', province_views.DetailsOfGuildsForPosMachineTransactionsViewSet, + basename="pos-machine-transactions") +router.register(r'dashboard-pos-machine-transactions', province_views.DashboardOfGuildsForPosMachineTransactionsViewSet, + basename="pos-machine-transactions") +router.register(r'cooperative-warehouse', province_views.CooperativeWarehouseDashboardViewSet, + basename="cooperative-warehouse") +router.register(r'cooperative-warehouse-dashboard', province_views.DashboardForCooperativeWarehouseViewSet, + basename="cooperative-warehouse-dashboard") +router.register(r'price-confirmation', province_views.PriceConfirmationViewset, + basename="price-confirmation") +router.register(r'beneficiary-accounts', province_views.CompanyBeneficiaryAccountViewset, + basename="beneficiary-accounts") +router.register(r'pos-machine-transactions-inspection', province_views.PosMachineTransactionsForInsPectionViewSet, + basename="pos-machine-transactions-inspection") +router.register(r'guild-ware-house-product', province_views.GuildsWareHouseProductViewSet, + basename="guild-ware-house-product") +router.register(r'guild-ware-house-total-product', province_views.GuildsWareHouseTotalProductViewSet, + basename="guild-ware-house-total-product") +router.register(r'cold-house', province_views.ColdHouseViewSet, + basename="cold-house") +router.register(r'total-cold-house-dashboard-roles', province_views.TotalColdHouseDashboardForRolesViewSet, + basename="total-cold-house-dashboard-roles") +router.register(r'cold-house-for-province', province_views.ColdHouseForProvinceViewSet, + basename="cold-house-for-province") + +router.register(r'cold-house-dashboard', province_views.ColdHouseDashboardViewSet, + basename="cold-house-dashboard") +router.register(r'cold-house-total-dashboard', province_views.ColdHouseTotalDashboardViewSet, + basename="cold-house-total-dashboard") +router.register(r'final-approval-out-province-poultry-request', province_views.FinalApprovalOutProvinceViewSet, + basename="final-approval-out-province-poultry-request") +router.register(r'cold-house-allocations', province_views.ColdHouseAllocationsViewSet, + basename="cold-house-allocations") + +router.register(r'check-cold-house-allocations', province_views.CheckColdHouseAllocationsViewSet, + basename="check-cold-house-allocations") +router.register(r'share-type', province_views.ShareTypeViewset, + basename="share-type") +router.register(r'wage-type', province_views.WageTypeViewset, + basename="wage-type") +router.register(r'poultry-out-province-wage-type', province_views.PoultryOutProvinceWageTypeViewset, + basename="poultry-out-province-wage-type") +router.register(r'wage-type-percentage', province_views.PercentageOfWageTypeViewset, + basename="wage-type-percentage") +router.register(r'sub-sector-wage-type-percentage', province_views.SubSectorPercentageOfWageTypeViewset, + basename="sub-sector-wage-type-percentage") +router.register(r'allow_direct_buying', province_views.ProvinceAllowKillHouseDirectBuyingViewset, + basename="allow_direct_buying") +router.register(r'poultry-export', province_views.PoultryExportViewset, + basename="poultry-export") +router.register(r'poultry-out-province-request', province_views.PoultryOutProvinceRequestViewset, + basename="poultry-out-province-request") +router.register(r'allow_direct_buying_total', province_views.ProvinceAllowKillHouseDirectBuyingTotalViewset, + basename="allow_direct_buying_total") + +router.register(r'allow_register_guilds', province_views.ProvinceAllowKillHouseRegisterGuildsViewset, + basename="allow_direct_buying") +router.register(r'pos-version', province_views.PosVersionViewSet, + basename="pos-version") +router.register(r'pos-error', province_views.POSIdViewSet, + basename="pos-error") +router.register(r'additional-products', province_views.AdditionalProductsViewSet, + basename="additional-products") +router.register(r'server-main-products', province_views.ServerMainProductsViewSet, + basename="server-main-products") +router.register(r'pos-item', province_views.PosItemViewSet, + basename="pos-item") +router.register(r'allow_register_guilds_total', province_views.ProvinceAllowKillHouseRegisterGuildsTotalViewset, + basename="allow_direct_buying_total") +router.register(r'wage_payment', province_views.WagePaymentViewset, basename="wage_payment") +router.register(r'wage-payment-total', province_views.WagePaymentTotalViewset, basename="wage-payment-total") +router.register(r'wage-payment-with-link', province_views.WagePaymentWithLinkViewset, basename="wage-payment-with-link") +router.register(r'wage_payment_based_on_weight', province_views.WagePaymentBasedOnWeightViewset, + basename="wage_payment_based_on_weight") +router.register(r'wage_payment_final_step', province_views.WagePaymentFinalStepViewset, + basename="wage_payment_final_step") +router.register(r'wage_payment_final_step_zarin_pal', province_views.WagePaymentFinalStepZarinPalViewset, + basename="wage_payment_final_step_zarin_pal") +router.register(r'wage_payment_with_link_final_step', province_views.WagePaymentWithLinkFinalStepViewset, + basename="wage_payment_with_link_final_step") +router.register(r'poultry_allow_city_province', province_views.PoultryAllowCityProvinceViewset, + basename="poultry_allow_city_province") +router.register(r'commerce', province_views.CommerceViewSet, + basename="commerce") +router.register(r'improving_livestock', province_views.ImprovingLivestockViewSet, + basename="improving_livestock") +router.register(r'observatory', province_views.ObservatoryViewSet, + basename="observatory") +router.register(r'check_direct_buying', province_views.ProvinceCheckDirectBuyingViewSet, + basename="check_direct_buying") +router.register(r'automatic-direct-buying-permission', province_views.AutomaticDirectBuyingPermissionViewSet, + basename="automatic-direct-buying-permission") +router.register(r'losses_permission', province_views.HatchingLossesPermissionViewSet, + basename="losses_permission") +router.register(r'city_commerce', province_views.CityCommerceViewSet, + basename="city_commerce") + +router.register(r'payment-gateway-percentage', province_views.PaymentGatewayPercentageViewset, + basename="payment-gateway-percentage") + +router.register(r'total-payment-gateway-percentage', province_views.TotalPaymentGatewayPercentageViewset, + basename="total-payment-gateway-percentage") + +router.register(r'province_supervisor', province_views.ProvinceSupervisorViewSet, + basename="province_supervisor") +router.register(r'city_supervisor', province_views.CitySupervisorViewSet, + basename="city_supervisor") +router.register(r'super-admin', province_views.SuperAdminViewSet, + basename="super-admin") +router.register(r'admin-x', province_views.AdminXViewSet, + basename="admin-x") +router.register(r'supporter', province_views.SupporterViewSet, + basename="supporter") +router.register(r'parent-company', province_views.ParentCompanyViewSet, + basename="parent-company") +router.register(r'city-guild', province_views.CityGuildViewSet, + basename="city-guild") +router.register(r'city-guild-wage-dashboard', province_views.CityGuildWageDashboardViewSet, + basename="city-guild-wage-dashboard") +router.register(r'city-guild-for-sub-sector', province_views.CityGuildForSubSectorViewSet, + basename="city-guild-for-sub-sector") +router.register(r'city-guild-for-sub-sector-transactions', province_views.CityGuildForSubSectorTransactionsViewSet, + basename="city-guild-for-sub-sector-transactions") +router.register(r'jahad_inspector', province_views.JahadInspectorViewSet, + basename="jahad_inspector") + +router.register(r'kill_request', killhouse_views.KillRequestViewSet, basename="kill_request") +router.register(r'dashboard_kill_request', killhouse_views.DashboardKillRequestViewSet, + basename="dashboard_kill_request") +router.register(r'delete-debtors-kill-requests', killhouse_views.DeleteDebtorsKillRequestsViewSet, + basename="delete-debtors-kill-requests") +router.register(r'kill_house_total_wage', killhouse_views.KillHouseForProvinceWageViewSet, + basename="kill_house_total_wage") +router.register(r'kill_house_total_transactions_wage', killhouse_views.KillHouseForTotalProvinceWageTransactionViewSet, + basename="kill_house_total_transactions_wage") +router.register(r'kill_house_free_bar_total_wage', killhouse_views.KillHouseForFreeBarWageViewSet, + basename="kill_house_free_bar_total_wage") +router.register(r'kill_house_for_free_sale_bar', killhouse_views.KillHouseForFreeSaleBarInformationViewSet, + basename="kill_house_for_free_sale_bar") +router.register(r'kill_house_creditors', killhouse_views.KillHouseCreditorsViewSet, basename="kill_house_creditors") +router.register(r'automatic_kill_request', killhouse_views.AutomaticKillRequestViewSet, + basename="automatic_kill_request") +router.register(r'kill_house_request', killhouse_views.KillHouseRequestViewSet, basename="kill_house_request") +router.register(r'kill_house_requests', killhouse_views.UpdateKillHouseRequestViewSet, basename="kill_house_requests") +router.register(r'kill_house_request_pricing', killhouse_views.KillHouseRequestPricingViewSet, basename="kill_house_request_pricing") +router.register(r'kill_house_request_complete_information', + killhouse_views.KillHouseRequestForCompleteInformationViewSet, + basename="kill_house_request_complete_information") +router.register(r'kill_house_request_aggregate_load', killhouse_views.KillHouseRequestForAggregateLoadsViewSet, + basename="kill_house_request_aggregate_load") +router.register(r'kill_house_wage_dashbord_in_weight', killhouse_views.KillHouseWageDashbordInWeightViewSet, + basename="kill_house_wage_dashbord_in_weight") +router.register(r'vet', killhouse_views.VetViewSet, basename="vet") +router.register(r'kill_house_vet', killhouse_views.KillHouseVetViewSet, basename="kill_house_vet") +router.register(r'kill_house_complaint', killhouse_views.KillHouseComplaintViewSet, basename="kill_house_complaint") +router.register(r'check_complaint', killhouse_views.CheckKillHouseComplaintViewSet, basename="check_complaint") +router.register(r'vet_check', killhouse_views.VetCheckRequestViewSet, basename="vet_check") +router.register(r'kill_house_check_request', killhouse_views.KillHouseCheckRequestViewSet, + basename="kill_house_check_request") +router.register(r'slaughter-house-transaction', killhouse_views.SlaughterHouseTransactionViewSet, + basename="slaughter-house-transaction") +router.register(r'kill_house_assignment_information', killhouse_views.KillHouseAssignmentInformationViewSet, + basename="kill_house_assignment_information") +router.register(r'kill_house_assignment_information_for_completed_loads', + killhouse_views.KillHouseAssignmentInformationForcompletedloadsViewSet, + basename="kill_house_assignment_information_for_completed_loads") +router.register(r'kill_house_assignment_information_aggregate_load', + killhouse_views.KillHouseAssignmentInformationForAggregateLoadViewSet, + basename="kill_house_assignment_information_aggregate_load") +router.register(r'kill_house_driver', killhouse_views.KillHouseDriverViewSet, + basename="kill_house_driver") +router.register(r'kill_house_driver_total_dashboard', killhouse_views.KillHouseDriverTotalDashboardViewSet, + basename="kill_house_driver_total_dashboard") +router.register(r'total-wage-exclusive-killer-information', killhouse_views.TotalWageInformationExclusiveKillerViewset, + basename="total-wage-exclusive-killer-information") +router.register(r'kill_request_for_poultry', killhouse_views.KillRequestForPoultryViewSet, + basename="kill_request_for_poultry") +router.register(r'kill_house_percent', killhouse_views.KillHousePercentageViewSet, + basename="kill_house_percent") +router.register(r'kill_request_factor', killhouse_views.KillRequestFactorViewSet, + basename="kill_request_factor") +router.register(r'kill_request_factor_payment', killhouse_views.KillRequestFactorPaymentViewSet, + basename="kill_request_factor_payment") +router.register(r'province_factor_to_kill_house', province_views.ProvinceFactorToKillHouseViewSet, + basename="province_factor_to_kill_house") +router.register(r'area-activity', province_views.AreaActivityViewSet, + basename="area-activity") +router.register(r'type-activity', province_views.TypeActivityViewSet, + basename="type-activity") +router.register(r'guilds', province_views.GuildsViewSet, + basename="guilds") + +router.register(r'real-guilds', province_views.RealGuildsViewSet, + basename="real-guilds") + +router.register(r'guild', province_views.RegisterGuildsViewSet, + basename="guild") +router.register(r'stewards-for-cold-house', province_views.StewardForColdHouseViewSet, + basename="stewards-for-cold-house") +router.register(r'steward-cold-houses', province_views.StewardColdHousesViewSet, + basename="steward-cold-houses") +router.register(r'pos-transaction', province_views.PosMachineTransactionViewSet, + basename="pos-transaction") +router.register(r'pos-ntransaction', province_views.NewPosMachineTransactionViewSet, + basename="pos-ntransaction") +router.register(r'live-stock-transactions', province_views.LiveStockTransactionViewSet, + basename="live-stock-transactions") +router.register(r'live-stock-transactions-dashboard', province_views.LiveStockTransactionDashboeardViewSet, + basename="live-stock-transactions-dashboard") +router.register(r'pos-allocation-transaction', province_views.PosAllocationTransactionsViewSet, + basename="pos-allocation-transaction") +router.register(r'broadcast-price', province_views.BroadcastPriceViewset, + basename="broadcast-price") +router.register(r'free-sale-limitation', province_views.OutProvinceSaleLimitationViewset, + basename="free-sale-limitation") +router.register(r'pos-broadcast-price', province_views.PosBroadcastPriceViewset, + basename="pos-broadcast-price") +router.register(r'new-pos-broadcast-price', province_views.NewPosBroadcastPriceViewset, + basename="new-pos-broadcast-price") +router.register(r'pos-guilds', province_views.PosGuildsViewSet, + basename="pos-guilds") +router.register(r'total-guilds-for-pos', province_views.TotalGuildsForPosViewSet, + basename="total-guilds-for-pos") + +router.register(r'cars', province_views.CarViewSet, + basename="cars") +router.register(r'check_guilds', province_views.ProvinceCheckKillHouseGuildsViewSet, + basename="check_guilds") +router.register(r'total_guilds', province_views.TotalGuildsViewSet, + basename="total_guilds") +router.register(r'total-guilds-distribution-management', province_views.TotalGuildsDistributionManagementViewSet, + basename="total-guilds-distribution-management") +router.register(r'test_total_guilds', province_views.TestTotalGuildsViewSet, + basename="test_total_guilds") +router.register(r'products-pricing-type', province_views.ProductPricingTypeViewset, + basename="products-pricing-type") +router.register(r'allow_register_code_for_guilds', province_views.AllowRegisterCodeForGuildsViewSet, + basename="allow_register_code_for_guilds") +router.register(r'steward-app-login', province_views.StewardAppLoginViewSet, + basename="steward-app-login") +router.register(r'total_guilds_for_companies', province_views.TotalGuildsForCompaniesViewSet, + basename="total_guilds_for_companies") +router.register(r'report-pos-device_session', province_views.ReportPosDeviceSessionViewSet, + basename="report-pos-device_session") +router.register(r'total_guilds_for_inspection', province_views.TotalGuildsForInspectionViewSet, + basename="total_guilds_for_inspection") +router.register(r'pos-for-inspection', province_views.POSMachineForInspectionViewSet, + basename="pos-for-inspection") +router.register(r'steward', province_views.StewardViewSet, + basename="steward") + +router.register(r'kill-house-price-permission', province_views.KillHousePricePermissionViewset, + basename="kill-house-price-permission") +router.register(r'pos-company', province_views.PosCompanyViewSet, + basename="pos-company") + +router.register(r'pos-machine', province_views.POSMachineViewSet, + basename="pos-machine") +router.register(r'new-pos-machine', province_views.FinalPOSMachineViewSet, + basename="new-pos-machine") +router.register(r'user-pos-machine', province_views.UserPOSMachineViewSet, + basename="user-pos-machine") + +router.register(r'cooperative-pos', province_views.POSMachineForLiveStackViewSet, + basename="cooperative-pos") + +router.register(r'pos_register_session', province_views.POSDeviceSessionViewSet, + basename="pos_register_session") +router.register(r'pos_register_session_inspection', province_views.POSDeviceSessionForInspectionViewSet, + basename="pos_register_session_inspection") + +router.register(r'pos_device_version', province_views.PosDeviceVersionViewSet, + basename="pos_device_version") +router.register(r'server-pos-machine', province_views.POSMachineForServerViewSet, + basename="server-pos-machine") +router.register(r'union-subsector-wage-dashboard', province_views.TotalCitySubSectorWageDashboardViewSet, + basename="union-subsector-wage-dashboard") +router.register(r'union-subsector-transaction-dashboard', province_views.TotalCitySubSectortransactionDashboardViewSet, + basename="union-subsector-transaction-dashboard") +router.register(r'sub-sector-transactions', province_views.SubSectorTransactionsViewSet, + basename="sub-sector-transactions") +router.register(r'pos-transactions', province_views.POSTransactionsViewSet, + basename="pos-transactions") +router.register(r'internal-transactions', province_views.InternalTransactionViewset, + basename="internal-transactions") +router.register(r'poultry-requests-transactions', province_views.PoultryRequestInternalTransactionViewset, + basename="poultry-requests-transactions") + +router.register(r'total-dashboard-poultry-requests-transactions', + province_views.TotalDashboardPoultryRequestInternalTransactionViewset, + basename="total-dashboard-poultry-requests-transactions") + +router.register(r'total-internal-transactions', province_views.TotalInternalTransactionViewset, + basename="total-internal-transactions") +router.register(r'parent-company-total-internal-transactions', + province_views.ParentCompanyTotalInternalTransactionViewset, + basename="parent-company-total-internal-transactions") +router.register(r'payer-internal-transactions', province_views.PayersInternalTransactionViewset, + basename="payer-internal-transactions") +router.register(r'steward_warehouse', province_views.StewardWareHouseViewSet, + basename="steward_warehouse") +router.register(r'steward_free_bar', province_views.StewardFreeBarInformationViewSet, + basename="steward_free_bar") +router.register(r'steward_free_bar_dashboard', province_views.StewardFreeBarInformationDashboardViewSet, + basename="steward_free_bar_dashboard") +router.register(r'pos-steward-free-bar', province_views.PosStewardFreeBarInformationViewSet, + basename="pos-steward-free-bar") +router.register(r'pos-segmentation', province_views.PosSegmentationViewSet, + basename="pos-segmentation") +router.register(r'new-pos-segmentation', province_views.NewPosSegmentationViewSet, + basename="new-pos-segmentation") +router.register(r'app-segmentation', province_views.AppSegmentationViewSet, + basename="app-segmentation") + +router.register(r'steward_free_sale_bar', province_views.StewardFreeSaleBarInformationViewSet, + basename="steward_free_sale_bar") +router.register(r'allow_register_code_for_steward_free_sale_bar_information', province_views.AllowRegisterCodeForStewardFreeSaleBarInformationViewSet, + basename="allow_register_code_for_steward_free_sale_bar_information") +router.register(r'allow_register_code_for_kill_house_free_sale_bar_information', province_views.AllowRegisterCodeForKillHouseFreeSaleBarInformationViewSet, + basename="allow_register_code_for_kill_house_free_sale_bar_information") +router.register(r'limitation_for_direct_purchase_and_bar_information', province_views.LimitationForDirectPurchaseAndBarInformationViewSet, + basename="limitation_for_direct_purchase_and_bar_information") +router.register(r'steward_free_sale_bar_dashboard', province_views.StewardFreeSaleBarInformationDashboardViewSet, + basename="steward_free_sale_bar_dashboard") +router.register(r'ware-house-archive', province_views.WarehouseArchiveViewSet, + basename="ware-house-archive") +router.register(r'guilds_warehouse', province_views.GuildsWareHouseViewSet, + basename="guilds_warehouse") + +router.register(r'steward-allocation', province_views.StewardAllocationViewSet, + basename="steward-allocation") +router.register(r'in-province-allocation-dashboard', province_views.InProvinceAllocationDashboardViewSet, + basename="in-province-allocation-dashboard") +router.register(r'in-province-allocation', province_views.InProvinceAllocationViewSet, + basename="in-province-allocation") +router.register(r'total-steward-dashboard', province_views.TotalStewardDashboardViewSet, + basename="total-steward-dashboard") +router.register(r'total-steward-dashboard-detail', province_views.TotalStewardDashboarDetailViewSet, + basename="total-steward-dashboard-detail") +router.register(r'batch-steward-allocation', province_views.BatchStewardAllocationViewSet, + basename="batch-steward-allocation") +router.register(r'upload-image-limit', province_views.UploadImageLimitationViewset, + basename="upload-image-limit") +router.register(r'apk-info', province_views.ApkInfoViewset, + basename="apk-info") +router.register(r'direct-buying-verification', province_views.DirectBuyingVerificationViewset, + basename="direct-buying-verification") +router.register(r'fine-permission', province_views.FinePermissionViewset, + basename="fine-permission") +router.register(r'show-market-requests', province_views.ShowMarketRequestViewset, + basename="show-market-requests") +router.register(r'market-daily-limitation', province_views.MarketDailyLimitationViewset, + basename="market-daily-limitation") +router.register(r'hatching-archive-percent', province_views.HatchingArchivePercentViewset, + basename="hatching-archive-percent") +router.register(r'index-weight-category', province_views.IndexWeightCategoryViewSet, + basename="index-weight-category") +router.register(r'drop-limit', province_views.PercentageDropLimitationViewset, + basename="drop-limit") +router.register(r'pos-allocations', province_views.PosStewardAllocationViewSet, + basename="pos-allocations") +router.register(r'new-pos-allocations', province_views.NewPosStewardAllocationViewSet, + basename="new-pos-allocations") +router.register(r'steward-guild-allocation', province_views.StewardGuildAllocationViewSet, + basename="steward-guild-allocation") + +router.register(r'automatic-steward-allocation', province_views.AutomaticStewardAllocationViewSet, + basename="automatic-steward-allocation") +router.register(r'first-automatic-steward-allocation', province_views.FirstAutomaticStewardAllocationViewSet, + basename="first-automatic-steward-allocation") + +router.register(r'kill_house_choose_steward_guilds', province_views.ProvinceAllowKillHouseChooseStewardGuildsViewset, + basename="kill_house_choose_steward_guilds") +router.register(r'province_check_kill_request', province_views.ProvinceCheckKillRequestViewSet, + basename="province_check_kill_request") +router.register(r'province_check_out_factors', province_views.ProvinceImportKillHouseOutFactorsViewSet, + basename="province_check_out_factors") +router.register(r'jahad', province_views.JahadViewSet, + basename="jahad") + +router.register(r'city_jahad', province_views.CityJahadViewSet, + basename="city_jahad") + +router.register(r'protein_guild', province_views.ProteinGuildViewSet, + basename="protein_guild") + +router.register(r'city-poultry', province_views.CityPoultryViewSet, + basename="city-poultry") + +router.register(r'dispenser', province_views.DispenserViewSet, + basename="dispenser") +router.register(r'dispenser-info', province_views.DispenserInformationViewSet, + basename="dispenser-info") +router.register(r'representative', province_views.RepresentativeViewSet, + basename="representative") +router.register(r'dispenser-dashboard', province_views.DispenserDashboardViewSet, + basename="dispenser-dashboard") +router.register(r'dispenser-allocations-dashboard', province_views.DispenserAllocationDashboardViewSet, + basename="dispenser-allocations-dashboard") +router.register(r'dispenser-allocations', province_views.DispenserAllocationViewSet, + basename="dispenser-allocations") +router.register(r'live_stock_support', province_views.LiveStockSupportViewSet, + basename="live_stock_support") +router.register(r'guild_room', province_views.GuildRoomViewSet, + basename="guild_room") +router.register(r'city_vet', province_views.CityVetViewSet, + basename="city_vet") +router.register(r'government', province_views.ProvincialGovernmentViewSet, + basename="government") +router.register(r'province_allow_kill_house_register_car', province_views.ProvinceAllowKillHouseRegisterCarViewset, + basename="province_allow_kill_house_register_car") +router.register(r'province_allow_poultry_choose_kill_house', province_views.ProvinceAllowPoultryChooseKillHouseViewset, + basename="province_allow_poultry_choose_kill_house") +router.register(r'province_allow_poultry_choose_kill_house_total', + province_views.ProvinceAllowPoultryChooseKillHouseTotalViewset, + basename="province_allow_poultry_choose_kill_house_total") + +router.register(r'province_allow_poultry_sell_free', province_views.ProvinceAllowPoultrySellFreeViewset, + basename="province_allow_poultry_sell_free") +router.register(r'province_allow_poultry_sell_free_total', province_views.ProvinceAllowPoultrySellFreeTotalViewset, + basename="province_allow_poultry_sell_free_total") + +router.register(r'province_operator', province_views.ProvinceOperatorViewSet, + basename="province_operator") + +router.register(r'total-wage-information', province_views.TotalWageInformationViewset, + basename="total-wage-information") + +router.register(r'parent-company-total-wage-information', province_views.ParentCompanyTotalWageInformationViewset, + basename="parent-company-total-wage-information") + +router.register(r'province_check_operator_request', province_views.ProvinceCheckOperatorRequestViewSet, + basename="province_check_operator_request") +router.register(r'province_check_operator_out_request', province_views.ProvinceCheckOperatorOutRequestViewSet, + basename="province_check_operator_out_request") +router.register(r'province_request_auction', province_views.ProvinceRequestActionViewSet, + basename="province_request_auction") +router.register(r'price_analysis', province_views.PriceAnalysisViewSet, + basename="price_analysis") +router.register(r'share', province_views.ShareOfAllocationViewSet, + basename="share") +router.register(r'province_check_info', province_views.ProvinceCheckInformationViewSet, + basename="province_check_info") +router.register(r'supervisor', province_views.VetSupervisorViewSet, + basename="supervisor") +router.register(r'province_factor_kill_house', province_views.ProvinceFactorToKillHouseViewSet, + basename="province_factor_kill_house") +router.register(r'province_factor_kill_house_for_poultry', province_views.ProvinceFactorToKillHouseForPoultryViewSet, + basename="province_factor_kill_house") +router.register(r'kill_house_list', province_views.KillHouseListForProvince, basename='kill_house_list') +router.register(r'activate_cars', province_views.ManageCarsByProvince, basename='activate_cars') +router.register(r'ware_house_factor', province_views.WareHouseFactorViewSet, + basename="ware_house_factor") +router.register(r'inspector_operator', province_views.InspectorOperatorViewSet, + basename="inspector_operator") +router.register(r'restriction_carcass_distribution', province_views.RestrictionCarcassDistributionViewSet, + basename="restriction_carcass_distribution") +router.register(r'inspector', province_views.PovinceInspectorViewSet, + basename="inspector") +router.register(r'sms_license', province_views.SmsLicenseViewset, + basename="sms_license") +router.register(r'province_check_requests_price', province_views.ProvinceCheckRequestsPriceViewSet, + basename="province_check_requests_price") +router.register(r'kill_house_factor_poultry', province_views.KillHouseFactorToPoultryViewSet, + basename="kill_house_factor_poultry") +router.register(r'kill_house_factor_province', province_views.KillHouseFactorToProvinceViewSet, + basename="kill_house_factor_province") +router.register(r'province_check_factor', province_views.ProvinceCheckKillHouseFactorViewSet, + basename="province_check_factor") + +router.register(r'chicken-age-range', province_views.ChickenAgeRangeViewset, + basename="chicken-age-range") + +router.register(r'time-range', province_views.TimeRangeViewset, + basename="time-range") + +router.register(r'evacuation_permit', province_views.EvacuationPermitViewSet, + basename="evacuation_permit") +router.register(r'sell-for-freezing', province_views.SellForFreezingViewSet, + basename="sell-for-freezing") +router.register(r'deposit_allocation', province_views.DepositAllocationViewSet, + basename="deposit_allocation") +router.register(r'deadline', province_views.PaymentDeadLineViewSet, + basename="deadline") +router.register(r'monthly_percent', province_views.MonthlyProfitPercentageViewSet, + basename="monthly_percent") + +router.register(r'rejected_requests', province_views.RejectedRequestsViewSet, + basename="rejected_requests") + +router.register(r'last-time-enter', main_views.OperatorLastTimeEnterViewSet, + basename="last-time-enter") + +router.register(r'reporting-role-limitation', main_views.ReportingFieldLimitationViewSet, + basename="reporting-role-limitation") + +router.register(r'wallet', province_views.WalletViewset, basename='wallet') +router.register(r'zarinpal-accounts', province_views.ZarinPalAccountsViewset, basename='zarinpal-accounts') +router.register(r'aggregate-permission', province_views.VetFarmAggregatePermissionViewset, + basename='aggregate-permission') +router.register(r'bar-limitation', province_views.KillHouseBarLimitationViewset, basename='bar-limitation') +router.register(r'out-province-carcasses-permission', province_views.OutOfProvinceSellingCarcassesPermissionViewset, + basename='out-province-carcasses-permission') +router.register(r'kill-house-distribution-management', + province_views.KillHouseDistributionManagementStewardGuildViewset, + basename='kill-house-distribution-management') +router.register(r'steward-distribution-management', province_views.StewardDistributionManagementGuildViewset, + basename='steward-distribution-management') +router.register(r'operation-limitation', province_views.OperationLimitationViewset, basename='operation-limitation') +router.register(r'approved-price', province_views.ApprovedPriceViewset, basename='approved-price') +router.register(r'announcements', province_views.AnnouncementsViewset, basename='announcements') +router.register(r'itransaction', province_views.ItransactionViewset, basename='itransaction') +router.register(r'debt', province_views.DebttViewset, basename='debt') +router.register(r'financial_transaction', province_views.FinancialTransactionViewset, basename='financial_transaction') +router.register(r'penalty', province_views.PenaltyViewset, basename='penalty') +router.register(r'deposit', province_views.DepositViewset, basename='deposit') +# router.register(r'iwallet', province_views.IwallletViewset, basename='iwallet') +router.register(r'financialdocument', province_views.FinancialDocumentViewset, basename='financialdocument') +router.register(r'searchwallet', province_views.ReportingAllwalletRequestsViewset, basename='searchwallet') +router.register(r'chikeninfotmation', poultry_views.Chicken_informationViewSet, basename='chikeninfotmation') +router.register(r'poultryinformation', poultry_views.PoultryRequestInformation, basename='poultryinformation') +router.register(r'chart', poultry_views.Chart_DashbourdViewSet, basename='chart') +router.register(r'typecheck', province_views.TypeCheckViewset, basename='typecheck') +router.register(r'automatic_allocation', province_views.ProvinceAutoAllocationViewset, + basename='automatic_allocation') +router.register(r'dashboard_detail_general_killhouse_wage', report_views.DashboardDetailsGeneralKillHoseWageViewSet, + basename='dashboard_detail_general_killhouse_wage') +router.register(r'forcast_hatching', report_views.ForcastViewSet, basename='forcast_hatching') +router.register(r'case_status', report_views.CasestatusViewSet, basename='case_status') +router.register(r'general_case_status', report_views.GeneralCasestatusViewSet, basename='general_case_status') +router.register(r'poultry_report', report_views.PoultryReporttViewSet, basename='poultry_report') +router.register(r'letter_report', report_views.PoultryRequestletterReportViewSet, basename='letter_report') +router.register(r'hatching_query', report_views.HatchingQueryViewSet, basename='letter_report') +router.register(r'buyer_remittance', report_views.BuyerRemittance, basename='buyer_remittance') +router.register(r'iran_province', report_views.IranProvinceViewSet, basename='iran_province') +router.register(r'age-notification-poultry', report_views.AgeNotificationPoultryViewSet, + basename='age-notification-poultry') +router.register(r'cookie-samasat', report_views.CookieSamasatViewSet, + basename='cookie-samasat') +router.register(r'iran_city', report_views.IranCityViewSet, basename='iran_city') +router.register(r'hour_limit', province_views.HourLimitViewset, + basename="hour_limit") +router.register(r'system-wallet', province_views.SystemWalletViewset, + basename="system-wallet") +router.register(r'get_one_pos_version', province_views.GetOnePosVersionViewSet, + basename="get_one_pos_version") + +router.register(r'commonly-used', province_views.CommonlyUsedViewSet, + basename="commonly-used") + +router.register(r'free_sale_within_province', province_views.FreeSaleWithinprovinceViewset, + basename="free_sale_within_province") +router.register(r'kill_house_hour_limit', province_views.KillHouseHourLimitViewset, + basename="kill_house_hour_limit") +router.register(r'auto_accept_province_kill_requests', province_views.AutoAcceptProvinceKillRequestViewset, + basename="auto_accept_province_kill_requests") +router.register(r'sms_recipient', province_views.SmsRecipientViewSet, + basename="sms_recipient") + +router.register(r'auto_make_kill_house_requests', province_views.AutoMakeKillHouseRequestViewset, + basename="auto_make_kill_house_requests") + +router.register(r'steward_ware_house_total_report_daily_broad_cast', + province_views.TotalReportOfStewardWareHouseForDailyBroadCastViewSet, + basename='steward_ware_house_total_report_daily_broad_cast') +router.register(r'steward_ware_house_total_report_daily_broad_cast_in_detail', + province_views.TotalReportOfStewardWareHouseForDailyBroadCastInDetailsViewSet, + basename='steward_ware_house_total_report_daily_broad_cast_in_detail') + +router.register(r'report-submission', province_views.ReportSubmissionTimeViewset, basename='report-submission') +router.register(r'out-province-carcasses-buyer', province_views.OutProvinceCarcassesBuyerViewSet, + basename='out-province-carcasses-buyer') +router.register(r'pos-out-province-carcasses-buyer', province_views.PosOutProvinceCarcassesBuyerViewSet, + basename='pos-out-province-carcasses-buyer') +router.register(r'base-out-province-carcasses-buyer', province_views.BaseOutProvinceCarcassesBuyerViewSet, + basename='base-out-province-carcasses-buyer') + +router.register(r'reports', province_views.ReportsViewset, basename='reports') +router.register(r'reports-users', province_views.ReportsUsersViewset, basename='reports-users') +router.register(r'user-reports', province_views.UserReportsViewset, basename='user-reports') +router.register(r'moving-text-dashboard', province_views.MovingTextDashboardStatusViewset, + basename='moving-text-dashboard') +router.register(r'moving-text', province_views.MovingTextViewset, basename='moving-text') +router.register(r'moving-text-with-role', province_views.MovingTextWithRoleViewset, basename='moving-text-with-role') + +router.register(r'bar_report', killhouse_views.KillHouseBarReportingViewSet, basename='bar_report') +router.register(r'kill-house-request-total-wage', killhouse_views.KillHouseForKillHouseRequestWageViewSet, + basename='kill-house-request-total-wage') +router.register(r'kill-house-new-wage', killhouse_views.KillHouseForNewWageInormationViewSet, + basename='kill-house-new-wage') +router.register(r'kill-house-cold-house', killhouse_views.KillHouseForColdHouseViewSet, + basename='kill-house-cold-house') +router.register(r'kill-house-cold-houses', killhouse_views.KillHouseColdHousesViewSet, + basename='kill-house-cold-houses') +router.register(r'parent-company-kill-house-new-wage', + killhouse_views.ParentCompanyKillHouseForNewWageInormationViewSet, + basename='parent-company-kill-house-new-wage') +router.register(r'kill-house-distribution-info', killhouse_views.KillHouseDistributionInormationViewSet, + basename='kill-house-distribution-info') +router.register(r'kill-house-dashboard-new-wage', killhouse_views.KillHouseTotalDashboardForNewWageInormationViewSet, + basename='kill-house-dashboard-new-wage') +router.register(r'wallet-wage-payment', killhouse_views.WalletWagePaymentViewSet, basename='wallet-wage-payment') +router.register(r'general_poultry_request_letter_report', killhouse_views.GeneralPoultryRequestLetterReportViewSet, + basename='general_poultry_request_letter_report') +router.register(r'killing_info_discrepancy_report', killhouse_views.KillingInformationDiscrepancyReportViewSet, + basename='killing_info_discrepancy_report') +router.register(r'total_report_daily_broad_cast', killhouse_views.TotalReportForDailyBroadCastViewSet, + basename='total_report_daily_broad_cast') + +router.register(r'kill_house_test', killhouse_views.KillHouseFortestViewSet, + basename='kill_house_test') + +router.register(r'kill_house_ware_house_total_report_daily_broad_cast', + killhouse_views.TotalReportOfKillHouseWareHouseForDailyBroadCastViewSet, + basename='kill_house_ware_house_total_report_daily_broad_cast') +router.register(r'kill_house_ware_house_total_report_daily_broad_cast_in_detail', + killhouse_views.TotalReportOfKillHouseWareHouseForDailyBroadCastInDetailsViewSet, + basename='kill_house_ware_house_total_report_daily_broad_cast_in_detail') +router.register(r'pre-cold-kill-house-ware-house', killhouse_views.PreColdKillHouseWareHouseViewSet, + basename='pre-cold-kill-house-ware-house') + +router.register(r'kill-house-warehouse-dashboard-for-province', + killhouse_views.KillHouseForProvinceWareHouseDashboardViewSet, + basename='kill-house-warehouse-dashboard-for-province') +router.register(r'total-kill-house-warehouse-dashboard-for-province', + killhouse_views.KillHouseForTotalProvinceWareHouseDashboardViewSet, + basename='total-kill-house-warehouse-dashboard-for-province') + +router.register(r'kill-house-ware-house-for-dispensers', killhouse_views.KillHouseWareHouseForDispensersViewSet, + basename='kill-house-ware-house-for-dispensers') + +router.register(r'kill_house_total_report_province_kill_requests', + killhouse_views.KillHouseForTotalReportAutomaticStewardAllocationViewSet, + basename='kill_house_total_report_province_kill_requests') +router.register(r'kill_house_total_province_kill_requests', + killhouse_views.KillHouseForAutomaticStewardAllocationViewSet, + basename='kill_house_total_province_kill_requests') +router.register(r'steward_guilds_allocations_for_statistical_profile', + killhouse_views.StewardGuildsAllocationsForStatisticalProfileViewSet, + basename='steward_guilds_allocations_for_statistical_profile') +router.register(r'kill_house_purchase_info', killhouse_views.KillHouseforPurchaseRequestViewSet, + basename='kill_house_purchase_info') +router.register(r'kill_house_purchase', killhouse_views.KillHousePurchaseRequestViewSet, basename='kill_house_purchase') +router.register(r'kill_house_purchase_permission', killhouse_views.KillHousePurchaseRequestPermissionViewSet, + basename='kill_house_purchase_permission') +router.register(r'allow_kill_house_vet', killhouse_views.KillHouseAllowVetViewSet, basename='allow_kill_house_vet') +router.register(r'check_losses', killhouse_views.CheckUnusualCasualtiesViewSet, basename='check_losses') +router.register(r'new', killhouse_views.KillHouseNewViewSet, basename='new') +router.register(r'detail_of_killing', killhouse_views.DetailOfKillingViewSet, basename='detail_of_killing') +router.register(r'dashboard_detail_of_killing', killhouse_views.DetailOfKillingDashboardView, + basename='dashboard_detail_of_killing') +router.register(r'parent_company_dashboard_detail_of_killing', + killhouse_views.ParentCompanyDetailOfKillingDashboardView, + basename='parent_company_dashboard_detail_of_killing') +router.register(r'comprehensive_report_of_slaughterhouse', + killhouse_views.ComprehensiveReportOfTheSlaughterhouseViewSet, + basename='comprehensive_report_of_slaughterhouse') +router.register(r'delete-bar', + killhouse_views.DeleteKillHouseRequest, + basename='detele_bar') + +router.register(r'non-receipt-request', + killhouse_views.NonReceiptKillHouseRequestViewSet, + basename='non-receipt-request') +router.register(r'return-kill-house-requests', + killhouse_views.ReturnKillHouseRequestViewSet, + basename='return-kill-house-request') +router.register(r'non-receipt-request-return', + killhouse_views.ReturnNonReceiptKillHouseRequestViewSet, + basename='non-receipt-request-return') + +router.register(r'direct-buying-payment', + killhouse_views.DirectBuyingPaymentViewSet, + basename='direct-buying-payment') + +router.register(r'direct-buying-requests', + killhouse_views.ProvinceKillRequestDirectBuyingViewSet, + basename='direct-buying-requests') + +router.register(r'market-requests', + killhouse_views.MarketKillRequestViewSet, + basename='market-requests') + +router.register(r'market-kill-houses', + killhouse_views.MarketKillHouseViewSet, + basename='market-kill-houses') + +# router.register(r'poultryamar', poultry_views.PoultryHatchingAmar, basename='poultryamar') + +# The API URLs are now determined automatically by the router. +urlpatterns = [ + path('', include(router.urls)), + path('update-excel/', user_excel_update), + path('add-excel/', user_excel), + path('cancel_poultry_exchange_request/', Cancel_Poultry_Exchange_request), + path('Check_Poultry_Auction_request_front/', Check_Poultry_Auction_request_front), + path('make_kill_request/', make_kill_request), + path('poultry_request_report_excel/', poultry_request_report_excel), + path('vet_check_excel/', vet_check_excel), + path('bar_excel/', bar_excel), + path('0/hatching_excel/', hatching_excel), + path('kill_house_excel/', kill_house_request_excel), + path('bar_excel_trash_true/', bar_excel_trash_true), + path('allocated_excel/', allocated_excel), + path('poultry_kill_request_excel/', poultry_kill_request_excel), + path('request_registration_kill_house/', request_registration_kill_house), + path('new_load_of_kill_house_vet/', new_load_of_kill_house_vet), + path('request_pending_allocation/', request_pending_allocation), + path('car_allocation_excel/', car_allocation_excel), + path('Test/', Test), + path('Test1/', Test1), + path('city_operator_for_poultry/', city_operator_for_poultry), + path('excel_for_all_user/', excel_for_all_user), + path('inventory/', inventory), + path('Broadcast_management/', Broadcast_management), + path('archive_hatching/', archive_hatching), + path('guilds_excel/', guilds_excel), + path('management_poultry/', management_poultry), + path('commerce_report_excel/', commerce_report_excel), + path('commerce_bar_excel/', commerce_bar_excel), + path('archive_hatching_excel/', archive_hatching_excel), + path('number_of_kills_weight_excel/', number_of_kills_weight_excel), + path('number_of_kills_excel/', number_of_kills_excel), + path('single_hatching_age_range_excel/', single_hatching_age_range_excel), + path('hatching_age_range_excel/', hatching_age_range_excel), + path('total_poultry_request_dashboard_excel/', total_poultry_request_dashboard_excel), + path('total_poultry_hatching_dashboard_excel/', total_poultry_hatching_dashboard_excel), + path('doughnut_hatching_excel/', doughnut_hatching_excel), + path('forecast_hatching_left_over_excel/', forecast_hatching_left_over_excel), + path('manager_of_farm_excel/', manager_of_farm_excel), + path('kill_house__request_vet_killing_process_excel/', kill_house__request_vet_killing_process_excel), + path('kill_house_percent_excel/', kill_house_percent_excel), + path('poultry_request_out_excel/', poultry_request_out_excel), + path('doughnut_left_hatching_excel/', doughnut_left_hatching_excel), + path('get_all_user_excel/', get_all_user_excel), + path('add_zero_for_user_mobile/', add_zero_for_user_mobile), + path('stewards_excel/', stewards_excel), + path('kill_house_total_wage_excel/', kill_house_total_wage_excel), + path('steward_excel/', steward_excel), + path('kill_house_total_wage_not_payid_excel/', kill_house_total_wage_not_payid_excel), + path('all_kill_house_total_wage_excel/', all_kill_house_total_wage_excel), + path('slaughterhouse_fee_excel/', slaughterhouse_fee_excel), + path('slaughterhouse_fee_not_paid_excel/', slaughterhouse_fee_not_paid_excel), + path('car_province_excel/', car_province_excel), + path('kill_house_wage_archive_excel/', kill_house_wage_archive_excel), + path('kill_house_total_wage_archive_excel/', kill_house_total_wage_archive_excel), + path('process-for-each-hatching/', process_for_each_hatching), + path('bar-management-kill-house-excel/', bar_management_kill_house_excel), + path('all_inventory_excel/', all_inventory_excel), + path('daily_process_excel/', daily_process_excel), + path('dpe/', daily_process_excel), + path('daily_process_klling_proccess_excel/', daily_process_klling_proccess_excel), + path('killing_process_from_date_excel/', killing_process_from_date_excel), + path('hatching_report_from_age_excel/', hatching_report_from_age_excel), + path('discrepancy_report_excel/', discrepancy_report_excel), + path('bar_for_each_persion_excel/', bar_for_each_persion_excel), + path('poultry_excel/', poultry_excel), + path('bar_contradiction_of_quarantine_excel/', bar_contradiction_of_quarantine_excel), + path('detail_of_killing_excel/', detail_of_killing_excel), + path('doke/', detail_of_killing_excel), + path('pos_excel/', pos_excel), + path('poultry_and_bar_daily_report_excel/', poultry_and_bar_daily_report_excel), + path('bar_free_excel/', bar_free_excel), + path('steward_ware_house_total_report_daily_excel/', steward_ware_house_total_report_daily_excel), + path('steward_ware_house_total_report_daily_detail_excel/', steward_ware_house_total_report_daily_detail_excel), + path('hatching_by_age_range/', hatching_by_age_range), + path('hatching_for_detail_killing_excel/', hatching_for_detail_killing_excel), + path('bar_live_stock_support_excel/', bar_live_stock_support_excel), + path('comprehensive_report_of_the_slaughterhouse_excel/', comprehensive_report_of_the_slaughterhouse_excel), + path('crotse/', comprehensive_report_of_the_slaughterhouse_excel), + path('successful_transactions_excel/', successful_transactions_excel), + path('unsuccessful_transactions_excel/', unsuccessful_transactions_excel), + path('poultry_hatching_between_50age_70age_excel/', poultry_hatching_between_50age_70age_excel), + path('number_of_times_with_quarantine_code_excel/', number_of_times_with_quarantine_code_excel), + path('the_burden_of_quarantine_excel/', the_burden_of_quarantine_excel), + path('bar_without_quarantine_code_excel/', bar_without_quarantine_code_excel), + path('loads_that_differ_in_quarantine_and_cooperation_excel/', + loads_that_differ_in_quarantine_and_cooperation_excel), + path('government_burden_excel/', government_burden_excel), + path('goverment_bar_state_with_a_certified_quarantine_code_excel/', + goverment_bar_state_with_a_certified_quarantine_code_excel), + path('free_loads_excel/', free_loads_excel), + path('free_cargoes_obtained_from_quarantine_excel/', free_cargoes_obtained_from_quarantine_excel), + path('free_loads_with_quarantine_code_excel/', free_loads_with_quarantine_code_excel), + path('loads_outside_the_province_excel/', loads_outside_the_province_excel), + path('loads_entering_the_slaughterhouse_excel/', loads_entering_the_slaughterhouse_excel), + path('veterinarian_unloaded_load_excel/', veterinarian_unloaded_load_excel), + path('completed_slaughterhouse_loads_excel/', completed_slaughterhouse_loads_excel), + path('unloaded_cargo_without_quarantine_code_excel/', unloaded_cargo_without_quarantine_code_excel), + path('unloaded_load_excel/', unloaded_load_excel), + path('loads_unloaded_and_not_completed_by_the_slaughterhouse_excel/', + loads_unloaded_and_not_completed_by_the_slaughterhouse_excel), + path('hatching_date_range_excel/', hatching_date_range_excel), + path('wallete_excel/', wallete_excel), + path('kill_house_request_suspended_load_excel/', kill_house_request_suspended_load_excel), + path('chain_excel/', chain_excel), + path('kill_house_total_transactions_wage_payid_excel/', kill_house_total_transactions_wage_payid_excel), + path('kill_house_total_transactions_wage_payid_super_admin_excel/', + kill_house_total_transactions_wage_payid_super_admin_excel), + path('kill_house_total_wage_excel_new/', kill_house_total_wage_excel_new), + path('kill_house_total_transactions_wage_payid_admin_x_excel/', + kill_house_total_transactions_wage_payid_admin_x_excel), + path('get-payer-info/', get_gate_way_payer_info), + path('direct_purchase_excel/', direct_purchase_excel), + path('direct_purchase_archive_excel/', direct_purchase_archive_excel), + path('payment_transactions_province_excel/', payment_transactions_province_excel), + path('general_free_bar_excel/', general_free_bar_excel), + path('out_province_poultry_request_buyers_excel/', out_province_poultry_request_buyers_excel), + path('chain_company_buyers_excel/', chain_company_buyers_excel), + path('bar_chain_excel/', bar_chain_excel), + path('kill_house_user_excel/', kill_house_user_excel), + path('general_city_operator/', general_city_operator), + path('poultry_monitoring_excel/', poultry_monitoring_excel), + path('get_country/', get_country), + path('export_kill_house_excel/', export_kill_house_excel), + path('monitor_loads_excel/', monitor_loads_excel), + path('kill_house_free_bar_excel/', kill_house_free_bar_excel), + path('check_excel/', check_excel), + path('find_gid_code/', find_gid_code), + path('roles-users/', Rolesusers), + path('technical_responsible_performance_excel/', technical_responsible_performance_excel), + path('totoal_technical_responsible_performance_excel/', totoal_technical_responsible_performance_excel), + path('bot_eitaa_for_bar/', bot_eitaa_for_bar), + path('bot_eitaa_free_bar/', bot_eitaa_free_bar), + path('bot_eitaa_for_hatching_gt_50/', bot_eitaa_for_hatching_gt_50), + path('transacion_out_request_excel/', transacion_out_request_excel), + path('bot_eitaa_for_province_kill_request/', bot_eitaa_for_province_kill_request), + path('out_province_carcasses_buyer_kill_house_excel/', out_province_carcasses_buyer_kill_house_excel), + path('kill_house_free_sale_bar_information_excel/', kill_house_free_sale_bar_information_excel), + path('kill_house_free_sale_bar_information_for_excel_excel/', kill_house_free_sale_bar_information_for_excel_excel), + path('fix_image_voilation_hatching/', fix_image_voilation_hatching), + path('fix_image_voilation_hatching_return/', fix_image_voilation_hatching_return), + path('from_allocation_to_distribution_excel/', from_allocation_to_distribution_excel), + path('pos-finder/', pos_finder), + path('check-server/', Check_server), + path('pos-get-finder/', pos_get_finder), + path('get_hatching_kill_ingo/', get_hatching_kill_ingo), + path('get-all-poultry/', GetAllPoultryViewSet.as_view()), + path('get-all-poultry-for-poultry-science/', GetAllPoultryForPoultryScienceViewSet.as_view()), + path('get-all-poultry-for-increase-hatching/', GetAllPoultryFoIncreaseHatchingViewSet.as_view()), + path('send_sms_for_poultry_from_age_notification/', send_sms_for_poultry_from_age_notification), + path('notentered_bars_for_kill_house_excel/', notentered_bars_for_kill_house_excel), + path('entered_bars_for_kill_house_excel/', entered_bars_for_kill_house_excel), + path('kill_house_free_bar_entered_for_warehouse_excel/', kill_house_free_bar_entered_for_warehouse_excel), + path('steward_allocation_for_warehouse_excel/', steward_allocation_for_warehouse_excel), + path('kill_house_free_bar_carcasses_for_warehouse_excel/', kill_house_free_bar_carcasses_for_warehouse_excel), + path('kill_house_inventory_data/', kill_house_inventory_data), + path('all_kill_house_inventory_data/', all_kill_house_inventory_data), + path('cold_house_excel/', cold_house_excel), + path('management_cold_house_excel/', management_cold_house_excel), + path('auto_warehouse_steward_allocations/', auto_warehouse_steward_allocations), + path('warehouse_archive_combined_excel/', warehouse_archive_combined_excel), + path('all_distribution_province/', all_distribution_province), + path('login_user_excel/', login_user_excel), + path('sub_section_of_cooperative_share_detail/', sub_section_of_cooperative_share_detail), + path('city_operator_for_sub_sector_excel/', city_operator_for_sub_sector_excel), + path('vet_for_sub_sector_excel/', vet_for_sub_sector_excel), + path('test_excel/', test_excel), + path('guild_for_sub_sector_excel/', guild_for_sub_sector_excel), + path('all_guilds_transaction_excel/', all_guilds_transaction_excel), + path('detail_guilds_transaction_excel/', detail_guilds_transaction_excel), + path('GetExcel/', GetExcel.as_view()), + path('management_hatching_excel/', management_hatching_excel), + path('user_without_role_excel/', user_without_role_excel), + path('poultry_hatching_prediction_chart_excel/', poultry_hatching_prediction_chart_excel), + path('poultry_hatching_prediction_excel/', poultry_hatching_prediction_excel), + path('bar_difference_reques_excel/', bar_difference_reques_excel), + path('api_update_poultry_hatching/', api_update_poultry_hatching), + path('api_update_chicken_breed/', api_update_chicken_breed), + path('create_kill_house_free_bar/', create_kill_house_free_bar), + path('fix_bar_without_quarantine/', fix_bar_without_quarantine), + path('get_gid_out_province_manual/', get_gid_out_province_manual), + path('get_all_pos_company/', get_all_pos_company), + path('update_role_product/', update_role_product), + path('create_update_chicken_commission_prices/', create_update_chicken_commission_prices), + path('update_cooperative_share/', update_cooperative_share), + path('dashboard_monitoring_view/', dashboard_monitoring_view), + path('create_update_chicken_commission_prices_manual/', create_update_chicken_commission_prices_manual), + path('api_update_poultry_hatching_from_rsi/', api_update_poultry_hatching_from_rsi), + path('get_all_pos_version/', get_all_pos_version), + path('dashboard_monitoring_bar_and_killing/', dashboard_monitoring_bar_and_killing), + path('dashboard_monitoring_bar_and_killing_excel/', dashboard_monitoring_bar_and_killing_excel), + path('remove_access_token_manual/', remove_access_token_manual), + path('find_gid_code_manual/', find_gid_code_manual), + path('dashboarad_bar_for_kill_house/', dashboarad_bar_for_kill_house), + path('dashboard_bar_difference_request/', dashboard_bar_difference_request), + path('daily_manual_transaction_for_eata/', daily_manual_transaction_for_eata), + path('get_all_pos_transaction/', get_all_pos_transaction), + path('send_clearance_code_to_rsi/', send_clearance_code_to_rsi), + path('api_send_clearance_code_to_rsi/', api_send_clearance_code_to_rsi), + path('create_steward_allocation_from_excel/', create_steward_allocation_from_excel), + path('send_bar_info_from_ticket/', send_bar_info_from_ticket), + path('steward_allocation_excel/', steward_allocation_excel), + path('free_sale_out_province_excel/', free_sale_out_province_excel), + path('get_all_guilds/', get_all_guilds), + path('steward_free_sale_out_province_excel/', steward_free_sale_out_province_excel), + path('sevrence_kill_house_steward_allocation_excel/', sevrence_kill_house_steward_allocation_excel), + path('total_steward_dashboard_excel/', total_steward_dashboard_excel), + path('sub_section_of_cooperative_share_detail_with_date_excel/', + sub_section_of_cooperative_share_detail_with_date_excel), + path('add_poultry_request_quarantine_code/', add_poultry_request_quarantine_code), + path('all_clearance_code_to_rsi/', all_clearance_code_to_rsi), + path('hatching-detail/', HatchingDetailView.as_view()), + path('direct-buying-poultry-requests/', PoultryRequestForDirectBuyingViewSet.as_view()), + path('direct-buying-poultry-hatching/', PoultryHatchingForDirectBuyingViewSet.as_view()), + path('direct-buying-poultry-requests-chart/', PoultryHatchingChartForDirectBuyingViewSet.as_view()), + path('kill-house-performance-dashboard/', KillHousePerformanceDashboardViewSet.as_view()), + path('kill-house-market-info/', KillHouseMarketInfoViewSet.as_view()), + path('kill-house-market-info-dashboard/', KillHouseMarketInfoDashboardViewSet.as_view()), + path('kill-house-sales-info-dashboard/', KillHouseSalesInformationViewSet.as_view()), + path('steward-sales-info-dashboard/', StewardSalesInformationViewSet.as_view()), + path('pos-sales-info/', PosSalesInformationViewSet.as_view()), + path('pos-cold-houses/', PosColdHouseViewSet.as_view()), + path('steward-remain-weight/', StewardRemainWeightViewSet.as_view()), + path('total-steward-remain-weight/', TotalStewardRemainWeightViewSet.as_view()), + path('pos-remain-weight/', PosRemainWeightViewSet.as_view()), + path('pos-remain-weight-date/', PosRemainWeightWithDateViewSet.as_view()), + path('kill-house-cold-house-allocations-info/', KillHouseForColdHouseAllocationViewSet.as_view()), + path('kill-house-segmentation-info/', KillHouseForSegmentationViewSet.as_view()), + path('kill-house-comparative-info/', KillHouseComparativeInformationViewSet.as_view()), + path('return-province-kill-requests/', ReturnProvinceKillRequestViewSet.as_view()), + path('return-requests-dashboard/', ReturnRequestDashboardViewSet.as_view()), + path('kill-house-remain-weight/', KillHouseRemainWeightViewSet.as_view()), + path('total-kill-house-remain-weight/', TotalKillHouseRemainWeightViewSet.as_view()), + path('total-kill-house-archive-dashboard/', TotalKillHouseWarehouseArchiveDashboardViewSet.as_view()), + path('total-guild-steward-archive-dashboard/', TotalGuildStewardWarehouseArchiveDashboardViewSet.as_view()), + path('segmentation-dashboard/', SegmentationDashboardViewSet.as_view()), + path('poultry_and_hatching_for_poultry_science/', PoultryAndHatchingForPoultryScience.as_view()), + path('kill-house-lock-info/', KillHouseLock.as_view()), + path('kill_request_pdf/', kill_request_pdf), + path('non_receipt_request_excel/', non_receipt_request_excel), + path('ticket_different_clearance_code_from_rsi/', ticket_different_clearance_code_from_rsi), + path('bulk_test_data/', bulk_test_data), + path('get_hatching_for_bazrasi/', get_hatching_for_bazrasi), + path('detail_of_killing_and_warehouse_excel/', detail_of_killing_and_warehouse_excel), + path('update_archive_date_poultry_hatching/', update_archive_date_poultry_hatching), + path('management_all_poultry_and_warehouse/', management_all_poultry_and_warehouse), + path('management_all_poultry_and_warehouse_pdf/', management_all_poultry_and_warehouse_pdf), + path('summary_report_pdf/', summary_report_pdf), + path('management_kill_house_dashboard/', management_kill_house_dashboard), + path('hatching_unknown/', hatching_unknown), + path('direct_buying_poultry_requests/', direct_buying_poultry_requests), + path('market_requests_excel/', market_requests_excel), + path('hatching_for_every_age_range/', hatching_for_every_age_range), + path('periodic_performance_report_dashboard/', periodic_performance_report_dashboard), + path('transaction_for_eata_new/', transaction_for_eata_new), + path('daily_report_for_each_vet_farm_manual/', daily_report_for_each_vet_farm_manual), + path('get_more_than_one_role/', get_more_than_one_role), + path('fix_killing_age/', fix_killing_age), + path('get_bar_from_rsi_with_hatching/', get_bar_from_rsi_with_hatching), + path('poultry_hatching_detail_pdf/', hatching_detail_pdf), + path('poultry_science_report_pdf/', poultry_science_report_pdf), + path('driver_from_rsi_excel/', driver_from_rsi_excel), + path('send_again_sms_for_register_code_guild/', send_again_sms_for_register_code_guild), + path('send_again_sms_steward_allocation/', send_again_sms_steward_allocation), + path('pos_send_again_sms_steward_allocation/', pos_send_again_sms_steward_allocation), + path('fix_number_from_rsi/', fix_number_from_rsi), + path('cancel_bar_and_province_request/', cancel_bar_and_province_request), + path('return_province_request_excel/', return_province_request_excel), + path('guilds_without_allocation_excel/', guilds_without_allocation_excel), + path('return_kill_house_request_excel/', return_kill_house_request_excel), + path('fix_wage/', fix_wage), + path('send_again_sms_steward_free_sale_bar/', send_again_sms_steward_free_sale_bar), + path('send_again_sms_kill_house_free_sale_bar/', send_again_sms_kill_house_free_sale_bar), + path('send_again_sms_direct_buying_code/', send_again_sms_direct_buying_code), + path('delete_guilds_without_allocation/', delete_guilds_without_allocation), + path('send_all_bar_to_eitaa/', send_all_bar_to_eitaa), + path('send_daily_slaughter_statistics_sms_manual/', send_daily_slaughter_statistics_sms_manual), + path('send_daily_distribution_report_sms_manual/', send_daily_distribution_report_sms_manual), + path('save_mobile_numbers/', save_mobile_numbers), + path('update_guild_by_national_id/', update_guild_by_national_id), + path('register_legal_guild/', register_legal_guild), + path('import_poultry_science_from_excel/', import_poultry_science_from_excel), + path('sync_guilds_user_profile_from_inquiry/', sync_guilds_user_profile_from_inquiry), + path('report_guilds_without_national_or_pos_transactions/', report_guilds_without_national_or_pos_transactions), + path('get_guilds_for_update_or_create/', get_guilds_for_update_or_create), + path('get_legal_person_unit_info/', get_legal_person_unit_info), + path('update_all_active_guilds_from_api/', update_all_active_guilds_from_api), + path('find_users_with_duplicate_national_id/', find_users_with_duplicate_national_id), + path('fix_duplicate_national_id_users/', fix_duplicate_national_id_users), + path('get_poultry_for_bazrasi/', get_poultry_for_bazrasi), + path('fix_duplicate_guilds_steward_allocation/', fix_duplicate_guilds_steward_allocation), + path('test_all_excel_functions/', test_all_excel_functions), + path('archive_poultry_hatching_with_archive_percent/', archive_poultry_hatching_with_archive_percent), + path('check_steward_allocation_role_mismatch/', check_steward_allocation_role_mismatch), + path('upload_image_to_server_for_poultry_science/', upload_image_to_server_for_poultry_science), + path('poultry_science_for_bazresi/', poultry_science_for_bazresi), + path('pos/pos_finder/', pos_login), + path('get_dispenser_user_info/', get_dispenser_user_info), + + +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/panel/validate_headers.py b/panel/validate_headers.py new file mode 100644 index 0000000..491594c --- /dev/null +++ b/panel/validate_headers.py @@ -0,0 +1,120 @@ +import datetime +import secrets +from django.http import JsonResponse + +from panel.models import PosDeviceVersion, PosCompany, POSDeviceSession, POSMachine + + +def make_pos_unique_id(): + while True: + random_number = '0' + ''.join(str(secrets.randbelow(10)) for _ in range(5)) + if not POSMachine.objects.filter(pos_unique_id=random_number).exists(): + return random_number + + +def get_client_ip(request): + x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') + if x_forwarded_for: + # اگر از پروکسی استفاده می‌شود، IP اول را برمی‌گردانیم + ip = x_forwarded_for.split(',')[0] + else: + # در غیر این صورت از REMOTE_ADDR استفاده می‌کنیم + ip = request.META.get('REMOTE_ADDR') + return ip + + +class PosDeviceValidator: + def __init__(self, request): + self.request = request + self.headers = request.headers + self.device_id = request.headers.get('device-id') + self.device_mac = request.headers.get('device-mac') + self.device_name = request.headers.get('device-name') + self.device_sdk = request.headers.get('device-sdk') + self.device_serial = request.headers.get('device-serial') + self.device_provider = request.headers.get('device-provider') + self.device_version = request.headers.get('device-version') + self.device_version_name = request.headers.get('device-vname') + self.device_lng = request.headers.get('device-lng') + self.device_lot = request.headers.get('device-lot') + self.role = request.headers.get('device-role') + + def validation_version(self): + if self.device_provider == "" or self.device_provider == None: + return JsonResponse({'result': 'پارامتر های ارسالی صحیح نمیباشد!'}, status=402) + + company = PosCompany.objects.filter(en_name=self.device_provider).first() + if not company: + return JsonResponse({'result': 'شرکت پرداخت الکترونیک پشتیبانی نمیشود!'}, status=402) + + if not company.active: + return JsonResponse({'result': 'شرکت پرداخت الکترونیک توسط مدیریت مسدود شده است!'}, status=402) + version = PosDeviceVersion.objects.filter(company=company).order_by('code') + if not version: + return JsonResponse({'result': ' هیچ نسخه معتبری برای این شرکت پرداخت الکترونیک منتشر نشده است!'}, + status=402) + + current_version = version.filter(code=self.device_version).first() + if not current_version or current_version.remove: + return JsonResponse({'result': f'نسخه {self.device_version_name} منقضی شده است لطفا بروز رسانی کنید '}, + status=402) + return None + + def validation_device(self): + pos_session = POSDeviceSession.objects.filter(pos__pos_id=self.device_id, mac=self.device_mac).first() + if not pos_session: + return None + else: + pos_session.session_last_seen_date = datetime.datetime.now() + pos_session.lng = self.device_lng + pos_session.lot = self.device_lot + pos_session.version = self.device_version + pos_session.ip = get_client_ip(self.request) + pos_session.save() + return pos_session.pos.pos_id + + def validation_pos(self): + pos = POSMachine.objects.filter(serial=self.device_serial, mac=self.device_mac).first() + if not pos: + return JsonResponse({"result": "دستگاه معتبر نمیباشد!"}, + status=401) + else: + + if not pos.owner: + return JsonResponse({"result": f"برای این دستگاه مالکی تعیین نشده!شناسه پوز:{pos.pos_unique_id}"}, + status=403) + + if not pos.active: + return JsonResponse({"result": f"دستگاه غیر فعال میباشد!شناسه پوز:{pos.pos_unique_id}"}, + status=403) + pos.last_check = datetime.datetime.now() + pos.Long = self.device_lng + pos.Lat = self.device_lot + pos.version = self.device_version + pos.ip = get_client_ip(self.request) + pos.save() + return pos + + def manage_device(self): + company = PosCompany.objects.get(en_name=self.device_provider, trash=False) + pos = POSMachine.objects.filter(serial=self.device_serial, mac=self.device_mac).first() + if not pos: + pos = POSMachine( + pos_company=company, + serial=self.device_serial, + mac=self.device_mac, + sdk=self.device_sdk, + version=self.device_version, + name=self.device_name, + Lat=self.device_lot, + Long=self.device_lng, + pos_unique_id=make_pos_unique_id(), + ip=get_client_ip(self.request) + ) + pos.save() + + if pos.pos_company.en_name != company.en_name: + pos.pos_company = company + pos.save(update_fields=['pos_company']) + + return pos diff --git a/panel/views.py b/panel/views.py new file mode 100644 index 0000000..921a9fd --- /dev/null +++ b/panel/views.py @@ -0,0 +1,77 @@ +from django.shortcuts import render +from django.contrib.auth.models import User +from rest_framework import viewsets +from oauth2_provider.contrib.rest_framework import ( + TokenHasReadWriteScope, +) +from notification.models import NotificationType +from authentication.models import UserProfile, UserMessage +from panel.models import ( + PoultryRequest, + PoultryAssignmentInformation, + KillHouseCheckRequest, + KillHouseRequest, + ProvinceCheckOperatorRequest, + OperatorLastTimeEnter, + ReportingFieldRoleLimitation, + Group +) +from panel.poultry.serializers import ( + PoultryRequestSerializer, + PoultryAssignmentInformationSerializer +) +from panel.ReportingPanel.serializer import ( + ReportingFieldLimitationSerializer +) +from authentication.serializers import GroupSerializer +from rest_framework.response import Response +from rest_framework import status +from datetime import datetime + + +class OperatorLastTimeEnterViewSet(viewsets.ModelViewSet): + queryset = OperatorLastTimeEnter.objects.all() + permission_classes = [TokenHasReadWriteScope] + serializer_class = [] + + def update(self, request, *args, **kwargs): + time = request.data['time'] + + if UserProfile.objects.filter(user=request.user): + if not OperatorLastTimeEnter.objects.filter( + operator__exact=UserProfile.objects.get(user__exact=request.user)): + obj = OperatorLastTimeEnter() + else: + obj = OperatorLastTimeEnter.objects.get( + operator__exact=UserProfile.objects.get(user__exact=request.user)) + if UserProfile.objects.get(user=request.user).role.name == "CityOperator": + obj.city_operator_last_time_check = time + obj.operator = UserProfile.objects.get(user=request.user) + elif UserProfile.objects.get(user=request.user).role.name == "ProvinceOperator": + obj.province_operator_last_time_check = time + obj.operator = UserProfile.objects.get(user=request.user) + elif UserProfile.objects.get(user=request.user).role.name == "KillHouse": + obj.kill_house_last_time_check = time + obj.operator = UserProfile.objects.get(user=request.user) + obj.save() + return Response({'msg': 'Done'}, status=status.HTTP_200_OK) + + +class ReportingFieldLimitationViewSet(viewsets.ModelViewSet): + queryset = ReportingFieldRoleLimitation.objects.all() + serializer_class = ReportingFieldLimitationSerializer + permission_classes = [TokenHasReadWriteScope] + + def create(self, request, *args, **kwargs): + group = Group.objects.get(name__exact=request.data['role_name']) + request.data.pop('role_name') + serializer = self.serializer_class(data=request.data) + if serializer.is_valid(): + obj = serializer.create(validated_data=request.data) + obj.role_name = group + obj.save() + serializer = self.serializer_class(obj) + return Response(serializer.data) + return Response(serializer.errors) + + diff --git a/pdf/__init__.py b/pdf/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pdf/views.py b/pdf/views.py new file mode 100644 index 0000000..7a055fa --- /dev/null +++ b/pdf/views.py @@ -0,0 +1,1391 @@ +import datetime +import io +from urllib.parse import quote + +import requests +from django.db.models import Sum, Count, Avg, Q +from django.http import HttpResponse +from django.template.loader import render_to_string +from weasyprint import HTML, CSS +from weasyprint.text.fonts import FontConfiguration + +from general_urls import base_url_for_sms_report +from panel.KillHouse.serializers import KillHouseRequestForHatchingDetailSerializer, \ + KillHouseRequestForBarManagementSerializer, ReturnProvinceKillRequestSerializer, BarDifferenceRequestSerializer +from panel.helper_excel import shamsi_date, to_locale_str +from panel.models import KillRequest, ProvinceKillRequest, PoultryHatching, KillHouseRequest, \ + KillHouseFreeBarInformation, KillHouse, StewardAllocation, KillHouseFreeSaleBarInformation, RolesProducts, \ + DirectBuyingPayment, PoultryRequest, ChainAllocation, BarDifferenceRequest, HatchingIncreaseRequest, \ + PoultryScienceReport +from panel.poultry.serializers import PoultryHatchingForDetailsSerializer, PoultryRequestForHatchingDetailSerializer, \ + ChainAllocationForHatchingDetailSerializer, HatchingIncreaseRequestSerializer, EvacuationHatchingDetailSerializer + + +def kill_request_pdf(request): + font_config = FontConfiguration() + kill_request = KillRequest.objects.filter(trash=False, key=request.GET['key']).select_related( + 'kill_house', 'poultry', 'poultry__address', 'poultry__user', 'kill_house__kill_house_operator' + ).only( + 'poultry__unit_name', + 'poultry__user__fullname', + 'poultry__user__mobile', + 'poultry__user__national_code', + 'poultry__breeding_unique_id', + 'poultry__breeding_unique_id', + 'poultry__address__address', + 'poultry__user__city__name', + 'kill_house__kill_house_operator__user__fullname', + 'kill_house__kill_house_operator__user__national_code', + 'kill_house__kill_house_operator__address__address', + 'kill_house__kill_house_operator__user__city__name', + 'kill_house__name', + 'kill_capacity', + 'amount', + 'recive_date', + 'Index_weight', + 'input_direct_buying_code', + 'direct_buying_state', + 'poultry_hatching__chicken_age', + 'poultry_hatching__licence_number', + 'payment_deadline_date', + 'payment_deadline_days', + 'direct_buying_intermediary_mobile', + + ).first() + recive_date = kill_request.recive_date + if isinstance(recive_date, str): + try: + recive_date = datetime.datetime.strptime(recive_date, '%Y-%m-%dT%H:%M:%S.%f') + except ValueError: + recive_date = datetime.datetime.strptime(recive_date, '%Y-%m-%dT%H:%M:%S') + + date = shamsi_date(recive_date.date(), in_value=True) + date_in_value = shamsi_date(recive_date.date()) + + if kill_request.market_state == 'accepted' or kill_request.input_direct_buying_code or \ + kill_request.direct_buying_state == 'accepted': + input_direct_buying_code = True + else: + input_direct_buying_code = False + if kill_request.market_final_accept or kill_request.final_accept: + final_accept = True + else: + final_accept = False + + if kill_request.kill_house.kill_house_operator.address.address is not None: + kill_house_address = kill_request.kill_house.kill_house_operator.address.address + elif kill_request.kill_house.kill_house_operator.user.city.name: + kill_house_address = kill_request.kill_house.kill_house_operator.user.city.name + else: + kill_house_address = '-' + + if kill_request.poultry.address.address: + poultry_address = kill_request.poultry.address.address + elif kill_request.poultry.user.city.name: + poultry_address = kill_request.poultry.user.city.name + else: + poultry_address = '-' + kill_house_request = KillHouseRequest.objects.filter(trash=False, kill_request=kill_request, + assignment_state_archive='True').aggregate( + total_quantity=Sum('accepted_real_quantity'), + total_weight=Sum('accepted_real_weight'), + ) + province_kill_req = ProvinceKillRequest.objects.filter(trash=False, kill_request=kill_request).only( + 'province_request__poultry_request__order_code' + ).first() + payments = DirectBuyingPayment.objects.filter(province_kill_request=province_kill_req, trash=False) + total_paid_amount = payments.aggregate(total=Sum('amount'))['total'] or 0 + avg_killed_weight = round((kill_house_request['total_weight'] or 0) / (kill_house_request['total_quantity'] or 0) + if (kill_house_request['total_quantity'] or 0) > 0 else 0, + 1) + html_content = render_to_string('Digital_agreement_for_buying_and_selling.html', { # noqa + 'date': date, + 'unit_name': kill_request.poultry.unit_name, + 'fullname': kill_request.poultry.user.fullname, + 'mobile': kill_request.poultry.user.mobile, + 'national_code': kill_request.poultry.user.national_code if kill_request.poultry.user.national_code else '-', + 'breeding_unique_id': kill_request.poultry.breeding_unique_id if + kill_request.poultry.breeding_unique_id else '-', + 'poultry_address': poultry_address, + 'kill_house_fullname': kill_request.kill_house.kill_house_operator.user.fullname, + 'kill_house_name': kill_request.kill_house.name, + 'kill_house_national_code': kill_request.kill_house.kill_house_operator.user.national_code if + kill_request.kill_house.kill_house_operator.user.national_code else '-', + 'kill_house_mobile': kill_request.kill_house.kill_house_operator.user.mobile, + 'kill_house_address': kill_house_address, + 'kill_capacity': to_locale_str(kill_request.kill_capacity), + 'date_in_value': date_in_value, + 'amount': to_locale_str(int(kill_request.amount)), + 'weight': to_locale_str(round(kill_request.Index_weight * kill_request.kill_capacity, 1)), + 'input_direct_buying_code': input_direct_buying_code, + 'direct_buying_state': final_accept, + 'Index_weight': kill_request.Index_weight, + 'chicken_age': kill_request.poultry_hatching.chicken_age, + 'licence_number': kill_request.poultry_hatching.licence_number if + kill_request.poultry_hatching.licence_number else '-', + 'max_time': shamsi_date(kill_request.payment_deadline_date) if kill_request.payment_deadline_date else '-', + 'payment_deadline_days': kill_request.payment_deadline_days, + 'number': province_kill_req.province_request.poultry_request.order_code if province_kill_req else '-', + 'total_killed_quantity': to_locale_str(kill_house_request['total_quantity'] or 0), + 'total_killed_weight': to_locale_str(kill_house_request['total_weight'] or 0), + 'avg_killed_weight': avg_killed_weight, + 'direct_buying_intermediary_mobile': kill_request.direct_buying_intermediary_mobile, + 'payment_deadline_state': province_kill_req.payment_deadline_state, + 'total_paid_amount': to_locale_str(total_paid_amount), + 'payment_deadline_checker_fullname': province_kill_req.payment_deadline_checker_fullname, + 'payment_deadline_check_date': shamsi_date(province_kill_req.payment_deadline_check_date) \ + if province_kill_req.payment_deadline_check_date else '-', + 'payment_deadline_archive_message': province_kill_req.payment_deadline_archive_message, + + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) # noqa + css = CSS(string=''' + ''', font_config=font_config) + + pdf_file = io.BytesIO() + html.write_pdf(pdf_file, stylesheets=[css], font_config=font_config) + pdf_file.seek(0) + + response = HttpResponse(pdf_file, content_type='application/pdf') + filename = 'توافق‌نامه {0}.pdf'.format( + province_kill_req.province_request.poultry_request.order_code if province_kill_req else "-") + encoded_filename = quote(filename) # کدگذاری نام فایل برای URL + response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' + return response + + +def management_all_poultry_and_warehouse_pdf(request): + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_hatching = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q(date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False).select_related('poultry', 'poultry__user__city') + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False + ).select_related('killhouse_user') + aggregate_kill_house_request = kill_house_request.aggregate( + total_id=Count('id'), + total_accepted_real_quantity=Sum('accepted_real_quantity'), + total_accepted_real_weight=Sum('accepted_real_weight'), + total_quantity_has_quarantine=Sum('accepted_real_quantity', filter=Q(quarantine_quantity__gt=0)), + total_count_has_quarantine=Count('id', filter=Q(quarantine_quantity__gt=0)), + total_quarantine_quantity=Sum('quarantine_quantity', filter=Q(quarantine_quantity__gt=0)), + + total_id_hasnt_code=Count('id', filter=Q(clearance_code__isnull=True)), + total_quantity_hasnt_code=Sum('accepted_real_quantity', filter=Q(clearance_code__isnull=True)), + total_weight_hasnt_code=Sum('accepted_real_weight', filter=Q(clearance_code__isnull=True)), + total_id_hasnt_warehouse=Count('id', filter=Q(ware_house_confirmation=False)), + total_quantity_hasnt_warehouse=Sum('accepted_real_quantity', filter=Q(ware_house_confirmation=False)), + total_weight_hasnt_warehouse=Sum('accepted_real_weight', filter=Q(ware_house_confirmation=False)), + total_id_hasnt_assignment_state_archive=Count('id', filter=Q(assignment_state_archive='pending')), + total_quantity_hasnt_assignment_state_archive=Sum('accepted_real_quantity', + filter=Q(assignment_state_archive='pending')), + total_weight_hasnt_assignment_state_archive=Sum('accepted_real_weight', + filter=Q(assignment_state_archive='pending')), + total_id_hasnt_killing_age=Count('id', filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_quantity_hasnt_killing_age=Sum('accepted_real_quantity', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + total_weight_hasnt_killing_age=Sum('accepted_real_weight', + filter=Q(province_request__poultry_request__killing_age__gte=60)), + + ) + kill_house_req_stats = kill_house_request.values('killhouse_user__name').annotate( + total_quantity=Sum('accepted_real_quantity'), + transaction_count=Count('id') + ).order_by('-total_quantity') + top_kill_house_req = kill_house_req_stats.first() if kill_house_req_stats else None + kill_house_name_req = "-" + total_quantity_top_inner = 0 + if top_kill_house_req: + kill_house_name_req = top_kill_house_req['killhouse_user__name'] + total_quantity_top_inner = top_kill_house_req['total_quantity'] + + poultry_req_stats = kill_house_request.values( + 'province_request__poultry_request__hatching__poultry__unit_name', + 'province_request__poultry_request__hatching__poultry__user__city__name') \ + .annotate(total_quantity=Sum('accepted_real_quantity'), + ).order_by('-total_quantity') + top_poultry_req_stats = poultry_req_stats.first() if poultry_req_stats else None + top_poultry_req_stats_total_quantity = 0 + poultry_req_name_req = "-" + poultry_city_req_name_req = "-" + if top_poultry_req_stats: + poultry_req_name_req = top_poultry_req_stats['province_request__poultry_request__hatching__poultry__unit_name'] + poultry_city_req_name_req = top_poultry_req_stats[ + 'province_request__poultry_request__hatching__poultry__user__city__name'] + top_poultry_req_stats_total_quantity = to_locale_str(top_poultry_req_stats['total_quantity'] or 0) + + poultry_hatching_gt_60 = poultry_hatching.filter(chicken_age__gt=60) + poultry_hatching_has_killed = PoultryRequest.objects.filter(state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), + trash=False, out=False, send_date__date__gte=date1, + send_date__date__lte=date2) + max_age_poultry = poultry_hatching_has_killed.order_by('-killing_age').first() + min_age_poultry = poultry_hatching_has_killed.order_by('killing_age').first() + aggregate_poultry_hatching_gt_60 = poultry_hatching_gt_60.aggregate( + total_quantity=Sum('quantity'), + left_over=Sum('left_over'), + ) + aggregate_hatching = poultry_hatching.aggregate( + total_quantity=Sum('quantity'), + total_losses_vet=Sum('losses'), + total_losses_union=Sum('direct_losses'), + total_losses=Sum('total_losses'), + killed_quantity=Sum('killed_quantity'), + total_killed_weight=Sum('total_killed_weight'), + left_over=Sum('left_over'), + total_killing_ave_age=Avg('poultry__killing_ave_age') + ) + top_total_killed_weight = poultry_hatching.values('id').annotate( + total_killed_weight=Sum('total_killed_weight'), + ).order_by('-total_killed_weight') + top_total_killed_weight_first = top_total_killed_weight.first() if top_total_killed_weight else None + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + trash=False, buy_type='live').select_related('kill_house') + kill_house_stats = free_bars.values('kill_house__name').annotate( + total_quantity=Sum('quantity'), + total_live_weight=Sum('live_weight'), + transaction_count=Count('id') + ).order_by('-total_quantity') + + top_kill_house = kill_house_stats.first() if kill_house_stats else None + kill_house_name = "-" + total_quantity_top_out = 0 + transaction_count = "-" + if top_kill_house: + kill_house_name = top_kill_house['kill_house__name'] + transaction_count = to_locale_str(top_kill_house['transaction_count'] or 0) + total_quantity_top_out = to_locale_str(top_kill_house['total_quantity'] or 0) + # + out_poultry_req_stats = free_bars.values('poultry_name', 'province', 'city').annotate( + total_quantity=Sum('quantity'), + ).order_by('-total_quantity') + top_out_poultry_req_stats = out_poultry_req_stats.first() if out_poultry_req_stats else None + out_top_poultry_req_stats_total_quantity = 0 + out_poultry_req_name_req = "-" + out_poultry_city_req_name_req = "-" + out_poultry_province_req_name_req = "-" + if top_out_poultry_req_stats: + out_poultry_req_name_req = top_out_poultry_req_stats['poultry_name'] + out_poultry_city_req_name_req = top_out_poultry_req_stats['city'] + out_poultry_province_req_name_req = top_out_poultry_req_stats['province'] + out_top_poultry_req_stats_total_quantity = to_locale_str(top_out_poultry_req_stats['total_quantity'] or 0) + + # + aggregate_free_bars = free_bars.aggregate( + id=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + max_kill_day = free_bars.values('date__date').annotate( + daily_quantity=Sum('quantity') + ).order_by('-daily_quantity').first() + persian_date = '-' + daily_quantity = '-' + if max_kill_day: + persian_date = shamsi_date(max_kill_day['date__date']) + daily_quantity = to_locale_str(max_kill_day['daily_quantity']) + + max_kill_day_req = kill_house_request.values('kill_request__recive_date__date').annotate( + daily_quantity=Sum('accepted_real_quantity') + ).order_by('-daily_quantity').first() + persian_date_req = '-' + daily_quantity_req = '-' + if max_kill_day_req: + persian_date_req = shamsi_date(max_kill_day_req['kill_request__recive_date__date']) + daily_quantity_req = to_locale_str(max_kill_day_req['daily_quantity']) + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('name') + kill_house_data = [] + duc_kill_house_data = [] + + for kh in kill_houses: + in_province_data = kill_house_request.filter( + killhouse_user=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('accepted_real_quantity'), + weight=Sum('accepted_real_weight') + ) + + out_province_data = free_bars.filter( + kill_house=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + in_qty = in_province_data.get('quantity', 0) or 0 + in_weight = in_province_data.get('weight', 0) or 0 + out_qty = out_province_data.get('quantity', 0) or 0 + out_weight = out_province_data.get('live_weight', 0) or 0 + total_quantity = in_qty + out_qty + total_weight = in_weight + out_weight + + in_loads = in_province_data.get('load_count', 0) or 0 + out_loads = out_province_data.get('load_count', 0) or 0 + total_loads = in_loads + out_loads + + if in_qty > 0 or out_qty > 0 or in_loads > 0 or out_loads > 0: + kill_house_data.append({ + 'name': kh.name, + 'load_count': to_locale_str(total_loads or 0), + 'in_province_quantity': to_locale_str(in_qty or 0), + 'in_province_wight': to_locale_str(in_weight or 0), + 'out_province_quantity': to_locale_str(out_qty or 0), + 'out_province_weight': to_locale_str(out_weight or 0), + 'total_quantity': to_locale_str(total_quantity or 0), + 'total_weight': to_locale_str(total_weight or 0), + }) + bar_assigment_pending_count1 = kill_house_request.filter(assignment_state_archive='True') \ + .exclude(bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + tomorrow_of_date1 = date1 + datetime.timedelta(days=1) + tomorrow_of_date2 = date2 + datetime.timedelta(days=1) + steward_allocations = StewardAllocation.objects.filter( + trash=False, + date__date__gte=tomorrow_of_date1, + date__date__lte=tomorrow_of_date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('real_weight_of_carcasses') + ) + + free_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, + date__date__gte=tomorrow_of_date1, + date__date__lte=tomorrow_of_date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('weight_of_carcasses') + ) + + in_province_data = kill_house_request.filter( + killhouse_user__in=kill_houses + ).values('killhouse_user_id').annotate( + total_quantity=Sum('accepted_real_weight') + ) + + in_warehouse_data = kill_house_request.filter( + killhouse_user__in=kill_houses, + ware_house_confirmation=True + ).values('killhouse_user_id').annotate( + total_quantity=Sum('ware_house_accepted_real_weight') + ) + + products = RolesProducts.objects.filter( + trash=False, + kill_house__in=kill_houses + ).values('kill_house_id', 'total_remain_weight') + + steward_dict = {item['kill_house_id']: item['total_quantity'] for item in steward_allocations} + free_bar_dict = {item['kill_house_id']: item['total_quantity'] for item in free_bars} + in_province_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_province_data} + in_warehouse_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_warehouse_data} + product_dict = {item['kill_house_id']: item['total_remain_weight'] for item in products} + + management_kill_house_data = [] + for kh in kill_houses: + kh_id = kh.id + + steward_qty = steward_dict.get(kh_id, 0) or 0 + free_bar_qty = free_bar_dict.get(kh_id, 0) or 0 + in_province_qty = in_province_dict.get(kh_id, 0) or 0 + in_warehouse_qty = in_warehouse_dict.get(kh_id, 0) or 0 + product_weight = product_dict.get(kh_id, 0) or 0 + + if any([in_province_qty, in_warehouse_qty, steward_qty, free_bar_qty]): + total = free_bar_qty + steward_qty + percent = round(total * 100 / in_province_qty, 1) if in_province_qty else 0 + + management_kill_house_data.append({ + 'name': kh.name, + 'in_province_quantity': to_locale_str(in_province_qty), + 'in_ware_house_quantity': to_locale_str(in_warehouse_qty), + 'steward_allocation_quantity': to_locale_str(steward_qty), + 'kill_house_free_bar_quantity': to_locale_str(free_bar_qty), + 'all_quantity': to_locale_str(total), + 'product': to_locale_str(product_weight), + 'percent': percent + }) + for kh in kill_houses: + kill_house_request1 = kill_house_request.filter( + killhouse_user=kh + ) + + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True') + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + bar_document_status_accepted = bar_assigment_true_count.filter( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + bar_document_status_rejected = bar_assigment_true_count.exclude( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + + if bar_assigment_true_count.count() > 0 or bar_assigment_pending_count > 0: + duc_kill_house_data.append({ + 'name': kh.name, + 'kill_house_request1_count': kill_house_request1.count(), + "bar_assigment_true_count": bar_assigment_true_count.count(), + "bar_assigment_pending_count": bar_assigment_pending_count, + "bar_document_status_accepted": bar_document_status_accepted, + "percent_bar_document_status_accepted": int((bar_document_status_accepted / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + "bar_document_status_rejected": bar_document_status_rejected, + "percent_bar_document_status_rejected": int((bar_document_status_rejected / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + + }) + if base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + font_config = FontConfiguration() + different_bar = (aggregate_kill_house_request['total_quantity_has_quarantine'] or 0) \ + - (aggregate_kill_house_request['total_quarantine_quantity'] or 0) + different_bar_percent = int(different_bar / (aggregate_kill_house_request['total_quarantine_quantity'] or 0) * 100) \ + if (aggregate_kill_house_request['total_quarantine_quantity'] or 0) > 0 else 0 + + if different_bar < 0: + color_different_bar = '#FF0000' + else: + color_different_bar = None + html_content = render_to_string('management_all_poultry_and_warehouse.html', { # noqa + 'number': 1234, + 'province': province, + "date": shamsi_date(datetime.datetime.now().date(), in_value=True), + "date1": request.GET['date1'], + "date2": request.GET['date2'], + "from_date": shamsi_date(date1), + "to_date": shamsi_date(date2), + "poultry_count": len(poultry_hatching.values_list('poultry', flat=True).distinct()), + "chain_count": len( + poultry_hatching.filter(Q(UnionTypeName='زنجیره') | + Q(chain_company__isnull=False)).values_list('poultry', flat=True).distinct()), + "poultry_hatching_quantity": to_locale_str(aggregate_hatching['total_quantity'] or 0), + "poultry_hatching_losses_vet": to_locale_str(aggregate_hatching['total_losses_vet'] or 0), + "poultry_hatching_losses_union": to_locale_str(aggregate_hatching['total_losses_union'] or 0), + "poultry_hatching_total_losses": to_locale_str(aggregate_hatching['total_losses'] or 0), + "poultry_hatching_killed_quantity": to_locale_str(aggregate_hatching['killed_quantity'] or 0), + "poultry_hatching_total_killed_weight": to_locale_str(aggregate_hatching['total_killed_weight'] or 0), + "poultry_hatching_left_over": to_locale_str(aggregate_hatching['left_over'] or 0), + "poultry_hatching_gt_60": len(poultry_hatching_gt_60.values_list('poultry', flat=True).distinct()), + "poultry_hatching_gt_60_quantity": to_locale_str(aggregate_poultry_hatching_gt_60['total_quantity'] or 0), + "poultry_hatching_gt_60_left_over": to_locale_str(aggregate_poultry_hatching_gt_60['left_over'] or 0), + "max_age_poultry": max_age_poultry.killing_age or 0, + "max_age_poultry_name": max_age_poultry.hatching.poultry.unit_name or '-', + "max_age_poultry_city": max_age_poultry.hatching.poultry.user.city.name if max_age_poultry.hatching.poultry.user.city else '-', + "max_age_poultry_quantity": max_age_poultry.hatching.quantity or 0, + "max_age_poultry_killed_quantity": max_age_poultry.hatching.killed_quantity or 0, + "max_age_poultry_left_over": max_age_poultry.hatching.left_over or 0, + "min_age_poultry": min_age_poultry.killing_age or 0, + "min_age_poultry_name": min_age_poultry.hatching.poultry.unit_name or '-', + "min_age_poultry_city": min_age_poultry.hatching.poultry.user.city.name if min_age_poultry.hatching.poultry.user.city else '-', + "min_age_poultry_quantity": min_age_poultry.hatching.quantity or 0, + "min_age_poultry_killed_quantity": min_age_poultry.hatching.killed_quantity or 0, + "min_age_poultry_left_over": min_age_poultry.hatching.left_over or 0, + "kill_house_request_count": to_locale_str(aggregate_kill_house_request['total_id'] or 0), + "kill_house_request_quantity": to_locale_str(aggregate_kill_house_request['total_accepted_real_quantity'] or 0), + "kill_house_request_weight": to_locale_str(aggregate_kill_house_request['total_accepted_real_weight'] or 0), + "kill_house_request_average_weight": round( + aggregate_kill_house_request['total_accepted_real_weight'] / aggregate_kill_house_request[ + 'total_accepted_real_quantity'], 1) + if (aggregate_kill_house_request['total_accepted_real_quantity'] or 0) > 0 else 0, + "free_bars_count": to_locale_str(aggregate_free_bars['id'] or 0), + "free_bars_quantity": to_locale_str(aggregate_free_bars['quantity'] or 0), + "free_bars_live_weight": to_locale_str(aggregate_free_bars['live_weight'] or 0), + "kill_house_name": kill_house_name, + "transaction_count": transaction_count, + "persian_date": persian_date, + "daily_quantity": daily_quantity, + "persian_date_req": persian_date_req, + "daily_quantity_req": daily_quantity_req, + 'kill_houses_data': kill_house_data, + 'kill_house_name_req': kill_house_name_req, + 'poultry_req_name_req': poultry_req_name_req, + 'top_poultry_req_stats_total_quantity': top_poultry_req_stats_total_quantity, + 'poultry_city_req_name_req': poultry_city_req_name_req, + 'out_poultry_req_name_req': out_poultry_req_name_req, + 'out_poultry_city_req_name_req': out_poultry_city_req_name_req, + 'out_poultry_province_req_name_req': out_poultry_province_req_name_req, + 'out_top_poultry_req_stats_total_quantity': out_top_poultry_req_stats_total_quantity, + 'management_kill_house_data': management_kill_house_data, + 'duc_kill_house_data': duc_kill_house_data, + 'avg_losses': to_locale_str(int((aggregate_hatching['total_losses'] or 0) / poultry_hatching.count())), + 'avg_total_killed_weight': round( + (aggregate_hatching['total_killed_weight'] or 0) / (aggregate_hatching['killed_quantity'] or 0), 1), + 'total_killing_ave_age': int(aggregate_hatching['total_killing_ave_age'] or 0), + 'top_total_killed_weight': to_locale_str(top_total_killed_weight_first['total_killed_weight'] or 0), + 'total_quantity_top_inner': to_locale_str(total_quantity_top_inner), + 'total_quantity_top_out': total_quantity_top_out, + 'bar_assigment_pending_count1': to_locale_str(bar_assigment_pending_count1 or 0), + 'base_url': base_url_for_sms_report, + "total_quarantine_quantity": to_locale_str(aggregate_kill_house_request['total_quarantine_quantity'] or 0), + "total_count_has_quarantine": to_locale_str(aggregate_kill_house_request['total_count_has_quarantine'] or 0), + "total_quantity_has_quarantine": to_locale_str( + aggregate_kill_house_request['total_quantity_has_quarantine'] or 0), + "different": to_locale_str(different_bar or 0), + "total_weight_hasnt_code": to_locale_str(aggregate_kill_house_request['total_weight_hasnt_code'] or 0), + "total_quantity_hasnt_code": to_locale_str(aggregate_kill_house_request['total_quantity_hasnt_code'] or 0), + "total_id_hasnt_code": to_locale_str(aggregate_kill_house_request['total_id_hasnt_code'] or 0), + "total_weight_hasnt_warehouse": to_locale_str( + aggregate_kill_house_request['total_weight_hasnt_warehouse'] or 0), + "total_quantity_hasnt_warehouse": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_warehouse'] or 0), + "total_id_hasnt_warehouse": to_locale_str(aggregate_kill_house_request['total_id_hasnt_warehouse'] or 0), + "total_weight_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_weight_hasnt_assignment_state_archive'] or 0), + "total_quantity_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_assignment_state_archive'] or 0), + "total_id_hasnt_assignment_state_archive": to_locale_str( + aggregate_kill_house_request['total_id_hasnt_assignment_state_archive'] or 0), + "total_weight_hasnt_killing_age": to_locale_str( + aggregate_kill_house_request['total_weight_hasnt_killing_age'] or 0), + "total_quantity_hasnt_killing_age": to_locale_str( + aggregate_kill_house_request['total_quantity_hasnt_killing_age'] or 0), + "total_id_hasnt_killing_age": to_locale_str(aggregate_kill_house_request['total_id_hasnt_killing_age'] or 0), + 'color_different_bar': color_different_bar, + 'different_bar_percent': different_bar_percent, + 'tomorrow_of_date1': shamsi_date(tomorrow_of_date1), + 'tomorrow_of_date2': shamsi_date(tomorrow_of_date2), + + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) # noqa + css = CSS(string=''' + ''', font_config=font_config) + + pdf_file = io.BytesIO() + html.write_pdf(pdf_file, stylesheets=[css], font_config=font_config) + pdf_file.seek(0) + + response = HttpResponse(pdf_file, content_type='application/pdf') + filename = 'عملکرد کشتار زنجیره.pdf' + encoded_filename = quote(filename) # کدگذاری نام فایل برای URL + response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' + return response + + +def summary_report_pdf(request): + if base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + date1 = datetime.datetime.strptime(str(request.GET['date1']), '%Y-%m-%d').date() + date2 = datetime.datetime.strptime(str(request.GET['date2']), '%Y-%m-%d').date() + poultry_hatching = PoultryHatching.objects.filter(Q(date__date__gte=date1, date__date__lte=date2) | + Q(date__date__lte=date1, + archive_date__isnull=True) | Q(date__date__lte=date1, + archive_date__gte=date1, + archive_date__isnull=False), + trash=False).select_related('poultry', 'poultry__user__city') + kill_house_request = KillHouseRequest.objects.filter( + trash=False, + kill_request__recive_date__date__gte=date1, + kill_request__recive_date__date__lte=date2, + temporary_trash=False, + temporary_deleted=False + ).select_related('killhouse_user') + aggregate_kill_house_request = kill_house_request.aggregate( + id=Count('id'), + accepted_real_quantity=Sum('accepted_real_quantity'), + accepted_real_weight=Sum('accepted_real_weight'), + ) + kill_house_req_stats = kill_house_request.values('killhouse_user__name').annotate( + total_quantity=Sum('accepted_real_quantity'), + transaction_count=Count('id') + ).order_by('-total_quantity') + top_kill_house_req = kill_house_req_stats.first() if kill_house_req_stats else None + kill_house_name_req = "-" + transaction_count_req = 0 + total_quantity_top_inner = 0 + if top_kill_house_req: + kill_house_name_req = top_kill_house_req['killhouse_user__name'] + total_quantity_top_inner = top_kill_house_req['total_quantity'] + transaction_count_req = top_kill_house_req['transaction_count'] + + # max_kill_day_req = kill_house_request.values('kill_request__recive_date__date').annotate( + # daily_quantity=Sum('quantity') + # ).order_by('-daily_quantity').first() + # persian_date_req = '-' + # daily_quantity_req = '-' + # if max_kill_day_req: + # persian_date = shamsi_date(max_kill_day_req['date__date']) + # daily_quantity = to_locale_str(max_kill_day_req['daily_quantity']) + + poultry_req_stats = kill_house_request.values( + 'province_request__poultry_request__hatching__poultry__unit_name', + 'province_request__poultry_request__hatching__poultry__user__city__name') \ + .annotate(total_quantity=Sum('accepted_real_quantity'), + ).order_by('-total_quantity') + top_poultry_req_stats = poultry_req_stats.first() if poultry_req_stats else None + top_poultry_req_stats_total_quantity = 0 + poultry_req_name_req = "-" + poultry_city_req_name_req = "-" + if top_poultry_req_stats: + poultry_req_name_req = top_poultry_req_stats['province_request__poultry_request__hatching__poultry__unit_name'] + poultry_city_req_name_req = top_poultry_req_stats[ + 'province_request__poultry_request__hatching__poultry__user__city__name'] + top_poultry_req_stats_total_quantity = to_locale_str(top_poultry_req_stats['total_quantity'] or 0) + + poultry_hatching_gt_60 = poultry_hatching.filter(chicken_age__gt=60) + poultry_hatching_has_killed = poultry_hatching.filter(total_killed_weight__gt=0) + max_age_poultry = poultry_hatching_has_killed.order_by('-chicken_age').first() + min_age_poultry = poultry_hatching_has_killed.order_by('chicken_age').first() + aggregate_poultry_hatching_gt_60 = poultry_hatching_gt_60.aggregate( + total_quantity=Sum('quantity'), + left_over=Sum('left_over'), + ) + aggregate_hatching = poultry_hatching.aggregate( + total_quantity=Sum('quantity'), + total_losses_vet=Sum('losses'), + total_losses_union=Sum('direct_losses'), + total_losses=Sum('total_losses'), + killed_quantity=Sum('killed_quantity'), + total_killed_weight=Sum('total_killed_weight'), + left_over=Sum('left_over'), + total_killing_ave_age=Avg('poultry__killing_ave_age') + ) + top_total_killed_weight = poultry_hatching.values('id').annotate( + total_killed_weight=Sum('total_killed_weight'), + ).order_by('-total_killed_weight') + top_total_killed_weight_first = top_total_killed_weight.first() if top_total_killed_weight else None + + free_bars = KillHouseFreeBarInformation.objects.filter(date__date__gte=date1, + date__date__lte=date2, + trash=False).select_related('kill_house') + kill_house_stats = free_bars.values('kill_house__name').annotate( + total_quantity=Sum('quantity'), + total_live_weight=Sum('live_weight'), + transaction_count=Count('id') + ).order_by('-total_quantity') + + top_kill_house = kill_house_stats.first() if kill_house_stats else None + kill_house_name = "-" + total_quantity_top_out = 0 + transaction_count = "-" + if top_kill_house: + kill_house_name = top_kill_house['kill_house__name'] + transaction_count = to_locale_str(top_kill_house['transaction_count'] or 0) + total_quantity_top_out = to_locale_str(top_kill_house['total_quantity'] or 0) + # + out_poultry_req_stats = free_bars.values('poultry_name', 'province', 'city').annotate( + total_quantity=Sum('quantity'), + ).order_by('-total_quantity') + top_out_poultry_req_stats = out_poultry_req_stats.first() if out_poultry_req_stats else None + out_top_poultry_req_stats_total_quantity = 0 + out_poultry_req_name_req = "-" + out_poultry_city_req_name_req = "-" + out_poultry_province_req_name_req = "-" + if top_out_poultry_req_stats: + out_poultry_req_name_req = top_out_poultry_req_stats['poultry_name'] + out_poultry_city_req_name_req = top_out_poultry_req_stats['city'] + out_poultry_province_req_name_req = top_out_poultry_req_stats['province'] + out_top_poultry_req_stats_total_quantity = to_locale_str(top_out_poultry_req_stats['total_quantity'] or 0) + + # + aggregate_free_bars = free_bars.aggregate( + id=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + max_kill_day = free_bars.values('date__date').annotate( + daily_quantity=Sum('quantity') + ).order_by('-daily_quantity').first() + persian_date = '-' + daily_quantity = '-' + if max_kill_day: + persian_date = shamsi_date(max_kill_day['date__date']) + daily_quantity = to_locale_str(max_kill_day['daily_quantity']) + + kill_houses = KillHouse.objects.filter(trash=False, out_province=False).order_by('name') + kill_house_data = [] + duc_kill_house_data = [] + + for kh in kill_houses: + in_province_data = kill_house_request.filter( + killhouse_user=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('accepted_real_quantity'), + weight=Sum('accepted_real_weight') + ) + + out_province_data = free_bars.filter( + kill_house=kh + ).aggregate( + load_count=Count('id'), + quantity=Sum('quantity'), + live_weight=Sum('live_weight'), + ) + + in_qty = in_province_data.get('quantity', 0) or 0 + out_qty = out_province_data.get('quantity', 0) or 0 + total_quantity = in_qty + out_qty + + in_loads = in_province_data.get('load_count', 0) or 0 + out_loads = out_province_data.get('load_count', 0) or 0 + total_loads = in_loads + out_loads + + if in_qty > 0 or out_qty > 0 or in_loads > 0 or out_loads > 0: + kill_house_data.append({ + 'name': kh.name, + 'load_count': to_locale_str(total_loads or 0), + 'in_province_quantity': to_locale_str(in_qty or 0), + 'out_province_quantity': to_locale_str(out_qty or 0), + 'total_quantity': to_locale_str(total_quantity or 0), + }) + bar_assigment_pending_count1 = kill_house_request.filter(assignment_state_archive='True') \ + .exclude(bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + + steward_allocations = StewardAllocation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ).values('kill_house_id').annotate( + total_quantity=Sum('real_weight_of_carcasses') + ) + + steward_allocations_stats = steward_allocations.values('kill_house__name').annotate( + total_quantity=Sum('real_weight_of_carcasses'), + ).order_by('-total_quantity') + top_steward_allocations_stats = steward_allocations_stats.first() if steward_allocations_stats else None + + out_kill_house_top = "-" + out_weight_top = 0 + if top_steward_allocations_stats: + out_kill_house_top = top_steward_allocations_stats['kill_house__name'] + out_weight_top = to_locale_str(top_steward_allocations_stats['total_quantity'] or 0) + + free_bars = KillHouseFreeSaleBarInformation.objects.filter( + trash=False, + date__date__gte=date1, + date__date__lte=date2, + kill_house__in=kill_houses + ).values('kill_house_id', 'kill_house__name').annotate( + total_quantity=Sum('weight_of_carcasses') + ).order_by('-total_quantity') + + top_free_bars_stats = free_bars.first() if free_bars else None + + free_bars_kill_house_top = "-" + free_bars_weight_top = 0 + if top_free_bars_stats: + free_bars_kill_house_top = top_free_bars_stats['kill_house__name'] + free_bars_weight_top = to_locale_str(top_free_bars_stats['total_quantity'] or 0) + + in_province_data = kill_house_request.filter( + killhouse_user__in=kill_houses + ).values('killhouse_user_id').annotate( + total_quantity=Sum('accepted_real_weight') + ) + + in_warehouse_data = kill_house_request.filter( + killhouse_user__in=kill_houses, + ware_house_confirmation=True + ).values('killhouse_user_id').annotate( + total_quantity=Sum('ware_house_accepted_real_weight') + ) + + products = RolesProducts.objects.filter( + trash=False, + kill_house__in=kill_houses + ).values('kill_house_id', 'total_remain_weight') + + steward_dict = {item['kill_house_id']: item['total_quantity'] for item in steward_allocations} + free_bar_dict = {item['kill_house_id']: item['total_quantity'] for item in free_bars} + in_province_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_province_data} + in_warehouse_dict = {item['killhouse_user_id']: item['total_quantity'] for item in in_warehouse_data} + product_dict = {item['kill_house_id']: item['total_remain_weight'] for item in products} + + bar_assigment_true_count1 = kill_house_request.filter(assignment_state_archive='True') + bar_document_status_rejected1 = bar_assigment_true_count1.exclude( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + + percent_bar_document_status_rejected_all = int((bar_document_status_rejected1 / + bar_assigment_true_count1.count()) * 100) if \ + bar_assigment_true_count1.count() > 0 else 0 + + management_kill_house_data = [] + for kh in kill_houses: + kh_id = kh.id + + steward_qty = steward_dict.get(kh_id, 0) or 0 + free_bar_qty = free_bar_dict.get(kh_id, 0) or 0 + in_province_qty = in_province_dict.get(kh_id, 0) or 0 + in_warehouse_qty = in_warehouse_dict.get(kh_id, 0) or 0 + product_weight = product_dict.get(kh_id, 0) or 0 + + if any([in_province_qty, in_warehouse_qty, steward_qty, free_bar_qty]): + total = free_bar_qty + steward_qty + percent = round(total * 100 / in_province_qty, 1) if in_province_qty else 0 + + management_kill_house_data.append({ + 'name': kh.name, + 'in_province_quantity': to_locale_str(in_province_qty), + 'in_ware_house_quantity': to_locale_str(in_warehouse_qty), + 'steward_allocation_quantity': to_locale_str(steward_qty), + 'kill_house_free_bar_quantity': to_locale_str(free_bar_qty), + 'all_quantity': to_locale_str(total), + 'product': to_locale_str(product_weight), + 'percent': percent + }) + for kh in kill_houses: + kill_house_request1 = kill_house_request.filter( + killhouse_user=kh + ) + + bar_assigment_true_count = kill_house_request1.filter(assignment_state_archive='True') + bar_assigment_pending_count = kill_house_request1.filter(assignment_state_archive='pending').count() + bar_document_status_accepted = bar_assigment_true_count.filter( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + bar_document_status_rejected = bar_assigment_true_count.exclude( + bar_document_status__title__in=('تایید شده بدون کیفیت', 'تایید شد')).count() + + if bar_assigment_true_count.count() > 0 or bar_assigment_pending_count > 0: + duc_kill_house_data.append({ + 'name': kh.name, + 'kill_house_request1_count': kill_house_request1.count(), + "bar_assigment_true_count": bar_assigment_true_count.count(), + "bar_assigment_pending_count": bar_assigment_pending_count, + "bar_document_status_accepted": bar_document_status_accepted, + "percent_bar_document_status_accepted": int((bar_document_status_accepted / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + "bar_document_status_rejected": bar_document_status_rejected, + "percent_bar_document_status_rejected": int((bar_document_status_rejected / + bar_assigment_true_count.count()) * 100) if + bar_assigment_true_count.count() > 0 else 0, + + }) + + font_config = FontConfiguration() + + html_content = render_to_string('summary_report.html', { # noqa + 'number': 1234, + 'province': province, + "date": shamsi_date(datetime.datetime.now().date(), in_value=True), + "date1": request.GET['date1'], + "date2": request.GET['date2'], + "from_date": shamsi_date(date1), + "to_date": shamsi_date(date2), + "out_kill_house_top": out_kill_house_top, + "out_weight_top": out_weight_top, + "free_bars_weight_top": free_bars_weight_top, + "free_bars_kill_house_top": free_bars_kill_house_top, + "steward_sum_weight_sale": to_locale_str(sum(steward_dict.values())), + "free_bar_sum_weight_sale": to_locale_str(sum(free_bar_dict.values())), + "poultry_count": len(poultry_hatching.values_list('poultry', flat=True).distinct()), + "chain_count": len( + poultry_hatching.filter(Q(UnionTypeName='زنجیره') | + Q(chain_company__isnull=False)).values_list('poultry', flat=True).distinct()), + "poultry_hatching_quantity": to_locale_str(aggregate_hatching['total_quantity'] or 0), + "poultry_hatching_total_losses": to_locale_str(aggregate_hatching['total_losses'] or 0), + "poultry_hatching_killed_quantity": to_locale_str(aggregate_hatching['killed_quantity'] or 0), + "poultry_hatching_left_over": to_locale_str(aggregate_hatching['left_over'] or 0), + "poultry_hatching_gt_60": len(poultry_hatching_gt_60.values_list('poultry', flat=True).distinct()), + "poultry_hatching_gt_60_quantity": to_locale_str(aggregate_poultry_hatching_gt_60['total_quantity'] or 0), + "poultry_hatching_gt_60_left_over": round(((aggregate_poultry_hatching_gt_60['left_over'] or 0) / + (aggregate_poultry_hatching_gt_60['total_quantity'] or 0) * 100, + 1) if + (aggregate_poultry_hatching_gt_60['total_quantity'] or 0) < 0 else + 0), + "max_age_poultry": to_locale_str(max_age_poultry.chicken_age or 0), + "max_age_poultry_name": max_age_poultry.poultry.unit_name or '-', + "max_age_poultry_city": max_age_poultry.poultry.user.city.name if max_age_poultry.poultry.user.city else '-', + "min_age_poultry": to_locale_str(min_age_poultry.chicken_age or 0), + "min_age_poultry_name": min_age_poultry.poultry.unit_name or '-', + "min_age_poultry_city": min_age_poultry.poultry.user.city.name if min_age_poultry.poultry.user.city else '-', + + "kill_house_request_count": to_locale_str(aggregate_kill_house_request['id'] or 0), + "kill_house_request_quantity": to_locale_str(aggregate_kill_house_request['accepted_real_quantity'] or 0), + "kill_house_request_weight": to_locale_str(aggregate_kill_house_request['accepted_real_weight'] or 0), + "kill_house_request_average_weight": round( + aggregate_kill_house_request['accepted_real_weight'] / aggregate_kill_house_request[ + 'accepted_real_quantity'], 1) + if (aggregate_kill_house_request['accepted_real_quantity'] or 0) > 0 else 0, + "free_bars_count": to_locale_str(aggregate_free_bars['id'] or 0), + "free_bars_quantity": to_locale_str(aggregate_free_bars['quantity'] or 0), + "free_bars_live_weight": to_locale_str(aggregate_free_bars['live_weight'] or 0), + "kill_house_name": kill_house_name, + "transaction_count": transaction_count, + "persian_date": persian_date, + "transaction_count_req": transaction_count_req, + "daily_quantity": daily_quantity, + 'kill_houses_data': kill_house_data, + 'kill_house_name_req': kill_house_name_req, + 'poultry_req_name_req': poultry_req_name_req, + 'top_poultry_req_stats_total_quantity': top_poultry_req_stats_total_quantity, + 'poultry_city_req_name_req': poultry_city_req_name_req, + 'out_poultry_req_name_req': out_poultry_req_name_req, + 'out_poultry_city_req_name_req': out_poultry_city_req_name_req, + 'out_poultry_province_req_name_req': out_poultry_province_req_name_req, + 'out_top_poultry_req_stats_total_quantity': out_top_poultry_req_stats_total_quantity, + 'management_kill_house_data': management_kill_house_data, + 'duc_kill_house_data': duc_kill_house_data, + 'avg_losses': to_locale_str(int((aggregate_hatching['total_losses'] or 0) / poultry_hatching.count())), + 'avg_total_killed_weight': round( + (aggregate_hatching['total_killed_weight'] or 0) / (aggregate_hatching['killed_quantity'] or 0), 1), + 'total_killing_ave_age': int(aggregate_hatching['total_killing_ave_age'] or 0), + 'top_total_killed_weight': to_locale_str(top_total_killed_weight_first['total_killed_weight'] or 0), + 'total_quantity_top_inner': to_locale_str(total_quantity_top_inner), + 'total_quantity_top_out': total_quantity_top_out, + 'bar_assigment_pending_count1': to_locale_str(bar_assigment_pending_count1 or 0), + 'base_url': base_url_for_sms_report, + 'percent_bar_document_status_rejected_all': percent_bar_document_status_rejected_all, + + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) # noqa + css = CSS(string=''' + ''', font_config=font_config) + + pdf_file = io.BytesIO() + html.write_pdf(pdf_file, stylesheets=[css], font_config=font_config) + pdf_file.seek(0) + + response = HttpResponse(pdf_file, content_type='application/pdf') + filename = 'عملکرد کشتار زنجیره.pdf' + encoded_filename = quote(filename) # کدگذاری نام فایل برای URL + response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' + return response + + +def hatching_detail_pdf(request): + if base_url_for_sms_report == 'ha': + province = 'همدان' + elif base_url_for_sms_report == 'ku': + province = 'کردستان' + elif base_url_for_sms_report == 'ma': + province = 'مرکزی' + elif base_url_for_sms_report == 'bu': + province = 'بوشهر' + else: + province = 'تست' + hatching = PoultryHatching.objects.filter( + trash=False, + key=request.GET['key'] + ).select_related('poultry').first() + ser_data = PoultryHatchingForDetailsSerializer(hatching).data + kill_requests = KillHouseRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=hatching, + ware_house_confirmation=True + ).select_related( + 'killhouse_user', + 'killer', + 'province_request', + 'province_request__poultry_request', + 'kill_request' + ).order_by('-create_date') + ser_data_kill_request = KillHouseRequestForHatchingDetailSerializer(kill_requests, many=True).data + + poultry_requests = PoultryRequest.objects.filter(hatching=hatching, trash=False, + state_process__in=('pending', 'accepted'), + province_state__in=('pending', 'accepted'), out=True, + out_province_request_cancel=False, + temporary_trash=False, + temporary_deleted=False) + + ser_data_poultry_request = PoultryRequestForHatchingDetailSerializer(poultry_requests, many=True).data + + chain_allocation = ChainAllocation.objects.filter(trash=False, state='accepted', poultry_hatching=hatching) + ser_data_chain_allocation = ChainAllocationForHatchingDetailSerializer(chain_allocation, many=True).data + + evacuation_reports = [] + if hatching: + detail_qs = hatching.evacuation_details.filter(trash=False).order_by('-ReportDate', '-create_date') + evacuation_reports = EvacuationHatchingDetailSerializer(detail_qs, many=True).data + + poultry_hatching_licence_number = hatching.licence_number + response = requests.post( + f'https://rsibackend.rasadyar.com/app/send_different_bar_with_licence_number/?' + f'licence_number={poultry_hatching_licence_number}' + f'&date1={None}&date2={None}', + headers={'Content-Type': 'application/json'} + ) + + kill_requests_non_receipt = KillHouseRequest.objects.filter( + trash=False, + province_request__poultry_request__hatching=hatching, + non_receipt=True, main_non_receipt=True + ).select_related( + 'killhouse_user', + 'killer', + 'province_request', + 'province_request__poultry_request', + 'kill_request' + ).order_by('-create_date') + ser_data_non_receipt_kill_request = KillHouseRequestForHatchingDetailSerializer(kill_requests_non_receipt, + many=True).data + bar_requests = BarDifferenceRequest.objects.filter(trash=False, + state='accepted', hatching=hatching).order_by('id') + bar_request_serilizer = BarDifferenceRequestSerializer(bar_requests, many=True).data + + hatching_increase = HatchingIncreaseRequest.objects.filter(trash=False, hatching=hatching).order_by('-date') + hatching_increase_serilizer = HatchingIncreaseRequestSerializer(hatching_increase, many=True).data + filters = { + 'archive_wage': False, + 'state__in': ('pending', 'accepted'), + 'first_car_allocated_quantity': 0 + } + return_province_kill_requests = ProvinceKillRequest.objects.filter( + Q(trash=False, return_to_province=True) | Q(trash=True, return_trash=True), **filters, + province_request__poultry_request__hatching=hatching).order_by('id') + return_province_kill_requests_serializer = ReturnProvinceKillRequestSerializer(return_province_kill_requests, + many=True).data + + kill_house_requests_return = KillHouseRequest.objects.filter( + Q(non_receipt=True, main_non_receipt=True, non_receipt_state='accepted') | Q(trash=True, return_trash=True), + province_request__poultry_request__hatching=hatching) + kill_house_requests_return_serializer = KillHouseRequestForBarManagementSerializer(kill_house_requests_return, + many=True).data + font_config = FontConfiguration() + + html_content = render_to_string('poultry_datail.html', { # noqa + 'province': province, + "shamsi_date": shamsi_date(datetime.datetime.now().date(), in_value=True), + "hatching_date": shamsi_date(hatching.date, in_value=True), + "create_date_hatching": shamsi_date(hatching.create_date, in_value=True), + "predicate_date_hatching": shamsi_date(hatching.predicate_date, + in_value=True) if hatching.predicate_date else '-', + **ser_data, + "bars": ser_data_kill_request[:20] if len(ser_data_kill_request) > 20 else ser_data_kill_request, + "bars2": ser_data_kill_request[20:] if len(ser_data_kill_request) > 20 else None, + 'outBars': ser_data_poultry_request[:20] if len(ser_data_poultry_request) > 20 else ser_data_poultry_request, + 'outBars2': ser_data_poultry_request[20:] if len(ser_data_poultry_request) > 20 else None, + 'chainAllocation': ser_data_chain_allocation[20:] if len( + ser_data_chain_allocation) > 20 else ser_data_chain_allocation, + 'chainAllocation2': ser_data_chain_allocation[20:] if len(ser_data_chain_allocation) > 20 else None, + 'percent_rasadyar1': round( + ((ser_data['killed_quantity'] + ser_data['total_losses']) * 100) / ser_data['quantity']) + if ser_data['quantity'] > 0 else 0, + 'active_kill1': 'دارد' if ser_data['active_kill']['active_kill'] else 'ندارد', + "differentBars": response.json()[:20], + "differentBars2": response.json()[20:], + "nonReceipt": ser_data_non_receipt_kill_request, + "returnProvinceRequest": return_province_kill_requests_serializer, + "returnKillHouseRequest": kill_house_requests_return_serializer, + "killingDifference": bar_request_serilizer, + "hatchingIncrease": hatching_increase_serilizer, + "evacuation_reports": evacuation_reports, + + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) # noqa + css = CSS(string=''' + ''', font_config=font_config) + + pdf_file = io.BytesIO() + html.write_pdf(pdf_file, stylesheets=[css], font_config=font_config) + pdf_file.seek(0) + + response = HttpResponse(pdf_file, content_type='application/pdf') + filename = 'عملکرد کشتار زنجیره.pdf' + encoded_filename = quote(filename) # کدگذاری نام فایل برای URL + response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' + return response + + +def poultry_science_report_pdf(request): + """ + تولید PDF گزارش بازرسی مرغداری + ساختار JSON بر اساس کد React: + - generalConditionHall, casualties, technicalOfficer + - inputStatus, infrastructureEnergy, facilities, hr + - inspectionNotes, inspectionStatus + """ + font_config = FontConfiguration() + report = PoultryScienceReport.objects.filter( + trash=False, + key=request.GET['key'] + ).select_related( + 'hatching', + 'hatching__poultry', + 'hatching__poultry__user', + 'hatching__poultry__user__city', + 'hatching__poultry__address', + 'poultry_science', + 'poultry_science__user', + 'user' + ).first() + + if not report: + return HttpResponse("گزارش یافت نشد", status=404) + + report_data = report.report_information or {} + hatching = report.hatching + poultry = hatching.poultry if hatching else None + + # استخراج بخش‌های مختلف JSON (با snake_case) + general_condition = report_data.get('general_condition_hall', {}) or {} + casualties = report_data.get('casualties', {}) or {} + technical_officer = report_data.get('technical_officer', {}) or {} + input_status_data = report_data.get('input_status', {}) or {} + infrastructure_energy = report_data.get('infrastructure_energy', {}) or {} + facilities = report_data.get('facilities', {}) or {} + hr = report_data.get('hr', {}) or {} + + # تابع کمکی برای مقادیر + def safe_get(data, key, default='---'): + if not isinstance(data, dict): + return default + value = data.get(key) + return value if value not in [None, '', 'null'] else default + + def format_number(value): + if value is None: + return '---' + try: + return f"{int(value):,}" + except (ValueError, TypeError): + return str(value) if value else '---' + + # اطلاعات سربرگ + inspection_date = shamsi_date(report.date, in_value=True) if report.date else '---' + report_id = report.report_id or '---' + unit_name = poultry.unit_name if poultry else '---' + breeding_unique_id = poultry.breeding_unique_id if poultry else '---' + licence_number = hatching.licence_number if hatching else '---' + city = poultry.user.city.name if poultry and poultry.user and poultry.user.city else '---' + hatching_date = shamsi_date(hatching.date, in_value=True) if hatching and hatching.date else '---' + initial_quantity = format_number(hatching.quantity) if hatching else '---' + + # وضعیت بازرسی + status_map = {'pending': 'در انتظار', 'accepted': 'تایید شده', 'rejected': 'رد شده'} + inspection_status = status_map.get(report.state, report.state or 'در انتظار') + + # === بخش اطلاعات (informationData) === + health_permit = poultry.health_certificate_number if poultry and hasattr(poultry, + 'health_certificate_number') else '---' + epidemiological_code = poultry.epidemiological_code if poultry and hasattr(poultry, + 'epidemiological_code') else '---' + permit_validity = format_number(poultry.operating_licence_capacity) if poultry and hasattr(poultry, + 'operating_licence_capacity') else '---' + tenant_status = hatching.InteractTypeName if hatching and hatching.InteractTypeName else ( + 'دارد' if (hatching and hasattr(hatching, 'has_tenant') and hatching.has_tenant) else 'ندارد') + owner_name = poultry.user.fullname if poultry and poultry.user else '---' + ownership_type = hatching.InteractTypeName if hatching else '---' + owner_national_code = (poultry.user.national_id if hasattr(poultry.user, 'national_id') and poultry.user.national_id + else (poultry.user.national_code if hasattr(poultry.user, + 'national_code') else '---')) if poultry and poultry.user else '---' + province = poultry.address.province.name if poultry and poultry.address and hasattr(poultry.address, + 'province') and poultry.address.province else '---' + coordinates = f"{report.lat}, {report.log}" if report.lat and report.log else ( + f"{poultry.Lat}, {poultry.Long}" if poultry and hasattr(poultry, 'Lat') and poultry.Lat else '---') + owner_mobile = poultry.user.mobile if poultry and poultry.user else '---' + nominal_capacity = format_number(poultry.total_capacity) if poultry and hasattr(poultry, + 'total_capacity') else '---' + vet_quantity = format_number(hatching.quantity) if hatching else '---' + self_declared_quantity = format_number(hatching.quantity) if hatching else '---' + chick_source = safe_get(casualties, 'source_of_hatching') + chicken_age = f"{hatching.chicken_age} روز" if hatching and hatching.chicken_age else '---' + breed_type = hatching.chicken_breed if hatching else '---' + + # === بخش پایش سلامت (healthMonitoringData) === + health_status = safe_get(general_condition, 'health_status') + ventilation_status = safe_get(general_condition, 'ventilation_status') + bedding_status = safe_get(general_condition, 'bed_condition') + temperature_humidity = f"{general_condition.get('temperature')} درجه" if general_condition.get( + 'temperature') else '---' + water_quality = safe_get(general_condition, 'drinking_water_quality') + water_source = safe_get(general_condition, 'drinking_water_source') + normal_losses = format_number(casualties.get('normal_losses')) if casualties.get( + 'normal_losses') is not None else '---' + abnormal_losses = format_number(casualties.get('abnormal_losses')) if casualties.get( + 'abnormal_losses') is not None else '---' + abnormal_losses_reason = safe_get(casualties, 'cause_abnormal_losses') + disease_type = safe_get(casualties, 'type_disease') + sampling_done = 'بله' if casualties.get('sampling_done') else 'خیر' + sample_type = safe_get(casualties, 'type_sampling') + health_responsible = safe_get(technical_officer, 'technical_health_officer') + engineering_responsible = safe_get(technical_officer, 'technical_engineering_officer') + + # === بخش زیرساخت (infrastructureData) === + input_status = safe_get(input_status_data, 'input_status') + feed_type = safe_get(input_status_data, 'type_of_grain') + feed_quality = safe_get(input_status_data, 'grade_grain') + inventory_until_visit = safe_get(input_status_data, 'inventory_until_visit') + warehouse_inventory = safe_get(input_status_data, 'inventory_in_warehouse') + tracking_code = safe_get(input_status_data, 'tracking_code') + company_name = safe_get(input_status_data, 'company_name') + generator_type = safe_get(infrastructure_energy, 'generator_type') + generator_model = safe_get(infrastructure_energy, 'generator_model') + generator_count = safe_get(infrastructure_energy, 'generator_count') + fuel_type = safe_get(infrastructure_energy, 'fuel_type') + generator_capacity = format_number(infrastructure_energy.get('generator_capacity')) + emergency_fuel = format_number(infrastructure_energy.get('emergency_fuel_inventory')) + power_cut_history = 'بله' if infrastructure_energy.get('has_power_cut_history') else 'خیر' + power_cut_duration = f"{infrastructure_energy.get('power_cut_duration')} ساعت" if infrastructure_energy.get( + 'power_cut_duration') else '---' + power_cut_hour = safe_get(infrastructure_energy, 'power_cut_hour') + generator_status = safe_get(infrastructure_energy, 'generator_performance') + additional_notes = safe_get(infrastructure_energy, 'additional_notes') + + # نیروی انسانی + employee_count = safe_get(hr, 'number_employed') + local_employee_count = safe_get(hr, 'number_indigenous') + non_local_employee_count = safe_get(hr, 'number_non_indigenous') + worker_contract_status = safe_get(hr, 'contract_status') + health_training = 'بله' if hr.get('trained') else 'خیر' + + # تسهیلات + active_facilities = 'بله' if facilities.get('has_facilities') else 'خیر' + facility_type = safe_get(facilities, 'type_of_facility') + facility_amount = format_number(facilities.get('amount')) + repayment_status = safe_get(facilities, 'repayment_status') + new_request = safe_get(facilities, 'request_facilities') + facility_date = shamsi_date(facilities.get('date')) if facilities.get('date') else '---' + + # مستندات + hall_images = general_condition.get('images', []) or [] + warehouse_images = input_status_data.get('images', []) or [] + losses_images = casualties.get('images', []) or [] + violation_images = hatching.violation_image if hatching and hasattr(hatching, + 'violation_image') and hatching.violation_image else [] + + # توصیه‌ها + recommendations = report_data.get('inspection_notes', '---') or '---' + inspection_status_text = report_data.get('inspection_status', '---') or '---' + + # احراز مسئول سالن (از vet_farm جوجه‌ریزی) + vet_farm = None + if hatching: + from panel.models import VetFarm + vet_farm = VetFarm.objects.filter(poultry=poultry, trash=False).first() + + hall_responsible_present = 'بله' if (vet_farm and vet_farm.vet and vet_farm.vet.user) else 'خیر' + hall_responsible_name = vet_farm.vet.user.fullname if vet_farm and vet_farm.vet and vet_farm.vet.user else '---' + hall_responsible_phone = vet_farm.vet.user.mobile if vet_farm and vet_farm.vet and vet_farm.vet.user else '---' + + html_content = render_to_string('poultry_science_report.html', { + # سربرگ + 'inspection_date': inspection_date, + 'report_id': report_id, + 'unit_name': unit_name, + 'breeding_unique_id': breeding_unique_id, + 'licence_number': licence_number, + 'city': city, + 'hatching_date': hatching_date, + 'initial_quantity': initial_quantity, + 'inspection_status': inspection_status, + + # اطلاعات واحد + 'health_permit': health_permit, + 'hatching_licence': licence_number, + 'epidemiological_code': epidemiological_code, + 'permit_validity': permit_validity, + 'tenant_status': tenant_status, + 'owner_name': owner_name, + 'ownership_type': ownership_type, + 'owner_national_code': owner_national_code, + 'province': province, + 'coordinates': coordinates, + 'owner_mobile': owner_mobile, + 'nominal_capacity': nominal_capacity, + 'vet_quantity': vet_quantity, + 'self_declared_quantity': self_declared_quantity, + 'chick_source': chick_source, + 'chicken_age': chicken_age, + 'breed_type': breed_type, + + # پایش سلامت + 'health_status': health_status, + 'ventilation_status': ventilation_status, + 'bedding_status': bedding_status, + 'temperature_humidity': temperature_humidity, + 'water_quality': water_quality, + 'water_source': water_source, + 'normal_losses': normal_losses, + 'abnormal_losses': abnormal_losses, + 'abnormal_losses_reason': abnormal_losses_reason, + 'disease_type': disease_type, + 'sampling_done': sampling_done, + 'sample_type': sample_type, + 'health_responsible': health_responsible, + 'engineering_responsible': engineering_responsible, + + # زیرساخت + 'input_status': input_status, + 'feed_type': feed_type, + 'feed_quality': feed_quality, + 'inventory_until_visit': inventory_until_visit, + 'warehouse_inventory': warehouse_inventory, + 'tracking_code': tracking_code, + 'company_name': company_name, + 'generator_type': generator_type, + 'generator_model': generator_model, + 'generator_count': generator_count, + 'fuel_type': fuel_type, + 'generator_capacity': generator_capacity, + 'emergency_fuel': emergency_fuel, + 'power_cut_history': power_cut_history, + 'power_cut_duration': power_cut_duration, + 'power_cut_hour': power_cut_hour, + 'generator_status': generator_status, + 'additional_notes': additional_notes, + + # نیروی انسانی + 'employee_count': employee_count, + 'local_employee_count': local_employee_count, + 'non_local_employee_count': non_local_employee_count, + 'worker_contract_status': worker_contract_status, + 'health_training': health_training, + 'active_facilities': active_facilities, + 'facility_type': facility_type, + 'facility_amount': facility_amount, + 'repayment_status': repayment_status, + 'new_request': new_request, + 'facility_date': facility_date, + + # مستندات + 'hall_images': hall_images, + 'warehouse_images': warehouse_images, + 'losses_images': losses_images, + 'violation_images': violation_images, + + # توصیه‌ها و احراز + 'recommendations': recommendations, + 'inspection_status_text': inspection_status_text, + 'hall_responsible_present': hall_responsible_present, + 'hall_responsible_name': hall_responsible_name, + 'hall_responsible_phone': hall_responsible_phone, + }) + + html = HTML(string=html_content, base_url=request.build_absolute_uri()) + css = CSS(string='', font_config=font_config) + + pdf_file = io.BytesIO() + html.write_pdf(pdf_file, stylesheets=[css], font_config=font_config) + pdf_file.seek(0) + + response = HttpResponse(pdf_file, content_type='application/pdf') + filename = f'گزارش بازرسی {report_id}.pdf' + encoded_filename = quote(filename) + response['Content-Disposition'] = f'attachment; filename*=UTF-8\'\'{encoded_filename}' + return response diff --git a/province_orderid.py b/province_orderid.py new file mode 100644 index 0000000..2913609 --- /dev/null +++ b/province_orderid.py @@ -0,0 +1,5 @@ +test_order_id=10 +sha_order_id=15 +ha_order_id=18 +ar_order_id=91 +ma_order_id=47 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b5a5296 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,92 @@ +aiohttp==3.8.3 +aiosignal==1.3.1 +amqp==5.1.1 +asgiref==3.4.1 +async-timeout==4.0.2 +attrs==23.1.0 +backports.weakref==1.0.post1 +billiard==3.6.4.0 +boto3==1.22.2 +botocore==1.25.2 +beautifulsoup4==4.12.3 +cached-property==1.5.2 +celery==5.2.7 +certifi==2021.10.8 +cffi==1.15.0 +charset-normalizer==2.0.12 +click==8.1.3 +click-didyoumean==0.3.0 +click-plugins==1.1.1 +click-repl==0.2.0 +crypto==1.4.1 +cryptocode==0.1 +cryptography==36.0.2 +Deprecated==1.2.13 +Django==3.2.13 +django-cors-headers==3.10.1 +django-debug-toolbar==3.2.4 +django-environ==0.9.0 +django-extensions==3.1.5 +django-filter==21.1 +django-jalali==5.1.0 +django-oauth-toolkit==1.7.1 +django-oauth2-provider==0.2.6.1 +django-redis==5.2.0 +django-split-settings==1.2.0 +django-url-filter==0.3.15 +djangorestframework==3.13.1 +djangorestframework-recursive==0.1.2 +docopt==0.6.2 +enum-compat==0.0.3 +et-xmlfile==1.1.0 +frozenlist==1.3.3 +gunicorn==20.1.0 +idna==3.3 +importlib-metadata==4.8.3 +jdatetime==3.8.2 +jmespath==0.10.0 +jwcrypto==1.0 +kombu==5.2.4 +multidict==6.0.4 +Naked==0.1.31 +num2fawords==1.1 +oauth2-provider==0.0 +oauthlib==3.2.0 +openpyxl==3.1.2 +packaging==21.3 +Pillow==9.2.0 +prompt-toolkit==3.0.38 +psycopg2-binary==2.9.3 +pyasn1==0.4.8 +pycparser==2.21 +pycryptodomex==3.14.1 +pyOpenSSL==22.0.0 +pyparsing==3.0.8 +python-dateutil==2.8.2 +pytz==2022.1 +PyYAML==6.0 +python-dotenv +redis==4.2.2 +requests==2.27.1 +rsa==4.8 +s3transfer==0.5.2 +schedule==1.1.0 +semantic-version==2.9.0 +setuptools-rust==1.1.2 +shellescape==3.8.1 +shortuuid==1.0.8 +six==1.16.0 +sqlparse==0.4.2 +suds==1.1.1 +tablib==3.2.1 +typing-extensions==4.1.1 +urllib3==1.26.9 +vine==5.0.0 +wcwidth==0.2.6 +wrapt==1.14.0 +weasyprint==65.1 +xlrd==2.0.1 +XlsxWriter==3.0.3 +yarl==1.9.2 +zipp==3.6.0 +utm==0.7.0 \ No newline at end of file diff --git a/samasat_cron.py b/samasat_cron.py new file mode 100644 index 0000000..6ec5322 --- /dev/null +++ b/samasat_cron.py @@ -0,0 +1,10 @@ +import os +import django + + +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "KuChicken.settings") + +django.setup() +from ticket.views import bot_eitaa_for_bar + +bot_eitaa_for_bar() diff --git a/static/assets/fonts/BNaznnBd.ttf b/static/assets/fonts/BNaznnBd.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8adddd0c4ae3463fff0075c5b1331cb1eea6edd7 GIT binary patch literal 60716 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 Rc2rZb?h^uG`&1R{{{eCks-OS> literal 0 HcmV?d00001 diff --git a/static/assets/fonts/btitrb.ttf b/static/assets/fonts/btitrb.ttf new file mode 100644 index 0000000000000000000000000000000000000000..b44e2977656435a1dd7c01b9f2955e418c6e7b4d GIT binary patch literal 62008 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"?HNly@B6UD(Z0%N`>{=D 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 literal 0 HcmV?d00001 diff --git a/static/assets/fonts/nazanin.ttf b/static/assets/fonts/nazanin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..bcc1f753434bc9a48ba19b4ed3e7e2a45668adf1 GIT binary patch literal 61560 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"?HNly@B6UD(Z0%N`>{=D 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 literal 0 HcmV?d00001 diff --git a/static/assets/img/bazrasi.png b/static/assets/img/bazrasi.png new file mode 100644 index 0000000000000000000000000000000000000000..ff08f88e0e95242d714640565169d89625155c0b GIT binary patch literal 231264 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 ?(K<0t2(PkGlq-zYp+Q$x+Xrn12wJn`Y|l4KcL> z?E*H^R%3!cny*Ps?$|{xUFBQwc9Yo2o#f1tCCzp0SZ$ zD3+WZh_PcdlJa1NRD4IC%Q-FFcpSx!6rkM8P-72f^smep5Yj2nJxWVu=BzPaM-{cR zM7#hh8PLglZ8ObJ!`N97Qk(%3J3MI>#WSoBdIqiP_;y65;%r|`dM786V6z8geUXzs zNDq-2wC_3_~`MB=8+Zc_kLMWXn&~M~9F&9@G z9z(j5?CV$~Jr^)kjk@v*NQrDA#=y3b2E!K2!~zFI(i1Pya_hkxFCv}P@X z$&+sh^U{p(474U%Q}Zd&gO+nq{dOLtY&)y`lR7 z_Pw{~Dshf8y3I%@v549vdxj*0Wzt zE)_Zkb(NHz$FrojbO^&kCqo9gIzzhbGwEUXMz2MS9AfSRZLFJ^=Hc zZqZ{%Ux%a3c|OaT@`!6<0FZUO+k#!~9kJ~|HGeMC3z7V<8@=l5ael>4-_V`N0N8~$ z+6Ml)D7B=up45Jnk9fJAyvq+%jpORBuz)eiJ3kbL)-`KDeBxJ2jb-Wp9=cJciV1)- zcuwguO1VU{AK!kxBv)TvgrVRki(wiS__$Oa7xl>Vd881R6X8px?jWZamWzUO4qlco zUJO}MfT1|%l3yjg11dR9jdYlYI477z8OACy!+#If4(#?w;hxxlhrw5e13wC{Wdu2I z)G0l+PvFUPEWIXCZpui|kB%ARo5si=Prq>=-x*F(%q|--5T^2!Ns4TctfEa|&wVa6 zf0?VOU^420K?BcxEQ7g25Y2o3&s>%{eutMt7ezDX1xX)D*ByNQ3wDgXZHE9~3@%~8(Xm4@ z88H*Jaw(gz5Q2#ESzFjVs)>0p+cB)D8yeAKAopr2eM0cO0#$-dDo9=K{pDu!L7@=s zL7~z7IaCLF!jhkV(&QLcBO<3)?71@H=Wkhku{wRs^SmH0)|E2iN?DXtO2va7>?T`+ zcsZWZ3U0LB;SB(}Lb}N96j#4J4AQ(HE^cIPH1QX~c|byJNGcDB$1zr;*0z zxDXlLuMT+>BW>>uutD1qsCC7bDwi9}@Qx_XTBeU7&W_H>w#k87jgD`t$%@3MdCZ%j z{E}j%a=qYl?T(7SlWJsnW6)e8dJ^37CbjGAb&+#yH^}0@$d*cn;~BD_1lm5=GKth! z{9=PDYbI;G|7i;NbX~t&F+P!fdQ>b{7E45qUJx)qoG0DMfc=SSQI2e_Okn=vrwifo zW9?l;-v2y_VG;p~9C#%bM73U$Xr9n^N#UX0_9BFr4a-wylbb|iN1vFaLoEAcZ3Z>nI_{j z!yMjrd5N0bH#(8g;@$8IN#J2It~1tf(=gVtEKKQ-gpl$oF@_9-GiTI3Yd`hfI)!l_ zVb;|E>Tyu{1#}ID$-+H@CY^FTA|{r`gB_Xhq9Q$e5iq1jY_9sDtI`MEVTBvHrJ83B z&GXE-Xu;+^HDF)$9EQ+OxK94;h|P*=F#DNjaUpvMk=~Np5$y!3iB^IXuYeVlw7nMU zp`UkIG1|_8PuFgPnK5<3zvkyDh10SO(548oKtInQ;ZszqW$zznw&}bK>0~$f3dpP& z$YedYlC<%M_!rXIC9yW{zf%zDTI}xBi3jW+wfr4~=DvSsHOo|#j0nE`?+J{hh%2Z9 zbSN%90(kqBJ!P0-LaTU@^5goL`ZPh!sJBkDYz1#}DpA&vk+Gb}>iC=)hjXy*)zi)O zHykL*!x9xsx&2=@2j+NYi;Y%Q%v3?c`);`j&dW8621DSf94)>CUGI<6r5x&}>j82C z8lAR&vwMCrsuGT(gLwQy9Kd&NL^Be0h4ot-&Q87lru)r7 zuOxWfO;Wz8VBXAhY;B5{Fy1}AGaW_*y>uEf7^?p}KDfHDh%Ptjt_G^Nj6+pu@j*4u z)%kc!(jyr)8DN>pqY^>mFs(xSt3!uT{_erF<@8wJ4_`CJKh@U%fN>F|>G^sW#?ej~ zzNsZB4~AObyy!4^PH`fj;N-dvN%g}?U;r@^0Ff zN5~FJ0&ITteWN2lB30d#=lR{*49d$Zd*05 zsNh%<5W#wJ0zHE2sTbh$A)6bQUuL#^th#x;8^@0c&vN)@FM;Q>Y5mLy{iF7A;IOug z+uFB0t#&-mOe+fGO?yd*wEeQHoYI|Imeq!VX6WeTsAZndwJcw7L&UQcfdRZzi_$8o z8<`Q7=i0Wflu7r1isAqj#b$NZ(^`t&fut2979`g%J~uUX@pJhOkqV(P4h=lAOxJm*8#Y|@(RAFOj# zg$^W0!JG_$CL~cc;e21?{W<6R4ztF(f-a&;Bf&wDIYWoO$dSdi%EPIHX;TdiDHCRh zP>XuDJL39rEE%P4s)3JsqeQ%7HnNe&l)F>n(R-EI9p(mShoPpeO%9?IV_qfz+?0_^ zVwLP&G)00BLn!6-V(#T8)7jh?FK360UFh($fr!O}Bd^`rBl&}|J+FrSz^%=_KL^sD zDxsa=6siqLxz;m|10M@qD>N{Bi49wMmIAu0AwGNuexS8gxLRk)!==mP|2GfeGB3yh zT_@YqDIx8)5=9cM&Q*I`)=l>OsyYe4F3mV54v+7K|6Wr^&F-}B2IitCNV_6fB5Y{C z^6@2!z9233m7cFAJ;H@Ic7w{U3>&w&oo(AB{8PyR7IMNE`~?42)HpiBS4hP@(I+@g z`9&8Si)sk$^<}$PSZqtQzM9hJX&WCvWxrc;iRv{v77E-knhI!zAl{9rWUR=Y?Fy9I z^(_sa9{kODz+|yw>7FX6F`{XBU%ugXEn6;Gy}Z=~RMS4%{!1F+T;&=c`wf#zZ*h~= zx9gN-kuK0e_wyScF? zRsDBkYtROe#Jrd$zTD~1Xq#r++4#m@vO($gp>#Zg9_9N6LWUzN&(ou(SzJ7OFAa|6 ziy-9L<^_RxG*a_D@W17@0G}z@Mjf;NuKs9mcIXJj%Kh9@rFHh%QCjQ~cBBbqez41l zoG&`ctT}l0cV(-b=BRj3v;-n}GVi^30=bzeyYf7|?WGZ0`i5N)+yP{BE};(D=PLmh zNfNKaOCTQQRL>1S?ZWhSvbu7CCldls#tj8kMBjdZ9(HNk8kA~aEv`HHfieR4V37wo zuQ-NCJHHe@bNHyN3MF5S3PZwRZ~z%Ul+uiJ)&a?s)J8{W5i%}jV&O?o&6Y^`5;PfG5MA2y2L zEEP}jD@p}#N~4rhf!ym>Onnk;vU52yYIL%9-mAH!BLAU|HOI5UHIaxAxNrgostBYs zmW&(gljolrXD7w4CP?rCOdCm-hcLA$@VQ7C$FDj+71&+$30AL8DG;pO`2x}};EIWu zzo!PL{}{4_H~Eh|-a3E8r61|_{ty$DTMnX#wAkE)vAEV((@jghQnyy?a<1kW%J;Pu z=hV;lw(m3gd$APBeV#Paz=Fa-i=4vN?CgX|gGjk0o><0i0|H($b=nb9U3VV)6kPH4 zc;c$8OB->mW_P3_{rjm~x}E_eWIBQJ{1}UcP{gh5kl56XS7({93F5hi0n7bO#^xB| zn%~pM2o}?ehdr?TV>h#y3O#hQ28=YrRuRDk{KMcP{_h&@3RT&Os!U zQNt^_2_a{ggV>4Prp~Re6Ndqxz&Dpf*NQ%L^OE}dvQb8 zX}a)zzs`TdL5C!9m(0adGaYMh3q0k)|2vkVx))A4vx{h3nK7M;+mGs%V(MMEpF_%yIqcIkxeUQG3g6vhC!q=UBRE<5Hdd^x$KFPRxV4UUVGPpB*(U* zWtt^A0wVWi=Y}jF8u3X{@rT$nN_7i@Zr4Q<3e-xM8;+$eAFQtuqlh{}xQ3v3?ZGk@ z+YLiwhJRz7)$&E9boFx!EjKDZjvR%_E^%-kMR%ODabvSjrBch~u`Z6~w5Vl&{DJc9WNbbma7@369T?wS|Nm&sPvb|!cgdP z)0V9mTRDMtnc*)YeWZ?&8T{ic+F zseI2uVDO`0b)Q%fa2c*1G;7N%XWr((39|=v{6zKyBYZXoPA1j8H1l0SEI0)|m5YgI zVd$4G*NeDXBPQ0f1$*Y>($)mziOl%RFbNfL{q-)TH)c9d%RiK-b+irt`yYUhouJtc zD_cY|o#ojg{_e2&VcASAUb4_XpTs>8lg0SkH$F1q4y)GPPQf0cLGU{yZoal1$BaiI z=cm#tETyrWBiDEcjx(3b#ABijulk(^_#5h&D`dssIJ!VK@jy$_SB7pyqjtz)MBa`n zZrS%9Xtl_kPseI+G;g;R#vy);*yFN9MD)8rJ`It57a{U~oh>6ON)>ZwA%sP_@J0>@ zOHHT{2}rfc8D_uAJ=*O|dmu?0uly|@UsRsnv4?h0t2y#-z53MsNojm`SWhZZX_pNI?suu@3kY}huUPP?3Uay)kqv2oE}w1hf~_Wu?EMMkALlUjR5)N z4FEzvxmu~8LJ2te-cWu*stk@_Z7m3~Hm9G+q{~)pwj{?3AsMkDY6I`JN{mGc`c8H~ zjqk0Clv%%LbHalGhB`0=J=ou#tXX2BuJZi{KZmb9`iFB#P|(34CUJokwKf=X3w+tD!sej^v+&` z{ zxp;k-Td-!lpNTMaaIj0)L{+6uvaALg?bo8^ix2b><9d3nkCTY3TXKK#uPZ*elj#(=Jf|`RvrdLB7JGs;zde`;QutB)M{+~jZVW* zdAcJuwKLB&9=MrVu2rj`6-KUU`beQ;&x1-yDosyD^+k-Nr?OXd22VD6OMhI!!QlRG zPHK4j{_tBtadB5^L-OEt|pW30RV-WWUA&rMlM8K8jI|ApF*%B`=nOQk)F zIy?iWQaxBxj^Bm?hWAJW=D$i$%oEc+>kY$ZuP*=iv{o>?{Z8NfXvL^FfFE9y!@_>T z-1NX+ixRuh<_^JFKr?dgL)o!WXOZV#-0psLzj=PIeyomRkq*prt(P7 zQ?HLWYfFwAXEWcw?R<_jj=0yK^P8OT*2W;`A_(@IRgCLL;`A}0W5KV+_tdVr{ zC{07Ul>pzMgAHVD%w)8Sl(c!#<^PW&HZ;)#bt0WPY#CwtWg2lE6I zk=x;r2#Bp+Xr_6V$Eh+-aZYcFEnTn7+_CTZrV{{pUC-{d1lapO7v)c>B6$cQp>pY3 z1CAZ#MY}Sau?O5LqUA3r(lH=Um5$Nk_?*(m7)7)#f(r`XBtG9vH0(57n>+BSxZPVp ze!5wO>dlUOw0TEqbNv}F!9v$U*7dB)M4pTN&IJPuegp&%vDC3$h_7cWr}W=m?ndn) z^=8}JRJ6K(L?LL=Im{?m)DrIQ-B()Ekxw@_a`ulr==H|@N$bc(QhL@_ZB%{3YIJ)r zgE2cNZrO|*dYXxyfoT@X-9mEl<>VqzfnsPgY`xZs?#vg6EQv)vVC3QDt^-!|7j>u* zOv-e7Y<`?&vm!a`q0Z@{3^-WXqz=SWR0vPy%vF%5=~Bs64bC;6&A= zij*?#B5F9TOIcDJ6d4p^W&=+rvXh%&foX^G$#Wmtj{bVA2P?Pq9I|CVUQ;)=t4pg% z+xnJ=wiUl8^VzR2?KJ$MN~ zS!A2bV_k>rCRdD;b6YOLcJK{Kz0I;Rdfslyn}J`uQ~lV_t7y9;*wx(mNu%~=C!ufnIb zh($|{k)nFldpXJA92RN*CecX8$>RIfzuzH#ZyVp`Zgjd= zb2a=ds=0;GpD%0p|3nNSMzpkjV%f_E!MWX^6KwWNi+^yy>F~X^A08huBJpW&-t3wi zm>>OTR1q67Y92qw2yX0uE9IEqvAyj1B={5iaaG%Rqt5K(9fN(VeGu98X!`*hr=T&L zY^t%diUfs&sL_k27Wt7(`z7Tmb{KmIAvK(DA@zV|5nH`O^5t3*P>p0RE-5(uB_hqC zV>QY5rgj0qdW8J%dl4fpF*K|WNkO%17isd~+ zK1Ns|^wbkgIS`5qn>z4XD$gV9IPQ5d0bwWNhQR z7haHwcc{uH9BU*OccvG{i^c<9c0Bz6Zo1i!aM0CXhphA{Lf;YOos`F_Lac2y|7s7$4Q)kBkh~!`V-CB#A7&kgdc^W6%_xAHp_{>j0 zT;$K4>q)k=-Jb%;xT|k|FMtjmnF>#U_REr|nbsrAWk6HSN3bsHH7B0GS~h*C-Q+Q{ z>1xn=mF~^51E=gXaMm;iF=({c##)Kg60R?3 z>K(WiI8FPMCF$*p5}baVhm;0zOnL+UD*Ay@g|!CW1CERK>s>=VkCeiJ)kWqxEdZX?bLk| zBC;=kEj8uDjyfg6MBX-CLD$VHCXe=qaKf)d+o ze&&u7?q!^mfwM~c|Nk2eQB{2{7%2Tl*}Fe?UrBbBYi&J<8r}cc9w2nfA$v7xXg&Vj z_=O+TuUw;TBgp|t?tE;IKQhRs^P ziO4}tUt733J9r(TMRdC?kZz&XpCUe+eV`(VTXP2r(m<1rzMN7L$t($QLSn*4x97nu zM7$Pu{!a@;2I4Wn64o}PB8|f6xV z^0aG>bb#}Qx>eWPB?>9g)AV3`$EcU(ZK)oI>fWG0i9)G_T}q(fgnZ3~{xq$A_&C!4}3M20gNk{jO9xN=@-jx_2cv|xC?s9V!OMWW>xL`C@NU_htWWSPh3t2s( zMz`N)jw~JAjpdqQ^LAW^m$32eetUajts%+|`;RVDZj1)zfn1@N@--84X{M5ZlK%SlEw*KnN^?dJI-UKTLLUh0I|oVhS4?QxLHfO6Zd zcqC(@G-Yq1?gb1rl4@?Oa@WcL_tL1nZR*rXx(#^v71Hc$pbZ_}N$V4VNJx*8krdFp zhu6iY_7fR|q<034)sA~VBkHVj3v~_N);|~oJEqYmfNo~9`X|6E zw8HW7dZcu6HcL823!kR-VLprat72$hA@p!n_YOLiiwVMt($1B?Dw;qKZGZT>(7f{u zB6}t83d021(kBtwvRh7wvW=mMy)G(JtC%K51K~) zRf&QDGZ@mN*88y0fV%4rAZYfup!&QuFRcV6xmjy6(A57r(bMM9^C!i5q` zE9gXrYnifE>>n)*J+T>7h=(Kpi`zR`-an8y-MEoa(ERU0^Q(&-LZqADyk4cw2_(Hz zwQ(1OX6`V~$fmpD+_-xFZ2H8ZlzT4%qxrui5Ef2&5CzzXX1ZgU@scx5o;k-V((EXT z??dHigHW1?tD2@Pkm~Xy(dMeVP9`@#9Y~U1@xAIU z9G#Y~@qd1_0NgKBEJrgVCOA)rV|lLtFrpI_OB2m^a>f=(2xaH_OBC~j^`r@B>y(+H zbUYyY%`=$?CtZ^>Rli3HkQ?9W5kE@Vjs73e#k%B?}=k5)!=`ukio zc!e8KEhX0URhL}1TN5j955YhrxA#fF6GRhHSaV21hcPsY5(#jDHG3xu3J1QyQwf5g0-;2O$K`jJ03lwd#R_>^B%7pZaw@NL^j$ z+*oOud`;#~0R^s)b)j7l?<7m=&)4+Oz>j$|L!!DrO4`$%hcvVlA$rMl2FOAM?T}%a z4o%t@pvKLqDpa0gB}#=i1pm=YmJfWw`~N-xxY4k3wVgZ;vCfNQNp1>fkAW~?pNhVP z%*3Y?-R%f>kHw2D11&v`H@4PHjm;(*@de4ym26OZ%6 z?dkAYJfUv}yBw+XNx?K}7-1jOYpDd>&X=3@7_@Brg;QGHHaet2L3R;9GurjS6ka{T zn``Ij@C*?pNxhXzo5pz*cF;81YJYYC-7hb9xBXmlYodD4 zib|-sPxCFx9E)5O{a9#sdcT{|Jka50;=<8@gPF^pM|`p^DVM-5sNhs6fE~`Y33k3IH4Ug#1{%f|jX~)s`<{G0h~=nMpHOWi z;Xyea;P2)ta__eBWJkvgOSaGGwSj1bk!HQ*?P0*9>AbcV&J=wcvO%WpB8_UYgtX=# z$a)>8@W^VOfuR;g5*O{O=0GzQORM;ZBfFgV=>Rd|ujlDZ-bX|y6;o{&>hKEn*AJF1olMvqD!PEx;gNAv@Nj0ITRB^>ttb@ zz9Yfsw>3LGA4q(%oVaQFki!V@;sdkiM!g|dlLuK~1(soDnY?E=B|z}Z9vYSo)~7=S zFfq!A$dSG>dsAY9rDt5@0czHrL>CU zgmWMM0f|11h_G?2*@O?q39eM9fIqS%qUKD}Lv&f1-32aC(vPDynnJVc09gq7$ItDK zy2KFA^6&AyWDSY(j0&|FYVu&zI0z}Jy3T|Gchg?;uO2MbSz%&We ze$-LguQ!@)&jX41lQRMCXo6~yMz6%*Q6K|tue_5we@flf(&o<;&ra#M8TbSP71lC( z1#ur3%h)hZz|P2>br24b>&A=ORRK#Minh_`*%@Dy!TgT5V(epY!=~X|P5%+O>K{<# zebkEjk%78(=8WH9sqh|Q{AO*FE&dH0B{%kjJgi1t;~%d+hD$h_;7#f@Yck^ zkiFYK_l^PCJ4Q_y8<(_Xz`pqEd5DI$4*e$TCwJlL^=vbp^`d&o~NNo zDtGK~QwG-#4vN+6&rU*E?H{e5m%sQ-FZ@4*eR)8Q+ZX89Amuhl z8ilJA(WqG?QZ%7RqmD|aNh3)m=i*X|5Y3%3RA|sVNIGZ`nnd$(8Wbv>G*a=_-pBpD z_uu>exNhg$-`;E9YpuQZ-e%;ju*IF3O{w6YSYr$Txz+3lvxEx*T7CNiZF8@K!Ng}y z!WkM{Yce1yb~52w|M;;PYRy7}o#2_*0H8CL(DB_~pF3J1cHdj;GdFq4XwfD)1D#Eo zcl6KedbI%P-E#Okl$)w??-85y(3_rKNsyRU=<_kJ5qIED+6fTwg@)(7tzqaGPuekz zU9*lPP};4xeEHqIVzSAi&C_d1CxBktG3lSiT~lNw(%6bU^u}zsd&TRzOWPi!ZRA?m z$m+KvGu<51Ue1|zTGr5q*Mxf_xDzhd_}}}2Ygz=c(|O6YzjmOFkx=UjNMm=6;$0K# zAPBZFO&PE{`P6U5^&H3mjfyQ;a}Fmp0aQ#s8jdlwC^?W{9_YDfbD9VSDNddJtYUt2dGudyfG@@}bfN0^Viin- zgw8|Ma{RE%tvB7lXT+bZAATJ>m?=0x?q8p2)4wt74ZM7Du=g0qn7+}kkcRpMS-^d+ zDo%#y)_w;thv%ivFY5jNeGN|f5g>?Q@;K-S(HqXQ{sl|{bBzyw{DMQBg7(H|Z`N~$ zA8@rG#rw9`MTm@--tooniCr@n5+2Spq3ORp8o!z>7f+_ zX$v+HpLa)XxCI^qee0Xe?(onCS+x*LIHQW%SX zO4i{9un3G6?YQAzQO~1Z-T0+$_I9*YQU0VG$d0fTOrwO#+ryh+ias*jc=ccZGxx^E z&krH*j`q!Z01}VQn~{dl1IjP&j5iY2vNY?}=j)NX7$+Xp!kfQ|cJtM>{J&H6Q`cdq--(J~tZeixi#sg1+ za;1p0qn|35$Ft@`fi}#Fh&0V3|FDIAbmGuf1Bcb)BS}8h2Jv($dnIrC*baKav7C zb2983o9ZpJ)mhS1Tg1dCTZSI~0wjZ&NxsB2EwK`zwf{JDHPlY6Q8O{2d&T^goBZ7y z*D%g`Z||?{*!d=E7SVjk{!RDd>}^1a%A6}oJ|qs?XxtN_YMPD47W%mrmT$h`X1R1A zgzr9_OmG(LQ@6~gP&T71PjCoGRhPdC!OTyH?HIk~ANcrxM5AuQseQjx{X$($f>jd)Ivr8--kP z>4m~j0nnVv)Hzp!;}$K6)z=+%+d9|Dk$baIxwJg+6bz=1ep(Ew}O|%Z{Y!poUFmLqEnO zuU1Y@smM1?{+KwV)5Jo*d++SbrwJZwbhL61Gyj`-XwA6MrAG7CvhJzG_N$Y1zxy`) zIJrkVvDu)Rpex-o)7ae~gZxK27n6Z6clcRKuF+b}L(X(p{Py*)*6)>~ajR{;qC(o( zXg`hR-Ni8AZq6X96pq{5F75su8~7yd5Mz8}ETzxgena8_K|1Gmz$nmpB_N0oW+hba zS|vHpcIH8rI{I5C$ptD^Me^e5=m(#HP;&*&B}?tCiBPIhXN8eD`z;J7xCv zI4>Wdlh1Td{#*@I=RXuhb;Q)#}2M(7Mk(B1)T9>?8D^uYP>9>6JdQ=<&;^i zfv&-D<1zDBYYgBjEp@WzN$ASYUJ7g$DWK%l=bAOzA)+hpZ;(xFYGl#tClh5yi?}N~ z!9`;p6icWHc9Uwo-(QqkJ-b7U>xV(+{$^NSxnZ&&u#3jw1Fgivtbknf?R~XW&|Ih( za3SobPAgJrZDtNW$>OE{n1s)qzu2vw&Ontk7TWR%u7ApAs=S$CF8X@NXsqjR$197=<4rgKqNW*5xO)^M^@ zx@%sCI8TDzP-Xf|qLS+FN21QC4Cb5Z8Qzs9=t6sc!e`dZ1<<5Ndl#bS46>}E&OC59 z6e`5y26yEasKV~=Jc*-U0K<-`lM1#1FA9b4X2@6XJ3MiU@J(umBX*zx?@>$OTZgG? zU`%atMnIO(x$w(RIpI?0_6QCq6F&f-hY7yK1+v;RxB4RX1p94Y%-EZ&n+W>Od~OAN zdgFHAy^sx{n01WZlTz{yc%Sw$-R*HC{cplI#cLN>-fY?(O@Kq~(8<7-8*!~}J+5^b z`-4^!xq@cZdj%o3_uYbL3bo@&kycSde+QMoskM;2(ToFa^yNGH2|f;by48AXB2@B3 zb!&6UP3&gpT$W{_?@YHwS4z$M?S)||nOVV2Zq+Jq0JYYdA$23YgG8BeW7`PW!3ivP zK~FuN^6`YX6}q2tckw}|cZWJYQvJ9M{)gzP6|{n3sEs2+avEGR6Yn*6_h$fz&M1QN z-5xiHVAyGA=Ot&TY`8Dt+qd7jo5UAMGOm3i=n7)O^+ZqVp3yVIyR2qF?as zv^~1%qYR&JNgNPdXIDV>a&Ha}`N z4vLRf|7NEgz{{TL<7HYrq{T`^J(wNW$Y@DdAj)c!<=Q|<#>!Yhr)ie%mL!vyw!%FT zX?MYNEIb#fv_XUa$th7y7NU6EU+#=e|6&fplWXw+CQ-`vGJFhwtHHN-9cCpGmrj`u z4Sxr~?mv_3>Q#WRL*ueQhzae6ZZ)e5IZ=k*8{TVdhH!$uYIL1pb~g+^$&BpW$B*X= z4hct}6k8r=p^ItSl>tTiv4co!J*=$WxsSccrRlooT3t3u)(2b5{6GNuInyj>=AWyv zl9p8GJGokyos!jnf@_KouI{3{NAL#_i9TP5;WVE(Adb+ z5P>jMu^dugQU$yDH3r|YTM=c)>V>`odGSeMM9``Rve$9(71tNseHDT4;85E_B71?E zCxj5gaLMJXG|`iRT^nYVI$fqnD(~Mzt%4h2KRBg(I2j<&#n~>JYk!C! zjb%=+U9ZENG!+TDl~Q1#n<}V;E|UWTkEgWtB@KX1x;DsKEij#*D+Q`Gt`DLh?<(9t z{w4?1m1mBfo#4GyAv;ey8mY?$MPnt}OU|#50^|qu+G_R+AhX@2kt9 zYw0lcH@u^+1yA;XywFb&1MJW8S;d&ifSpRh(K$Z+9is8gT_UPGVClYb@=@Pm7J~kn zIsVpl7GT*9pmi+*8!zqKsZ4}h}>GJ+;l$<7vuwi@bB3k$L^+tpo|+Qze?ng#XCbn%^TE7Ki}p&SqCQqUEHpzykszH$!uuyF z6C@sTP~Y>JJPYkBUhiQhdl-r(X&s5z4u)kyLZVIBQ{E>ZMmPO4dVZ2ugVO6s@ihcP zq|M=fFS57IC6AOp`2D*|cKF4}+SI9=W`0CaGPaQ7O)@|`nlWTVN4L>;?GcY$8cydT zHf-r54{4J`E`t#j$G0C4XCh>c8c%Sg?DC8?Yc6dn(dR-F$%buxp4b3utaS!2mngGQ zNvV9kirSJZ73w-CJqbLb=Np^D5HIi<^z?0`8HI_)G8e>8Z4%Qk>?J>N*{n!t!!d+| z6Zq!pKcn?q8Jh*kq#F78q%964^IR1iR8g`1RMR_=+dCD-l80UoYE*fN=R?{bH=Vt2`%teYDkuZRX+Q zn^2T;7_VmjdAo;Q#XtA0>&-NdkOFoYv-3N%2UqYA)W^f6>Fx0#2l#+Qg2a{h$s(36 zI(|re2u3pE5jR@9j!w{~?Y&(OAqQX)FYfq~;+kzP`LAWmKV!2ne#2?n4l*#>sYsxh zM>!HJ1$QMUM>dOI$&czA_Fd{>A+1Zlt#WOI3ehSv`5|t~t~4TUMrIWiKX6QKS6#JI z^;j|pxR<24`e0>HGa9X8#A7>9dRO&GlXl$9PFP#y-A=Cib+fumLE#LMcP)rd?I)xR z=J3vIxc(~aKvetMmy~(4W{Xx054y$$Q0u(A78Z#g{)TRHu>&z~eW~%@m;EE$VOK{l zF*<*xu$3NLh7=9|&*)O;7+^W`A~PaztJ+x!lJh&Br7vrY#l|muvsH2uBoaxz;Akyo zj6y&uA0 z>vsf#2~Jbuzff-*O8?@t_ONPLq1NLSsCNG+ z&8>AGqLbgQX0-NPOHJBi)~d0& zOET{-V)<&xXp0yyCU6fzkQP(pY7#Xopnb9AQ|YLC%e$83pk|3${IdU}w{Su0%E>Vx)JAMU z`PT60@LMZM@c!IFDM?9w`yP@9<3=jGD>PwZojd;U=`}#n>PVk?p{p4=&+d1KXsaT3 zL|szhp(MxwDr72MyRQn)?2I`^@~Ts46qp9PsFsgz3qe!oU~27FKxd%Ez;P+`KW4#s{rxv?RZ1! zm0?KNp7MP75w8D*<>G4h)-n5-)-80gR*eVl?=Q?%aDM(I@%k?!ImLXa0It_0eqyC$ z2&X@oFHz1kr=5f-H)=@x=?Sl??lJeGeXN8%l-J@js#2qRVQyO3eQ9&SOxo%g6;T=8ZqqHAM-5VqXuoq@Q@i_0sokMu*<|oH!U{mCbgrP?xsWC!Xa?xNPc3Azw0w->d>-UYkl4( zA&?2|&itJ+SrkoA$YW=i@@qqGjJ+k8@2&$Y+3!*PM+msYT2?Lki-EQ_|ftli8JBFO>fWBH$HGiK2tJ8~(iuik};X}!5Sgu9tbaaHL)DG0OH~DvR zKEHJ8nluNo;Y8x)Q;C>!eRwYBC5sj&nB3B03uY)0Lh=KJQ##>+ybpSXjVmC*v#|7w z?6a}bij_EUyaD9?9A0DLmFj9N7}=2K9Jgk1X#?+K?+LHbPhxqg6JY0 zglTvNFFUbR=pt^&%L+8Z~BF$)&qs`<7xV)e7nqFQA6i-4vOu<`B>;c%RwCyMZ z(ea2g>5~OJvRgZEs2+jL^BJ^!K~&rc$Uh7JHb=m%RA{5uPwWPaH=cdx>YyeM%|Gu+ zeu+)dIqb^^N+mYJsvNxdIV2Cl^E5FwV1Gc# z7kKZx`O}1oFNl)<7zViEO?ierrt5V>WS?esq5n2NXfKx?Le$WpzNXeVi-6zVtcZN+ zG#S4$AyHkjQt-}~8EDUlEZZfs;nfZ3#t>z2 z2{lV&vuRWmLC{7YU-bgC@nvaw5y_EYZXq5!(o+Nw6yYpL(9>kk#6lkUoA{Oc^$q04 zGg1H(n!w(n1hnu-^xu_(>8=X{6C`#G1}E$x$&ZURna5|yz}Bkl&G37f;T;&C;)<;s zpL){?cgSnQ(k8wh%MFL)jDseO?2fI_n67pt0#e&5OejRaio%&CM`EUd?ryl~fU)`l z8Z3KLhPM?a70!3lzG6;T$DkB&5mpxKBaKIp*ieoLjwS$waHK*~<=0LM*bg1#Wh7og zO0pN3Guk%%c@Xxw)9|HUv|i><4>(iNm4*5ts5PbHHd_3JjYe28m<6-msG8F{`Ha2EeqbeNgk3Gn3i@_vwxlbJ*kf^r)(g07fRWCbf)?fh*cX+D z02NFP%7L1#FVsDE4Nwo=Tb0YN%1da7vN!-p$w|{u^iQg^5^Fu*ug)_ zVV#f)5|TuL5j^w?gfyLw83lirVKXQW4z|BMU`RYY*#FD#H^i?h*k$3BwT0$HnsB2N zXqX)0yYIm#0sB8r48qUw^xzr{-mSGKYk}bC@y4lvl`5mRn19nZ;I9;aSB|)##aHyq zBRfuEOBltH0YA{TVX*!-&XEzWNAepy+5>Z&EnX2`$&Xf>(UT{HBt?UwiSLz!A81d} zccf7dxKR@7@4!M{Ov(ay*P}7>ocXmwRMFj+@K9EwNFHvStW`d9i3uu$6SuNV|8P4J zEw`hGSv#mDg~fA&`vPb&^Wa6^hH_bCFNi#KRn2~=sI@{N9E}$oLHr@Z4R@yeBtYo` zG668+6_g`@wZB^B|KMjHgf{*<`9CQN;zbB`MA&;g9)Thl^e{H#j@WK$zGW(1$hQh` z+41dmG~RdRWpj{HgNIr3sy}L+^Jr}gA{ji8Bm;fec@z}|i#z8w;NqwpZO z_3K>!gUJgQ1?&{OMlN23COLTWa6Q=P!!pS3!b7t{R8HHI{$Vr9eV|`rnZGFcGpS3I zV6Q2q-eioq%nfb2F_W(w3}?rq8#ihHl&=Txy9={){UZ~6GbJ>mG$13VZ&cuiEGj%I zczgQJLmov`Z2sUUX4&~?gT@Pg1fd8^=gx!0i25|AeK5mp#}Ki>na}uX#=At_>~m!9 zVC{w(h{Z|;QT{W*EQ;Hrj%n=@(&LdJq(NxF0G5Fx4Kh)O8 z*G;D>DR~zrmLZ)465NUxxp@-6jX|_iq(CWh<`Dy^tdy;j;Sw+mR8Y|wgtZr|Bq~^Fs;RIMs^{hEW{m0 z)W(O6r?DUy(M6c>=o?{7SthC+8#SxLew z(}g3nbvyi+(n`VA4z$bICqbj&`i2fH4rtU$%u}BF|47Sx9gb?Gh_W^WIMXH=UPV(U zVSnNV%+3^?Go=~+uTy0VS~zY3t#q(8xQ0C>${4;1{UqWig-5nr`9FEvi36y0s6R-I z^Pq*|G#QN0ivKM5XOwXvywcFb0vX&H_=h>akp4mq311!TpW%$ISDG;*6zwDCJ2v0Y z0zLLPCs=Y&^*=)5Ew~-}H}S|>JQrU8*O+%=Ge015F=)&`Xde-;>Gd9}0f?fxCk82y-ZZcb8Y|v5j}4BBESDXbf|5jG`c(fBn8N5DWE1=yIJ&`bWZF7 zSm%cyKV~=nE?qaVy!5N*k)H0-_nO7jcE?{cg`*D36AC)20EG^60sg>}A}YV}$~4Ej z6MU{BVcxHo#3z5A4$402xZ<lEKg9ttT_L22I@4xHqf1bVNY!`(^CaFb zO5Gm`Z&5jHHT-@+G51QD5yV>&~Cyz4vjWV`^lp{HEeWQz#rsb2Kjl z=#F4LW7(A+=wSQqa^EhCz9G@ zXLB=;?t<8)zQF(_4F?<@`&0rxCNE@sGM^vVv2$8{=ej;Uwv%?$tjVTysA^WtDY7~Tyy@pT4h~mDm_iU;qs8rkd`I%KTYrpB zF&}QeNa=n%|95S)hZ@^+=LN~zKRp#EdTz~mY5*|5aCpH)S<>iP(DSJFkVUeXyrimX z63duKY-wQy>g)b(pltbZ)Wo*v zo*-%l&lzlntWLWtSFkq}C9&j`KU2HrSp1+;{XSPZ3*qIn&wMKYiKqFzyPR%!)^ne? zTJUommA%%@R+Rrv#|GjH& z&NF#%OsSy|O6X{MDj zozxT_9zETXB;Cd0fp`1N=w;}A34Jp-@3zcoBvLv*+0t_G{Vxq(y$wXN+^(M1_+u+j zFE4oxf(+nl{SND>C+~PvQfu}#ERcgYKKjC{M;n#69rB)n_5xfKumm1r3+m-H7Wsu= zr9vgSJeQB5Gs>U5Cvh~ePMVFFX_VOp_8%7#s0sb^Ba!8nDV9h78&`#{ z9Xze{;@^QCRss8VlL(Q^=qA-?(q+FA7G&;Kp6y-FrXX+6L>K{Z@mh+b8513 zyXh=B&nv0I2=;kjZ*XAG;W)z3ex0rz$Fseky~N&s_V%T?CYw7y4%m;j^Uwn)c?Q7B zcOxB6<8O}=NQiCj{JdLR|Nb#^=U_oVuPk92mc~Bg5K=`VH_K?T^XRUBIWuee6(oCs z+(;sHk{2QF#JAg}`N2gXwM8l^EX{FJl)1#1B`5_yjT{YqoSRMC)EY9~>3{8*DCRYax^ksu)*$s#M)vhNt5_5l-m^qqTCXx|mV4|OQG=TN2 ztqxavp-ed!F?hYz-58e7qX)tAf4;b04%$$*g!6oei)%65M$q(<+f9VPrEO-zGZtlw zXn&x^eU=6*c-MY;;lvB@CGnszd))IAeW8hg*@b+=pUiCz43{B|2VaH@xCvV314OBH zx&FxM^CF2|IhE*@%}OkJ7a0Id-ppy&%O$b))Xq+a6;St&0`(c}mJ*~rts3%jfP=mD zI-m!0J(y4n+=)!YB{v?g`t2_siI zfLn*@iMSbf6+cflw1d4;$Lj|mi}qjpHS2N}6k>o!zWZu#{6D`7gyd$%yoF2*V!nM1 z@}}LIHFzPvL%VB0oX06X2fq~p@O#=Jlz#UA!9i$T-ISmM5#2dISTunb$1`PE-2#uZ zP?p!7KvdCsNoM@+s3>Gtza^{GuBP!&wO6j^)67MoyH}1~FG*94xRk_I$N$2mK%<)S zqG4(A-c1_^hp!nsF8G#pHw8eCq*14zHrWI0M0{ej7C|VABjQ2jY>no)djtXN-lp5h z=+5}4T1gXlLD?l+yz}-7BI88!cKFcA`Re!@E}=u$UqelX)Bc%yxA)>FwYRAtL@F3O;H# zW44GKmOEkhii=QudJp--n<6keOE!$CrOwHg4j5>fKyE?(~dwaj5lR>OV_AbLDc?@p!56F?bfJCu(7cmN{qEC3%8gsCiR(Kav! zfsZ=`Kmhjq`PKW;Ua-9I^dzHTo}d#F`pP!!Q1ZLra;vau3yigcIo2*&ll_fnSSY<^ zp^8%|v0E#R>8TN}(XAu5VI>Q!OhMd7nL3NMED*kb=XZJ7B+sxCO=Kwz;Ozm-TVKWE z+i%|~uGOk8+99!cF9Zx$wko-J?=Izz|* z^>fgVZWjl)PQa|8`ww&^{--0Mm?kHLyyS_oDp*ZgMU_QrZfO@{vSd>({;TaPAwmR+ zr)mTFc`-LhwsNzlyax+Qtvxy=z=nrJ9uU`D>;al7uf~*{{@Q&$A#Bc&KTVT^gZL&t z`T)gWn&C)pDDK5_IwsvSg}=T(`BACCeoP3Y$k*|54tR*#7$RCxa1{r+dq#Ooy??Wn zPuo`m5jd+Q>p8%-;m`Ovzm+G(Lw~eaCWXxj6$@Q?Nzi(+oJ=zTX#J_FsukJPH(s=M zdpwb%AT2nqfOuDLxf?nmZJSJSDKRq^NUOAyI}0@v z&-S9vXt$X>RFT-^xskKJ(aI<6b;0dnaZw`ZuT=P&WX@!PSohk(nXs`>za306QqNUe z=p17ue#t&n_JqKUWKQKpgl@IgQ+hGpW2(0pZczXe_riV7rXoayEeAM2*eEj99}0`l zhX&hZkB#@v6h=Q(_2Gw!`3Wat)-mQdt4ght&VGX-K3Ei14&yz_Xt|Egtn(T z^>B&z?{zEOHVTdvLkoRHRNOE!BJ(%2P%N6|y=l#@Yge%_uI$n9Xzi5-xV)F2>W+}} zW+G=j!Mk1EF(*e#cS}a9rVj^Y=>1)QeTfM`URzj|zU-}%wiRxv{4wUSHA7nnjmO!@ zNPao{b0v(yEhA0s4N)EG{Mv9J@?%n)4=Zh|`eRiGvbe2G6!+}ZBW>%{X%F5|ZxP@R z7P{`1iT^Sz`Li)K?Unl%ze63UgST-p(E3UhDKzBRu z-2(`~nZd*-$eK7aiuhmv5kpfQ&jazh+Z=zvbv&Iv&4~D8fj`04UKtod04PS0O?4K3 zov+A==(di%HB2TH74B-Hf+ehrBD=GnhmOoBwKjQgxqe?5;3wJEGy4~Fg&a61Ty;xRR&~q8Ltrcr zi!_9=y5@Q2fAv2gP}e4{TX82j!1i&SC7~!V0qP(gnHd7Z&~j7Glze^vwV}HpOn?~S zKYmuN4Z;N8y;w}gt+KnL>d7H%suE9=t1?>TB8?6ciflRvjp!}-d->V7?R^>4N{@`x z-owe3Fa?uBZIEMmW#|zsros`+{as;fPvS${K-5bQ=k&8v29C7*1B6U>BTq|d%FAa= z?R?3+V}Cff5|W;Th-G8$AWTaJOkq1J@pb29(AUna(-g-cx54J8Rx8^HMTvG_=tP={ z=60o7FZQV{uZv5zMi!n*nkxv7;qN>^D5f6~IOM6tSKR1d96T+b4G`oTXdL?h`s}-p zIfAgnu*bz>`zg=s3f{1}*WZuAL)`c6gv`#+8f=jc2=lj>mSpf>Q+af9b7l=NTV(Gc zWOR<>xsQ^0_0*WQTaZvSd0qfmNm&+%0(D?|1n@F~EIDe&pL&|5%b|L$V9a4SA*JMW zr+hm=V2vT5yEo?W=xNG^&1Nl(dwWbRtb#pbTM?&6zN`l-GS+(fd3d!Ri_kd5hwefke=F7t7;DX@k>#^z9qbmrlwF3#BkY^B2!a^7HFrI%d zC&yiFY_nz0oX4XL&MdS(mpGt=hIT2`T@bWa)u-|T>@w{SiMIB<)2&Fg_&&!<%)KfG ziDBvmUyGwOwRrzuISaq73WKL}oqi@rdc!(Jr~@)j|BVywlat;lY^j!|KDn*2)XbWN za_$CNTiJ!hs^`c%*2Sl0+DYfPbv(`KQ&}FTdYI}dpIAXqa}T#WgOki`)~Pl%u0OVw z?6Cc*a7&6DZv_kekpz1wT3O&^lFj@1Nr9&8#aBUq7ysCiX@fHvC{=j@V_X*bB3c#ad0zNR|HolLBIw~) z7a+&NKX%Abq_;{G{d67dJY(gfYhIa5NdhpU`Qv&l#8GkSZ{I7>h6sJ5s;xXVPVUu< zzG4$aVxe5=u=2hNz6WJv&<=o@2(_MEmeN-KG)B%kFU@CZ+;@ziof8cPRa<(8SBMzL z`-26jaQ)b^U!B^Ev(7g{7Q{q>pDskk1#Z{SMtA#gUo-V9Yyzk_PeG z&LpQp;*lhuHhITiGCDA^?C~SY1a87+oBv)nwDpxROb^bgDJ{JF+E5q4$bJX~lp}** zJzhaBkg?qx%8Lk!`j3)-$l z+rM%9^%|4Y8oWfQ%MgM@iwQ}oQ)6d4XA}G3jncXy&uk$&Abj_vYna3A9M;f_=4gfq zzu7svqf;NY%uakt9gy66#`UKt(F3L1A5H-St0b{U_3Kr6@yWpim#=DVBdNppKif}_W7rK+xKLY05^r1Vp7Fwn3M5w6?`J<5tRAr1*{Ti!U zv$zTOsCF~y+*m_mgI4$pa(=M#mY6*oWHM5VgA%k?5*u%s^tGWmrf+Hf{O>b^KP1>^ zMq%j|j&thj{O!>6vQX=L)10QqX%a87@kkC@R{6CX%lgVQ-g4(Wtpxh)gj03))@ur` z9EIbxa_<6|{dnSsBFvbw#&c$BYjiKylbbAa`q(LF1RxqAd@x)TwyUa187Vqe=g(@^ zo_nUD-K3eMyONkhp$XB4y+A_aM!3)Ok|RNL>~^7T%K_(OPfUq$6Mft6O;|gCv1F)I zpF)37q1jdUq|)a1g2As&y#w4nN-tIreHphon?Z_bjy6coiI~V9_miGG|4OAc_7sjj zR?Tc%(uHNDM>XTX8~RDCJ&O6U!9UyD9%yx6u?`V))D)Ha&YiC-+ZKMhY7-n2{ynhL z6ngR*jLwCBXqO~%B0i6gZPV_KS+Ej$Hf#TO&`*R|int5bi561!FQQ`oGjlDwBjgH~ zuWbQ$#IJm+dm4c0vDW7y0>J0Jdtj3-z6 zdM0H5ob0m6?l2v9FwwR%Jyjof@wDY>rrf+DkH?yevFEb87kd z6abVD0Bs#fIkFvmMar4)w}EH`NAVoUd&5k|Kz!M3s9%Y9*d zZ)mKHXyj=7sTwv|?o@2;DRh@r|KZ0gV94mpOo(pyRHh%1Ret6=F(O~>k*_M%&qMGk zT&5-<@d&+y)rP}2ETYk1M?iRS($t-pJ$>Y?;s?{)KC{z1Bwn{6QP{{7h4qm=<2~6O z$!6!5Blq-WMhZHQd4O)z31vZXCZWreIIRzk_X>}kQp@4|E9{qF5rcFtvN71BcRWk7`}sWo1~K)5 zbxO3kl%-f^cZT4n6hxQI%`8ZzKyR~~$Xdmk#BHlqx_aeZZ zx&;rZ6?sGILZPaKq}gA3pXa>4nTuDa9<4gW65l=c6vq9pyA*@x1#_`&u9ebNZObm> z=8rT##a_Bcm^NVRYK4LGb>?52BPX45dTepwer!jQ#+4_knbVz<4#bFHJ2?InJ3N2V zu01o~>6sI8HE5mRp!^+s`ST6}#JjB-R6%EOuPN(r07TnTX}&Y^Q=*w^wHAopkNSER z2DSQZsElUu$h_2%6%#p+|KXF2tp7ll^NTKTXlK3%ixG{(G?$roY%=E*R5TK9C!4q)!5Y9_+Jb{wp0 zxyyKNQ^`ep=mFCvaR#Ok3On&m-v4It6Zexk`;9v8drypfLoLE3sEw=600pmO3Yva7 z{iZYcY|YgM@AslwBbfoe2N}90K3|&%k^RLxAz4+Xj7ijL6H;MFzMyP)oYA@3Smsd< zoXN@w;TlH%3{KLJR!y9EV{?hDDE8O!y1e!DCtSqkgIOp^P^O3b*b~_?-jnmu#Vahh z?#8sLzGt8hYhFON>h?$^L5nzgQcNz%`S8q;Ohg0sNbLFBY|%2hHui}q$E$A_p8l)p z(#Cf+2WB)p>fI~FM?%)IlAhetj2we0oF<7Qq>f_FhGX}YDLUa_$YWo1xG3kYj@^EQ ztnq#3`;>hscSAOj6758h>`R3CPcx!oYx_!TiW#PP~57GlPnaz$a2tvQif?Ti}=m^ zVFWcts9h2SBgZ$N z4JsZ!Wls2RoZ5f<5r%dVN6H=L@#K<{=gT@yh2H7wXx=pjiO5+zbMP^i=UZ{n#VJeSfb>ud~&nqeZjNMRbT}v zAw^@79bkwh=TtgeR8C61^{D??PO2zH?NPv*v?c~<4IvXhK zWSFn2@T)WaDQ(j&K!~Q?6i@9^ru6=OAq;7%a z%YeSzO>n;CR7=|JTVO2b%#pq_VmKSxI2$e0JGp~6Cptr&CR|Ok{6tykl3y+Gq;(lf z&%&-tr~QZ7kVFpL_Gu%#W(u1xolrm|?o{JX!kRRH23zleue zg4rJ;mXE{v31x8FQ<@ggsga9>(K$xJZEXA^?O2-&OKpS zIAkyE0fz}f0>3E*TwKL;&Zg(Zsx0F+N{i!)kOy6QXeA7!W+vrHJ0U6^<0AF5@2@)) zTF4S~$OO}rnUS}QppSbBQ&|?{O5-k$-p>mZpd2mUnFv6Q4Dhamtfb)q1%am9WEx=# zJ9rlY7h~C03pCmD0bmK3WA34za;l$16}h)G89DzHrRCS0PP1wU+(`1M=2gUg*mbmI zRTJfId}yHd^G`%w$p={j04~EBIjD-yic8;`1aU;w>`55n7bnDz+OrwMDbg@J^L&Ry$iN;MU~oqDC=Tbc8(q0&^uYBPCsvo>3;0H2HaE;gD{b+t0q z3L8wmO|#(I&L(?xvm3fB4=UA^_Rc6%oI5k9a@U;ziL>QHfa~R%hR0?kQcX|c(D$5` z8n-RhzXA{f0@{Jb+@qd$mdf9`MGhAkWjL;no7AECRonftsGNkC0hsxFH0PzY*)B`# z?kpL17pEP!M!|*nKU%;KX$ zzxtfZRByWk@viA9xHj~ySm;(iFHyBA;fj*aIK~yNxXexR&Xfvyf6L%3O!Y*(XPeBD&V{;68|a-@U`#yDd$v1K3KP z+B$85I7|&fYipZWXtzDCJtFr3Jt)rD->I0*$*C_eBMDh~f8PeqONPMYgvse);Hr4E z)+YEq&Z*aR?7cE+gH#Cjt2;B?B;7WY=rH>9Xbadbt>y10dZiWDwdO9!cR%A&jIqu- ziTLJw80j17XmHhKvMZHEIimS>g31&Bf(wEqA-`)+BJTrJ>193qz?X`Gx#yLHt3}C& zeO}dkOB#gf-B<}lL;y2P0K@K=%42H({P-}=&;8q#XFF{n8;%WSX2P`mzhwd4Pn8Hp z?v@N2G-4%%77I;|0#OFAU^r;Z$0mN~jz4I+*H6Boi9LdF&XUTYLfIDORe&e-qV1qU z_AK-kh_}r5k8!*~Wr^C}_sSVrc>*J_va#W*8OdC!=kdd+g?|@16_>b4+EZ;8%(@~ z^~j55_v`9-rcZnL58KH$`&OW33@vg%sr5H1LI3_^3!%GFp_`vPb>?m{hrhl z=I}QwfXno|jg?ZAguOu-GJ|pjscR_?c8@V$=W*g^gLDQ})v}3FZv(E`&~_;w1wi?i zDdMX3JMdBz%WqB3T~MF8&zfg4HTMi_6hrzO74W_S7^A`cGpJJ=rdkJ$I7p5q46l4t zE>6#3!k7FnnKnEa_0%=mHb~(#8;#2BK$jX0NStX8KHypCFA(2tq3t@bY}&@s5gmHg z@;dT0h-WDkTcMwCZSvY|(s2rWHir#h#U*{`4iLv6g)v0isgyl=T;C= zkJ_wD6X46BEv5MF-XLimHrG;@XzK+LwrPT@&=-m0orQQbHTJZ0wXrJ}CcgdDY`cq{ zki1%-p1Bv*tTPUMgQORw0-|m?mUlTq1EL!tu}TZLxC9FeWsw*&3vH_bq1${!w3SI8T9hFeXQ{W~AN6*N16g;H zXw}B1Is!a?Y++Yn7kk`W)lfebc}h*3@bV-%0=EJHH}+Z>6|>`}h*SnFNh<@M@*(by$OkLvvDKU|)d| zWK`?1(<%as$9t7wor2*@y@&Y6@2Sq>>emIm5|R(4GVh^qFlZIhcwd1*Ws;DpBX3?I zn-?Ln%Ye*8GFoc~0v5=_eNWTQ*o?6?H{$@^H6A{uC-mF_kWyViXCtL-O6xDq zKG0`dpp+d`P~Gy%7+z8Fl4@w8asY`V-=k0{+L$1*zr9s@2U$7oxGj%?zL}?gh$@zy z>~)=sXD19-x7hH*`V29Cp#tbdZ}sYBHxvd-Rp|gnEb~+4KDGd7XvfO-KpWkLVP%p_ z+sW@Tjp*H>dcYRwLV2|nG;c0_ z-8l}%#@qp$>cKY{!s#M_a6!drH*IUIMJ1Vq*7(uZLMFEZhLU8i@m%q}dK!cyu$Hb& zIUo7i6e+mkb!1%#)7+6{WM}g{fB0AG%H_7Bul$5z%Iu-kv(v&(uIx;ghF$k1W3%-) zVMU4N)>Dtz2PSI{Ca#yqAbspxnHnBJ{su)vMD5TQ_=n-%DZ`&vVGAa|ITr1q?H*feEbMm9g-08LCaXK z7|{yl${!>yYiiZr)nU6XJ(_H8vi~v^Kth?50N4S#bapR0Ri^J^?4Z(0=PwRn9O7>a zTu@O1%>`#ay4Tt9(jy%LL@63ov6nstTeU?XNg`z?r?k~q3vv)8&BhxEq-9@kOO3L#o1b4W!F@e z=u>Y#R`Bj=^<*o|Vj4hcoOAQeuuW&ve*MV0zlQq*nf6RV+fK-6HSnM?U=(pTYBhV% zrNp;$7jB-kgjxvNg90=>U9ku4zEeNKzKOP8PSeM-iNw*ROfuBW{fO1!mG4SU`1p1b zH~pAX@uY>v1<@IK9k!8aF>1mU_}*8%5fb~9q-`~a1bjnIBn3%pJ8wW{$xqnV*8hz+ zjQnRUy65ma&DXB$3H7yRS&XR8_)v~_n{}5Jl%`BkUc^@eyE-FR_iUjX<_>g9xS!Yw za7go06DVjHob#ZMJYL`~`$tyW*%eID8Vn$_;!0h3EYMVsO;@sS*Yn|R+Rn!3LLN0y zra;WLA%)UV!3HeAZwaz#x*ou!-rZL57Nvm#B95loSs(eK4XveI8D@)b_gqTX(dv?o zO|=E6N($hCv>XvYiXSwf0+c9=Eb9bEJLpM#&`9OQ&V*o&D9CxsNu%k6@p8QcfU15( zpY_?RI172cZO?oZt8#VOI0Rc8W53!$Bu3N2^W2vF;KE^Q;+{Y{-#yD~N0MGD^S(O4 zFJfwc_pRF0yJ8Sb%6Vl}(NUH(al_b@b*V-sDX2CduuzQm8U&#us_;U=w{2F_8X2r% zQqt6Ok4`7u;;e%*yV^tY!s93Wa)7Gz_8ujWz%znhY{acumbUf@ns+`nyS_#3P`4pZ z)Vmm0M486F0~35vJqxj^IpD2Kk~ zed41qE1GxU31$Xer)NJP#wVcucO=2X3;vPb=eXbRA^ct|&=gx!jfZM_#0N|{Xd)lC zjz81Zmwjqc=cO|J4S0sp$F@+p5K|X8nZ7Il6MyUyS$h4;s$xju&M|w?eQQYqj0T)| z9Q|IdXx({7V#mLZP(Y~VgvnA$->(P*tmV(t7`;$lJ^4i;JtJ}X*JVeg1@4YWF@Yv? zjIu5!uJ+#Np$Sp!)34)N$2glzRWIosN@ZyhZvXm}vj$|RjAx4uh)1hzIp+})t5jWe zAtbqJPiDi;v1qr>N07mm5#Bhc)BY$^A@|SCz52o1PA9o?E*-O^vK+923I%A#8&i4KZWc!gWIIi9BC6J#IGIT8Gl(4R``K^{3!R< zB@54OR-ay0%q##4_^dpiKeI1HNIgMQ&bUE?X0iSIE<4saDXSr>vFTQo`>XpPrq}Lr zuYVM8u?p~JD_aEJ3p^onHqxH59IiNH^5~`VLRudfvLV@GaE?G4M9!o^%UpvV|CC(z z@fR|2ZzuO}_Zv`#i9xb@bo7KwH*!4A3W$IL0uoh{!~uaJ=cFKvN*G|sQF6{{`<%ml`+n|^ z-F^G^^ZZffobIl!uBxu8uBwi&PIw8Z(s}lg#aD@w^vpGRfG~wwJ|3Tg75FN8SVh+l z%**F_Vz+$Qh5Fee|D(7aZNs z6w>s8)hsGdwb!B1v?oD+pqL*1(SrC^=9BB9kHzov22J5A6_mpFQl zp&w`9eU3XNuKF$z*S&Z2@=ROIU>gvqNsUQ>5{AN?DSE#j6>u#)2~oSNf0kHV{2}27 zkl!6O6ZIYZQ}xz>?PDBKu;A#9e5@ulw((CnhJaQ1P7%bzQtSyxDhCbkg0(jf zo!QH_Y-EQ8F|I;j zhgjFKP%bEW1?Is^4-p@4T-4ShRpo(B!CQM1C#Rb8`7f6kF+>C7<#K(2SW4XaZOEr| zF3*IlMo&&Uk}dYhmV?qHAW@oL4|vw`qSDUd8iCT3&#Fn)UdqqnZGN!Q_mbL zmBC_@0aar#Iu38Q|1>pI=b!wkbKy8|%EqmV>@ES;V{7T94X8>A&3T>WF&2p3kMEFI1xcdp*9%%xLH1r8Gkys?k+A8IcO0DMOAe6hCY;`B5EGQGC1A z8O{E5#$YG2A-ct+hjykP958t^HWrkfhL}1k3_1=GNs5wOBv9vDD_tt3YHPLNNTcbd zC9h3Bx*_k2PGzz20hrj)oi{GT7U1>Z1bUrjMTEcIF* z-OR)UzDB|vv4Lu7X=@cqcc?xsa`91*h4c8ecZ07}Y}5p(s%SzCC3RAgA>Kyi!EU-T ze{(gK#?Q6!o%j@1rom^!6E^HD-&>6o0iVxu7(~We*hzrS2ND0aR2pB_XRfsMh}Lr5 z#0LHP{JbZ+`xc_7-(;3*R1J-3#azJ%IROSh(fLD@9K106gI9yWyLcziNw?9Q@>1c2 zU)qXdM;d7Qv>o1I?{c!FKH;kb79l7|5BaNiWcxbpZltZ^Up{61w5Sbu)|zLC_J_3V z@y3Fz?o2*GO;}R!L1;ns8;NQ4YA~m?tEx`o|O9;z=fyUlx~IKr`A7Q z8>%GpjQJ1G{A^WkCKNJ{9e@|LSNo{EVB_@GfSf-~bV>_NQ$6#;$b8NEYW=O;)!FrTl(s0dGf_C%$BZimMFuYwEe&e_w;AX z_WH8duln42Kg|G)0^rhuPf>H2H=i_Vd|%zJBzi{$cN$i%oSk1XRb1OmSX^^?M!UdQ z!yl#QDI~(pG6}8ZL41zb1vTNO%9KQX=KSkFdzwpH!?X9dz8Pqmj?Wtsk33fUf%V}1 zKsipuDHNG}4Qe(EIloXZ+|FcvPUnz1uRcI@wzlh$`lREtnPBa6B`IGPypbE%a=9W2>h<6%8nD6gKr*gM##@hlGlOZ`!+-6!;>w;%#G1golmI#Gfed$jR+Yh-~vTxD4<%t15i|)BuuHQ7J%wcz+i;kyFgKFFIgb} zSHoVp*`$RP{N9U1(WCmmwew%pR1^(_yD5S_mXL-Dx=En}5=OZ`8qyVtZXNW0Tcw8o zVhi4E`BCT$H1Hg(YJvW9vWNLE0@ba<-3tJWT1SG?u$4LXR1Flx-CwoxAb}SGAButS zsi)u!338h}VTXQpB}cm7d6|X=CrTrkH*R$>!5Wkt5|vuTu+m?T&N1bi&Ah>){T1#C zHs-)BEje~nYt1l}u1Eq3YNs0bJ!h1I|71oydIMGM!KNN`V*|q3tygGgn($_M5#jK5 zx!?#%c!0v7DEAbJ7hd0PrNoULH0wjW1XVWRq;~tC>h7=M*Wm8FV8H_--DO-mqc_Oo zzrzgCC44Z88V>OnsT{z);s%0*!RTHGqpO&Z%rK{1pWkbl3RUBVln78r4>Ie43p&5Q zupp+&RMrNR+$M(yL87-&gKQx9#o~HF{!r(*u*2(!1PCSN<@7;44Ka_|zMSp0=+_J)iuZu7{4R6@H;;8<6qI_7@{*Kp51w|2_#0Jz?~oMWT1AjI)4uc0mK|CKZ`o z?GUyOLVCfQESAA}i-3h6@Tw0E8~~*{53oA`B2G>chN0y^Nx@T7ydl} zdZG+}RBx@K_rqfC?D;RIifJEOxBpA5hXSye|cl0e-$6ON!_V1YxlMEseU?{qOF-`oz zsiS2|VtFQzm?;uO7T7NbZ#_lp7YYLII7FeTBB4njHYv)z;hl`F21Z^R+$IX-&pT)j z09g_RfUoK9WOj-p{D1`RfZtCMqVzMn^ep<}DP!djj^i!p_t4Q?q;+`xC$qCG3);O< zuCUJnWK;34zR{NbKZg(xK!yOJN7VwK`8i2R{0J635iF*3xDRw%*N`ubVYKZzG%SHZ zf)YazX`}<9Gfh2jP2@jt3KHL^f%H44Rw2oIx6(EJSX@@NJ5U$IXTVW_?zKvg5Oni)Xo^7Gu}5KOix zhjt5IJ_I;5-qknd*I81N&BEX&lL#4IG?)kTj|b5_s(JD-WS@|}F7}t;j}rcAYhe=N zpM=(1aDhPkV&tI)$w&(f&L2e-O<(3=jRI(lZ- zxQ=Kw3Ya4;5d@H9toqvd=fL=SU*YjlmB>D0q&3|`*&B%b=7We@qkAdwcIQ~(_GNJh zi7*zZyERyK0AS>!Av(tv9*|pX=l0rjLeru;@G8T)(toM}iX1Jt`sOk(4Bw!`0URvH z@YbRs+G4kUTlqgR#bt%o@=LtC4Gvr?)Q% zUZDyP7X6~t`S?Yl%_a5eRbT>vF!%#h+<`E@_q6$kz2dD>WikFg5dH=$BKGHf_HlLI zI|=*yKG4dc_S$;fL*p04a#bDD{wo6%Vho40qDo!j+&d|Eu4`b%Ln~BZVjIkbrm`co zHpi7~_ZZX8d5J@UC8WBx_+0!8!@X`-a{4fZqqfDjnPk~Jo*g|*QKd8SSY0F1XJtGh;1-G|yE_XVxg3xZ(eeH1`= z{A;_DSG{+AQl6S+R`+#?%u)AY6&!U{EG`XQdOla1*9II+OOABnI+p|tr{GcDhJ=ulEGuu|*RhNP&`!B+A( zaau`&Q{B;wZz$6$I-Lfl7CI!&1Is1jXf~zo7CnwHNa2Gq=!ekCRWdLsZFw2^w*!RV zA+i(fHHDp=C}HH-9#EA-t;njPXGBIxc7_@!vhETH>&3htomuVG90kF`LeKM>6EH2X zUYUT*Cnv2UFb#eF!&B>D+T2LH6A0FXI#!$VvVzoFqth*J`23847HL8E;9c7}J}?~q zy??8+mAar3bX@_e>RF`cHK ztnh$Frw%&(wVD#2l@&agSz(>QE&}Z}M&`(?&}k1fLMJtd3M8EaKclpeoKS2Mlc<;r z2v@P{(NMF6HX&(_g9cNI61tB_{VB2Cn$S96>kt60b*!hvOEiZ=A^~NOh?J|eY6N<< z#{FoESnE!`J-rxvxToU>Ehv6z53m!)zu4qzs|k-l<|*nb+rcOxG`~C-E%kbk>v&9k zM0CsS1k~?aW(4!{D_(|+1tn=2YHIsIkg1Bg>Vh=XxS&QLm+-KeX`U*vhymPFFboq} z4YJ5u>N05kRPmVh4nZMI&on+7YWsi#={4i^f~CktSDra%ODFPX1~#%mc|#{J!z=1- zdW9XCBXW>zK_L-@C?i3Am&^q&$~;kgdnOK`{$H4Oa!e1PaR^`IV#>ppL(#oZvtT63 zzKWxD;?t#9pL!DccrK^L=zF&lHxwNpzhk&3^ zG{pI9;@e_FGfQFPG_mF|gALw??Zv9k*=mHQe(Ssnt7JC|C3vl|xPw01i>Dh=Spuu2 zr_k?VK1O*T$bP$xzTV64fr%t>Q4(aV0}mtQ%h#LF5AHJBBG69hoO1_;@SXX@IPw(#*}OsALEn}MiJ=w1K8yCjBJc1zuP z4ORj%7H?WD>S2baM(nn#yR8!y?lMQsenl1F+aM8%{fyu#Drv`UvAD61( zMl-Jv@!4H6x9uZoo!}N@-T4~9NF*}YkKgNe1wC)BS08--Kg%!Bv)l ze}Hfak;0Amv{-Q}<-(oP1tXmrPWu_hT6RVui1I_MyFp?P>%Vd8P$#Ggb#SbNJXHrO z9Q>CVvVp+==S8yr;QwR05t!gVejuAa{C^`Mgg4+n@{sAm|BpH_mZ3kYkmzFgchvuf zhmbaY^(no?8w9+72M=d3pswHZMdK#2r|MyntZG2;@G`0K>wq=e$d<$+PWqS9=D7l7!5@OInIN@FhB|bpw`VR~eBB znNS3jSFCmXe$iB7{e>J{lLj7DL?m2uoO?CpIhRpD{vIm31Nui;=`BFIexZRYjR}ai z29NY6a!{&6UPI4Bl+8=MhGrQ6)OP51a0cISrBufT+8I%;M$a z&iEkF5#-bN2hD#AY<8gag&!B3zYcwy!*KAefRp|ck)6y-98k3c@VhvS)T-xGir}7I z=oc=8(Q-bD*8W0!*-S$&rvIcW_Lv~8vLu<;fF|@KN&)emaDDl1x6)nT-3eL9sHz%- zq{%Y)&-^^@fgp?Q;7hKywI3_+Y8pK}07y_NepP$m-1{MfKvfS~W9+YZX~<$b4@MG! zAXDb9Xy5pwS*=@2^(wY0Az6+-nz7eJW&LC^-&yw02F6>hVSBs10F*3`JB&P&irGo@EW7i4v1evcnMiep9B17 zs1=~`P>wAMMR@=em%69W7s8-7g4uW+Un z>aBFi5c)Z76z841kfCv>Ep6B~6Gq@W)#XOD)V^9fFe@ZAwOs)*@*oDm=FvLz+k_~~ zHFZ}SOIRQ*AZoYt;esvlugmUp-n}{wIqQ&Ytvc9IPqnK@Zz!@JsiabC@osxxkB@~Q z^n`N|0376!3hxqVe;<_!{5VrOD>SfMTKT3O`XU&?=-YdJUG7wP8pdv$+C2FI!uC2e zjRTbpMRy07ca4kO4Rr4iNpR zV4L5HyzGLm)s596a5M_R=!yvFdtZe1$U_6NZbp(flr-bm7NB)Mc!zRkW6F(k$LCiV z?!oSj>+g~M>r>Alzm`6{3F^Fv6Nb9$N2rN1y#t+766K2TT#GsoJXpj}bd_rF)d>K)7}opY5olZ7?39@IjS9fYN%k~K!PQN2qOHYO;%s8e#i-8MmA_^omA)` z0$WFIq7aa#cGoFRQm~FXoiwnm=<8-TI-QbjBCV0tPKq11PY{X}D^w|B7%#q@j?Wr= z`)X)+rE+iWf}K}fc1~Mzr{D!3p%V}a5774Z>7|ZY?Hg;fJ;N}*QRJwDH5kvLeI`OnZ<=DDid&zaC{O3V!gd0*@ zjD5G-*LPhjq|;PSR3-$R!Ynegeu|TUx{y6ECW_5}D-+jaWY015$vx#s?R=C`BQQG_ zE2{ZjhO=AaL44MW0YaVCCXT^6?B^w-Ay}O^2$?x2w@(bGIYO1B~la`~Sxy`P`o82B@jxIBhmyDRbU zKXa8g1*{|*1k<|Q!zk+ng|o}`8-8`mO)RcO-vO$~Tjl{!XA)?9RqrkkOna0SDFeB= z6;2UY`56DK_MUes4Y43Umf_eMNA zt?1jMo5O;=ewUQAOY<~$3wMvz$>kQv7U+YMSTzk+qbH5Gm^xGkKe!H2tQf!E)AP$`LS-%w5Cl*rK zXyyq;(B_4dsvyps)_Fd8_D@)vG`d(YBWQoDDVri51?~TmLhR%50J$3^gSyyM7#oji7!$zPt zZdkTy^_;NQk2QY)JSW?v(?4L!zMA@vT6l#dc;p^+*y7%jEF)nRDucU~(vOPP0T zW_HocZeJ`VVJyR(vH^WZhGzWIPM*J{1n^Lze#3hFLJnO`p2vhT_FwG?>-tV>f_vC; zpBBa@O$WD+N#s9${kg_2#TOsnf7J+bs1CFt`cPe0A&QT{FFG!O?~YAnV4D}wDz>1q zE>EK}Ii&`25|_l#xMKhXq3{^Ix*$MP2Kz6&s%6+Fmu{IvtK(orHWVOO#D=Ki%0=ni@nw=8@s9}Zwp?7J^W(Nr!b~eIU8vsQw454c7QJ8$W_}H3 ziX9y;&j^9t>xTu@c)n@3z91;}xWzx^u}Kx`EBx2$&^KoL1c4YaB19kpP=l)Ma;ppI z#Yye9qe;K-gzpAK9p(#D1vqRm>!;BNg zg_)SBezI-QkBc%ezN&(iavvFgeoUd5``V zn$)gN64F-L=uy?@b~U2eNFL^+ANnXeHdgn^GH$=yg2zQUeOV$qjE(JxRMZ{oq3)YE za0ZcH*%CS1ME6}+2}}b9SQXg$GC+}~t9%h#T){&w_YIE*ne)@w5&4zAZ~YKpe6gd{ zcIG9z`Q|K#4Idw`x+ul%>^9^0#4ET-(HX&J`{M-jz)e?!e>1I10Necoqrut>Z_6ef zV-s7I`$G2Ta?u}~XO`x>JT;PwhL;G6k%8N}byiLagHhu+d6DAOd3`dUn^qt81~BXE zjTHDpH=I0{d(8ij3Q zXhz)oj?b4K-!|p@`H^YpF!RHjq%E#aN)w&V*n)K?bGBXAv zO{|+wj5jISN|5HEZyY)A`6c_=eFja3z3NSR^^B4vtx~^6=XRn0bqA>)@~D5Sk#@L1I^ikThkw=`D&2Nz_Qefi%3{~-cJSn2CYK_Ap5&P}H1KOYnN`xSQaiTy z8vT}W+0J`-bYj<8w?!m!oyHG>3Dyps(aMSxWKl|OKTb0QGtoTT{&9ht;rzrmb2c)f z?i4yZB4%T`xM+`y>iX_nl`_?t(z=j&b`i0lPj}1zxc!uou`AhoKGNAVaoe_vtA*P_ z(XLZwqnpESf00DAAx?yT+8|o%`l3y3oymL{Zh4y~2?eE;)mM&CHw|q?+u?ARLo7>d zd`7H9jYkSVI4Rv5Nc-%1KcFm8ijIjQ%$fsY7#25o$+0a@_WnYz!y9t-OE%rQ;Lf;X zKZmn_nrcf;b+;x{`qTY(CIK_djR|vN@-4%)e^j{5=Y(1*7RqCrB)rpb^|{;*zLiRO zJA8p{MM2Y^YWrt?>3OW1&V`eT@U!Nkj6jhV>j$KRDqZ?h_c9AF-qgWNVQAhOC$>Wy zqC9o;{F5s!JcSAhSH$XumlGn#g`T9|=cpKOp2gV6TWSZh4i*0{rm5ifxIFRPFg2-+ zM!3ysV~M$bQ-1(|cW*hBmhDH$-g~Rq@U5x>4*G;RVmI(vT!$20BjIsNvgLnXHuSfsy`G)m?I>_9Ia_JzdL^DIAKxc*hpI|q?!)?##ftmTh7KqSSjtAiTWl9Z zQdA}z*KFmSeF01SE}ZT8ojBn?Xme%Ym?gWZUjg39LqkTEhiA3uqV-n)YOMc=ZQs;_ zdkfBnG=63G7VlVRjMqSjaqBOoi4ncU0ZWN)+hA(q@X0LY)Uxc_)MitQr&D~7dmaxb zM7o`GbDZifcWt$b#(%8^p@lOE^VSfSbLtMu`^$zVHuA|uxdY$Xj9o32+VLw(j=$^A zx+#ioD|2}_Qh!WrRByY*_tLekn1Wa{ofK`Va!AST?DSRKtEt>04^{6)59`no@li`r zBTlZ-cidK{ZR8`|Z`>>H0~&G;9Eg)crf?%-f4zsn`Q7L}H3BPI_izi%^e*9wV56sb zLj7?t-_VqEaXll)|Eavi*4mew*lRc4B4g^lbwqN)d;EicX1K%Z*3c`9^AxCkH}gh} z?i^Lhuu#0>c5}Zf!_)`wtf-}vU|KOQ?qH8wjL^IKA@-c;=9oW~4c8t)n4A#DhL_Om zZ|pakUEnhDi(=BaGqdo4Pg;Tc$C$n6cq~<4HAA9O&3x4BoAEKPv}=~-kH%s8TG>%I zCPnEAZ#}`9H8*ZXcuVDsn*y|bdjYY>_5MrMkGS4Co`~^xs!Kyt1@144dlY3#We-_7 zd4XYSo=N#E^_wgUn~)W;-hThK`C+t!GMxnFJvZx^ip}25i0!mX>+_dzY6|DDBW`sx zv2K^x-e)Zw9$xkA{r(#e=23_+KR(4MO2lLq%c=$k(_PluNto!iYE`V%>ZfMNq>b-u zJnKPmsHbO&9F)hmTl{t889*CH9J7r>&-}*bO5IJ51T@`l(xmg zo2`d*t+~-z3taTgR+p=5y`?HIwz+@AL+*0P z+?D}NQ-MRyLalF^0^JgOf$Z2xELxctxhDztqx?d zjNMZI%#wO$ErpNUEJ&V(!t@G@I9Y}jTZxmanZlS~viE(_;lB2B%}T$23~fFRIu$PG zkBxCJXL;Q-)rd=u4W(^+WmS0=_|S%Dfx-JAsh#AnU)e7SrhIZ*In}+lWbRk}uZ?-- z)bWz46635-zc%`pC{m8ZCwBF4fBwm=6lkuo)nYBVYS}pCc-pB(EN5VG`VEe&+hhGQ zgV<2_$dr4zGO;~xKw)<|U;g%Q=rQ|H7)gQM*=&2G z){Zy2L|l(B=q+4`iadFR>6*l_h8E`7XY&+an;+5JS zhfu0?aO!h9M5XIKw|+saT#TA6I}2*-Bk^qYlR~F`8)QS{vKrP^Zfw>0CJEB4nY`Aq ztS_#o&d*9s9kmE*jO*fIX!DIrzN5-YQnvS;S{$qX(EBbWfm`CeP4h(9G|lr46X44+ zi{@IVs~h+u6dmeT;i<182xQl}ibNn)s8dO{mvgPrx=|AR?AJ`*3$k6S|2!>njC-;D zH9SU^L*={`Sy4fvPfQYzkhh?anf z?pf~P;o>{CnTDHpx(ejhbC<6`ZapjsVq*y+OA$Nuv!Om^$}TlhfYW^hAAhQFh&o{x zGnsZ{eN9LyN1!GzL$I~hePq5wo8Z%*Q@uKQvW?K`e&xMr@ATGKZ633=2VJLYX1Cq4 z3%-BLz6H8p7*YH`UccpQ=%Ibh&AGXS)i{e%OeH*l2|Bjv}2x?==e z7oA6zhPtCh{xDkW#o$E`<0f_^UVx)~h0;|s&$wl6SG@0{lT$(2zg}yJuGhzHvxK2z zmnK-fdY!w9=UrdRxwrJgq>YBmo&AVF8zFmmam{@$y&$f%zdf*SIQN=(sSfk?;2d24 z!r&U&OEtN(cBN+$Ce{U>tR^luRpO{|ga~hI@s+x~_pPg0xa#CT{Kc(N(Af*(ajE}i zE~+}IdrY!)Y+R!O#eI7tMZ!Z@Po?0ZYrpx^ccAv~aPDLMy^_K5`x`lnF1-=28-gzl zpQTkiQqpj7TXb*HLub1v#a}DJ(^}l#l?IngJlz|EA3lLmX7u!hPHi5*Zm0*o{>k<_ zM;Qu7I9wkV@wmp+wx!Xs>12L)b}$E)VxuQ6%-jCvOSIet0{ecsb4Hv)s`Ci9aO7*k zS$FoCn;#l3l5FOZrF1!0c6KmX>rN4GNWqulgLESdf=ArymrJe03A@({iF#<=98h}x zR~Z>F5njJFj3im^p; zbO|)&B{+VtwsTwgUJJ1L6>?`hz-lEm+il5lowg}2@6l6Gk_cR|Zl08+_`QLl7zS ztd}#x+y}|7kpdu*!{Pc@)W)%tcG}n7ysl^j2GR4~_$I9WkhIMuNWtbkpW246Tx?U2 zh^NAc)Qo0LUyEdH9%KsM_rdKJ`O}fDb}}+JgfCdWZn=S(Ec|KQHOd!T>uiIu%+NF0 zS-EWYrJ*RB;L~HmzFwUlXLy6*qSkN`w;+W;_BoGA`o@C7N`1dVSF7BKd(QHU;!dK1 zi$*QhUrhoSz)kTe$l8;>J*>9CV`|xsKL2qwQXLq8ax0s=#nr8b)lhYG=9znu zjk8f>%*a$!%eL=j-F5FxZ??mr84A0E90MG#vD(kBZt<39cX5cs)bZiR#>I&aH*u(} zx^vJ04XmH==Kiy|^!p8oVf91i#YRzG-S?*7Usgvcu1-85Wl=EuYOzU{?p^m<#6+Vy z)+Y-Y^nMH8x!kbL{P`|p&-(pyS5l%Z#a(a(+D=|k6CP(LcvrbHX?@CM#mB4y#Cn

aQuJJ^WTVq-F&l!JupIF;>rnq0%>CnP{r&yMwZ_GMDv^GDtB@5T6g7W2?|9Cu7z0W+a++&tES5`b~b;i`EPqpgoFPNji?A`_w^ ze*14TB0XLM;>Yf!Z>E)5%EDpt=J+~?VeHWN5s2_Qn_rT-_C5O^-l8!{%&9HHy7w5l zNe>AmiuOAhRWS|Cdpo6&fX7pahKIC=N??&59xkq zn??j2!fPT&!6QspA`f@`cyf1lJQ`pw3c5JiH8g$fANFe4tZ(~Rh!|{FFJ}Gv)t3pl z|Cncf_Jm(t^7_rAMOfO3SYA=&4U#YJSqVA_|6macO!Up$0?yry8kf!9C8O61UUx^% zC2Ju8qbO!f?-615RnF6&rhyoeJ@AnfvFP#Z3GJe^vW~q^i;W&5%e@+XqaX#D?R6Qr zDRI96FT`KZH>y$d+*E|7EuOi%B2@ja84M*blJxL!i4>`GKYJ{~k9u_Bd z5C`C#=mqgni(bdG?-#OPJ`ROscWhH`jEkcAM70n(W44JfO{#5I*Bo2?HH=0`6+^Jb zo8sjantHtij+h-!J8x)(1qS_#6%AL5-L3r|+VV7g~RawAd-I>>Wi?>Fhn4Vp8LkBxQa}S@Fu!em1@O3X4Roa-7uU_ucnh z`cERE-P}*8j5m zO^BLl1wOpc4S)KZfrM1cQN2xo+wCj$@ZZ%Hf9sxD`SrRLo{({a->BXXC1|9cf{X-y z3GCND*^Ga~hX0t3h3&0BGr3c_pb?Y+ zo`Hy!b|#`4jX&cezF+Crq> z3J3J9UAI9vC3`gRM|GMA7+_wHrzI>J`CCo{WnJF96D;2t+oOLCKBD3 zmEKPuq)Q;p=Z=zXi`Qj38C%G7K2s~Cj~*-15@WZC&l%q=UG?}RgZF_w;ATfhhrhvU zuZrH{>-Mc-&?686JG;p4%Wv|5b@O$%A&TS~8sFfnD5p^E9P27 z4K>bfYKRoMUeeqGJ-Qm#^~D^%ar-YqL(?D1QWtnkBTPq3W=hIRs5|DBP9OBdXb?JJ z4PAHtnn%F*tlB9==doA^QV$%=#0#No<(b}9|CmU-ej!l5j_nHJnIj*-)PZ{}i*MDR zQC)l)s$94$Efjm5@{lJ7D&;B7yXt)W+jV~++&31tJ5mCst`P~53n2V(rdm?7x7@GBA@t)!;w&onUd*j)TAt-@J=X@CKn||Oah{1Ng_=4)GCCR=@}O47(qveFFc61!^LOJ{ z-|OvbAvXXb1TW3i2tW1ckVKu0e$2Snu$l~gHT`2_-GGmRG$Y3^#g}Z5ix`7__U|bA z^aA*WA&;B4z?4b$6Qw|n2O=ih%9082hK3p96z)ES;{=5T_Wad0Uy@5dTS=w_w2Zs| zLLIdYUD%5**b1u=G)A3Fax&Uy3%Z&mnLFd`jW!ogm(MTg@H%|r;=h1H6o$WjXN{C| zJ?gD|n{>n5I|KdcfB${iGNX;5lDXz;Z@48C)WO9cPErjbFN^op-((?oGxU}<{S9gZ zdba^!#mK&tq@<>h=LcCCUDov5z#jPTEUH1y-R4z;0I-nrfQU%Vp_7E6$U^1%>2#o` z|MSJV-tv2Yvrs8=s_aj$V~}gJd*Fd#xCpNCyE$uLQ6|?nr3@L6Y}LG_hey-X;P_+A zh+bBuN(D$QYU|9+sa_HaAw#!DH9dDSb6apy5PRRbX6b8LXf91V6VHOKWm_qAat|jF zKcJH_Ky30P(vKnMlr+YdrI{}?#OvliNZ#>qTx+4_$)sK~J98B%#e3f1*OTDa_qZXD ztDXggYIao?xNOw?rDSFFpwPVvoS2&WH;D8C7-|Hl+iC;-qAY|DJqnrJzfJvL41jt} zNH}mE0bqcFp zY_FGlXm&l_r7Usu4-a_N^jLr&)xMVJd%F4j?WIJXyDArBx_EJFMfz*OEZp6P)=;*f zLQD22`zUs3Kvb^)CrX8NHZu}l`Mh$aFT`sZ*i8P3X(;E z<`-qW0TC8VA?{Q$BqY_W=F2Zt_kAx{(q79O5PAy7w0Cc4D5k_(=a9t0bQZs%$Jh8O zHAvL=>g=;GYshF{krw1^*-PEYzI0i<2tKIB^vh91NM^IUtAyOm zL_V!ryhIyzWg!rvAYMDLGRlH+)fBb&dI?LxDyZX2cm|dfB+R2{?<~X~2GUgION((c z1&u-Z3|~XUd1()qkiVcXB3MF=FaxoO)SK9p$BG707}qiieZYDk5vg&AD9Wn zVaOP2+MsB@^d<$~bP=aGYlSGJ&x&ADOIJsck&ei?b)L;PByNjFxzh3P3YlPBa~8R@ zu2FT;&KU26i+;_Pc}+}l%#7)fY4EPbudHA?B9Yd3<@>N%>e(4(G%dKctenW<@=5VU z#FPKLCfkJx&uHr2P>Q{6EZQlj17Pr^U!uL&%v!S)fWAYKR^#HVY(IaOpV#3Xuh4(% zKNX=xr-IxM!A@z0KYiH|J1HiodtRIg5MEdCkuC(#TIU-`UDe_AP}sgHlpu*QjNzwC z*mm|zAmT`lGE1GKxxVK0ZO0XeH<{3VQgD>ql6k|3r;~X_tv$#6^h7+uyKEjR`MNVG zJ)+Lt7q@Op%(UFd&V(sL7md~eS!p~AQl7gL2Zw58Hl*Iv!N367pLD{D0KH7Gm zI8K${ijt=O@{%<5Dlp39ZPms>#O2iP+)4HWHlohGa+{7vbcTEEYq9_wHnsFrcAqD6 zObQh(2SG9VcITm$BIs0)49-Ngju#v-tO&K}*Id6aak7kU`zTYB(I{CfboN$S@(-ilRyiku%JM z7G^EkFn0vT1)0kq*qXu2=MargTeUB)>cnwnLVT*O;Of|2<>Yi*)@3s`Q^c;13ev| z6}q^K4}N;xJnKEaLYfOyeV=w)fz1H_jdfeypWVQ_v+Zn2AV}txUsP1YvY0nC1~y?g z-vHo$qOad!5~p~PgS2Tzb$()M9=S18fw8X-7O(8U%V5Bi2gGuy`X$@(6Fdm-Ns!Ov zZu-VWaDGphv%-X2wk81&Iko>Z>c1#_Dm;)5)aa6|{(WpRX-Ge=b^%1Of0+4g2x`eT z>IK)g)mnzjVX~=J2|5S-BSgAAFS*TXtO2Y#q1@K&Y(pOcxF!69Uj!i+_2a}(@@v0g zxA_fl+;a@+>-&EIvFN`9P~oj~Il1-^^IG)uQw%CCcEG{R9`VV^}Zms^Wy4MRs3&YP{;{Px@Eds)O9-FE-a0>#GwJ6C0bG zl=2D=$pfe*>eqAX%SE@4jmzqHoWOO?!VzG8Hoc*deKnqhvz`K6eSp?j5ilj*;rx$2 z^muz}4;)|5?zd}9bj-7zuxrGG;oiP|dzS3i9eLaRYye>3_zn)&wI4RP{)Ogd9o&y# z7AZMr-A5{sOT}skn6}pfzxaT`^)P@KUG<(-Ok7e@Z7%=wnd|FFa+CcuRe7d@wtx(i zo|y*QuV$CxrJ~ASN+%#?IgRDzZR+ZK$~eaoD^uaIn-MmIDPQBt(^!tpnvSppsW)Oxmcpy?lYc zm;p@%rh}`tF00MafjuwzT+%!;TxhHn@664qAb_WaJmoJWG~-8|H=>BO{U7SlDH^yJ zs*}EJmrb7T+CVCBu{e$K&8JM7sz!8t(izlTlfl1~?+Tx3a8X=vp1A#8ErW}je)YHzDORdQvEdhM z@%Z{Ao;*Fp*Vn3GRErmdrBL8ai_VDD%h@jT5xz71s($ce zy!6v_=s5LDwseUbdZ1$w-O0R@AW!tEzRR0!kw!j_o(>H()c=6xdO$cUrZqjM*rnHk zv*4V0N}jo=;42LHJ-G^Nrzw|LIowC{C{r!P?DXCn*JgPtyVAds6G7jenG5$8v6O6T z{H@k$Sv2Z5>PcV}Gm4r4H9`|)1lbJ3CnALv+^m z|5@$^yfglL^||0Ao%#=c9%xxY<3qql6V3r5gl&fU2NG3R9-VE0KcT)jUOmX)T-FA% zCdtt%WW=M>(?jMMF%d2}A|;enqrYaoT<}@?6cj*@zw-qE-X7w-gYu*>NOk0Fg z{Iz&#zjs@yDIRA|=L2M}GYC-3VVf;X9fR9)Sx_W9`s=L>T~tNh)mW1Xp;h=G|2%+Z zw%EpbotEDDrWu@Dp!v5FqN&X$qo&?k?)Y15+#zryUtpRx-lHv5PsaR81u^`D+vCSQ z^g_Jvh5czl+_eIa)dYLziszT+$=>-$VP)IB#5dDN&(cX^*_O6B?DArlxSAe!=ee>T z_nh@_q@pmQQg!G|HtQ5uv(%p-PuPV$u-YrC(Dd3#mL#gtpE8!lnOPcebF2zX4j2h8 z0>%(-l6KMWvo> z3B|aWsWwgd4|Mr$Ohr4MDg1GedMsbOxs5F8+l|x_(&$5Nuw-dzu_D$64yc*QMEHm_ zx`j25oYwvp$`g}yM5@{~dh|V_dXbK{xZoi1qxxG&DidW^Hnj6dy^)FJ+>AnoCYxZ| zHk(S3ZpceH3$Ct-T~*0&yVGD(^S=7$@oWxabYw7U(SD=!qj6TtL~S+*OC_IBq=e^N zzY&H(aRGz-Z-}lfT&78+Zajj#vv=lgHu76L|1D7^Y@trCIq8wrREx&8f{jbi0 z-_Ai*^o;HeG?-vHBbVRGHDtxwd@|@K%hJqv`(BJbom>sYX(Swt2o?KVCaM*n)|=%Y zCb+4DqHM`L{&>cONLT4pY@m+UaO#T>uaBp5j@)PDug8XWlNOKq4UiCI#X042(Rvmo z8)UgV!R&$iXM)~a%{1|Nt@o{rdgz=bv^3y!pCl%z%Su1+WgRnyk8WQ*RALASg?Y?> z>Quv(2*|NTagd%&-9NXZa55VIO`sr>L^^TQ>b5+0(7*}1QW-n35hcjBP?h7%ljzhLOr*Nu@QGsz#X*Uf%zC9gKC(fz}N@Fez zPA|0^^-22MY%O3Kqk*0~wG~e~OLnyC>Je1hB9Uhy=JS$#u&_5^*%q6Tn~N9g`*9Re zf%b4$`4cde6;mZ-7&0kg(h{S{i$M@g*s#5nb5w@tS3h>}1 ztfiYf+g3ft!l?JzuWj3u(GROAR{LIu379pyf0O8@$nV#+mF{#K26eE+JNP{UK^u?j zMMHw*l)+ID%A49vt5sjLa>HsA_vg%idnO7I_b?z{Uah77X)6BBy%hj0%C#LeQE3Oz z-IL#eDEGh82awP4uvL^*QF&msBq?nxFS0RW1Vx5*opz;k{r#Q*%y|@wgPmnrgYpXI zWdzy5G8GYBKsV>$zqM|@M^Whi$ao1;eWQKKPT+VNOq69goQ<7^r|B##2g+m#i~8iQ zENaoZ+@R*=lNkh^p|xp4{YUM|o>9VMy_xUhiGu%1MfA$achY*#`!O|sW!l00#*l7X zepF)3_bD3l-_PVWubT5Z4|1IW7A|bXe~GA?-5Xp=Mk`ALfTRFo;@nZQfcW&p_AbS` zUzj{9_P?1`WJ+i@gDSwT1dz>97lhL+7wf?7bokqHyb1u$>fIBNzc z1P>gL$dd3A1=t==5Q?PXsU*y>N0{p?nq#1vY)45SY+eb>2gu|o<_F)bcJFh#m9%tB zq@hx6-<|JrB#%Uu!Pitu>?4P6e9{5;#}P2+1YD>JHRSF6dAIq~L#LtV!bIv}HdcQ6 zrSZ>3UxrBXXEPJK!2>Mt7n?5`G*QFG`-B^e4%;e^qL8O!!&wcUn|H5S*=8PCnTxN1 zJsRnE8gycqV}X(n&%H&=tyE;0n6nlyykW1J|2ZFV=&)+;hs(C%ZEMT(fmr4;TlZ3h zkFhX$+PnLKs`~w%MR3Fj)rZ6p>d<^3XWz3)(aJyBocQH{p+F#5WP6p)VP7p9I+}a0{g8B(%;iIlRsh{~80F^?}w_$5r~TSfT%-Lp0LFy<3!2 z&lOd$Nb0WXoZC#W!qS?=j8c9&qNwxPiG-ZdFlzuxue1!NYc}954giOFIfY>ZJ#U~w z1ElzXzufxsTZFGBRl>D6Zu^=Kz0`;nv2ld9z-EP=>Ojb_`{4L=5LAr*MVB$Bfb!s| z5%f#H2xBnS2PQMgPNHUI(5G*Vi!?DY;SK>z*Dtp{)RFLDKG3+}?Z{dM;8(7jVV1nZp_2{@%Qq@b|mT@H}xw&5jF*lN#7>S6*#tcXk^*eA`@y_E#5aMC`Qt3 z^}jp^J+46x9$<}7LPLw8fgSu^>#~*g8JO>vW%5+w4gtlVc-a;qqHe*kccMTOCXHZT zg%wD@A#$ebJ~v3GREbYcrxbsG2J~cOpA0=-jO}Mnp{-8vt2z+|y^>|I2oYMIKyjqm ze=}g>Bp?d+#0S1PUqvmx`z(%(~fHdY`41hnFR_CnUT0iSaZWX_GZqwB*b?_#iCM^|I}W8Xs0VU_C#*agXjUGr!X9$W3>k5D z?Ow&e7mMTQyw+jQyjkB{cu>6fIe;H}Z5TS#a|=;+#WV@9q$ue=Q?D)xeJy1n>sMd~ zh>k`^TZb*vd`*^!)c2#xcSp;;l%80O-l*gCQre8nm`Y@CHnRm=@?TuD0+8j(9oOd837)@p1bVu%( znH6UBA>EZz<|23~Kt49kJ~6Zyb+1^i0l;bK&c)2%(?!#@cnDUpoG5-weWwxH6&y4kgwj# zZipz!tI{A>LP~7?D1YP?O-*6el z1z4|Su>rn4W%LA|$&MJS#q;k1xThPpCvtP&NgoxO{&v*FQcyy1YWnOKpRM;Hb|2$> zU?_vtnfWZJ!Xx>R8OC-)b!+a3)9ddx2UUdI- zvi{t2I(y>FJB+{JRLyeHOs!V(X~%y_DaB#nJyI=_sPWi|{(Fifk)0)+S32tZ`=b4Q zL$jD++Gd1LP!4XcX0O29F~AJ+;j&XfH!sMi>2K|irET^Fd?fUk0kTL2riOa@2HB+u z22GMS$*7aT-bkC7Y&Z z${bnANpkb!3fgcLlcUC4+zh(6YIR^CwXwk9K*zVK$ki+gPSIfW@^c0LZT63#@HsL< zhfG1+QxE7G3X>=(DU~){3v5DP7Pd~};tFaV9!;0VR-sQdR(hkH-`6xm|0Y?~xn#6I z%C@58;*8RRf?xPUzWCpcNWUJK*`bWK7H)yv#$8u4u+WOz#LDw}p}@L(<(aAR$aJo` zB7-w}(+(-iz6$o~>wdj*ydbW^SirdM=FW!vkf9(nfLJeycF#q(t2rxWrX-x$dg|UK zV@&zYdSoK&F>1ak4K9g8(WXOkmuJPH1<_IGi_?thpre&w8~1q-xCO1f^Bw*7x75Mm6{yGuXQYU=>S;eg|{3-!dLi{7Fj=?^z2_JO|P zo1VlK;3iBowamdInLkUv;U_jpzVl)lMir2y)QI^U`}cBOUEU zw9PS@hSJ^(E0Aci=Pr79g7%9kfTlW#3!+FFs<%W_=EVNTYX27$5B(ZX-+gX(#Vfl{XQmqUwAP|U%C{;moqE%w4!!Q=(?YZ8PhjjRCd>bo( znfq=8KkJ1F^!{fM@J<{JZ|hNBCE~c7rN5rWW$Ndv{hy%~QuKaE*>k%FJjpj%#+6Kh zG|xRnSvxPBCcosm4ZGXO+n$rz)6iS!pPdOC`N#nfD`U?<`$9swg_;2qcRlEpG?cZK%w?Zgl^tI&>MAx{2 za*q;U6qmP#0-RBvn3$Me5$s~=zoFTk1-U;7m9NJui6&lYTC%F6#}rhwRGm+(HmB!C zmpUI?yW6XBwRR0DRH}_`>Mb=Vu}Dglld`8?_QYdnkZ(Dv^?MfBZx4BFzi+d6AxXQ^ z*T{y(22!fQ(+}X1Dn>fp2;&h4 z0WoP=iJgL6CiGB%k?Ve;$1b1<{H1X(dwDK4$5hEXX>VnKj}CM7+kfQOM!dmSst*Mb z1{=IW_}a^~;}N5jX>$&QIx32qPIl>01gcYem7G^IQEl2>9d}lNXn!PugSg*EiAi^j zIj1DL@*DWZtnz@5ZLF5ynS2W76W`UxI}M^NvHTC4$oXv^h|lKPTBwM~*BrlQKv7qj z6#8@yrUB3FTyCpP53O_}Rpg?Rz58uVYUmk9O6wcO{6a1#V7r<6-fU%l!z27+&Xri=o+Y7K%u+3w=d#j~Rs`@( z?&=|T%cen7$PCY1bE2*2Ig*}Hk*GL)-+ISHq4|TOdx2lyXHb+NupsKO8ypzHZ6~@Z z)=0dzr$FsS*pxY@E+*)4+_#!yEFII%Y2-frc=H!Cz>?SYlcbh;L8z!Y0PJnj87z+J zkHR8~`&>}4|I=#N=+J06N@>e-Y9M@!-bEXZRJIsYhO6Iuh;n2RN~vJ%<28I*>xE!= z6FseOe82odhPj_4W()(u_f{?OJgrPOe!{p8>5JfkoG&-q0fxL4)*&4GQyUiLdrHgd zL*KQD+bsVLnE8k??Aulyqvw7%cToaKK(9xe0Z&_eAA5Mm_}ly6WttLGhJCYSb3o(SxuAlLfr6HCm>H$`^X#mIRbRrS zi~6giZx;Q_+g2E?gNZ*DUwG6pa(mXfzfIEIMo>3fK4SRqLPDNZwsD?uAvdsI!`ul= zl@+goDV5i5D+a{+Y*$bfof%PVoExc^nAo=B`?r(BN9+%zFElLbh~q;Ktsfa>OpUnm z;%9)^V@i@<$r^)0ZMVC}uxxgT-0k)QL9 zrf$f*N}&O1u=K+C@A;;EPOqrN*u!e@J(S{_SN-;(y}u@OSqA+2g~7rrc<^NHhE1np zP_*%s_I#D0aN-hyn!Z3^k3x6G-*64tAcvoQ)uBaxW?;lbd@%l~h5rR?@i^6f2YEfi zS?zM8w(L3Bp0(X7s)&oZDf}7m4g)@k&Z6E7c(_9F2T01}eGi7O@qsO>)y1g@fLg7@ z5ZszTQOoe_naYxX7zMwUQ3)dv3?8VRgNnGMVbRo?Uw8eEyO0f3bnhGc!So3dWo-F` zp{5Y#MaBC5m$P=rhN`efjT9ocibf@zR5f(wyAMWnk`y%}v)9mbtcfFKJK8q_{-tqs8DO95JN57GbllY3^ z@t&AsGp0~n?JLilRtfcm0%nb@>U~NR4~0QO0fpflgM4wpA;E0Z0hqL7Z{bjUQi=1+7ZUZ@H~K<_HD*E^av>{YR*U z#LMO~hihG~tuSKjnNflPa*@qsishjHDvGr`Q>mH5OtttvFmWh7PAO4+jUvD|84EW2 zWdy5rZcj0u-Lq~oH9(GClXOgX&kFSby6V0pWW(}Q5)&?; zm8Iinlb&#N!YR9IIEF0OzQ}kvQ&a2P`420>Ho3E$_D#>-Eoj~{+;3Peg0@JQ9Odd~ zi#fhLY;&;Pj-tMJI^-9*PUMf93k>Zuz?_*crJ%5??uhLIZ=B3pX?WNVBEh z-kl41s<1e)554GdaZHk(D@%r?OwC$PP>2pZ#Gx^9ttH1f88OHy6(c!jA!1itd*OQdWn>H|aZx2B_L2P$X`9`GQO_qrhF#QXC=)D|m^lvBlyTm?=MZE7_DVWUnPl+{ z%8Qs{bFp;x3#^IZtM{2^3IBbU4Rh9*C3`oLv)IusvtnDWHs%?LEgvBwhfKzdOqAd; z>__k6ujx-+)F;WJtn{(@TBydzy- zQyIaIDRiku`=8DcyI-RCKhn%_aB{oR8!%Qe=`cluY%NXDQ6s>IU zdA(a2R+Q71Jxe&2a!&FwJqep4g+_e1N~H65m};oqkH9S$_Ax2sFBhiTII-aC+B_p% zzG0no&=rec(7r}8g}4%KbVv_(n`~kWi1E!&W#d)i2#)E_z4QeCL72H_wPcS1n=u{g z+kpIst0c@q`;5gVOs&8>nr}g_6*R);zm&6rKD641p2!v(xp2?MlF?8Oh?dgOURa)|8kU-n}2z5T*{Da1M!nng&*peS&KkxGA zFvydsR?AH|;*tbCTW(;lQktVhFcJ!=7CA85rNtTEhR%YGq*MmAkwDiB-`t#Q-<80-2lA0{%#` zVb(pd_#7t7iUqbwNZ2{s>}iyA-|A<#Vznjts6iC{)i=5dhw-NtI)J3yv`ps`u>9y(P}m|iUCm`hjA!hhdu z)k>t(x0FRpoMyr=C8e?C0sxkO#7I9`esf(>fq-oc8m@e}({McYZWYJHjC%(lSM^>7 zso^v;VkSOjG1M{l>CCXwt^6`=X9>S5_R|CE@cRA51|{y5@Y1hKy%+hmothnYI=rfl zF;tX{(_Y^b5=?>b-G6a^pts=V{TgzyV{FP@v24y{@t1BsF?U8_FvkSfs(HQki!j+? zb#fAeSc7iua@sYMX$NIJoi|vkR#4mWEoTGX2o_W7(;W8;hWX=n;ft*`>g`Qxsh_u} zue4o-zav#2Mop4F-;)9dIJPTmEk5sVot;w9+R^zRofHF+Uk~R#`I3C_hvB82slHmP zKkm@A(`-Q*TM=YaqCnW-$d=Vww=6&O3>7F6N?7~zjY7P5ge*YA;Gc3LzaYs8@L`Z*a6Mfs!nkd0gG8?Y-yfL1)3I+qP?svQ~hnU||Q8|NaKZXck($2l@>Q zLaycN$#UCY!QW`o<4q(7$dq$!s!c>@iU|hO$iqCO97YEIa7_Q*oSZw~HUDCEAF$4b zp;q@j^!eq3>~cJvJ|k}}H%>$t&^j?ma?Hxg0-S3i8%-ecy6Q_*S(#irM9C zLnAuoI3z=-L9Zv8#QoP8pA89(yr5Qac5}bU?)Jd`tt#t}Pn0qOz_fmLg6|+>vu4+e z(H6kj=ho-k%+UerAYtkI20yQxhZd5zd(w6=-!5}BGripl<-8TtMX2X9>^d-V`9&%s z!YP}*;`Z1N^>)J%yK2L=@#v(N4?DR3-ir8p$?>b!b)aHoRk3;P{Mf^U-+^jEJ`Kp| z*azskB0Wo316K+lA&E`Wg>^h!u&;a%;eT$8`Gw)swEX+)6n2Aky#XREugtUw0;}T! zoy)d_lj5756%2wkow(iK&W-!(Zh-_qb!PAIhdl6H2_V7^PhQ8~s;Rcmm#jMBjqn03 zaA4HlhvPA^n<70`^m0_>IVHL#@?qXCT>$tO;cY7tsH|~2IYS!Rfh|A&xpt@muRLxx ze90Z2Db$mX@3$lh5B^A7q^W=)9`CI-#9X^hgj|D;e)+@5LlAWDrpNfSqY$$hVoj0~ zxOy@>N2YhjBE@-`alBC6vmPT^E>?*p`0A!6 zCOew1SDKwC-`0SkdiA0VD|fCz?c%=}h>OcaACV$ZzWOlgf{XcLz{ruQ^LCWYn8xtG z%_G9v8A3Ug@@gZ;%|PScni__RD;>ne)u7q9FsQ}Of+Hz{)uQ!v(9Ae%-F5_=*}#f* zZEPJKHy?;_n4$WBCBP3&;Uh~RMc@T5l^`pONOwy72C>N9lL#Ri6Ko)3az|vT!{SLR z;j-eGnTb@R0ghJCj_gFG?r&3aP=8y@RQcWolMG9tUITZjL~y`%ZFn_g3Knn;bKTlD zYjFhAC>oBP>raUFR?gFGM3{aX(!Y zrD@2h?Jx3MjE{YD9JzV<_~g3g&-H3~E-qDc+9(MN=l^2b1(4QlH?ub$5KBE-N?mQ< z^5ZWaa&q#_Imv;;eY`8}N1K7(n>3E#T$n(GwIu@;ZGSp38geqtmHr5aMJ1JU<9jYc zrwO$k#Q%^ug_WDUb1G2(GKcwzeokEuPmZWIkjTTxQ6 z>N9fH!A1R4i%tuvBbRUyn^LoNb#zaQ=8Fr%rcq(_R4qpuh-f1X*P*i1Gb-N7Hy91! zH1-x%gpWpYNhE~Vxq}D~hc5tR1}*@>in_M>_4@R`bptXuI?TchIQIsHiEY1;A2Nvj z=zZyA_L7`3Y7eSK8trew{Uj8NSu|q4imD^uMl&&>kip6KhG*jcLWfctIKzp+Clm;M z;jAV|6Hnl>{lJOMsn0s@?<8(ktH3#^|4PMBIQ|U$p5e0|Cty{pP)*cEIH5$wCn>zmwLL7Ee-yF?>t^x4vqjg?Qe7U7kS$s-xbNz97Z zGD*GtpaK&o1v)IeYbQMX{PNPO4z~mYfrx}dMzpFI2!uuENLp+`LYHnUAAFZbNdD$dtCaqD912$Ud5+U-4HeDc_IXcEtgna*-=-89IW6_eBJ^*IY4bDw)MgM7-<5R?oif`{Gle3nYWH@K5CGw_ zOa5!=cq^Zn-CEp`0E%D|^6Mz&{#H{6WTYCPni5yX75_m){GOf7A3p!S11E5lkyzGg zE8EG$Qzw=z_m2CB#-N|Z6pjIHUSjM2-BOX)OkM=GK9!=L(QArMcWqn)Hk!aS0!;~z zT`^oslJEPz5PPZJ9EtPpS2Zl-lw?mp9|92P%sU#jsX1UC6qesv*^*aZSFG0qpal~e znuGp>mmAR}SIUh<_iFq1rvm^uDS=D6=pRf3Abe+D8Jp<(a;KU!t(#Y_l99H4Uj_Q} zMNfOo!0DMDv@1J(WHO2RteDFu#@nQ3`Ko6CMh1vtL-zsh$=7*89wR61W#m}Xi&MHF z`2i6sB$z%5AoYm|>61P@ryOa*LHQW?&aFmJ!igpsFwaERAHz%W^78uk%sK#MWRyl! z+5Uym6`8cIV|@$BP$`FFNOl1Syw>xYs4|et14)p{@8H^22uyoCu+|-sRzpt&SV39^|vpsMFOG=;T+wLlt=;Fh+BMu@X_Rki7W%nB6T$8oP zDJz;nBLPO!-{`9W<|7d+9;o&HhpHJUu5E zk=Ddpw9b0VKK*#eLbrghY`k-KF8Xs$LTD_9j8r+AR_Im*WC)HDtJ)cl^pnXe!y1^u z5S_I3N)&o0kXgFu1V~Cy39+rcqWDswITEOjqx>YKtNm8#GDg<7e>Yl{PY(u`d$K}) z+i&cF{{>u~53-5=eJ2?KKFxS*lil4tRX-lz?5r#;HC{1M)vBV|ydvh`U&H^cqan{5 z5Zi~Jn6Eqb(i7j~RO2~DND{zv#HzJ#PCrt;rqSqq{7*1*@$|j6lOV}1K^VSjJ7k|6 za)`k`-xN1(C6j=Y1$yfzL(h) zkI5m!;wB)yLSI$}R;8v?S_vrvcI#fxU=n#gX-x@U**DQ(FbfT~b*9(V2g&kOf#p`-Dy^(19Wk+c*v=kJxDFp3d5U1J`MkqVpbVysy7T z6RQ|i59fpy@n9NWV^e>l0R`cTRp-v!N%sSx@a)O8qrx^^n*iYL1eDeoCsaZN-8Tn${)dxpcEG2pc80?F zd7d~Ej^sOZsgwrZ>6#1($S&lm_W~xv%VWchi5RIfUAVnY#q60Uk*qz@Lz=C13@)0^ zL%PEC=NWXlAAy`vuG|1$b}1zWNw)v$>I!*hj2SZ5eH?*WdX6=HbwL%5PWp*gH60&E z5B|BMb_v-}?0T2qci23vKo#zZzc~Y0zUp1E2Fjavlq<&htg-rtFq+XviqJpX+0y4p z;+qnme3(Y$VWuAp7RrcFl-pUfCdoD?#1RS}l+3S_ad7j!NJq(P@aEgBcsxEXmB8>W zm6L(pimUa=)CgKGmS;(ITkeWRvlCwRR`Vy%^RKvDs?@exnMO`ySZ44-O3R(ULgplu=od*f~^lXB?8gE}WKRT7|fVzg}6qL`gp0;49$Casrrv zo>dYpe4Bb9Tu%&VJk@l}-^%)*Uf8O2)b96WNzb^sxd~E|u^XmUv~HJ~ZxaT-66C$* zj_?9crHL!sgI>&gptQm0lo0sgy6!2)+dh1wx*Os2z|_^0UH>g_W$h@Pc))}hK~ro{ zdkd*#J^p#FI!i|5W+6i%zsInHollh-eY-7yDwiy9cem zd(M5rby;mCjiyn5_-P4f0CMv4ZCovhOk@MNBn-Vn9D#&YP`ZlRlqgi^dx0Xg0w^H^ zflzfvE1i(kF&BS0yy^=Hw-t(Km)x_KY1A-oXis5N(Q*LpM!&52xShWc~y zH%oeY@^AfjNDC$|>qO_dE#_l=fsc82OF&mbw>>n=ZPQ1Xe?&73q-7bY;t-)BYv$0J zprWfOFvMWB8Z*D-R^lMF$@9)E1aY*dw4^!Q^IF)^Hc_0|E`ZptzPW8wulvDl0$H!esyX~Q-2gOPPG;^~n0K?-46S#^*RG5Kox ztiIR(?0Wr(H#QzusyRDZc!U^Je(XseYm`RQ{dt#O_^Lt7{`#-Z2vo&uH z$sfA$Aky&04VM{Db?t*93nD9MQ$C<6nw$YFvY3Aj1chDlV9PVbIk+0179QmAD+(Z6 zqLpUn*!c^%*$GY0CIxbW3#c@*mlyO zjcuEE_q)F!BV(Vl-}gMvT66vq4erN_#?RD>CZnczmDpO27C0xfFFGGB6)M&m^Dwo_D$OLxl(7S;qoQVh{R_$JkmZL5*m>l2x>^V{fsbi8fFyK=pH!u{7728 zn%`C|OC-fRbJE2709JG$dn*8KRh!F&nAWb^6MR8JsCfC@`?|U*NA*oVI^0*pB#uO}0s>tkiNkFdjfj{&O9up)b0yy0%QG3!dDp1Sn4tBIbg z+q2EC=o$ZO`2Ye5qU}%&aN!EgN|QBsWkU_J-~qGh#x+aeHU^Xll2=zC24 z)_0zh)XDZgpE?WJBeg6=Mv)1N%i5Ds$6?uFaP-zx2oHik zl77AXoUWYd@>{5!5%S&5t3}QXFm&0tEHQE|rTEBBGviC9SCh9oi+OiAR{-0}E9gRT z=``WjK{LKG7}nyu?MJol>%Y5ektX)PJD-@CNQ*_wJ|`=2~>C)f7^sHvj<#tX9i5l||AE{U{ltBPmS0-TpXi+=aZ zm%9#!D2835x3h>}K<{+U6q2r1j-prvZ65<(9zG^64&W~cKZOVz1L#4L60Oc^tidnY z3v^dy4eKFMYR53u``tBDu73-JW(UB&ryw%7f#-75FSC|KRFXQ`1(X`rB0n@%6sk`n ziBM^BU@1KSWtRz-(iT@3+j?aJ_1}9^MXWL?i?*Cx_A4S?hX497B2NE`IJUM?iHWFe zp(*Kk3Yq^;^Yf0PZ3XdNA@T22RtVn$xxVV%(A zs_7hmXAMa!6fRt$R8HAX;PSjjS4xR@c)071)9fRbb2`!0dfcoVFfP{fP0+(C@coDG^JUov8HY5`_h^J@tJw&( zr6ehmI|6Ur>X1eShhA29SK9;jz^7HpF#sCgrhnBcZ|YxLz1@2n&@k}&czCaNOnNZHj{m97nteujv3oWGK@jK)B zy6%CU_X6CTfGRty&G=I|qB|USnaC>~Wr%O(pYYd3t97Qk*Q%Z^FvI&Btt%&>411W( zsAu#0gr;|Vz7b>Jk1ZPp1FU3FK<^?D-z%B94 z4sjk<>p)$LZN=;Zk3!&SE99sj zdgGTa;Ttl9&BVQOitYQrhjhshNr}WBZ?$d?Fp>pQ%eXdiHSKB9V6KO#O28iH+wxe= z9EnZLqu#;6LAo2H+lbW>wS$kmL(@$y<71M>a+e$x5_F$Nl0>SIXzO1K;KO}=?ZOqK zko&flMkJnU^{*y`@7M;4Y8?kavFv>I=tqy=z(m!}7FMkqEq19K+qR*AKO2;EIy2sG zL|HV8p#BUkBM9CP=U#qsWbfTY-&0JmInNhrQMdGPXlbLMq;|be&mo`rvr_jgXS~9f zJId_85Yl~`;Y7r@1MwAsBBH0$^hmXQ78sajiYdfu%bb6-Nr7%VZoqXkxW#i*n7?X| zR1>Dc%p{5xP6{v+7f(IxyQTrMz%QT`_pF6&AYsXnStx;wWc`8?zSwHN{Vz`1&7Vs< zVj!A7(8s58UduYX&$Zd^b~xSITGM@y_>?X0STx#^;bRlbmNx zj~&J(&N4j-Pa~fef-Wx1?Z#uH=A>(c|ixr36Zd{N(bpyYEtqKW#Z z10}qvC-^YpWMr{YQ`-(s?4DNh0)*4_y@=3gT$P!xSX;kZtK)cma9^$ac8`=geKJsE z9h5iYnU{Qt$Jrs352ESZJu%*5(NF@fVu+F}$Bc+d3G-`HOQ_b}RN9$D;GLxw2l!Cm z_PLjBL109MYk5APnHq)n!S#3;1gR>S7%45qq~65BE&QGm*%G7zpJe_?C>6Q(G|n+junZcVI6DmL zym2w9R>Jq-ZWeRxYC_XJ4`y{0zw}qXB5&xD%GMeB0Xuhcd6i5d}DV) zay{k{-4LHDug3|dT??(enWFffjK4iz&;V}TfFQt{`&6nl9gnbd`Lupfk76V#WpRNy zBj)z6Khp)KJ{Q~AuvB#0mk|rWOm9*7C%9%*EOK$qb}jO%y9w&l#lytV7(@wxH{3>>$KnA8+?>2h87KQmEg4Qwu9v zc_vyG1urRm!OrM2hH3 z)-6)J-7F)(S4FVfYb4EkD+rp$(+>(&5+atb90Q{MaD=}ZEaW~VAcQl#>Tkg+!S(sz z0d_*cL3`SI?~LD*)pIXke>PVi*$*$w0{GZVwju|qCK8m77s&%;EKgg5Aq9jUc7Biz z!Nr={4y3Buwsaytg5+nP1=tc2MB1&mBQ823w)%2nJS-!d0=4TD;+nyzIp=Xse%*A{ z!7DnVAtccE$R1nEM61Wm{&x0OBEu{|5Wy4U(`NwBjU|wF7irDA8cZr|u9=qHrim?< z+M^J|sTyO|iDN|24#U8sy%RYnI`p2Sr|N^Poo0g6)C6r5eROk<1BtAI;^YXea!yY| zHHYN5Val4buacMIocx0!5j0Oa{4xy+#wkKIH8}|slli@VPZ+Y|wAvls6MH*ISIMa$ z&#c?Dv-KdOO+J~!Z_Oddc{4S0V*IMjK4l^KE~fUy7+yG{t>5`*OVm@~hUVwrpR4u_ zXE%LaDv&7yvVkYvxKexSK3uwXT=B{*ynIk1MRVG2L^wx{z~ZNY!B>g3NOw%4IpvNd z5`-35#{ozTQ^nzJt2_&rZHTUYt{}RQt%AJ+IWU_c-~f`0^o-d}Cu>|GBVSC?EPBXx z6MAaB)x!y0bG@zPz3ja0ygIvc`E$+{cD3WmHTJ#Oa(6h^-moXg;crX5qaRwFD=gCHSWyMHMhB0WhUnnO@N5kP#8c(8n{jU5tF5Im zWH$nUwkC7xfaKVfu2C(KUnOW~6&Q7B<-KqKj62R{0}qYznyuM_yxkiCN(6F_I25mQ zMQ%4IT7|Z{I^ciCc~YY<3&BnW;lV64v{S5IA0B2k=^E}|W5|12v+^1O!j_e_-I=pc z)+MSUTW-b}d{W8=z2W#9!K>bZ7k&QLKhWhi=cJ+tDs6ENCCXkM{ZmI*r7r+odcVA( zFl&p8aG!Qo+r{Db=okAO><{9$j{oMWm;Jyd{v%_xobLIX9zKJY?!x-#*>6C|`cw^^ z%T`Y6Q9Lm@Xys-3!4jyE_Z9QxW<~$JIl!R?*^kn&HgFO&>E%)&0+++#jQtpO^&JS^itqjEw(a&<5=*HVR8{kr zE+ICy209vCPxI{C&gSNnB$EgR95IY+U{rek?H=DwkJE9Z(_3S{pdumMghvKU{RJYW zMZ9s<+;yHlM=So`$3Nv30GHN1_*J`t1p#q&xA*(y+pQ4fmtI%<7|%bYG;BCxJnFAj z4cWltE$-n95+&5KH5)6JlD?*Xbf+=x@!XV~?i8OWjY@sLBwoRU+pcEKz}PI2ckY)x zr~?0?Av{^;sf^3wY;EmAk2jolR;BAnfuci$-aT)<#2<)MAyCVJt9tj8%XNaW_Ao2& zoenwRkmy0MD_UyN7%=7S2c%J477om|%4eMyObO}gq}9is;zXM@O&opwvuI1SWCMwF z$bw_9nqZYto6K*N5vjhXXIvu*zXEo=Nb*ds@jW#Y2=hk*fbEB@&As8TRph!oafY>1 z5AdzG|C-PHN_ory2kd~EqaS96ho~vJqC#Fx&NddRODTdSPN&BP{e0iTQ}71n8;|e| zxv*bCyx$(V{ol^8sVwdV81Q}-QpCMq#Kc8ru^O-Z0zv`FbQk4SV#NqrjFon0q?HL- z+5OMcG|hEV+i;$j>jN8IzRx>pJ-}{3pf8S^sPxDkMtTI7kZ@>AX2HEzuyr1(jCVkj zn2=IgK-%lJ#bM3o^sm=t$Ho*8ua{;2PU}O2i3$OFG_S){nJxyiS-U|zR?)keirIJQ zRag^T^&%B*f{}>rV4hfb;xUSz3Sa{IpozA6cjMheRZ*ZpO|}ldd`ZS*D$!1-kvos! zoV_|B(7X+cc(()}A*O^LMN+132r+haBxrCM`mQ#b=M1E5aioM0Mrxy0b8WpTTyul&2;izPqX0;gLAvx#J@rk5_ z3g>8yVii;35g!8fr~fcRQ4`Ff{6S-au_Op$u4w>=-vz^zP=?kEaLA1Pd)#R~Zx+Bi zvSJykY=i|tSsoPUY}Z&z>#~tGylw6(N5z&i6CM3*y*XOh|Ky9l>lkIsu+WcOJ>mWG zlNa8Ijk=(JZ@-)gHwFUXC`8HvwKl&J6tZNLd!Kc}3r}u<7O)$;`?t2c)MI-Qd7Kzp zgH$|%!d_q2p*%Ocp8cV)hGwMAZ-@9w0&nM8E$!V1 zggp3B`tmXIbBSR*MQMH6>I%7EIe)Zv#+&}t6eCQ+iW6Bz!HO~rM*=sec)CEo-2Y+p zK_H!Wh?9|BZ0FBxxgaZueeTY7Ra&nNS!^R$1uj+q)QfHm(;j2T$f@>E9PN=rHQ^Kf9vwpruq!)KMNM&s5r1PDG!z|ntvLxBKfRgPEw14=b& zaEu&u%$hkxwmo!Dmt)421JjC#FdUuR9<>KG9X$gfkN$baRgrUewD{J$C{pCKC~8Si zQQevhwqr5jCBL$7eZmoWxR%M6PEo1Aq;rznj_RAT)zVa=Nn#k-)FcvrVm;?>M?Q=% z&f^wOB~FtmAV~(-VbS_pW0HG7XAi?fYRA-3+pe^Uw)utnUC5?BD60PT!-~CSF0MCW z&zi~Gt3X6Fd`yadep#+L_>%X6f&6xbiuLL?*qmNI3(r2qote!Nz8hI2_+vg2zUB|h zSi5FUCZe->D3kav1Ol8yv+6-iUZfG#dIiO$1iU6h8=MdpFomEg*E*z1jIbX#YN70d z{V1lhI`PlY7pCDc)lLEM_lSr6HyqshKCnISo9|G6Xg?0z@`|*22W8MnA>g|#Bn;5G z$PQj^If^pBy59ot)U13W^kZ5}tb?a4{_bA?c%i{lr)SuW>$tDZ=P6q3^Y(>_N7{2S zU1huZU4Kn)A9@q|t%w$!%rP92wspggC0b8WO-oTKbO-UuzzAiU-tb;-<1sgH&%mi8 zWo(XhUZ9|dWklP5UReRHF5y6klw=%BuO?Gkt~ypuSECILj7e>lBwGY!>v{Y4oE<<2 zl<5#bPEFhHbv(H2z^{Kbna(jZZL9F=FMOqWFuiCc?}mChT(89sH-YKNy<#( zfXmCS7bPx$!Nj`{RJdIz{V5WnP>`!14!}`&gTT$ZfIg z#mBT23to7KEn!Y@tXz~#V#N0?L^3VT0MhkL2ql_~vb1_XH4U zdf5}XW=9YUDUvF2V^yUmif%WYQ=(E=4s~4OQ3EYTD<)LM7xSF+#H&J@Ef> zIZ~ZB7qIZ0(u(C!;F4g5ql5eoP{#n#-hQSpdE?V|N;W_n1hLtfQ~?8Z_718S+O~}8 zqg5t{F_$R7#7j{7V$O?{SBx4aDcS8{#RyYi�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